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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +8 -3
  3. data/README.md +5 -0
  4. data/Rakefile +24 -2
  5. data/ciri-rlp/.gitignore +11 -0
  6. data/ciri-rlp/.rspec +3 -0
  7. data/ciri-rlp/.travis.yml +5 -0
  8. data/ciri-rlp/CODE_OF_CONDUCT.md +74 -0
  9. data/ciri-rlp/Gemfile +6 -0
  10. data/ciri-rlp/Gemfile.lock +39 -0
  11. data/ciri-rlp/LICENSE.txt +21 -0
  12. data/ciri-rlp/README.md +98 -0
  13. data/ciri-rlp/Rakefile +6 -0
  14. data/ciri-rlp/bin/console +14 -0
  15. data/ciri-rlp/bin/setup +8 -0
  16. data/ciri-rlp/ciri-rlp.gemspec +28 -0
  17. data/{lib → ciri-rlp/lib}/ciri/rlp.rb +2 -2
  18. data/ciri-rlp/lib/ciri/rlp/decode.rb +144 -0
  19. data/ciri-rlp/lib/ciri/rlp/encode.rb +140 -0
  20. data/ciri-rlp/lib/ciri/rlp/serializable.rb +241 -0
  21. data/ciri-rlp/lib/ciri/rlp/version.rb +5 -0
  22. data/ciri-rlp/spec/ciri/fixture_spec.rb +95 -0
  23. data/ciri-rlp/spec/ciri/rlp/decode_spec.rb +68 -0
  24. data/ciri-rlp/spec/ciri/rlp/encode_spec.rb +72 -0
  25. data/ciri-rlp/spec/ciri/rlp/serializable_spec.rb +147 -0
  26. data/ciri-rlp/spec/ciri/rlp_spec.rb +5 -0
  27. data/ciri-rlp/spec/spec_helper.rb +14 -0
  28. data/ciri-utils/.gitignore +11 -0
  29. data/ciri-utils/.rspec +3 -0
  30. data/ciri-utils/.travis.yml +5 -0
  31. data/ciri-utils/CODE_OF_CONDUCT.md +74 -0
  32. data/ciri-utils/Gemfile +6 -0
  33. data/ciri-utils/Gemfile.lock +37 -0
  34. data/ciri-utils/LICENSE.txt +21 -0
  35. data/ciri-utils/README.md +61 -0
  36. data/ciri-utils/Rakefile +6 -0
  37. data/ciri-utils/bin/console +14 -0
  38. data/ciri-utils/bin/setup +8 -0
  39. data/ciri-utils/ciri-utils.gemspec +28 -0
  40. data/{lib → ciri-utils/lib}/ciri/utils.rb +9 -33
  41. data/{lib → ciri-utils/lib}/ciri/utils/logger.rb +0 -0
  42. data/{lib → ciri-utils/lib}/ciri/utils/number.rb +15 -12
  43. data/ciri-utils/lib/ciri/utils/version.rb +5 -0
  44. data/ciri-utils/spec/ciri/utils_spec.rb +5 -0
  45. data/ciri-utils/spec/spec_helper.rb +14 -0
  46. data/ciri.gemspec +6 -3
  47. data/lib/ciri/bloom_filter.rb +83 -0
  48. data/lib/ciri/chain.rb +67 -130
  49. data/lib/ciri/chain/header.rb +2 -2
  50. data/lib/ciri/chain/header_chain.rb +136 -0
  51. data/lib/ciri/chain/transaction.rb +1 -1
  52. data/lib/ciri/crypto.rb +2 -2
  53. data/lib/ciri/db/account_db.rb +145 -0
  54. data/lib/ciri/db/backend/memory.rb +24 -1
  55. data/lib/ciri/devp2p/peer.rb +1 -1
  56. data/lib/ciri/devp2p/rlpx/connection.rb +5 -5
  57. data/lib/ciri/eth/peer.rb +3 -3
  58. data/lib/ciri/eth/protocol_manage.rb +3 -3
  59. data/lib/ciri/eth/protocol_messages.rb +27 -26
  60. data/lib/ciri/ethash.rb +18 -3
  61. data/lib/ciri/evm.rb +101 -56
  62. data/lib/ciri/{utils/lib_c.rb → evm/errors.rb} +28 -18
  63. data/lib/ciri/evm/instruction.rb +3 -1
  64. data/lib/ciri/evm/{serialize.rb → log_entry.rb} +9 -27
  65. data/lib/ciri/evm/machine_state.rb +21 -2
  66. data/lib/ciri/evm/op.rb +19 -16
  67. data/lib/ciri/evm/state.rb +61 -0
  68. data/lib/ciri/evm/vm.rb +78 -102
  69. data/lib/ciri/forks.rb +1 -4
  70. data/lib/ciri/forks/base.rb +55 -0
  71. data/lib/ciri/forks/frontier.rb +37 -10
  72. data/lib/ciri/forks/frontier/cost.rb +186 -0
  73. data/lib/ciri/key.rb +1 -1
  74. data/lib/ciri/pow.rb +1 -1
  75. data/lib/ciri/rlp/decode.rb +6 -3
  76. data/lib/ciri/rlp/encode.rb +10 -10
  77. data/lib/ciri/rlp/serializable.rb +12 -9
  78. data/lib/ciri/serialize.rb +58 -0
  79. data/lib/ciri/trie.rb +362 -0
  80. data/lib/ciri/trie/nibbles.rb +97 -0
  81. data/lib/ciri/trie/nodes.rb +187 -0
  82. data/lib/ciri/{evm → types}/account.rb +20 -13
  83. data/lib/ciri/types/address.rb +16 -11
  84. data/lib/ciri/types/number.rb +73 -0
  85. data/lib/ciri/types/receipt.rb +57 -0
  86. data/lib/ciri/version.rb +1 -1
  87. metadata +82 -19
  88. 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
- def_delegators :@db, :[], :[]=
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
@@ -52,7 +52,7 @@ module Ciri
52
52
 
53
53
  def to_s
54
54
  @display_name ||= begin
55
- Utils.data_to_hex(node_id.id)[0..8]
55
+ Utils.to_hex(node_id.id)[0..8]
56
56
  end
57
57
  end
58
58
 
@@ -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! auth_ack_mgs_binary
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!(msg.payload)
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!(msg.payload)
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!(msg.payload).headers
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!(msg.payload).bodies
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
- def initialize(value)
38
- @value = value
39
- end
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
- def rlp_encode!
42
- if value.is_a? Integer
43
- RLP.encode(value, Integer)
44
- else
45
- RLP.encode(value)
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 self.rlp_decode!(s)
50
- s = StringIO.new(s) if s.is_a?(String)
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!(payload)
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!(payload)
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!(bodies)
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 = Utils::LibC.malloc(cache_size)
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
- Utils::LibC.free cache_ptr
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/account'
27
- require 'ciri/forks'
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
- BLOCK_REWARD = 3 * 10.pow(18) # 3 ether
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
- # block -> new block(mining)
58
- # return new_block and status change
59
- def transition(block)
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
- # status transfer
65
- # state[c].balance += mining reward
66
- # ommers: state[u.c].balance += uncle reward
67
- #
68
- # block.nonce
69
- # block.mix
70
- # R[i].gas_used = gas_used(state[i - 1], block.transactions[i]) + R[i - 1].gas_used
71
- # R[i].logs = logs(state[i - 1], block.transactions[i])
72
- # R[i].z = z(state[i - 1], block.transactions[i])
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
- if (account = find_account t.to)
93
- instruction.bytes_code = account.code
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: t.gas_limit,
129
+ gas_limit: gas_limit,
102
130
  instruction: instruction,
103
131
  header: header,
104
132
  block_info: block_info,
105
- fork_config: Ciri::Forks.detect_fork(header: header, number: block_info&.number)
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
- # transact ether
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
- nil
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(@vm.sub_state.log_series))
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 account_dead?(address)
132
- Account.account_dead?(state, address)
133
- end
134
-
135
- def find_account(address)
136
- Account.find_account(state, address)
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