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
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