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 @@
|
|
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
|