ciri 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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