ciri 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +8 -3
- data/README.md +5 -0
- data/Rakefile +24 -2
- data/ciri-rlp/.gitignore +11 -0
- data/ciri-rlp/.rspec +3 -0
- data/ciri-rlp/.travis.yml +5 -0
- data/ciri-rlp/CODE_OF_CONDUCT.md +74 -0
- data/ciri-rlp/Gemfile +6 -0
- data/ciri-rlp/Gemfile.lock +39 -0
- data/ciri-rlp/LICENSE.txt +21 -0
- data/ciri-rlp/README.md +98 -0
- data/ciri-rlp/Rakefile +6 -0
- data/ciri-rlp/bin/console +14 -0
- data/ciri-rlp/bin/setup +8 -0
- data/ciri-rlp/ciri-rlp.gemspec +28 -0
- data/{lib → ciri-rlp/lib}/ciri/rlp.rb +2 -2
- data/ciri-rlp/lib/ciri/rlp/decode.rb +144 -0
- data/ciri-rlp/lib/ciri/rlp/encode.rb +140 -0
- data/ciri-rlp/lib/ciri/rlp/serializable.rb +241 -0
- data/ciri-rlp/lib/ciri/rlp/version.rb +5 -0
- data/ciri-rlp/spec/ciri/fixture_spec.rb +95 -0
- data/ciri-rlp/spec/ciri/rlp/decode_spec.rb +68 -0
- data/ciri-rlp/spec/ciri/rlp/encode_spec.rb +72 -0
- data/ciri-rlp/spec/ciri/rlp/serializable_spec.rb +147 -0
- data/ciri-rlp/spec/ciri/rlp_spec.rb +5 -0
- data/ciri-rlp/spec/spec_helper.rb +14 -0
- data/ciri-utils/.gitignore +11 -0
- data/ciri-utils/.rspec +3 -0
- data/ciri-utils/.travis.yml +5 -0
- data/ciri-utils/CODE_OF_CONDUCT.md +74 -0
- data/ciri-utils/Gemfile +6 -0
- data/ciri-utils/Gemfile.lock +37 -0
- data/ciri-utils/LICENSE.txt +21 -0
- data/ciri-utils/README.md +61 -0
- data/ciri-utils/Rakefile +6 -0
- data/ciri-utils/bin/console +14 -0
- data/ciri-utils/bin/setup +8 -0
- data/ciri-utils/ciri-utils.gemspec +28 -0
- data/{lib → ciri-utils/lib}/ciri/utils.rb +9 -33
- data/{lib → ciri-utils/lib}/ciri/utils/logger.rb +0 -0
- data/{lib → ciri-utils/lib}/ciri/utils/number.rb +15 -12
- data/ciri-utils/lib/ciri/utils/version.rb +5 -0
- data/ciri-utils/spec/ciri/utils_spec.rb +5 -0
- data/ciri-utils/spec/spec_helper.rb +14 -0
- data/ciri.gemspec +6 -3
- data/lib/ciri/bloom_filter.rb +83 -0
- data/lib/ciri/chain.rb +67 -130
- data/lib/ciri/chain/header.rb +2 -2
- data/lib/ciri/chain/header_chain.rb +136 -0
- data/lib/ciri/chain/transaction.rb +1 -1
- data/lib/ciri/crypto.rb +2 -2
- data/lib/ciri/db/account_db.rb +145 -0
- data/lib/ciri/db/backend/memory.rb +24 -1
- data/lib/ciri/devp2p/peer.rb +1 -1
- data/lib/ciri/devp2p/rlpx/connection.rb +5 -5
- data/lib/ciri/eth/peer.rb +3 -3
- data/lib/ciri/eth/protocol_manage.rb +3 -3
- data/lib/ciri/eth/protocol_messages.rb +27 -26
- data/lib/ciri/ethash.rb +18 -3
- data/lib/ciri/evm.rb +101 -56
- data/lib/ciri/{utils/lib_c.rb → evm/errors.rb} +28 -18
- data/lib/ciri/evm/instruction.rb +3 -1
- data/lib/ciri/evm/{serialize.rb → log_entry.rb} +9 -27
- data/lib/ciri/evm/machine_state.rb +21 -2
- data/lib/ciri/evm/op.rb +19 -16
- data/lib/ciri/evm/state.rb +61 -0
- data/lib/ciri/evm/vm.rb +78 -102
- data/lib/ciri/forks.rb +1 -4
- data/lib/ciri/forks/base.rb +55 -0
- data/lib/ciri/forks/frontier.rb +37 -10
- data/lib/ciri/forks/frontier/cost.rb +186 -0
- data/lib/ciri/key.rb +1 -1
- data/lib/ciri/pow.rb +1 -1
- data/lib/ciri/rlp/decode.rb +6 -3
- data/lib/ciri/rlp/encode.rb +10 -10
- data/lib/ciri/rlp/serializable.rb +12 -9
- data/lib/ciri/serialize.rb +58 -0
- data/lib/ciri/trie.rb +362 -0
- data/lib/ciri/trie/nibbles.rb +97 -0
- data/lib/ciri/trie/nodes.rb +187 -0
- data/lib/ciri/{evm → types}/account.rb +20 -13
- data/lib/ciri/types/address.rb +16 -11
- data/lib/ciri/types/number.rb +73 -0
- data/lib/ciri/types/receipt.rb +57 -0
- data/lib/ciri/version.rb +1 -1
- metadata +82 -19
- data/lib/ciri/evm/forks/frontier.rb +0 -183
@@ -31,6 +31,18 @@ module Ciri
|
|
31
31
|
# implement kvstore
|
32
32
|
class Memory
|
33
33
|
|
34
|
+
class Batch
|
35
|
+
attr_reader :value
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@value = Hash.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def put(k, v)
|
42
|
+
@value[k] = v
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
34
46
|
class InvalidError < StandardError
|
35
47
|
end
|
36
48
|
|
@@ -40,7 +52,12 @@ module Ciri
|
|
40
52
|
@db = {}
|
41
53
|
end
|
42
54
|
|
43
|
-
|
55
|
+
def initialize_copy(orig)
|
56
|
+
super
|
57
|
+
@db = orig.instance_variable_get(:@db).dup
|
58
|
+
end
|
59
|
+
|
60
|
+
def_delegators :@db, :[], :[]=, :fetch, :delete, :include?
|
44
61
|
|
45
62
|
def get(key)
|
46
63
|
@db[key]
|
@@ -54,6 +71,12 @@ module Ciri
|
|
54
71
|
keys.each(&blk)
|
55
72
|
end
|
56
73
|
|
74
|
+
def batch
|
75
|
+
b = Batch.new
|
76
|
+
yield(b)
|
77
|
+
@db.merge! b.value
|
78
|
+
end
|
79
|
+
|
57
80
|
def close
|
58
81
|
@db = nil
|
59
82
|
end
|
data/lib/ciri/devp2p/peer.rb
CHANGED
@@ -67,7 +67,7 @@ module Ciri
|
|
67
67
|
|
68
68
|
# protocol handshake
|
69
69
|
def protocol_handshake!(our_hs)
|
70
|
-
@frame_io.send_data(MESSAGES[:handshake], our_hs.rlp_encode
|
70
|
+
@frame_io.send_data(MESSAGES[:handshake], our_hs.rlp_encode)
|
71
71
|
remote_hs = read_protocol_handshake
|
72
72
|
# enable snappy compress if remote peer support
|
73
73
|
@frame_io.snappy = remote_hs.version >= SNAPPY_PROTOCOL_VERSION
|
@@ -81,7 +81,7 @@ module Ciri
|
|
81
81
|
receiver.handle_auth_msg(auth_msg)
|
82
82
|
|
83
83
|
auth_ack_msg = receiver.auth_ack_msg
|
84
|
-
auth_ack_msg_plain_text = auth_ack_msg.rlp_encode
|
84
|
+
auth_ack_msg_plain_text = auth_ack_msg.rlp_encode
|
85
85
|
auth_ack_packet = if auth_msg.got_plain
|
86
86
|
raise NotImplementedError.new('not support pre eip8 plain text seal')
|
87
87
|
else
|
@@ -94,13 +94,13 @@ module Ciri
|
|
94
94
|
|
95
95
|
def initiator_enc_handshake(initiator)
|
96
96
|
initiator_auth_msg = initiator.auth_msg
|
97
|
-
auth_msg_plain_text = initiator_auth_msg.rlp_encode
|
97
|
+
auth_msg_plain_text = initiator_auth_msg.rlp_encode
|
98
98
|
# seal eip8
|
99
99
|
auth_packet = seal_eip8(auth_msg_plain_text, initiator)
|
100
100
|
@io.write(auth_packet)
|
101
101
|
|
102
102
|
auth_ack_mgs_binary, auth_ack_packet = read_enc_handshake_msg(ENC_AUTH_RESP_MSG_LENGTH, initiator.private_key)
|
103
|
-
auth_ack_msg = AuthRespV4.rlp_decode
|
103
|
+
auth_ack_msg = AuthRespV4.rlp_decode auth_ack_mgs_binary
|
104
104
|
initiator.handle_auth_ack_msg(auth_ack_msg)
|
105
105
|
|
106
106
|
initiator.extract_secrets(auth_packet, auth_ack_packet, initiator: true)
|
@@ -142,7 +142,7 @@ module Ciri
|
|
142
142
|
if msg.code != MESSAGES[:handshake]
|
143
143
|
raise UnexpectedMessageError.new("expected handshake, get #{msg.code}")
|
144
144
|
end
|
145
|
-
ProtocolHandshake.rlp_decode
|
145
|
+
ProtocolHandshake.rlp_decode(msg.payload)
|
146
146
|
end
|
147
147
|
|
148
148
|
def set_timeout(io)
|
data/lib/ciri/eth/peer.rb
CHANGED
@@ -47,16 +47,16 @@ module Ciri
|
|
47
47
|
def handshake(network_id, total_difficulty, head_hash, genesis_hash)
|
48
48
|
status = Status.new(protocol_version: 63, network_id: network_id,
|
49
49
|
total_difficulty: total_difficulty, current_block: head_hash, genesis_block: genesis_hash)
|
50
|
-
io.send_data(Status::CODE, status.rlp_encode
|
50
|
+
io.send_data(Status::CODE, status.rlp_encode)
|
51
51
|
msg = io.read_msg
|
52
|
-
@status = Status.rlp_decode
|
52
|
+
@status = Status.rlp_decode(msg.payload)
|
53
53
|
@total_difficulty = @status.total_difficulty
|
54
54
|
@status
|
55
55
|
end
|
56
56
|
|
57
57
|
def send_msg(msg_class, **data)
|
58
58
|
msg = msg_class.new(data)
|
59
|
-
io.send_data(msg_class::CODE, msg.rlp_encode
|
59
|
+
io.send_data(msg_class::CODE, msg.rlp_encode)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -104,13 +104,13 @@ module Ciri
|
|
104
104
|
header.reverse! if get_header_msg.reverse
|
105
105
|
end
|
106
106
|
|
107
|
-
headers_msg = BlockHeaders.new(headers: headers).rlp_encode
|
107
|
+
headers_msg = BlockHeaders.new(headers: headers).rlp_encode
|
108
108
|
peer.io.send_data(BlockHeaders::CODE, headers_msg)
|
109
109
|
when BlockHeaders::CODE
|
110
|
-
headers = BlockHeaders.rlp_decode
|
110
|
+
headers = BlockHeaders.rlp_decode(msg.payload).headers
|
111
111
|
synchronizer << [:receive_headers, peer, headers] unless headers.empty?
|
112
112
|
when BlockBodies::CODE
|
113
|
-
bodies = BlockBodies.rlp_decode
|
113
|
+
bodies = BlockBodies.rlp_decode(msg.payload).bodies
|
114
114
|
synchronizer << [:receive_bodies, peer, bodies] unless bodies.empty?
|
115
115
|
else
|
116
116
|
raise StandardError, "unknown code #{msg.code}, #{msg}"
|
@@ -30,32 +30,33 @@ module Ciri
|
|
30
30
|
|
31
31
|
# represent a hash or a number
|
32
32
|
class HashOrNumber
|
33
|
-
include Ciri::RLP::Serializable
|
34
|
-
|
35
33
|
attr_reader :value
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
class << self
|
36
|
+
def rlp_encode(item)
|
37
|
+
value = item.value
|
38
|
+
if value.is_a? Integer
|
39
|
+
RLP.encode(value, Integer)
|
40
|
+
else
|
41
|
+
RLP.encode(value)
|
42
|
+
end
|
43
|
+
end
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
def rlp_decode(s)
|
46
|
+
s = StringIO.new(s) if s.is_a?(String)
|
47
|
+
# start with 0xA0, represent s is a 32 length hash bytes
|
48
|
+
c = s.getc
|
49
|
+
s.ungetc(c)
|
50
|
+
if c.ord == 0xa0
|
51
|
+
RLP.decode(s)
|
52
|
+
else
|
53
|
+
RLP.decode(s, Integer)
|
54
|
+
end
|
46
55
|
end
|
47
56
|
end
|
48
57
|
|
49
|
-
def
|
50
|
-
|
51
|
-
# start with 0xA0, represent s is a 32 length hash bytes
|
52
|
-
c = s.getc
|
53
|
-
s.ungetc(c)
|
54
|
-
if c.ord == 0xa0
|
55
|
-
RLP.decode(s)
|
56
|
-
else
|
57
|
-
RLP.decode(s, Integer)
|
58
|
-
end
|
58
|
+
def initialize(value)
|
59
|
+
@value = value
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
@@ -100,11 +101,11 @@ module Ciri
|
|
100
101
|
@headers = headers
|
101
102
|
end
|
102
103
|
|
103
|
-
def rlp_encode
|
104
|
+
def rlp_encode
|
104
105
|
Ciri::RLP.encode(@headers, [Chain::Header])
|
105
106
|
end
|
106
107
|
|
107
|
-
def self.rlp_decode
|
108
|
+
def self.rlp_decode(payload)
|
108
109
|
new headers: Ciri::RLP.decode(payload, [Chain::Header])
|
109
110
|
end
|
110
111
|
end
|
@@ -118,11 +119,11 @@ module Ciri
|
|
118
119
|
@hashes = hashes
|
119
120
|
end
|
120
121
|
|
121
|
-
def rlp_encode
|
122
|
+
def rlp_encode
|
122
123
|
Ciri::RLP.encode(@hashes)
|
123
124
|
end
|
124
125
|
|
125
|
-
def self.rlp_decode
|
126
|
+
def self.rlp_decode(payload)
|
126
127
|
new hashes: Ciri::RLP.decode(payload)
|
127
128
|
end
|
128
129
|
end
|
@@ -145,11 +146,11 @@ module Ciri
|
|
145
146
|
@bodies = bodies
|
146
147
|
end
|
147
148
|
|
148
|
-
def rlp_encode
|
149
|
+
def rlp_encode
|
149
150
|
Ciri::RLP.encode(@bodies, [Bodies])
|
150
151
|
end
|
151
152
|
|
152
|
-
def self.rlp_decode
|
153
|
+
def self.rlp_decode(bodies)
|
153
154
|
new bodies: Ciri::RLP.decode(bodies, [Bodies])
|
154
155
|
end
|
155
156
|
end
|
data/lib/ciri/ethash.rb
CHANGED
@@ -22,7 +22,6 @@
|
|
22
22
|
|
23
23
|
|
24
24
|
require 'ffi'
|
25
|
-
require 'ciri/utils/lib_c'
|
26
25
|
|
27
26
|
module Ciri
|
28
27
|
|
@@ -30,6 +29,22 @@ module Ciri
|
|
30
29
|
# from https://github.com/ethereum/ethash/blob/master/src/python/core.c
|
31
30
|
module Ethash
|
32
31
|
|
32
|
+
module LibC
|
33
|
+
extend FFI::Library
|
34
|
+
ffi_lib FFI::Library::LIBC
|
35
|
+
|
36
|
+
# memory allocators
|
37
|
+
attach_function :malloc, [:size_t], :pointer
|
38
|
+
attach_function :calloc, [:size_t], :pointer
|
39
|
+
attach_function :valloc, [:size_t], :pointer
|
40
|
+
attach_function :realloc, [:pointer, :size_t], :pointer
|
41
|
+
attach_function :free, [:pointer], :void
|
42
|
+
|
43
|
+
# memory movers
|
44
|
+
attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
45
|
+
attach_function :bcopy, [:pointer, :pointer, :size_t], :void
|
46
|
+
end
|
47
|
+
|
33
48
|
module Lib
|
34
49
|
extend FFI::Library
|
35
50
|
ffi_lib 'libethash'
|
@@ -88,7 +103,7 @@ module Ciri
|
|
88
103
|
cache_size = cache_bytes.size
|
89
104
|
raise Error.new("seed must be 32 bytes long, (was #{header_size})") if header_size != 32
|
90
105
|
|
91
|
-
cache_ptr =
|
106
|
+
cache_ptr = LibC.malloc(cache_size)
|
92
107
|
cache_ptr.write_string_length(cache_bytes, cache_size)
|
93
108
|
|
94
109
|
light = Lib::Light.new
|
@@ -105,7 +120,7 @@ module Ciri
|
|
105
120
|
result = [value[:mix_hash].get_bytes, value[:result].get_bytes]
|
106
121
|
|
107
122
|
# release memory *_*
|
108
|
-
|
123
|
+
LibC.free cache_ptr
|
109
124
|
|
110
125
|
result
|
111
126
|
end
|
data/lib/ciri/evm.rb
CHANGED
@@ -21,15 +21,21 @@
|
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
23
|
|
24
|
+
require 'forwardable'
|
25
|
+
require 'ciri/forks'
|
24
26
|
require_relative 'evm/op'
|
25
27
|
require_relative 'evm/vm'
|
26
|
-
require_relative 'evm/
|
27
|
-
|
28
|
+
require_relative 'evm/errors'
|
29
|
+
require_relative 'types/account'
|
30
|
+
require_relative 'types/receipt'
|
28
31
|
|
29
32
|
module Ciri
|
30
33
|
class EVM
|
34
|
+
extend Forwardable
|
35
|
+
|
36
|
+
ExecutionResult = Struct.new(:status, :state_root, :logs, :gas_used, :gas_price, :exception, keyword_init: true)
|
31
37
|
|
32
|
-
|
38
|
+
def_delegators :@state, :find_account, :account_dead?, :get_account_code, :state_root
|
33
39
|
|
34
40
|
attr_reader :state
|
35
41
|
|
@@ -37,45 +43,69 @@ module Ciri
|
|
37
43
|
@state = state
|
38
44
|
end
|
39
45
|
|
40
|
-
# run block
|
41
|
-
def finalize_block(block)
|
42
|
-
# validate block
|
43
|
-
# transition
|
44
|
-
# apply_changes
|
45
|
-
end
|
46
|
-
|
47
|
-
def validate_block(block)
|
48
|
-
# valid ommers
|
49
|
-
# valid transactions(block.gas_used == transactions...gas)
|
50
|
-
# Reward miner, ommers(reward == block reward + ommers reward)
|
51
|
-
# apply changes
|
52
|
-
# verify state and block nonce
|
53
|
-
# 1. parent header root == trie(state[i]) 当前状态的 root 相等, 返回 state[i] otherwise state[0]
|
54
|
-
end
|
55
|
-
|
56
46
|
# transition block
|
57
|
-
|
58
|
-
|
59
|
-
|
47
|
+
def transition(block, check_gas_limit: true, check_gas_used: true)
|
48
|
+
receipts = []
|
49
|
+
|
50
|
+
total_gas_used = 0
|
60
51
|
# execute transactions, we don't need to valid transactions, it should be done before evm(in Chain module).
|
61
52
|
block.transactions.each do |transaction|
|
62
|
-
execute_transaction(transaction, header: block.header)
|
53
|
+
result = execute_transaction(transaction, header: block.header, ignore_exception: true)
|
54
|
+
|
55
|
+
total_gas_used += result.gas_used
|
56
|
+
if check_gas_limit && total_gas_used > block.header.gas_limit
|
57
|
+
raise InvalidTransition.new('reach block gas_limit')
|
58
|
+
end
|
59
|
+
if check_gas_used && total_gas_used > block.header.gas_used
|
60
|
+
raise InvalidTransition.new("incorrect gas_used, total_gas_used: #{total_gas_used}, block gas_used: #{block.header.gas_used}")
|
61
|
+
end
|
62
|
+
|
63
|
+
# calculate fee
|
64
|
+
fee = result.gas_used * result.gas_price
|
65
|
+
|
66
|
+
miner_account = find_account(block.header.beneficiary)
|
67
|
+
miner_account.balance += fee
|
68
|
+
state.set_balance(block.header.beneficiary, miner_account.balance)
|
69
|
+
|
70
|
+
# update actually state_root(after calculate fee)
|
71
|
+
result.state_root = state.state_root
|
72
|
+
|
73
|
+
receipts << Types::Receipt.new(state_root: result.state_root, gas_used: total_gas_used, logs: result.logs)
|
74
|
+
end
|
75
|
+
|
76
|
+
if check_gas_used && total_gas_used != block.header.gas_used
|
77
|
+
raise InvalidTransition.new("incorrect gas_used, actual used: #{total_gas_used} header: #{block.header.gas_used}")
|
63
78
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
79
|
+
|
80
|
+
fork_config = Ciri::Forks.detect_fork(header: block.header, number: block.header.number)
|
81
|
+
rewards = fork_config.mining_rewards_of_block(block)
|
82
|
+
|
83
|
+
# apply rewards
|
84
|
+
rewards.each do |address, value|
|
85
|
+
if value > 0
|
86
|
+
account = find_account(address)
|
87
|
+
account.balance += value
|
88
|
+
state.set_balance(address, account.balance)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
receipts
|
73
93
|
end
|
74
94
|
|
75
95
|
# execute transaction
|
76
96
|
# @param t Transaction
|
77
97
|
# @param header Chain::Header
|
78
98
|
def execute_transaction(t, header: nil, block_info: nil, ignore_exception: false)
|
99
|
+
unless state.find_account(t.sender).balance >= t.gas_price * t.gas_limit + t.value
|
100
|
+
raise InvalidTransaction.new('account balance not enough')
|
101
|
+
end
|
102
|
+
|
103
|
+
# remove gas fee from account balance
|
104
|
+
state.add_balance(t.sender, -1 * t.gas_limit * t.gas_price)
|
105
|
+
fork_config = Ciri::Forks.detect_fork(header: header, number: block_info&.number)
|
106
|
+
|
107
|
+
gas_limit = t.gas_limit - fork_config.intrinsic_gas_of_transaction(t)
|
108
|
+
|
79
109
|
instruction = Instruction.new(
|
80
110
|
origin: t.sender,
|
81
111
|
price: t.gas_price,
|
@@ -89,51 +119,66 @@ module Ciri
|
|
89
119
|
instruction.bytes_code = t.data
|
90
120
|
instruction.address = t.sender
|
91
121
|
else
|
92
|
-
|
93
|
-
|
94
|
-
instruction.address = account.address
|
95
|
-
end
|
122
|
+
instruction.bytes_code = get_account_code(t.to)
|
123
|
+
instruction.address = t.to
|
96
124
|
instruction.data = t.data
|
97
125
|
end
|
98
126
|
|
99
127
|
@vm = VM.spawn(
|
100
128
|
state: state,
|
101
|
-
gas_limit:
|
129
|
+
gas_limit: gas_limit,
|
102
130
|
instruction: instruction,
|
103
131
|
header: header,
|
104
132
|
block_info: block_info,
|
105
|
-
fork_config:
|
133
|
+
fork_config: fork_config
|
106
134
|
)
|
107
135
|
|
136
|
+
# transact ether
|
137
|
+
exception = nil
|
138
|
+
# begin
|
108
139
|
if t.contract_creation?
|
109
140
|
# contract creation
|
110
|
-
@vm.create_contract(value: instruction.value, init: instruction.bytes_code)
|
141
|
+
_, exception = @vm.create_contract(value: instruction.value, init: instruction.bytes_code)
|
111
142
|
else
|
112
|
-
|
113
|
-
begin
|
114
|
-
@vm.transact(sender: t.sender, value: t.value, to: t.to)
|
115
|
-
rescue VM::VMError
|
116
|
-
raise unless ignore_exception
|
117
|
-
return nil
|
118
|
-
end
|
119
|
-
@vm.run(ignore_exception: ignore_exception)
|
143
|
+
_, _, exception = @vm.call_message(sender: t.sender, value: t.value, receipt: t.to, data: t.data)
|
120
144
|
end
|
121
|
-
|
145
|
+
# rescue ArgumentError => e
|
146
|
+
# raise unless ignore_exception
|
147
|
+
# exception = e
|
148
|
+
# end
|
149
|
+
raise exception if !ignore_exception && exception
|
150
|
+
|
151
|
+
# refund gas
|
152
|
+
refund_gas = fork_config.calculate_refund_gas(@vm)
|
153
|
+
gas_used = t.gas_limit - @vm.remain_gas
|
154
|
+
refund_gas = [refund_gas, gas_used / 2].min
|
155
|
+
state.add_balance(t.sender, (refund_gas + @vm.remain_gas) * t.gas_price)
|
156
|
+
|
157
|
+
# destroy accounts
|
158
|
+
@vm.sub_state.suicide_accounts.each do |address|
|
159
|
+
state.set_balance(address, 0)
|
160
|
+
state.delete_account(address)
|
161
|
+
end
|
162
|
+
|
163
|
+
ExecutionResult.new(status: @vm.status, state_root: state_root, logs: @vm.sub_state.log_series, gas_used: gas_used - refund_gas,
|
164
|
+
gas_price: t.gas_price, exception: @vm.exception)
|
122
165
|
end
|
123
166
|
|
124
167
|
def logs_hash
|
125
|
-
return nil unless @vm
|
126
|
-
Utils.sha3(RLP.encode_simple(
|
168
|
+
# return nil unless @vm
|
169
|
+
Utils.sha3(RLP.encode_simple(vm.sub_state.log_series))
|
127
170
|
end
|
128
171
|
|
129
172
|
private
|
130
173
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
174
|
+
def vm
|
175
|
+
@vm ||= VM.spawn(
|
176
|
+
state: state,
|
177
|
+
gas_limit: 0,
|
178
|
+
instruction: nil,
|
179
|
+
block_info: BlockInfo.new,
|
180
|
+
fork_config: nil
|
181
|
+
)
|
137
182
|
end
|
138
183
|
|
139
184
|
end
|