ciri 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +0 -1
- data/Gemfile.lock +11 -7
- data/LICENSE.txt +201 -21
- data/README.md +78 -25
- data/Rakefile +45 -17
- data/bin/bundle +105 -0
- data/bin/htmldiff +29 -0
- data/bin/ldiff +29 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/ciri-crypto/.gitignore +11 -0
- data/ciri-crypto/.rspec +3 -0
- data/ciri-crypto/.travis.yml +5 -0
- data/ciri-crypto/CODE_OF_CONDUCT.md +74 -0
- data/ciri-crypto/Gemfile +6 -0
- data/ciri-crypto/Gemfile.lock +43 -0
- data/ciri-crypto/LICENSE.txt +201 -0
- data/ciri-crypto/README.md +58 -0
- data/ciri-crypto/Rakefile +6 -0
- data/ciri-crypto/bin/console +14 -0
- data/ciri-crypto/bin/setup +8 -0
- data/ciri-crypto/ciri-crypto.gemspec +40 -0
- data/ciri-crypto/lib/ciri/crypto/errors.rb +29 -0
- data/ciri-crypto/lib/ciri/crypto/signature.rb +71 -0
- data/ciri-crypto/lib/ciri/crypto/version.rb +5 -0
- data/{lib → ciri-crypto/lib}/ciri/crypto.rb +16 -69
- data/ciri-crypto/spec/ciri/crypto_spec.rb +56 -0
- data/ciri-crypto/spec/spec_helper.rb +14 -0
- data/ciri-rlp/Gemfile.lock +5 -5
- data/ciri-rlp/LICENSE.txt +201 -21
- data/ciri-rlp/README.md +1 -1
- data/ciri-rlp/ciri-rlp.gemspec +3 -3
- data/ciri-rlp/lib/ciri/rlp/decode.rb +10 -16
- data/ciri-rlp/lib/ciri/rlp/encode.rb +10 -16
- data/ciri-rlp/lib/ciri/rlp/serializable.rb +10 -16
- data/ciri-rlp/lib/ciri/rlp.rb +10 -16
- data/ciri-rlp/spec/ciri/fixture_spec.rb +10 -16
- data/ciri-rlp/spec/ciri/rlp/serializable_spec.rb +10 -16
- data/ciri-utils/Gemfile.lock +4 -4
- data/ciri-utils/LICENSE.txt +201 -21
- data/ciri-utils/README.md +1 -1
- data/ciri-utils/ciri-utils.gemspec +2 -2
- data/ciri-utils/lib/ciri/utils/logger.rb +10 -16
- data/ciri-utils/lib/ciri/utils/number.rb +10 -16
- data/ciri-utils/lib/ciri/utils/version.rb +1 -1
- data/ciri-utils/lib/ciri/utils.rb +3 -3
- data/ciri.gemspec +4 -3
- data/docker/{Base → Dockerfile} +9 -3
- data/lib/ciri/actor.rb +10 -16
- data/lib/ciri/bloom_filter.rb +11 -17
- data/lib/ciri/chain/block.rb +10 -16
- data/lib/ciri/chain/header.rb +12 -18
- data/lib/ciri/chain/header_chain.rb +8 -22
- data/lib/ciri/chain/transaction.rb +38 -33
- data/lib/ciri/chain.rb +27 -26
- data/lib/ciri/core_ext.rb +61 -0
- data/lib/ciri/db/account_db.rb +25 -21
- data/lib/ciri/db/backend/memory.rb +10 -16
- data/lib/ciri/db/backend/rocks.rb +10 -16
- data/lib/ciri/db/backend/rocks_db.rb +10 -16
- data/lib/ciri/devp2p/peer.rb +10 -16
- data/lib/ciri/devp2p/protocol.rb +10 -16
- data/lib/ciri/devp2p/protocol_io.rb +10 -16
- data/lib/ciri/devp2p/rlpx/connection.rb +10 -16
- data/lib/ciri/devp2p/rlpx/encryption_handshake.rb +13 -19
- data/lib/ciri/devp2p/rlpx/error.rb +10 -16
- data/lib/ciri/devp2p/rlpx/frame_io.rb +10 -16
- data/lib/ciri/devp2p/rlpx/message.rb +10 -16
- data/lib/ciri/devp2p/rlpx/node.rb +10 -16
- data/lib/ciri/devp2p/rlpx/protocol_handshake.rb +10 -16
- data/lib/ciri/devp2p/rlpx/protocol_messages.rb +10 -16
- data/lib/ciri/devp2p/rlpx/secrets.rb +10 -16
- data/lib/ciri/devp2p/rlpx.rb +10 -16
- data/lib/ciri/devp2p/server.rb +10 -16
- data/lib/ciri/eth/peer.rb +10 -16
- data/lib/ciri/eth/protocol_manage.rb +10 -16
- data/lib/ciri/eth/protocol_messages.rb +10 -16
- data/lib/ciri/eth/synchronizer.rb +10 -16
- data/lib/ciri/eth.rb +10 -16
- data/lib/ciri/ethash.rb +10 -16
- data/lib/ciri/evm/block_info.rb +25 -17
- data/lib/ciri/evm/errors.rb +13 -16
- data/lib/ciri/evm/execution_context.rb +136 -0
- data/lib/ciri/evm/instruction.rb +17 -24
- data/lib/ciri/evm/log_entry.rb +12 -18
- data/lib/ciri/evm/machine_state.rb +28 -33
- data/lib/ciri/evm/op.rb +52 -89
- data/lib/ciri/evm/op_call.rb +114 -0
- data/lib/ciri/evm/precompile_contract.rb +102 -0
- data/lib/ciri/evm/state.rb +28 -21
- data/lib/ciri/evm/sub_state.rb +18 -24
- data/lib/ciri/evm/vm.rb +128 -190
- data/lib/ciri/evm.rb +77 -85
- data/lib/ciri/forks/base.rb +28 -16
- data/lib/ciri/forks/byzantium.rb +43 -0
- data/lib/ciri/forks/config.rb +36 -0
- data/lib/ciri/forks/frontier/cost.rb +42 -33
- data/lib/ciri/forks/frontier.rb +47 -18
- data/lib/ciri/forks/homestead/cost.rb +195 -0
- data/lib/ciri/forks/homestead.rb +46 -0
- data/lib/ciri/forks.rb +12 -22
- data/lib/ciri/key.rb +14 -3
- data/lib/ciri/pow.rb +11 -17
- data/lib/ciri/rlp/decode.rb +10 -16
- data/lib/ciri/rlp/encode.rb +10 -16
- data/lib/ciri/rlp/serializable.rb +10 -16
- data/lib/ciri/serialize.rb +14 -17
- data/lib/ciri/trie/nibbles.rb +10 -16
- data/lib/ciri/trie/nodes.rb +12 -17
- data/lib/ciri/trie.rb +12 -18
- data/lib/ciri/types/account.rb +15 -17
- data/lib/ciri/types/address.rb +11 -17
- data/lib/ciri/types/errors.rb +10 -16
- data/lib/ciri/types/receipt.rb +12 -18
- data/lib/ciri/types/uint.rb +79 -0
- data/lib/ciri/version.rb +1 -1
- data/lib/ciri.rb +10 -16
- metadata +54 -10
- 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
|
3
|
+
# Copyright 2018 Jiang Jinyang <https://justjjy.com>
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
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
|
-
#
|
13
|
-
# all copies or substantial portions of the Software.
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
14
10
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
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("
|
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
|
-
|
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
|
-
|
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
|
-
|
128
|
-
|
129
|
-
gas_limit: gas_limit,
|
130
|
-
|
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
|
-
|
137
|
-
|
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
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
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
|
data/lib/ciri/forks/base.rb
CHANGED
@@ -1,24 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright
|
3
|
+
# Copyright 2018 Jiang Jinyang <https://justjjy.com>
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
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
|
-
#
|
13
|
-
# all copies or substantial portions of the Software.
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
14
10
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
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
|
3
|
+
# Copyright 2018 Jiang Jinyang <https://justjjy.com>
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
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
|
-
#
|
13
|
-
# all copies or substantial portions of the Software.
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
14
10
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
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 =
|
42
|
-
G_BALANCE =
|
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 =
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
157
|
-
|
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
|
-
|
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
|
-
|
172
|
-
|
173
|
-
|
174
|
-
if
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
data/lib/ciri/forks/frontier.rb
CHANGED
@@ -1,33 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright
|
3
|
+
# Copyright 2018 Jiang Jinyang <https://justjjy.com>
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
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
|
-
#
|
13
|
-
# all copies or substantial portions of the Software.
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
14
10
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
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
|
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.
|
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
|