ciri 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +0 -1
  4. data/Gemfile.lock +11 -7
  5. data/LICENSE.txt +201 -21
  6. data/README.md +78 -25
  7. data/Rakefile +45 -17
  8. data/bin/bundle +105 -0
  9. data/bin/htmldiff +29 -0
  10. data/bin/ldiff +29 -0
  11. data/bin/rake +29 -0
  12. data/bin/rspec +29 -0
  13. data/ciri-crypto/.gitignore +11 -0
  14. data/ciri-crypto/.rspec +3 -0
  15. data/ciri-crypto/.travis.yml +5 -0
  16. data/ciri-crypto/CODE_OF_CONDUCT.md +74 -0
  17. data/ciri-crypto/Gemfile +6 -0
  18. data/ciri-crypto/Gemfile.lock +43 -0
  19. data/ciri-crypto/LICENSE.txt +201 -0
  20. data/ciri-crypto/README.md +58 -0
  21. data/ciri-crypto/Rakefile +6 -0
  22. data/ciri-crypto/bin/console +14 -0
  23. data/ciri-crypto/bin/setup +8 -0
  24. data/ciri-crypto/ciri-crypto.gemspec +40 -0
  25. data/ciri-crypto/lib/ciri/crypto/errors.rb +29 -0
  26. data/ciri-crypto/lib/ciri/crypto/signature.rb +71 -0
  27. data/ciri-crypto/lib/ciri/crypto/version.rb +5 -0
  28. data/{lib → ciri-crypto/lib}/ciri/crypto.rb +16 -69
  29. data/ciri-crypto/spec/ciri/crypto_spec.rb +56 -0
  30. data/ciri-crypto/spec/spec_helper.rb +14 -0
  31. data/ciri-rlp/Gemfile.lock +5 -5
  32. data/ciri-rlp/LICENSE.txt +201 -21
  33. data/ciri-rlp/README.md +1 -1
  34. data/ciri-rlp/ciri-rlp.gemspec +3 -3
  35. data/ciri-rlp/lib/ciri/rlp/decode.rb +10 -16
  36. data/ciri-rlp/lib/ciri/rlp/encode.rb +10 -16
  37. data/ciri-rlp/lib/ciri/rlp/serializable.rb +10 -16
  38. data/ciri-rlp/lib/ciri/rlp.rb +10 -16
  39. data/ciri-rlp/spec/ciri/fixture_spec.rb +10 -16
  40. data/ciri-rlp/spec/ciri/rlp/serializable_spec.rb +10 -16
  41. data/ciri-utils/Gemfile.lock +4 -4
  42. data/ciri-utils/LICENSE.txt +201 -21
  43. data/ciri-utils/README.md +1 -1
  44. data/ciri-utils/ciri-utils.gemspec +2 -2
  45. data/ciri-utils/lib/ciri/utils/logger.rb +10 -16
  46. data/ciri-utils/lib/ciri/utils/number.rb +10 -16
  47. data/ciri-utils/lib/ciri/utils/version.rb +1 -1
  48. data/ciri-utils/lib/ciri/utils.rb +3 -3
  49. data/ciri.gemspec +4 -3
  50. data/docker/{Base → Dockerfile} +9 -3
  51. data/lib/ciri/actor.rb +10 -16
  52. data/lib/ciri/bloom_filter.rb +11 -17
  53. data/lib/ciri/chain/block.rb +10 -16
  54. data/lib/ciri/chain/header.rb +12 -18
  55. data/lib/ciri/chain/header_chain.rb +8 -22
  56. data/lib/ciri/chain/transaction.rb +38 -33
  57. data/lib/ciri/chain.rb +27 -26
  58. data/lib/ciri/core_ext.rb +61 -0
  59. data/lib/ciri/db/account_db.rb +25 -21
  60. data/lib/ciri/db/backend/memory.rb +10 -16
  61. data/lib/ciri/db/backend/rocks.rb +10 -16
  62. data/lib/ciri/db/backend/rocks_db.rb +10 -16
  63. data/lib/ciri/devp2p/peer.rb +10 -16
  64. data/lib/ciri/devp2p/protocol.rb +10 -16
  65. data/lib/ciri/devp2p/protocol_io.rb +10 -16
  66. data/lib/ciri/devp2p/rlpx/connection.rb +10 -16
  67. data/lib/ciri/devp2p/rlpx/encryption_handshake.rb +13 -19
  68. data/lib/ciri/devp2p/rlpx/error.rb +10 -16
  69. data/lib/ciri/devp2p/rlpx/frame_io.rb +10 -16
  70. data/lib/ciri/devp2p/rlpx/message.rb +10 -16
  71. data/lib/ciri/devp2p/rlpx/node.rb +10 -16
  72. data/lib/ciri/devp2p/rlpx/protocol_handshake.rb +10 -16
  73. data/lib/ciri/devp2p/rlpx/protocol_messages.rb +10 -16
  74. data/lib/ciri/devp2p/rlpx/secrets.rb +10 -16
  75. data/lib/ciri/devp2p/rlpx.rb +10 -16
  76. data/lib/ciri/devp2p/server.rb +10 -16
  77. data/lib/ciri/eth/peer.rb +10 -16
  78. data/lib/ciri/eth/protocol_manage.rb +10 -16
  79. data/lib/ciri/eth/protocol_messages.rb +10 -16
  80. data/lib/ciri/eth/synchronizer.rb +10 -16
  81. data/lib/ciri/eth.rb +10 -16
  82. data/lib/ciri/ethash.rb +10 -16
  83. data/lib/ciri/evm/block_info.rb +25 -17
  84. data/lib/ciri/evm/errors.rb +13 -16
  85. data/lib/ciri/evm/execution_context.rb +136 -0
  86. data/lib/ciri/evm/instruction.rb +17 -24
  87. data/lib/ciri/evm/log_entry.rb +12 -18
  88. data/lib/ciri/evm/machine_state.rb +28 -33
  89. data/lib/ciri/evm/op.rb +52 -89
  90. data/lib/ciri/evm/op_call.rb +114 -0
  91. data/lib/ciri/evm/precompile_contract.rb +102 -0
  92. data/lib/ciri/evm/state.rb +28 -21
  93. data/lib/ciri/evm/sub_state.rb +18 -24
  94. data/lib/ciri/evm/vm.rb +128 -190
  95. data/lib/ciri/evm.rb +77 -85
  96. data/lib/ciri/forks/base.rb +28 -16
  97. data/lib/ciri/forks/byzantium.rb +43 -0
  98. data/lib/ciri/forks/config.rb +36 -0
  99. data/lib/ciri/forks/frontier/cost.rb +42 -33
  100. data/lib/ciri/forks/frontier.rb +47 -18
  101. data/lib/ciri/forks/homestead/cost.rb +195 -0
  102. data/lib/ciri/forks/homestead.rb +46 -0
  103. data/lib/ciri/forks.rb +12 -22
  104. data/lib/ciri/key.rb +14 -3
  105. data/lib/ciri/pow.rb +11 -17
  106. data/lib/ciri/rlp/decode.rb +10 -16
  107. data/lib/ciri/rlp/encode.rb +10 -16
  108. data/lib/ciri/rlp/serializable.rb +10 -16
  109. data/lib/ciri/serialize.rb +14 -17
  110. data/lib/ciri/trie/nibbles.rb +10 -16
  111. data/lib/ciri/trie/nodes.rb +12 -17
  112. data/lib/ciri/trie.rb +12 -18
  113. data/lib/ciri/types/account.rb +15 -17
  114. data/lib/ciri/types/address.rb +11 -17
  115. data/lib/ciri/types/errors.rb +10 -16
  116. data/lib/ciri/types/receipt.rb +12 -18
  117. data/lib/ciri/types/uint.rb +79 -0
  118. data/lib/ciri/version.rb +1 -1
  119. data/lib/ciri.rb +10 -16
  120. metadata +54 -10
  121. data/lib/ciri/types/number.rb +0 -73
@@ -1,26 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
4
  #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
11
8
  #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
9
+ # http://www.apache.org/licenses/LICENSE-2.0
14
10
  #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
22
16
 
23
17
 
18
+ require 'ciri/utils/logger'
24
19
  require 'ciri/serialize'
25
20
  require 'ciri/evm/errors'
26
21
 
@@ -29,23 +24,13 @@ module Ciri
29
24
 
30
25
  # represent current vm status, include stack, memory..
31
26
  class MachineState
27
+ include Utils::Logger
32
28
 
33
- attr_reader :remain_gas, :memory, :stack
34
- attr_accessor :pc, :output, :memory_item
29
+ attr_reader :memory, :stack
35
30
 
36
- def initialize(remain_gas:, pc:, memory:, memory_item:, stack:, output: ''.b)
37
- raise ArgumentError.new("remain_gas must more than 0") if remain_gas < 0
38
- @remain_gas = remain_gas
39
- @pc = pc
31
+ def initialize(memory: ''.b, stack: [])
40
32
  @memory = memory
41
- @memory_item = memory_item
42
33
  @stack = stack
43
- @output = output
44
- end
45
-
46
- def consume_gas(gas)
47
- raise GasNotEnoughError.new("can't consume gas to negative, remain_gas: #{remain_gas}, consumed: #{gas}") if gas > remain_gas
48
- @remain_gas -= gas
49
34
  end
50
35
 
51
36
  # fetch a list of items from stack
@@ -72,7 +57,7 @@ module Ciri
72
57
 
73
58
  # store data to memory
74
59
  def memory_store(start, size, data)
75
- if start < memory.size && start + size - 1 < memory.size
60
+ if size > 0 && start < memory.size && start + size - 1 < memory.size
76
61
  memory[start..(start + size - 1)] = Serialize.serialize(data).rjust(size, "\x00".b)
77
62
  end
78
63
  end
@@ -87,10 +72,20 @@ module Ciri
87
72
  end
88
73
  end
89
74
 
75
+ def memory_item
76
+ Utils.ceil_div(memory.size, 32)
77
+ end
78
+
90
79
  # extend vm memory, used for memory_gas calculation
91
- def extend_memory(pos, size)
92
- if size != 0 && (i = Utils.ceil_div(pos + size, 32)) > memory_item
93
- self.memory_item = i
80
+ def extend_memory(context, pos, size)
81
+ if size != 0 && (new_item = Utils.ceil_div(pos + size, 32)) > memory_item
82
+ debug("extend memory: from #{memory_item} -> #{new_item}")
83
+ old_cost_gas = context.fork_schema.gas_of_memory memory_item
84
+ new_cost_gas = context.fork_schema.gas_of_memory new_item
85
+ context.consume_gas(new_cost_gas - old_cost_gas)
86
+
87
+ extend_size = (new_item - memory_item) * 32
88
+ self.memory << "\x00".b * extend_size
94
89
  end
95
90
  end
96
91
 
data/lib/ciri/evm/op.rb CHANGED
@@ -1,29 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
4
  #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
11
8
  #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
9
+ # http://www.apache.org/licenses/LICENSE-2.0
14
10
  #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
22
16
 
23
17
 
24
18
  require 'ciri/utils'
25
19
  require 'ciri/utils/number'
26
20
  require 'ciri/types/address'
21
+ require_relative 'op_call'
27
22
 
28
23
  module Ciri
29
24
  class EVM
@@ -206,7 +201,8 @@ module Ciri
206
201
  # 20s: sha3
207
202
  def_op :SHA3, 0x20, 2, 1 do |vm|
208
203
  pos, size = vm.pop_list(2, Integer)
209
- hashed = Ciri::Utils.sha3 vm.memory_fetch(pos, size)
204
+ vm.extend_memory(pos, size)
205
+ hashed = Ciri::Utils.keccak vm.memory_fetch(pos, size)
210
206
  vm.extend_memory(pos, size)
211
207
  vm.push hashed
212
208
  end
@@ -246,8 +242,8 @@ module Ciri
246
242
  def_op :CALLDATACOPY, 0x37, 3, 0 do |vm|
247
243
  mem_pos, data_pos, size = vm.pop_list(3, Integer)
248
244
  data = vm.get_data(data_pos, size)
249
- vm.memory_store(mem_pos, size, data)
250
245
  vm.extend_memory(mem_pos, size)
246
+ vm.memory_store(mem_pos, size, data)
251
247
  end
252
248
 
253
249
  def_op :CODESIZE, 0x38, 0, 1 do |vm|
@@ -257,6 +253,7 @@ module Ciri
257
253
  def_op :CODECOPY, 0x39, 3, 0 do |vm|
258
254
  mem_pos, code_pos, size = vm.pop_list(3, Integer)
259
255
  data = vm.get_code(code_pos, size)
256
+ vm.extend_memory(mem_pos, size)
260
257
  vm.memory_store(mem_pos, size, data)
261
258
  end
262
259
 
@@ -283,6 +280,7 @@ module Ciri
283
280
  else
284
281
  code[data_pos..data_end_pos]
285
282
  end
283
+ vm.extend_memory(mem_pos, size)
286
284
  vm.memory_store(mem_pos, size, data)
287
285
  end
288
286
 
@@ -290,7 +288,14 @@ module Ciri
290
288
  RETURNDATACOPY = 0x3e
291
289
 
292
290
  # 40s: block information
293
- BLOCKHASH = 0x40
291
+ def_op :BLOCKHASH, 0x40, 1, 1 do |vm|
292
+ height = vm.pop(Integer)
293
+ # cause current block hash do not exists in chain
294
+ # here we compute distance of parent height and ancestor height
295
+ # and use parent_hash to find ancestor hash
296
+ distance = vm.block_info.number - height - 1
297
+ vm.push vm.state.get_ancestor_hash(vm.block_info.parent_hash, distance)
298
+ end
294
299
 
295
300
  def_op :COINBASE, 0x41, 0, 1 do |vm|
296
301
  vm.push vm.block_info.coinbase
@@ -319,22 +324,22 @@ module Ciri
319
324
 
320
325
  def_op :MLOAD, 0x51, 1, 1 do |vm|
321
326
  index = vm.pop(Integer)
322
- vm.push vm.memory_fetch(index, 32)
323
327
  vm.extend_memory(index, 32)
328
+ vm.push vm.memory_fetch(index, 32)
324
329
  end
325
330
 
326
331
  def_op :MSTORE, 0x52, 2, 0 do |vm|
327
332
  index = vm.pop(Integer)
328
333
  data = vm.pop
329
- vm.memory_store(index, 32, data)
330
334
  vm.extend_memory(index, 32)
335
+ vm.memory_store(index, 32, data)
331
336
  end
332
337
 
333
338
  def_op :MSTORE8, 0x53, 2, 0 do |vm|
334
339
  index = vm.pop(Integer)
335
340
  data = vm.pop(Integer)
336
- vm.memory_store(index, 1, data % 256)
337
341
  vm.extend_memory(index, 8)
342
+ vm.memory_store(index, 1, data % 256)
338
343
  end
339
344
 
340
345
  def_op :SLOAD, 0x54, 1, 1 do |vm|
@@ -356,10 +361,12 @@ module Ciri
356
361
 
357
362
  def_op :JUMPI, 0x57, 2, 0 do |vm|
358
363
  dest, cond = vm.pop_list(2, Integer)
364
+ # if cond is non zero jump to dest, else just goto next pc
359
365
  if cond != 0
360
366
  vm.jump_to(dest)
361
367
  else
362
- vm.jump_to(vm.pc + 1)
368
+ # clear jump_to
369
+ vm.jump_to(nil)
363
370
  end
364
371
  end
365
372
 
@@ -372,7 +379,7 @@ module Ciri
372
379
  end
373
380
 
374
381
  def_op :GAS, 0x5a, 0, 1 do |vm|
375
- vm.push vm.machine_state.remain_gas
382
+ vm.push vm.remain_gas
376
383
  end
377
384
 
378
385
  def_op :JUMPDEST, 0x5b, 0, 0
@@ -417,8 +424,8 @@ module Ciri
417
424
  def_op name, 0xa0 + i, i + 2, 0, &(proc do |i|
418
425
  proc do |vm|
419
426
  pos, size = vm.pop_list(2, Integer)
420
- log_data = vm.memory_fetch(pos, size)
421
427
  vm.extend_memory(pos, size)
428
+ log_data = vm.memory_fetch(pos, size)
422
429
  topics = vm.pop_list(i, Integer)
423
430
  vm.add_log_entry(topics, log_data)
424
431
  end
@@ -430,75 +437,39 @@ module Ciri
430
437
  value = vm.pop(Integer)
431
438
  mem_pos, size = vm.pop_list(2, Integer)
432
439
 
433
- init = vm.memory_fetch(mem_pos, size)
434
440
  vm.extend_memory(mem_pos, size)
435
441
 
436
- contract_address, _ = vm.create_contract(value: value, init: init)
437
- vm.push contract_address
442
+ # have not enough money
443
+ if vm.find_account(vm.instruction.address).balance < value
444
+ vm.push(0)
445
+ else
446
+ init = vm.memory_fetch(mem_pos, size)
447
+ create_gas = vm.remain_gas
448
+ vm.consume_gas(create_gas)
449
+ child_context = vm.execution_context.child_context(gas_limit: create_gas)
450
+ contract_address, _ = vm.create_contract(value: value, init: init, touch_nonce: true, context: child_context)
451
+ vm.execution_context.return_gas(child_context.remain_gas)
452
+
453
+ vm.push contract_address
454
+ end
438
455
  end
439
456
 
440
457
  def_op :CALL, 0xf1, 7, 1 do |vm|
441
- vm.pop
442
- target = vm.pop(Address)
443
- value = vm.pop(Integer)
444
- input_mem_pos, input_size = vm.pop_list(2, Integer)
445
- output_mem_pos, output_mem_size = vm.pop_list(2, Integer)
446
-
447
- data = vm.memory_fetch(input_mem_pos, input_size)
448
- vm.extend_memory(input_mem_pos, input_size)
449
-
450
- status, output = vm.call_message(sender: vm.instruction.address, value: value,
451
- data: data, receipt: target, code_address: target)
452
-
453
- output_size = [output_mem_size, output.size].min
454
- vm.memory_store(output_mem_pos, output_size, output)
455
- vm.extend_memory(output_mem_pos, output_size)
456
- vm.push status
458
+ OPCall::Call.new.call(vm)
457
459
  end
458
460
 
459
461
  def_op :CALLCODE, 0xf2, 7, 1 do |vm|
460
- # this method consume 7 items from stack, but seems not all of them are used
461
- # skip item
462
- vm.pop
463
- target = vm.pop(Address)
464
- value = vm.pop(Integer)
465
- input_mem_pos, input_size = vm.pop_list(2, Integer)
466
- output_mem_pos, output_mem_size = vm.pop_list(2, Integer)
467
-
468
- data = vm.memory_fetch(input_mem_pos, input_size)
469
- vm.extend_memory(input_mem_pos, input_size)
470
-
471
- status, output = vm.call_message(sender: vm.instruction.address, value: value,
472
- data: data, receipt: vm.instruction.address, code_address: target)
473
-
474
- output_size = [output_mem_size, output.size].min
475
- vm.memory_store(output_mem_pos, output_size, output)
476
- vm.extend_memory(output_mem_pos, output_size)
477
- vm.push status
462
+ OPCall::CallCode.new.call(vm)
478
463
  end
479
464
 
480
465
  def_op :RETURN, 0xf3, 2, 0 do |vm|
481
466
  index, size = vm.pop_list(2, Integer)
482
- vm.output = vm.memory_fetch(index, size)
483
467
  vm.extend_memory(index, size)
468
+ vm.set_output vm.memory_fetch(index, size)
484
469
  end
485
470
 
486
- def_op :DELEGATECALL, 0xf4, 6, 1 do |vm|
487
- vm.pop
488
- target = vm.pop(Address)
489
- input_mem_pos, input_size = vm.pop_list(2, Integer)
490
- output_mem_pos, output_mem_size = vm.pop_list(2, Integer)
491
-
492
- data = vm.memory_fetch(input_mem_pos, input_size)
493
- vm.extend_memory(input_mem_pos, input_size)
494
-
495
- status, output = vm.call_message(sender: vm.instruction.sender, value: vm.instruction.value,
496
- data: data, receipt: vm.instruction.address, code_address: target)
497
-
498
- output_size = [output_mem_size, output.size].min
499
- vm.memory_store(output_mem_pos, output_size, output)
500
- vm.extend_memory(output_mem_pos, output_size)
501
- vm.push status
471
+ def_op :DELEGATECALL, -0xf4, 6, 1 do |vm|
472
+ OPCall::DelegateCall.new.call(vm)
502
473
  end
503
474
 
504
475
  STATICCALL = 0xfa
@@ -516,18 +487,10 @@ module Ciri
516
487
 
517
488
  def_op :SELFDESTRUCT, 0xff, 1, 0 do |vm|
518
489
  refund_address = vm.pop(Address)
519
- refund_account = vm.find_account(refund_address)
520
-
521
490
  contract_account = vm.find_account vm.instruction.address
522
491
 
523
- if refund_address != vm.instruction.address
524
- refund_account.balance += contract_account.balance
525
- end
526
-
527
- contract_account.balance = 0
528
-
529
- vm.state.set_balance(refund_address, refund_account.balance)
530
- vm.state.set_balance(vm.instruction.address, contract_account.balance)
492
+ vm.state.add_balance(refund_address, contract_account.balance)
493
+ vm.state.set_balance(vm.instruction.address, 0)
531
494
 
532
495
  # register changed accounts
533
496
  vm.add_refund_account(refund_address)
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ require 'ciri/types/address'
19
+
20
+ module Ciri
21
+ class EVM
22
+ # handle EVM call operations
23
+ module OPCall
24
+ class Base
25
+
26
+ include Types
27
+
28
+ def call(vm)
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def extract_call_argument(vm)
33
+ gas = vm.pop(Integer)
34
+ to = vm.pop(Address)
35
+ value = vm.pop(Integer)
36
+ input_mem_pos, input_size = vm.pop_list(2, Integer)
37
+ output_mem_pos, output_mem_size = vm.pop_list(2, Integer)
38
+
39
+ # extend input output memory
40
+ vm.extend_memory(input_mem_pos, input_size)
41
+ vm.extend_memory(output_mem_pos, output_mem_size)
42
+
43
+ data = vm.memory_fetch(input_mem_pos, input_size)
44
+ [gas, to, value, data, output_mem_pos, output_mem_size]
45
+ end
46
+
47
+ def call_message(vm:, gas:, sender:, value:, data:, to:, code_address: to, output_mem_pos:, output_mem_size:)
48
+ context = vm.execution_context
49
+ child_gas_limit, child_gas_fee = context.fork_schema.gas_of_call(vm: vm,
50
+ gas: gas, to: to, value: value)
51
+ context.consume_gas(child_gas_fee)
52
+ if context.depth + 1 > 1024
53
+ context.return_gas(child_gas_limit)
54
+ vm.push 0
55
+ return
56
+ end
57
+ child_context = context.child_context(gas_limit: child_gas_limit)
58
+ child_context.instruction.sender = sender
59
+ child_context.instruction.value = value
60
+ child_context.instruction.data = data
61
+ child_context.instruction.address = to
62
+ child_context.instruction.bytes_code = vm.state.get_account_code(code_address)
63
+ status, output = vm.call_message(code_address: code_address, context: child_context)
64
+
65
+ context.return_gas(child_context.remain_gas)
66
+ output_size = [output_mem_size, output.size].min
67
+ vm.extend_memory(output_mem_pos, output_size)
68
+ vm.memory_store(output_mem_pos, output_size, output)
69
+ vm.push status
70
+ end
71
+ end
72
+
73
+ class Call < Base
74
+ def call(vm)
75
+ gas, to, value, data, output_mem_pos, output_mem_size = extract_call_argument(vm)
76
+ call_message(vm: vm, sender: vm.instruction.address, value: value, gas: gas, to: to,
77
+ data: data, code_address: to, output_mem_pos: output_mem_pos, output_mem_size: output_mem_size)
78
+ end
79
+ end
80
+
81
+ class CallCode < Base
82
+ def call(vm)
83
+ gas, to, value, data, output_mem_pos, output_mem_size = extract_call_argument(vm)
84
+ call_message(vm: vm, sender: vm.instruction.address, value: value, gas: gas, to: vm.instruction.address,
85
+ data: data, code_address: to, output_mem_pos: output_mem_pos, output_mem_size: output_mem_size)
86
+ end
87
+ end
88
+
89
+ class DelegateCall < Base
90
+ def call(vm)
91
+ gas, to, data, output_mem_pos, output_mem_size = extract_call_argument(vm)
92
+ call_message(vm: vm, sender: vm.instruction.sender, value: vm.instruction.value, gas: gas,
93
+ to: vm.instruction.address, data: data, code_address: to,
94
+ output_mem_pos: output_mem_pos, output_mem_size: output_mem_size)
95
+ end
96
+
97
+ def extract_call_argument(vm)
98
+ gas = vm.pop(Integer)
99
+ to = vm.pop(Address)
100
+ input_mem_pos, input_size = vm.pop_list(2, Integer)
101
+ output_mem_pos, output_mem_size = vm.pop_list(2, Integer)
102
+
103
+ # extend input output memory
104
+ vm.extend_memory(input_mem_pos, input_size)
105
+ vm.extend_memory(output_mem_pos, output_mem_size)
106
+
107
+ data = vm.memory_fetch(input_mem_pos, input_size)
108
+ [gas, to, data, output_mem_pos, output_mem_size]
109
+ end
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ require 'ciri/core_ext'
19
+ require 'ciri/crypto'
20
+ require 'digest'
21
+
22
+ using Ciri::CoreExt
23
+
24
+ module Ciri
25
+ class EVM
26
+ module PrecompileContract
27
+
28
+ class ECRecover
29
+ GAS_ECRECOVER = 3000
30
+
31
+ def call(vm)
32
+ vm.consume_gas(GAS_ECRECOVER)
33
+ message_hash = vm.instruction.data[0...32].pad_zero(32)
34
+
35
+ v = vm.instruction.data[32...64].decode_big_endian
36
+ r = vm.instruction.data[64...96].decode_big_endian
37
+ s = vm.instruction.data[96...128].decode_big_endian
38
+ unless valid_vrs?(v, r, s)
39
+ return vm.set_exception(Error.new("invalid vrs"))
40
+ end
41
+ raw_v = v - 27
42
+ begin
43
+ signature = Ciri::Crypto::Signature.new(vrs: [raw_v, r, s])
44
+ key = Ciri::Key.ecdsa_recover(message_hash, signature)
45
+ rescue StandardError => e
46
+ return vm.set_exception(e)
47
+ end
48
+
49
+ vm.set_output(key.to_address.to_s)
50
+ end
51
+
52
+ def valid_vrs?(v, r, s)
53
+ return false unless r < Ciri::Crypto::SECP256K1N
54
+ return false unless s < Ciri::Crypto::SECP256K1N
55
+ return false unless v == 28 || v == 27
56
+ true
57
+ end
58
+ end
59
+
60
+ class SHA256
61
+ GAS_SHA256 = 60
62
+ GAS_SHA256WORD = 12
63
+
64
+ def call(vm)
65
+ input_bytes = vm.instruction.data
66
+ word_count = input_bytes.size.ceil_div(32) / 32
67
+ gas_fee = GAS_SHA256 + word_count * GAS_SHA256WORD
68
+ vm.consume_gas(gas_fee)
69
+ vm.set_output input_bytes.keccak
70
+ end
71
+ end
72
+
73
+ class RIPEMD160
74
+ GAS_RIPEMD160 = 600
75
+ GAS_RIPEMD160WORD = 120
76
+
77
+ def call(vm)
78
+ input_bytes = vm.instruction.data
79
+ word_count = input_bytes.size.ceil_div(32) / 32
80
+ gas_fee = GAS_RIPEMD160 + word_count * GAS_RIPEMD160WORD
81
+ vm.consume_gas(gas_fee)
82
+ vm.set_output Digest::RMD160.digest(input_bytes).pad_zero(32)
83
+ end
84
+ end
85
+
86
+ class Identity
87
+ GAS_IDENTITY = 15
88
+ GAS_IDENTITYWORD = 3
89
+
90
+ def call(vm)
91
+ input_bytes = vm.instruction.data
92
+ word_count = input_bytes.size.ceil_div(32) / 32
93
+ gas_fee = GAS_IDENTITY + word_count * GAS_IDENTITYWORD
94
+ vm.consume_gas(gas_fee)
95
+ computation.output = input_bytes
96
+ end
97
+ end
98
+
99
+
100
+ end
101
+ end
102
+ end
@@ -1,24 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
4
  #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
11
8
  #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
9
+ # http://www.apache.org/licenses/LICENSE-2.0
14
10
  #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
22
16
 
23
17
 
24
18
  require 'forwardable'
@@ -31,11 +25,25 @@ module Ciri
31
25
  extend Forwardable
32
26
 
33
27
  def_delegators :@account_db, :set_nonce, :increment_nonce, :set_balance, :add_balance, :touch_account,
34
- :find_account, :delete_account, :account_dead?, :store, :fetch, :set_account_code, :get_account_code
28
+ :find_account, :delete_account, :account_dead?, :store, :fetch,
29
+ :set_account_code, :get_account_code, :account_exist?
35
30
 
36
- def initialize(db, state_root: nil)
31
+ def initialize(db, state_root: nil, chain: nil)
37
32
  @db = db
38
33
  @account_db = DB::AccountDB.new(db, root_hash: state_root)
34
+ @chain = chain
35
+ end
36
+
37
+ # get ancestor hash
38
+ def get_ancestor_hash(current_hash, ancestor_distance)
39
+ if ancestor_distance > 256 || ancestor_distance < 0
40
+ ''.b
41
+ elsif ancestor_distance == 0
42
+ current_hash
43
+ else
44
+ parent_hash = @chain.get_header(current_hash).parent_hash
45
+ get_ancestor_hash(parent_hash, ancestor_distance - 1)
46
+ end
39
47
  end
40
48
 
41
49
  def snapshot
@@ -43,9 +51,8 @@ module Ciri
43
51
  end
44
52
 
45
53
  def revert(snapshot)
46
- state_root, db = snapshot
47
- @db = db
48
- @account_db = DB::AccountDB.new(db, root_hash: state_root)
54
+ state_root, _db = snapshot
55
+ @account_db = DB::AccountDB.new(@db, root_hash: state_root)
49
56
  end
50
57
 
51
58
  def commit(snapshot)