sbuilder-ethereum 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 @@
|
|
1
|
+
accounts_type == \A e \in {{#SPEC_NAME}}eth.accounts{{/SPEC_NAME}}: e \in {{#SPEC_NAME}}definitions.Accounts{{/SPEC_NAME}}
|
@@ -0,0 +1 @@
|
|
1
|
+
total_value == Stable => ( {{#SPEC_NAME}}eth.mined{{/SPEC_NAME}} + SumRecordField( {{#SPEC_NAME}}eth.accounts{{/SPEC_NAME}}, "balance" ) = 0 )
|
@@ -0,0 +1 @@
|
|
1
|
+
{{#SPEC_NAME}}eth.mined{{/SPEC_NAME}} = 0;
|
@@ -0,0 +1 @@
|
|
1
|
+
{{#SPEC_NAME}}eth.storageRoot{{/SPEC_NAME}} = {};
|
@@ -0,0 +1 @@
|
|
1
|
+
{{#SPEC_NAME}}eth.storageRoot_temp{{/SPEC_NAME}} = <<>>;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
procedure {{#SPEC_NAME}}eth.mine{{/SPEC_NAME}}( input ) {
|
2
|
+
|
3
|
+
{{#SPEC_NAME}}eth.mine{{/SPEC_NAME}}_enter:
|
4
|
+
|
5
|
+
\* Check that account input.etherbase exists
|
6
|
+
if ( { e \in {{#SPEC_NAME}}eth.accounts{{/SPEC_NAME}}: e.address = input.beneficiary } = {}) {
|
7
|
+
goto {{#SPEC_NAME}}eth.mine{{/SPEC_NAME}}_exit;
|
8
|
+
};
|
9
|
+
|
10
|
+
{{#SPEC_NAME}}eth.mine{{/SPEC_NAME}}_ok:
|
11
|
+
|
12
|
+
\* Update on 'account.balance' with 'input.value'
|
13
|
+
{{#SPEC_NAME}}eth.accounts{{/SPEC_NAME}} :=
|
14
|
+
{ IF e.address = input.beneficiary THEN [ e EXCEPT !.balance = e.balance + input.value ] ELSE e : e \in {{#SPEC_NAME}}eth.accounts{{/SPEC_NAME}} };
|
15
|
+
|
16
|
+
\* Update total value 'mined'
|
17
|
+
{{#SPEC_NAME}}eth.mined{{/SPEC_NAME}} := {{#SPEC_NAME}}eth.mined{{/SPEC_NAME}} - input.value;
|
18
|
+
|
19
|
+
{{#SPEC_NAME}}eth.mine{{/SPEC_NAME}}_exit:
|
20
|
+
return;
|
21
|
+
|
22
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
macro personal_newAccount_done( interface ) {
|
2
|
+
|
3
|
+
\* like ethereum_service_done( interface ) + creates eth_storageRoot
|
4
|
+
|
5
|
+
|
6
|
+
eth_storageRoot := Head(eth_storageRoot_temp) \union { [address |-> InfrastructureServiceGetResponse( "personal_newAccount()" ) ] };
|
7
|
+
eth_accounts := Head(eth_accounts_temp);
|
8
|
+
\* eth_gasUsed := Head(eth_gasUsed_temp);
|
9
|
+
|
10
|
+
eth_storageRoot_temp := <<>>;
|
11
|
+
eth_accounts_temp := <<>>;
|
12
|
+
\* eth_gasUsed_temp := <<>>;
|
13
|
+
|
14
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
macro {{#SPEC_NAME}}service_implementation.personal_newAccount(){{/SPEC_NAME}}( input ) {
|
2
|
+
|
3
|
+
\* prepare for transaction
|
4
|
+
\* print <<"TRACE>","TX-start@personal_newAccount(): push block state to stack">>;
|
5
|
+
|
6
|
+
ethereum_service_start();
|
7
|
+
|
8
|
+
call {{#SPEC_NAME}}eth.personal_newAccount{{/SPEC_NAME}}( [ codeHash |-> input.dummy, address |-> Nil ] );
|
9
|
+
|
10
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
(*
|
3
|
+
* @param [codeHash] class name, Nil for non-contract accounts
|
4
|
+
* @param [address] Nil|address to take from pools
|
5
|
+
*)
|
6
|
+
procedure {{#SPEC_NAME}}eth.personal_newAccount{{/SPEC_NAME}}( input ) {
|
7
|
+
|
8
|
+
{{#SPEC_NAME}}eth.personal_newAccount{{/SPEC_NAME}}_enter:
|
9
|
+
|
10
|
+
\* Must have NextId available in free address pool
|
11
|
+
assert( {{#SPEC_NAME}}eth.address_free{{/SPEC_NAME}} # {} );
|
12
|
+
|
13
|
+
\* Create account record in 'accounts' variable, input.dummy is default - because no input defined
|
14
|
+
{{#SPEC_NAME}}eth.accounts_temp{{/SPEC_NAME}} :=
|
15
|
+
UpdateTop( {{#SPEC_NAME}}eth.accounts_temp{{/SPEC_NAME}},
|
16
|
+
Head( {{#SPEC_NAME}}eth.accounts_temp{{/SPEC_NAME}} ) \union { [ address |-> NextId( {{#SPEC_NAME}}eth.address_free{{/SPEC_NAME}}, input.address ), balance |-> 0, codeHash |-> input.codeHash ]});
|
17
|
+
|
18
|
+
\* Set return
|
19
|
+
InfrastructureServiceReturn( "personal_newAccount()", status_OK, NextId( {{#SPEC_NAME}}eth.address_free{{/SPEC_NAME}}, input.address ) );
|
20
|
+
|
21
|
+
\* Remove 'NextId' from frees address pool
|
22
|
+
{{#SPEC_NAME}}eth.address_free{{/SPEC_NAME}} :=
|
23
|
+
{{#SPEC_NAME}}eth.address_free{{/SPEC_NAME}} \ { NextId( {{#SPEC_NAME}}eth.address_free{{/SPEC_NAME}}, input.address ) };
|
24
|
+
|
25
|
+
{{#SPEC_NAME}}eth.personal_newAccount{{/SPEC_NAME}}_exit:
|
26
|
+
|
27
|
+
return;
|
28
|
+
|
29
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
procedure sendTransaction( input ) {
|
2
|
+
|
3
|
+
sendTransaction_enter:
|
4
|
+
|
5
|
+
|
6
|
+
(* Validate send transaction
|
7
|
+
- must be transferring accross different addresses 'to' <> 'from'
|
8
|
+
- sender 'from' must have enough 'value'
|
9
|
+
*)
|
10
|
+
|
11
|
+
if (
|
12
|
+
{ e \in accounts : e.aid = input.from } = {}
|
13
|
+
\/ input.from = input.to
|
14
|
+
\/ (CHOOSE x \in { e \in accounts: e.aid = input.from } : TRUE ).value < input.value
|
15
|
+
) {
|
16
|
+
|
17
|
+
goto sendTransaction_exit;
|
18
|
+
|
19
|
+
};
|
20
|
+
|
21
|
+
sendTransaction_transaction_ok:
|
22
|
+
|
23
|
+
|
24
|
+
\* Send: 'to.value' += input.value; 'from.value' -= input.value
|
25
|
+
|
26
|
+
accounts := { e \in accounts : e.aid # input.from /\ e.aid # input.to }
|
27
|
+
\union
|
28
|
+
{ [ e_to_new EXCEPT !.value = e_to_new.value + input.value ] : e_to_new \in { e_to \in accounts: e_to.aid = input.to } }
|
29
|
+
\union
|
30
|
+
{ [ e_from_new EXCEPT !.value = e_from_new.value - input.value ] : e_from_new \in { e_from \in accounts: e_from.aid = input.from } }
|
31
|
+
;
|
32
|
+
|
33
|
+
sendTransaction_exit:
|
34
|
+
return;
|
35
|
+
|
36
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
tst == TRUE
|
@@ -0,0 +1,24 @@
|
|
1
|
+
(*
|
2
|
+
* Interface process (called scheduled) has finished.
|
3
|
+
* Check service response status, and
|
4
|
+
* commit changes in 'eth_storageRoot' and 'eth_accounts', if success.
|
5
|
+
* In any case clear variables modeling block status because
|
6
|
+
* they are not needed anymore (after all scheduler starts a new
|
7
|
+
* round).
|
8
|
+
*
|
9
|
+
*)
|
10
|
+
macro ethereum_service_done( interface ) {
|
11
|
+
|
12
|
+
if ( InfrastructureServiceGetStatus(interface ) = TRUE ) {
|
13
|
+
\* Success commit changes to 'temp' & cleanup
|
14
|
+
{|^preferences.tla-trace|}\* {|/preferences.tla-trace|} print <<"TRACE>", "TX-end@", interface, "success: restore eth_storageRoot ">>;
|
15
|
+
{|^preferences.tla-trace|}\* {|/preferences.tla-trace|} print <<"TRACE>", "TX-end@", interface, "success: restore eth_accounts ">>;
|
16
|
+
(* {|^preferences.tla-trace|}\* {|/preferences.tla-trace|} print <<"TRACE>", "TX-end@", interface, "success: restore eth_gasUsed ">>; *)
|
17
|
+
eth_storageRoot := Head(eth_storageRoot_temp);
|
18
|
+
eth_accounts := Head(eth_accounts_temp);
|
19
|
+
\* eth_gasUsed := Head(eth_gasUsed_temp);
|
20
|
+
};
|
21
|
+
eth_storageRoot_temp := <<>>;
|
22
|
+
eth_accounts_temp := <<>>;
|
23
|
+
\* eth_gasUsed_temp := <<>>;
|
24
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
(*
|
2
|
+
* Service procedure for 'interface' has finished.
|
3
|
+
* Check status of service response.
|
4
|
+
* For success make changes in procedure permanent by propagating
|
5
|
+
* stack top to top-1..bottom.
|
6
|
+
*
|
7
|
+
* In any case pop one element from stack.
|
8
|
+
*
|
9
|
+
*)
|
10
|
+
|
11
|
+
macro ethereum_service_pop( interface ) {
|
12
|
+
|
13
|
+
if ( InfrastructureServiceGetStatus(interface ) = TRUE ) {
|
14
|
+
\* Success - propage changes, and make the permanent
|
15
|
+
eth_storageRoot_temp := PropageTopAndPop( eth_storageRoot_temp );
|
16
|
+
eth_accounts_temp := PropageTopAndPop( eth_accounts_temp );
|
17
|
+
\* eth_gasUsed_temp := PropageTopAndPop( eth_gasUsed_temp );
|
18
|
+
}
|
19
|
+
else {
|
20
|
+
eth_storageRoot_temp := Tail(eth_storageRoot_temp);
|
21
|
+
eth_accounts_temp := Tail(eth_accounts_temp);
|
22
|
+
\* eth_gasUsed_temp := Tail( eth_gasUsed_temp );
|
23
|
+
};
|
24
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
(*
|
2
|
+
* Macro called when service starts. Duplicates current
|
3
|
+
* top of stack.
|
4
|
+
*
|
5
|
+
* @see ethereum_service_start
|
6
|
+
* @see ethereum_service_done
|
7
|
+
*)
|
8
|
+
macro {{#SPEC_NAME}}framework-svc.ethereum_service_push{{/SPEC_NAME}}() {
|
9
|
+
|
10
|
+
eth_storageRoot_temp := Push( eth_storageRoot_temp, Head( eth_storageRoot_temp )) ;
|
11
|
+
eth_accounts_temp := Push( eth_accounts_temp, Head( eth_accounts_temp ));
|
12
|
+
\* eth_gasUsed_temp := Push( eth_gasUsed_temp, Head(eth_gasUsed_temp));
|
13
|
+
|
14
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
(*
|
2
|
+
* Macro called when transaction starts.
|
3
|
+
* Inializes ethreum block context to stack.
|
4
|
+
*
|
5
|
+
* @see ethereum_service_done
|
6
|
+
* @see ethereum_service_push
|
7
|
+
*)
|
8
|
+
macro {{#SPEC_NAME}}framework-svc.ethereum_service_start{{/SPEC_NAME}}() {
|
9
|
+
|
10
|
+
eth_storageRoot_temp := <<eth_storageRoot>>;
|
11
|
+
eth_accounts_temp := <<eth_accounts>>;
|
12
|
+
\* eth_gasUsed_temp := <<eth_gasUsed>>;
|
13
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
status_FAIL == FALSE
|
@@ -0,0 +1 @@
|
|
1
|
+
status_OK == TRUE
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
require 'sbuilder'
|
3
|
+
|
4
|
+
require_relative "utils/string_inject"
|
5
|
+
require_relative "utils/logger"
|
6
|
+
|
7
|
+
|
8
|
+
require_relative "sbuilder/exception"
|
9
|
+
|
10
|
+
# mixers
|
11
|
+
require_relative "mixer/type_symbol"
|
12
|
+
require_relative "mixer/symbol_ref"
|
13
|
+
require_relative "mixer/scope"
|
14
|
+
require_relative "mixer/scoped"
|
15
|
+
require_relative "mixer/decl_ref"
|
16
|
+
require_relative "mixer/domain_ref"
|
17
|
+
|
18
|
+
# constants
|
19
|
+
require_relative "sbuilder/constants"
|
20
|
+
|
21
|
+
# solidity stuff
|
22
|
+
require_relative "sbuilder/compile"
|
23
|
+
require_relative "sbuilder/load"
|
24
|
+
|
25
|
+
|
26
|
+
require_relative "sbuilder/sexp_ast"
|
27
|
+
require_relative "sbuilder/sexp_utils"
|
28
|
+
|
29
|
+
# sex processors
|
30
|
+
require_relative "sbuilder/sexp_processor_ethereum"
|
31
|
+
require_relative "sbuilder/sexp_processor_need_to_canonize"
|
32
|
+
require_relative "sbuilder/sexp_processor_canonize"
|
33
|
+
require_relative "sbuilder/sexp_processor_symboltable1"
|
34
|
+
require_relative "sbuilder/sexp_processor_symboltable2"
|
35
|
+
require_relative "sbuilder/sexp_processor_dataflow"
|
36
|
+
require_relative "sbuilder/sexp_processor_api"
|
37
|
+
require_relative "sbuilder/sexp_processor_snippet"
|
38
|
+
require_relative "sbuilder/s"
|
39
|
+
|
40
|
+
# Code generation
|
41
|
+
require_relative "sbuilder/generate/tla_element_text"
|
42
|
+
require_relative "sbuilder/generate/tla_element_generator"
|
43
|
+
require_relative "sbuilder/generate/sexp_processor_tla"
|
44
|
+
|
45
|
+
|
46
|
+
# mustache
|
47
|
+
require_relative "sbuilder/mustache/renderer"
|
48
|
+
require_relative "sbuilder/render"
|
49
|
+
|
50
|
+
# plugin && main
|
51
|
+
require_relative "plugin/plugin"
|
52
|
+
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'open3'
|
2
|
+
module Sbuilder
|
3
|
+
module Ethereum
|
4
|
+
|
5
|
+
|
6
|
+
##
|
7
|
+
# Compile solidity source.
|
8
|
+
#
|
9
|
+
class Compile
|
10
|
+
|
11
|
+
PROGNAME = nil # progname for logger default class name
|
12
|
+
include MyLogger # mix logger
|
13
|
+
|
14
|
+
# @attr [String] solc_command
|
15
|
+
attr_writer :solc_command
|
16
|
+
|
17
|
+
# @attr [String] solc_flags
|
18
|
+
attr_reader :solc_flags
|
19
|
+
|
20
|
+
# @attr [String] output_directory, can be configured outside
|
21
|
+
attr_accessor :output_directory
|
22
|
+
|
23
|
+
# @attr [String] compiled_ast
|
24
|
+
attr_accessor :compiledAst
|
25
|
+
|
26
|
+
# ------------------------------------------------------------------
|
27
|
+
# @!group construct & configure
|
28
|
+
|
29
|
+
def initialize( options = {} )
|
30
|
+
|
31
|
+
@options = options
|
32
|
+
@logger = getLogger( nil, options )
|
33
|
+
@logger.info "#{__method__}: initalized"
|
34
|
+
|
35
|
+
initDefaults
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# set configuration values
|
40
|
+
def initDefaults
|
41
|
+
@output_directory ||= "tmp/solidity"
|
42
|
+
@solc_flags ||= "--combined-json ast -o #{output_directory}"
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [String] path to solc executable
|
46
|
+
def solc_command
|
47
|
+
@solc_command ||= "#{Dir.pwd}/solc/solidity/build/solc/solc"
|
48
|
+
end
|
49
|
+
|
50
|
+
# @!endgroup
|
51
|
+
|
52
|
+
|
53
|
+
# ------------------------------------------------------------------
|
54
|
+
# @!group public services
|
55
|
+
|
56
|
+
##
|
57
|
+
# Call +solc_command+ to compile solidity source in +sourcePath+
|
58
|
+
# to create abstract syntax tree file in +compiledAst+
|
59
|
+
#
|
60
|
+
# @param [String|String:Array] soliditySource to solidity file to compile
|
61
|
+
#
|
62
|
+
def compile( soliditySource )
|
63
|
+
|
64
|
+
self.compiledAst = nil
|
65
|
+
|
66
|
+
sourcePaths = soliditySource.is_a?( Array ) ? soliditySource : [soliditySource]
|
67
|
+
|
68
|
+
# Check sourcePath & compiler command
|
69
|
+
sourcePaths.each do |sourcePath|
|
70
|
+
@logger.info "#{__method__}: solc_command=#{solc_command}, solc_flags=#{solc_flags}, sourcePath=#{sourcePath}, pwd=#{Dir.pwd}"
|
71
|
+
raise SbuilderEtherumCompileException, "Solidity source file '#{sourcePath}': no such file" unless File.exists?( sourcePath )
|
72
|
+
end
|
73
|
+
raise SbuilderEtherumCompileException, "Solidity output directory '#{output_directory}': no such directory" unless Dir.exists?( output_directory )
|
74
|
+
raise SbuilderEtherumCompileException, "Solidity compiler '#{solc_command}': executabable not found" unless which( solc_command )
|
75
|
+
|
76
|
+
|
77
|
+
# ast named after first source file, must not exist
|
78
|
+
astPath = ast_path( sourcePaths.first )
|
79
|
+
File.delete( astPath ) if File.exists?( astPath )
|
80
|
+
raise SbuilderEtherumCompileException, "Solidity ast file '#{astPath}': could not remove" if File.exists?( astPath )
|
81
|
+
|
82
|
+
|
83
|
+
cmd = "#{solc_command} #{solc_flags} #{sourcePaths.join(' ')} > #{astPath}"
|
84
|
+
@logger.info "#{__method__}: cmd:#{cmd}"
|
85
|
+
out,err,exit_status = Open3.capture3( cmd )
|
86
|
+
|
87
|
+
@logger.info "#{__method__}: out=#{out}, err=#{err}, st=#{exit_status}"
|
88
|
+
raise SbuilderEtherumCompileException, <<-EOS if exit_status != 0
|
89
|
+
Error compiling #{sourcePaths.join(',')}
|
90
|
+
|
91
|
+
Compiler : #{solc_command}
|
92
|
+
Flags : #{solc_flags}
|
93
|
+
|
94
|
+
Exit status: #{exit_status}
|
95
|
+
|
96
|
+
Stderr: #{err}
|
97
|
+
|
98
|
+
Output: #{out}
|
99
|
+
|
100
|
+
EOS
|
101
|
+
|
102
|
+
|
103
|
+
# check that ast file was created
|
104
|
+
raise SbuilderEtherumCompileException, <<-EOS unless File.exists?( astPath )
|
105
|
+
Error compiling #{sourcePaths.join(',')}
|
106
|
+
|
107
|
+
Compiler command
|
108
|
+
|
109
|
+
#{cmd}
|
110
|
+
|
111
|
+
in cwd #{Dir.getwd}
|
112
|
+
|
113
|
+
failed to create solidity ast file '#{astPath}'
|
114
|
+
|
115
|
+
EOS
|
116
|
+
|
117
|
+
|
118
|
+
# return path to compiled ast file
|
119
|
+
self.compiledAst = astPath
|
120
|
+
@logger.info "#{__method__}, compiledAst=#{compiledAst}"
|
121
|
+
compiledAst
|
122
|
+
end
|
123
|
+
|
124
|
+
# @!endgroup
|
125
|
+
|
126
|
+
|
127
|
+
# ------------------------------------------------------------------
|
128
|
+
# @!group configuration
|
129
|
+
|
130
|
+
# @return [String] path to a file in output directory
|
131
|
+
def ast_path( sourcePath )
|
132
|
+
"#{output_directory}/#{ast_file(sourcePath)}"
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
# @return [String] filename for abstract syntax tree for
|
137
|
+
# solidity source in +sourcePath+
|
138
|
+
def ast_file( sourcePath )
|
139
|
+
"#{File.basename( sourcePath, File.extname(sourcePath) )}.sol_json.ast"
|
140
|
+
end
|
141
|
+
|
142
|
+
# @!endgroup
|
143
|
+
|
144
|
+
# ------------------------------------------------------------------
|
145
|
+
# @!group utilities
|
146
|
+
|
147
|
+
# @return [Boolean] true if +cmd+ points to executable or it is
|
148
|
+
# found in PATH
|
149
|
+
def which( cmd )
|
150
|
+
File.exists?( cmd ) && File.executable?( cmd ) ||
|
151
|
+
ENV['PATH'].split(':').select do |folder|
|
152
|
+
f = "#{folder}/#{cmd}"
|
153
|
+
File.exists?(f) && File.executable?(f)
|
154
|
+
end.any?
|
155
|
+
end
|
156
|
+
|
157
|
+
# @!endgroup
|
158
|
+
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|