ciri 0.0.2 → 0.0.3

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 (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
data/lib/ciri/evm.rb CHANGED
@@ -1,46 +1,52 @@
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'
25
19
  require 'ciri/forks'
20
+ require 'ciri/core_ext'
21
+ require 'ciri/utils'
26
22
  require_relative 'evm/op'
27
23
  require_relative 'evm/vm'
28
24
  require_relative 'evm/errors'
25
+ require_relative 'evm/execution_context'
29
26
  require_relative 'types/account'
30
27
  require_relative 'types/receipt'
31
28
 
29
+ using Ciri::CoreExt
30
+
32
31
  module Ciri
33
32
  class EVM
33
+ include Utils::Logger
34
34
  extend Forwardable
35
35
 
36
- ExecutionResult = Struct.new(:status, :state_root, :logs, :gas_used, :gas_price, :exception, keyword_init: true)
36
+ ExecutionResult = Struct.new(:status, :state_root, :logs, :gas_used, :gas_price, :exception, keyword_init: true) do
37
+ def logs_hash
38
+ # return nil unless vm
39
+ Utils.keccak(RLP.encode_simple(logs))
40
+ end
41
+ end
37
42
 
38
43
  def_delegators :@state, :find_account, :account_dead?, :get_account_code, :state_root
39
44
 
40
- attr_reader :state
45
+ attr_reader :state, :fork_schema
41
46
 
42
- def initialize(state:)
47
+ def initialize(state:, fork_schema: Ciri::Forks::Frontier::Schema.new)
43
48
  @state = state
49
+ @fork_schema = fork_schema
44
50
  end
45
51
 
46
52
  # transition block
@@ -57,19 +63,9 @@ module Ciri
57
63
  raise InvalidTransition.new('reach block gas_limit')
58
64
  end
59
65
  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}")
66
+ raise InvalidTransition.new("overflow header gas_used, total_gas_used: #{total_gas_used}, block gas_used: #{block.header.gas_used}")
61
67
  end
62
68
 
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
69
  receipts << Types::Receipt.new(state_root: result.state_root, gas_used: total_gas_used, logs: result.logs)
74
70
  end
75
71
 
@@ -77,8 +73,7 @@ module Ciri
77
73
  raise InvalidTransition.new("incorrect gas_used, actual used: #{total_gas_used} header: #{block.header.gas_used}")
78
74
  end
79
75
 
80
- fork_config = Ciri::Forks.detect_fork(header: block.header, number: block.header.number)
81
- rewards = fork_config.mining_rewards_of_block(block)
76
+ rewards = fork_schema.mining_rewards_of_block(block)
82
77
 
83
78
  # apply rewards
84
79
  rewards.each do |address, value|
@@ -102,9 +97,13 @@ module Ciri
102
97
 
103
98
  # remove gas fee from account balance
104
99
  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
100
 
107
- gas_limit = t.gas_limit - fork_config.intrinsic_gas_of_transaction(t)
101
+ intrinsic_gas = fork_schema.intrinsic_gas_of_transaction(t)
102
+ if intrinsic_gas > t.gas_limit
103
+ raise InvalidTransaction.new('intrinsic gas overflowed gas limit')
104
+ end
105
+
106
+ gas_limit = t.gas_limit - intrinsic_gas
108
107
 
109
108
  instruction = Instruction.new(
110
109
  origin: t.sender,
@@ -112,73 +111,66 @@ module Ciri
112
111
  sender: t.sender,
113
112
  value: t.value,
114
113
  header: header,
115
- execute_depth: 0,
116
114
  )
117
115
 
118
116
  if t.contract_creation?
119
117
  instruction.bytes_code = t.data
120
- instruction.address = t.sender
121
118
  else
122
119
  instruction.bytes_code = get_account_code(t.to)
123
120
  instruction.address = t.to
124
121
  instruction.data = t.data
125
122
  end
126
123
 
127
- @vm = VM.spawn(
128
- state: state,
129
- gas_limit: gas_limit,
130
- instruction: instruction,
131
- header: header,
132
- block_info: block_info,
133
- fork_config: fork_config
124
+ block_info ||= header && BlockInfo.from_header(header)
125
+ context = Ciri::EVM::ExecutionContext.new(
126
+ instruction: instruction, gas_limit: gas_limit,
127
+ block_info: block_info, fork_schema: fork_schema
134
128
  )
129
+ vm = Ciri::EVM::VM.new(state: state, burn_gas_on_exception: true)
135
130
 
136
- # transact ether
137
- exception = nil
138
- # begin
139
- if t.contract_creation?
140
- # contract creation
141
- _, exception = @vm.create_contract(value: instruction.value, init: instruction.bytes_code)
142
- else
143
- _, _, exception = @vm.call_message(sender: t.sender, value: t.value, receipt: t.to, data: t.data)
144
- end
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)
131
+ unless instruction.value > state.find_account(instruction.sender).balance
132
+ state.increment_nonce(instruction.sender)
161
133
  end
162
134
 
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)
165
- end
166
-
167
- def logs_hash
168
- # return nil unless @vm
169
- Utils.sha3(RLP.encode_simple(vm.sub_state.log_series))
170
- end
135
+ vm.with_context(context) do
136
+ if t.contract_creation?
137
+ # contract creation
138
+ vm.create_contract(context: context)
139
+ else
140
+ vm.call_message(context: context)
141
+ end
142
+ raise context.exception if !ignore_exception && context.exception
143
+
144
+ # refund gas
145
+ sub_state_refund_gas = fork_schema.calculate_refund_gas(vm)
146
+ context.refund_gas(sub_state_refund_gas)
147
+ refund_gas = context.reset_refund_gas
148
+ remain_gas = context.remain_gas
149
+ actually_gas_used = t.gas_limit - remain_gas
150
+ actually_refund_gas = [refund_gas, actually_gas_used / 2].min
151
+ refund_gas_amount = (actually_refund_gas + remain_gas) * t.gas_price
152
+ debug("Transaction refund #{refund_gas_amount} to #{t.sender.to_s.to_hex}")
153
+ state.add_balance(t.sender, refund_gas_amount)
154
+
155
+ # gas_used after refund gas
156
+ gas_used = actually_gas_used - actually_refund_gas
157
+
158
+ # miner fee
159
+ fee = gas_used * t.gas_price
160
+ debug("Transaction fee #{fee}")
161
+ miner_account = find_account(block_info.coinbase)
162
+ miner_account.balance += fee
163
+ state.set_balance(block_info.coinbase, miner_account.balance)
171
164
 
172
- private
165
+ # destroy accounts
166
+ vm.execution_context.all_suicide_accounts.each do |address|
167
+ state.set_balance(address, 0)
168
+ state.delete_account(address)
169
+ end
173
170
 
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
- )
171
+ ExecutionResult.new(status: context.status, state_root: state_root, logs: context.all_log_series,
172
+ gas_used: gas_used, gas_price: t.gas_price, exception: context.exception)
173
+ end
182
174
  end
183
175
 
184
176
  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
  module Ciri
@@ -34,6 +28,10 @@ module Ciri
34
28
  raise NotImplementedError
35
29
  end
36
30
 
31
+ def gas_of_call(vm:, gas:, to:, value:)
32
+ raise NotImplementedError
33
+ end
34
+
37
35
  def intrinsic_gas_of_transaction(transaction)
38
36
  raise NotImplementedError
39
37
  end
@@ -49,6 +47,20 @@ module Ciri
49
47
  def calculate_refund_gas(vm)
50
48
  raise NotImplementedError
51
49
  end
50
+
51
+ # chain difficulty method
52
+ def difficulty_time_factor(header, parent_header)
53
+ raise NotImplementedError
54
+ end
55
+
56
+ def difficulty_virtual_height(height)
57
+ raise NotImplementedError
58
+ end
59
+
60
+ # EVM op code and contract
61
+ def find_precompile_contract(address)
62
+ raise NotImplementedError
63
+ end
52
64
  end
53
65
 
54
66
  end
@@ -0,0 +1,43 @@
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_relative 'base'
19
+ require_relative 'homestead'
20
+
21
+ module Ciri
22
+ module Forks
23
+ module Byzantium
24
+ class Schema < Forks::Frontier::Schema
25
+
26
+ include Forks::Frontier::Cost
27
+
28
+ # chain difficulty method
29
+ # https://github.com/ethereum/EIPs/blob/181867ae830df5419eb9982d2a24797b2dcad28f/EIPS/eip-609.md
30
+ # https://github.com/ethereum/EIPs/blob/984cf5de90bbf5fbe7e49be227b0c2f9567e661e/EIPS/eip-100.md
31
+ def difficulty_time_factor(header, parent_header)
32
+ y = header.ommers_hash == Utils::BLANK_SHA3 ? 1 : 2
33
+ [y - (header.timestamp - parent_header.timestamp) / 9, -99].max
34
+ end
35
+
36
+ def difficulty_virtual_height(height)
37
+ [(height - 3000000), 0].max
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,36 @@
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
+ module Ciri
18
+ module Forks
19
+
20
+ class Config
21
+
22
+ # @schema_rule [[0, Frontier], [100, Homestead]]
23
+ def initialize(schema_rules)
24
+ @schema_rules = schema_rules
25
+ end
26
+
27
+ def choose_fork(number)
28
+ @schema_rules.reverse_each.find do |start_number, _schema|
29
+ number >= start_number
30
+ end[1]
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ 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 'ciri/evm/op'
@@ -38,8 +32,8 @@ module Ciri
38
32
  G_LOW = 5
39
33
  G_MID = 8
40
34
  G_HIGH = 10
41
- G_EXTCODE = 700
42
- G_BALANCE = 400
35
+ G_EXTCODE = 20
36
+ G_BALANCE = 20
43
37
  G_SLOAD = 50
44
38
  G_JUMPDEST = 1
45
39
  G_SSET = 20000
@@ -49,7 +43,7 @@ module Ciri
49
43
  G_SELFDESTRUCT = 0
50
44
  G_CREATE = 32000
51
45
  G_CODEDEPOSIT = 200
52
- G_CALL = 700
46
+ G_CALL = 40
53
47
  G_CALLVALUE = 9000
54
48
  G_CALLSTIPEND = 2300
55
49
  G_NEWACCOUNT = 25000
@@ -93,7 +87,7 @@ module Ciri
93
87
  def cost_of_operation(vm)
94
88
  ms = vm.machine_state
95
89
  instruction = vm.instruction
96
- w = instruction.get_op(ms.pc)
90
+ w = instruction.get_op(vm.pc)
97
91
  if w == SSTORE
98
92
  cost_of_sstore(vm)
99
93
  elsif w == EXP && ms.get_stack(1, Integer) == 0
@@ -107,7 +101,7 @@ module Ciri
107
101
  elsif (LOG0..LOG4).include? w
108
102
  G_LOG + G_LOGDATA * ms.get_stack(1, Integer) + (w - LOG0) * G_TOPIC
109
103
  elsif w == CALL || w == CALLCODE || w == DELEGATECALL
110
- 1 # cost_of_call(state, ms)
104
+ G_CALL
111
105
  elsif w == SELFDESTRUCT
112
106
  cost_of_self_destruct(vm)
113
107
  elsif w == CREATE
@@ -151,14 +145,22 @@ module Ciri
151
145
  gas + G_TRANSACTION
152
146
  end
153
147
 
154
- private
148
+ def gas_of_call(vm:, gas:, to:, value:)
149
+ # TODO handle gas calculation for all categories calls
150
+ account_exists = vm.account_exist?(to)
151
+ transfer_gas_fee = value > 0 ? G_CALLVALUE : 0
152
+ create_gas_fee = !account_exists ? G_NEWACCOUNT : 0
153
+ extra_gas = transfer_gas_fee + create_gas_fee
155
154
 
156
- def cost_of_self_destruct(vm)
157
- G_SELFDESTRUCT
155
+ total_fee = gas + extra_gas
156
+ child_gas_limit = gas + (value > 0 ? G_CALLSTIPEND : 0)
157
+ [child_gas_limit, total_fee]
158
158
  end
159
159
 
160
- def cost_of_call
160
+ private
161
161
 
162
+ def cost_of_self_destruct(vm)
163
+ G_SELFDESTRUCT
162
164
  end
163
165
 
164
166
  def cost_of_sstore(vm)
@@ -168,14 +170,21 @@ module Ciri
168
170
  key = ms.get_stack(0, Integer)
169
171
  value = ms.get_stack(1, Integer)
170
172
 
171
- stored_is_empty = vm.fetch(instruction.address, key).zero?
172
- value_is_non_zero = value && !value.zero?
173
-
174
- if value_is_non_zero && stored_is_empty
175
- G_SSET
176
- else
177
- G_RESET
178
- end
173
+ current_is_empty = vm.fetch(instruction.address, key).zero?
174
+ value_is_empty = value.nil? || value.zero?
175
+
176
+ gas_cost = if current_is_empty && !value_is_empty
177
+ G_SSET
178
+ else
179
+ G_RESET
180
+ end
181
+ gas_refund = if !current_is_empty && value_is_empty
182
+ R_SCLEAR
183
+ else
184
+ 0
185
+ end
186
+
187
+ [gas_cost, gas_refund]
179
188
  end
180
189
 
181
190
  end
@@ -1,33 +1,31 @@
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_relative 'base'
25
19
  require_relative 'frontier/cost'
20
+ require 'ciri/core_ext'
21
+ require 'ciri/evm/precompile_contract'
22
+
23
+ using Ciri::CoreExt
26
24
 
27
25
  module Ciri
28
26
  module Forks
29
27
  module Frontier
30
- class Config < Base
28
+ class Schema < Base
31
29
 
32
30
  BLOCK_REWARD = 5 * 10.pow(18) # 5 ether
33
31
 
@@ -40,6 +38,10 @@ module Ciri
40
38
  Cost.cost_of_memory word_count
41
39
  end
42
40
 
41
+ def gas_of_call(vm:, gas:, to:, value:)
42
+ Cost.gas_of_call(vm: vm, gas: gas, to: to, value: value)
43
+ end
44
+
43
45
  def intrinsic_gas_of_transaction(transaction)
44
46
  Cost.intrinsic_gas_of_transaction transaction
45
47
  end
@@ -49,7 +51,7 @@ module Ciri
49
51
  end
50
52
 
51
53
  def calculate_refund_gas(vm)
52
- vm.sub_state.suicide_accounts.size * Cost::R_SELFDESTRUCT
54
+ vm.execution_context.all_suicide_accounts.size * Cost::R_SELFDESTRUCT
53
55
  end
54
56
 
55
57
  def mining_rewards_of_block(block)
@@ -64,6 +66,33 @@ module Ciri
64
66
  rewards
65
67
  end
66
68
 
69
+ def validate_transaction(transaction)
70
+ unless transaction.v >= 27 && transaction.v <= 28
71
+ "v can be only 27 or 28 in frontier schema, found: #{transaction.v}"
72
+ end
73
+ end
74
+
75
+ # chain difficulty method
76
+ def difficulty_time_factor(header, parent_header)
77
+ (header.timestamp - parent_header.timestamp) < 13 ? 1 : -1
78
+ end
79
+
80
+ def difficulty_virtual_height(height)
81
+ height
82
+ end
83
+
84
+ PRECOMPILE_CONTRACTS = {
85
+ "\x01".pad_zero(20).b => EVM::PrecompileContract::ECRecover.new,
86
+ "\x02".pad_zero(20).b => EVM::PrecompileContract::SHA256.new,
87
+ "\x03".pad_zero(20).b => EVM::PrecompileContract::RIPEMD160.new,
88
+ "\x04".pad_zero(20).b => EVM::PrecompileContract::Identity.new,
89
+ }.freeze
90
+
91
+ # EVM op code and contract
92
+ def find_precompile_contract(address)
93
+ PRECOMPILE_CONTRACTS[address.to_s]
94
+ end
95
+
67
96
  end
68
97
  end
69
98
  end