sbuilder-ethereum 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/VERSION +1 -0
- data/lib/mixer/decl_ref.rb +19 -0
- data/lib/mixer/domain_ref.rb +18 -0
- data/lib/mixer/scope.rb +92 -0
- data/lib/mixer/scoped.rb +17 -0
- data/lib/mixer/symbol_ref.rb +16 -0
- data/lib/mixer/type_symbol.rb +75 -0
- data/lib/plugin/plugin.rb +332 -0
- data/lib/resources/correctness/accouns_type.tla +1 -0
- data/lib/resources/correctness/accounts_unique.tla +2 -0
- data/lib/resources/correctness/accounts_valid.tla +2 -0
- data/lib/resources/correctness/storage_root_unique.tla +2 -0
- data/lib/resources/correctness/total_value.tla +1 -0
- data/lib/resources/eth/accounts_state.tla +2 -0
- data/lib/resources/eth/accounts_temp.tla +2 -0
- data/lib/resources/eth/address_free.tla +2 -0
- data/lib/resources/eth/mined_state.tla +1 -0
- data/lib/resources/eth/storageRoot.tla +1 -0
- data/lib/resources/eth/storageRoot_temp.tla +1 -0
- data/lib/resources/mine/mine_entry.tla +4 -0
- data/lib/resources/mine/mine_service.tla +22 -0
- data/lib/resources/operators/elementExists.tla +4 -0
- data/lib/resources/operators/gasPrice.tla +2 -0
- data/lib/resources/operators/gasValue.tla +2 -0
- data/lib/resources/operators/getElement.tla +5 -0
- data/lib/resources/operators/intrinsicGas.tla +4 -0
- data/lib/resources/operators/transactionGas.tla +4 -0
- data/lib/resources/operators/upFrontCost.tla +6 -0
- data/lib/resources/personal_newAccount/personal_newAccount_done.tla +14 -0
- data/lib/resources/personal_newAccount/personal_newAccount_entry.tla +10 -0
- data/lib/resources/personal_newAccount/personal_newAccount_service.tla +29 -0
- data/lib/resources/removed/sendTransaction_entry.tla +5 -0
- data/lib/resources/removed/sendTransaction_service.tla +36 -0
- data/lib/resources/removed/tst.tla +1 -0
- data/lib/resources/transaction/ethereum_service_done.tla +24 -0
- data/lib/resources/transaction/ethereum_service_pop.tla +24 -0
- data/lib/resources/transaction/ethereum_service_push.tla +14 -0
- data/lib/resources/transaction/ethereum_service_start.tla +13 -0
- data/lib/resources/transaction/status_fail.tla +1 -0
- data/lib/resources/transaction/status_ok.tla +1 -0
- data/lib/sbuilder-ethereum.rb +52 -0
- data/lib/sbuilder/compile.rb +163 -0
- data/lib/sbuilder/constants.rb +93 -0
- data/lib/sbuilder/exception.rb +22 -0
- data/lib/sbuilder/generate/sexp_processor_tla.rb +2674 -0
- data/lib/sbuilder/generate/tla_element_generator.rb +1206 -0
- data/lib/sbuilder/generate/tla_element_text.rb +703 -0
- data/lib/sbuilder/load.rb +119 -0
- data/lib/sbuilder/mustache/renderer.rb +152 -0
- data/lib/sbuilder/render.rb +141 -0
- data/lib/sbuilder/s.rb +21 -0
- data/lib/sbuilder/sexp_ast.rb +1378 -0
- data/lib/sbuilder/sexp_processor_api.rb +184 -0
- data/lib/sbuilder/sexp_processor_canonize.rb +326 -0
- data/lib/sbuilder/sexp_processor_dataflow.rb +461 -0
- data/lib/sbuilder/sexp_processor_ethereum.rb +127 -0
- data/lib/sbuilder/sexp_processor_need_to_canonize.rb +572 -0
- data/lib/sbuilder/sexp_processor_snippet.rb +154 -0
- data/lib/sbuilder/sexp_processor_symboltable1.rb +296 -0
- data/lib/sbuilder/sexp_processor_symboltable2.rb +175 -0
- data/lib/sbuilder/sexp_utils.rb +417 -0
- data/lib/utils/logger.rb +82 -0
- data/lib/utils/string_inject.rb +11 -0
- data/sbuilder-ethereum.gemspec +39 -0
- metadata +190 -0
@@ -0,0 +1,417 @@
|
|
1
|
+
module Sbuilder
|
2
|
+
module Ethereum
|
3
|
+
|
4
|
+
class SexpUtils
|
5
|
+
|
6
|
+
# ------------------------------------------------------------------
|
7
|
+
# @!group Id-generator
|
8
|
+
|
9
|
+
# @attr [Integer] idGenerator class variable used to generate
|
10
|
+
# unique identifiers
|
11
|
+
@@idGenerator = 1
|
12
|
+
|
13
|
+
##
|
14
|
+
# @return [String] nextId unique indetifier generated for each call
|
15
|
+
def self.nextId
|
16
|
+
@@idGenerator += 1
|
17
|
+
"canonized-#{@@idGenerator}"
|
18
|
+
end
|
19
|
+
|
20
|
+
# ##
|
21
|
+
# # Wrap to self.class.nextId
|
22
|
+
# def nextId
|
23
|
+
# self.class.nextId
|
24
|
+
# end
|
25
|
+
|
26
|
+
# @!endgroup
|
27
|
+
|
28
|
+
# ------------------------------------------------------------------
|
29
|
+
# @!group create nodes
|
30
|
+
|
31
|
+
##
|
32
|
+
# Add 'chldExp' to 'exp'
|
33
|
+
def self.addNewChild( exp, chldExp )
|
34
|
+
chldExp.setParent( exp )
|
35
|
+
exp << chldExp
|
36
|
+
exp
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Add method to FunctionDefintion 'exp'. It returns inteface
|
41
|
+
# names like 'Demo()', 'Send()', 'Demo(set)', to be used for
|
42
|
+
# example on setup step 'interface' properties. for function
|
43
|
+
def self.defineInterfaceName( exp, interfaceName )
|
44
|
+
exp.define_singleton_method( :interfaceName ) do
|
45
|
+
interfaceName
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# @!endgroup
|
51
|
+
|
52
|
+
# ------------------------------------------------------------------
|
53
|
+
# @!group create nodes
|
54
|
+
|
55
|
+
##
|
56
|
+
# @return [FunctionDefinition] functionAst for +functionName+
|
57
|
+
def self.createFunction( functionName, isConstructor )
|
58
|
+
|
59
|
+
yaml_str=<<-EOS
|
60
|
+
name: FunctionDefinition
|
61
|
+
id: #{nextId}
|
62
|
+
attributes:
|
63
|
+
constant: false
|
64
|
+
name: #{functionName}
|
65
|
+
public: true
|
66
|
+
children:
|
67
|
+
- children: []
|
68
|
+
id: #{nextId}
|
69
|
+
name: ParameterList
|
70
|
+
- children: []
|
71
|
+
id: #{nextId}
|
72
|
+
name: ParameterList
|
73
|
+
- name: Block
|
74
|
+
children: []
|
75
|
+
id: #{nextId}
|
76
|
+
EOS
|
77
|
+
hash = YAML.load(yaml_str)
|
78
|
+
# logger.debug "#{__method__}: function hash #{hash}"
|
79
|
+
exp = SexpAst.build_sexp( hash )
|
80
|
+
exp
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# ##
|
85
|
+
# # Contruct 'FunctionDefinition' sexp for 'functionName'.
|
86
|
+
# # Add also 'interfaceName' method to this sexp.
|
87
|
+
# def self.createBoolFunction( functionName )
|
88
|
+
|
89
|
+
# yaml_str=<<-EOS
|
90
|
+
# name: FunctionDefinition
|
91
|
+
# id: #{nextId}
|
92
|
+
# attributes:
|
93
|
+
# constant: false
|
94
|
+
# name: #{functionName}
|
95
|
+
# public: true
|
96
|
+
# children:
|
97
|
+
# - children: []
|
98
|
+
# id: #{nextId}
|
99
|
+
# name: ParameterList
|
100
|
+
# - children:
|
101
|
+
# - attributes:
|
102
|
+
# name: ''
|
103
|
+
# type: bool
|
104
|
+
# children:
|
105
|
+
# - attributes:
|
106
|
+
# name: bool
|
107
|
+
# id: #{nextId}
|
108
|
+
# name: ElementaryTypeName
|
109
|
+
# id: #{nextId}
|
110
|
+
# name: VariableDeclaration
|
111
|
+
# id: #{nextId}
|
112
|
+
# name: ParameterList
|
113
|
+
# - children: []
|
114
|
+
# id: #{nextId}
|
115
|
+
# name: Block
|
116
|
+
# EOS
|
117
|
+
# hash = YAML.load(yaml_str)
|
118
|
+
# # logger.debug "#{__method__}: function hash #{hash}"
|
119
|
+
# exp = SexpAst.build_sexp( hash )
|
120
|
+
|
121
|
+
# interfaceName = "#{functionName}()"
|
122
|
+
# defineInterfaceName( exp, interfaceName )
|
123
|
+
# exp
|
124
|
+
# end
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
##
|
129
|
+
# @return [FunctionDefinition] constructor for +contractName+
|
130
|
+
#
|
131
|
+
# @see createFunction
|
132
|
+
def self.createConstructorNode( contractName )
|
133
|
+
constructor = createFunction( contractName, true )
|
134
|
+
|
135
|
+
interfaceName = "#{contractName}()"
|
136
|
+
defineInterfaceName( constructor, interfaceName )
|
137
|
+
constructor
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
# @param [String] operator like +=, *=
|
142
|
+
# @return [String] operator like +, *, ...
|
143
|
+
def self.mapAssignmentOperator( operator )
|
144
|
+
operatorMapper = {
|
145
|
+
"+=" => '+'
|
146
|
+
}
|
147
|
+
mapped = operatorMapper[operator]
|
148
|
+
raise "DO not know how to map operator #{operator}" if mapped.nil?
|
149
|
+
mapped
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.createBinaryOperator( operator )
|
153
|
+
yaml_str=<<-EOS
|
154
|
+
name: BinaryOperation
|
155
|
+
id: #{nextId}
|
156
|
+
attributes:
|
157
|
+
operator: #{operator}
|
158
|
+
type: uint256
|
159
|
+
children: []
|
160
|
+
EOS
|
161
|
+
hash = YAML.load(yaml_str)
|
162
|
+
exp = SexpAst.build_sexp( hash )
|
163
|
+
exp
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.createBoolDecl
|
167
|
+
yaml_str=<<-EOS
|
168
|
+
name: VariableDeclaration
|
169
|
+
id: #{nextId}
|
170
|
+
attributes:
|
171
|
+
name: ''
|
172
|
+
type: bool
|
173
|
+
children:
|
174
|
+
- name: ElementaryTypeName
|
175
|
+
id: #{nextId}
|
176
|
+
children:
|
177
|
+
attributes:
|
178
|
+
name: bool
|
179
|
+
EOS
|
180
|
+
hash = YAML.load(yaml_str)
|
181
|
+
exp = SexpAst.build_sexp( hash )
|
182
|
+
exp
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.createReturn()
|
186
|
+
yaml_str=<<-EOS
|
187
|
+
name: Return
|
188
|
+
id: #{nextId}
|
189
|
+
children:
|
190
|
+
- name: Literal
|
191
|
+
id: #{nextId}
|
192
|
+
attributes:
|
193
|
+
string: 'true'
|
194
|
+
type: bool
|
195
|
+
value: 'true'
|
196
|
+
EOS
|
197
|
+
hash = YAML.load(yaml_str)
|
198
|
+
exp = SexpAst.build_sexp( hash )
|
199
|
+
exp
|
200
|
+
end
|
201
|
+
|
202
|
+
def splitOperator( operator, assigned, expr )
|
203
|
+
end
|
204
|
+
|
205
|
+
# @return [FunctionDefinition] getter SexpAst for +variableName+
|
206
|
+
def self.createGetter( variableName )
|
207
|
+
|
208
|
+
getterForVariable = variableName[0,1].upcase + variableName[1..-1]
|
209
|
+
getterName = "get#{getterForVariable}"
|
210
|
+
|
211
|
+
|
212
|
+
# Type should be of no interest because specification uses
|
213
|
+
# domains. use
|
214
|
+
type ="uint256"
|
215
|
+
elementaryType="uint"
|
216
|
+
|
217
|
+
|
218
|
+
getterStr = <<-EOS
|
219
|
+
attributes:
|
220
|
+
constant: true
|
221
|
+
name: #{getterName}
|
222
|
+
public: true
|
223
|
+
children:
|
224
|
+
- children: []
|
225
|
+
id: #{nextId}
|
226
|
+
name: ParameterList
|
227
|
+
src: ""
|
228
|
+
- children:
|
229
|
+
- attributes:
|
230
|
+
name: #{variableName}
|
231
|
+
type: uint256
|
232
|
+
children:
|
233
|
+
- attributes:
|
234
|
+
name: uint
|
235
|
+
id: #{nextId}
|
236
|
+
name: ElementaryTypeName
|
237
|
+
src: ""
|
238
|
+
id: #{nextId}
|
239
|
+
name: VariableDeclaration
|
240
|
+
src: ""
|
241
|
+
id: #{nextId}
|
242
|
+
name: ParameterList
|
243
|
+
src: ""
|
244
|
+
- children:
|
245
|
+
- children:
|
246
|
+
- attributes:
|
247
|
+
type: uint256
|
248
|
+
value: #{variableName}
|
249
|
+
id: #{nextId}
|
250
|
+
name: Identifier
|
251
|
+
src: ""
|
252
|
+
id: #{nextId}
|
253
|
+
name: Return
|
254
|
+
src: ""
|
255
|
+
id: #{nextId}
|
256
|
+
name: Block
|
257
|
+
src: ""
|
258
|
+
id: #{nextId}
|
259
|
+
name: FunctionDefinition
|
260
|
+
src: ""
|
261
|
+
EOS
|
262
|
+
|
263
|
+
getterHash = YAML.load(getterStr)
|
264
|
+
# logger.debug "#{__method__}: getterHash=#{getterHash}"
|
265
|
+
SexpAst.build_sexp( getterHash )
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
# @return [VariableDeclaration] variableDeclarion SexpAst for +variableName+
|
270
|
+
def self.createVariableDeclaration( variableName )
|
271
|
+
|
272
|
+
|
273
|
+
# Type should be of no interest because specification uses
|
274
|
+
# domains. use
|
275
|
+
type ="uint256"
|
276
|
+
elementaryType="uint"
|
277
|
+
|
278
|
+
variableStr=<<-EOS
|
279
|
+
name: VariableDeclaration
|
280
|
+
id: #{nextId}
|
281
|
+
attributes:
|
282
|
+
name: #{variableName}
|
283
|
+
type: #{type}
|
284
|
+
children:
|
285
|
+
- attributes:
|
286
|
+
name: #{elementaryType}
|
287
|
+
name: ElementaryTypeName
|
288
|
+
id: #{nextId}
|
289
|
+
EOS
|
290
|
+
|
291
|
+
|
292
|
+
variable = YAML.load(variableStr)
|
293
|
+
# logger.debug "#{__method__}: variable #{hash}"
|
294
|
+
SexpAst.build_sexp( variable )
|
295
|
+
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
def self.createVariableDeclarationWithDomain( variableName, domainName )
|
301
|
+
|
302
|
+
# Type should be of no interest because specification uses
|
303
|
+
# domains. use
|
304
|
+
type =domainName
|
305
|
+
elementaryType="uint"
|
306
|
+
|
307
|
+
# eg. knows how to resolve 'send' and other address releated functions
|
308
|
+
solidityType = domainName == Constants::DOMAIN_ADDRESS ? Constants::SOL_ADDRESS : nil
|
309
|
+
|
310
|
+
variableStr=<<-EOS
|
311
|
+
name: VariableDeclaration
|
312
|
+
id: #{nextId}
|
313
|
+
attributes:
|
314
|
+
name: #{variableName}
|
315
|
+
type: #{type}
|
316
|
+
children:
|
317
|
+
- attributes:
|
318
|
+
name: #{domainName}
|
319
|
+
solidityType: #{solidityType}
|
320
|
+
name: Domain
|
321
|
+
id: #{nextId}
|
322
|
+
EOS
|
323
|
+
|
324
|
+
variable = YAML.load(variableStr)
|
325
|
+
# logger.debug "#{__method__}: variable #{hash}"
|
326
|
+
SexpAst.build_sexp( variable )
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
# @!endgroup
|
331
|
+
|
332
|
+
# ------------------------------------------------------------------
|
333
|
+
# @!group Id-generator
|
334
|
+
|
335
|
+
def self.createGlobalScope
|
336
|
+
|
337
|
+
scope = GlobalScope.new
|
338
|
+
|
339
|
+
scopeName = "GlobalScope"
|
340
|
+
|
341
|
+
globalFunctions = [Constants::SOL_SEND].inject( { }) do |memo,fname|
|
342
|
+
memo[fname] = initFunction( scopeName, fname )
|
343
|
+
memo
|
344
|
+
end
|
345
|
+
|
346
|
+
|
347
|
+
# generate uqiue identfiers
|
348
|
+
# id = 1
|
349
|
+
# scope.define( Constants::SOL_NOW, Now.new( "GLOB-#{id}" ) ); id += 1;
|
350
|
+
|
351
|
+
# global scope acts as a contract - add global functions there
|
352
|
+
globalFunctions.each do |name, func |
|
353
|
+
scope << func
|
354
|
+
scope.define( func.interfaceName, func )
|
355
|
+
end
|
356
|
+
|
357
|
+
# add built in types, possibly define some function
|
358
|
+
# e.g. address send
|
359
|
+
[
|
360
|
+
[ Constants::SOL_BOOLEAN_TYPE, nil],
|
361
|
+
[ Constants::SOL_UINT, nil],
|
362
|
+
[ Constants::SOL_ADDRESS, globalFunctions],
|
363
|
+
].each do |builtIn|
|
364
|
+
builtInType = builtIn[0]
|
365
|
+
funcs = builtIn[1]
|
366
|
+
newType = BuiltInSymbol.new( builtInType )
|
367
|
+
scope.define( builtInType, newType )
|
368
|
+
|
369
|
+
# funcs is a hash
|
370
|
+
funcs && funcs.each do |name,func|
|
371
|
+
newType.define( name, func)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
scope
|
376
|
+
end
|
377
|
+
|
378
|
+
##
|
379
|
+
# Create function 'functionName', in 'scopeName', and add common
|
380
|
+
# request paramerters
|
381
|
+
def self.initFunction( scopeName, functionName )
|
382
|
+
|
383
|
+
isConstructor = false
|
384
|
+
functionSexp = SexpUtils.createFunction(functionName, isConstructor)
|
385
|
+
interfaceName = "#{scopeName}(#{functionName})"
|
386
|
+
defineInterfaceName( functionSexp, interfaceName )
|
387
|
+
|
388
|
+
functionSexp.block<< SexpUtils.createReturn()
|
389
|
+
|
390
|
+
# add common requet parameters
|
391
|
+
requestParameters = functionSexp.parameterList
|
392
|
+
TlaElementText.commonMsgProperties( 'request', isConstructor ).each do |parameter|
|
393
|
+
newParameter = SexpUtils.createVariableDeclarationWithDomain( parameter[1], parameter[2] )
|
394
|
+
SexpUtils.addNewChild( requestParameters, newParameter )
|
395
|
+
end
|
396
|
+
|
397
|
+
# Add return parameters for boolean variable
|
398
|
+
TlaElementText.commonMsgProperties( 'response-bool', isConstructor ).each do |parameter|
|
399
|
+
newParameter = SexpUtils.createVariableDeclarationWithDomain( parameter[1], parameter[2] )
|
400
|
+
SexpUtils.addNewChild( functionSexp.returnList, newParameter )
|
401
|
+
end
|
402
|
+
|
403
|
+
#
|
404
|
+
return functionSexp
|
405
|
+
end
|
406
|
+
|
407
|
+
|
408
|
+
|
409
|
+
# @!endgroup
|
410
|
+
|
411
|
+
|
412
|
+
|
413
|
+
end
|
414
|
+
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|
data/lib/utils/logger.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module Sbuilder
|
2
|
+
module Ethereum
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
# see http://hawkins.io/2013/08/using-the-ruby-logger/
|
6
|
+
|
7
|
+
module MyLogger
|
8
|
+
|
9
|
+
# no logging done
|
10
|
+
|
11
|
+
class NullLoger < Logger
|
12
|
+
def initialize(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(*args, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def debug?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
@@logfile = nil # absolute path to log file
|
24
|
+
LOGFILE="sbuilder.log"
|
25
|
+
|
26
|
+
def logfile( options )
|
27
|
+
return @@logfile if @@logfile
|
28
|
+
@@logfile = options[:logfile] || File.join( Dir.getwd, LOGFILE )
|
29
|
+
@@logfile
|
30
|
+
end
|
31
|
+
|
32
|
+
def getLogger( progname=nil, options={} )
|
33
|
+
|
34
|
+
|
35
|
+
progname = self.class.name.split('::').last if progname.nil?
|
36
|
+
level = get_level( options )
|
37
|
+
|
38
|
+
if level.nil?
|
39
|
+
|
40
|
+
return NullLoger.new
|
41
|
+
|
42
|
+
else
|
43
|
+
|
44
|
+
|
45
|
+
logger = Logger.new( logfile(options) )
|
46
|
+
logger.level=level
|
47
|
+
logger.progname = progname
|
48
|
+
return logger
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end # getLogger
|
53
|
+
|
54
|
+
|
55
|
+
# ------------------------------------------------------------------
|
56
|
+
private
|
57
|
+
|
58
|
+
def get_level( options )
|
59
|
+
|
60
|
+
level_name = options && options[:log] ? options[:log] : ENV['LOG_LEVEL']
|
61
|
+
|
62
|
+
level = case level_name
|
63
|
+
when 'warn', 'WARN'
|
64
|
+
Logger::WARN
|
65
|
+
when 'info', 'INFO'
|
66
|
+
Logger::INFO
|
67
|
+
when 'debug', 'DEBUG'
|
68
|
+
Logger::DEBUG
|
69
|
+
when 'error', 'ERROR'
|
70
|
+
Logger::ERROR
|
71
|
+
else
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
return level
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|