ciri 0.0.1 → 0.0.2
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 +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
|