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