ciri 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/Gemfile.lock +6 -6
  4. data/README.md +68 -48
  5. data/Rakefile +16 -11
  6. data/ciri-crypto/lib/ciri/crypto/signature.rb +7 -5
  7. data/ciri-rlp/ciri-rlp.gemspec +1 -1
  8. data/ciri-rlp/lib/ciri/rlp.rb +1 -1
  9. data/ciri-rlp/lib/ciri/rlp/decode.rb +23 -7
  10. data/ciri-rlp/lib/ciri/rlp/encode.rb +8 -2
  11. data/ciri-rlp/lib/ciri/rlp/serializable.rb +14 -4
  12. data/ciri-rlp/lib/ciri/rlp/version.rb +1 -1
  13. data/ciri-rlp/spec/ciri/fixture_spec.rb +2 -2
  14. data/ciri-utils/Gemfile.lock +1 -1
  15. data/ciri-utils/lib/ciri/utils/version.rb +1 -1
  16. data/ciri.gemspec +4 -4
  17. data/lib/ciri/chain/header.rb +13 -11
  18. data/lib/ciri/chain/header_chain.rb +1 -10
  19. data/lib/ciri/chain/transaction.rb +5 -23
  20. data/lib/ciri/db/account_db.rb +0 -4
  21. data/lib/ciri/db/backend/errors.rb +27 -0
  22. data/lib/ciri/db/backend/memory.rb +10 -12
  23. data/lib/ciri/db/backend/rocks.rb +13 -6
  24. data/lib/ciri/db/backend/rocks_db.rb +4 -0
  25. data/lib/ciri/evm.rb +6 -1
  26. data/lib/ciri/evm/execution_context.rb +6 -2
  27. data/lib/ciri/evm/instruction.rb +0 -1
  28. data/lib/ciri/evm/op.rb +11 -5
  29. data/lib/ciri/evm/op/errors.rb +37 -0
  30. data/lib/ciri/evm/state.rb +1 -1
  31. data/lib/ciri/evm/sub_state.rb +6 -6
  32. data/lib/ciri/evm/vm.rb +53 -33
  33. data/lib/ciri/forks.rb +4 -0
  34. data/lib/ciri/forks/base.rb +28 -0
  35. data/lib/ciri/forks/byzantium.rb +45 -11
  36. data/lib/ciri/forks/byzantium/opcodes.rb +37 -0
  37. data/lib/ciri/forks/constantinople.rb +29 -0
  38. data/lib/ciri/forks/frontier.rb +49 -29
  39. data/lib/ciri/forks/frontier/cost.rb +91 -95
  40. data/lib/ciri/forks/frontier/opcodes.rb +99 -0
  41. data/lib/ciri/forks/frontier/transaction.rb +62 -0
  42. data/lib/ciri/forks/homestead.rb +31 -7
  43. data/lib/ciri/forks/homestead/opcodes.rb +37 -0
  44. data/lib/ciri/forks/homestead/transaction.rb +43 -0
  45. data/lib/ciri/forks/spurious_dragon.rb +55 -0
  46. data/lib/ciri/forks/spurious_dragon/cost.rb +91 -0
  47. data/lib/ciri/forks/spurious_dragon/transaction.rb +44 -0
  48. data/lib/ciri/forks/tangerine_whistle.rb +37 -0
  49. data/lib/ciri/forks/tangerine_whistle/cost.rb +98 -0
  50. data/lib/ciri/rlp/decode.rb +4 -4
  51. data/lib/ciri/rlp/encode.rb +2 -2
  52. data/lib/ciri/version.rb +1 -1
  53. metadata +22 -10
  54. data/lib/ciri/forks/homestead/cost.rb +0 -195
@@ -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 'ciri/forks/frontier/transaction'
19
+
20
+ module Ciri
21
+ module Forks
22
+ module Homestead
23
+ class Transaction < Frontier::Transaction
24
+
25
+ def validate!
26
+ super
27
+ raise InvalidError.new('signature s is low') unless signature.low_s?
28
+ end
29
+
30
+ def validate_intrinsic_gas!
31
+ begin
32
+ fork_schema = Schema.new(support_dao_fork: false)
33
+ intrinsic_gas = fork_schema.intrinsic_gas_of_transaction(self)
34
+ rescue StandardError
35
+ raise InvalidError.new 'intrinsic gas calculation error'
36
+ end
37
+ raise InvalidError.new 'intrinsic gas not enough' unless intrinsic_gas <= gas_limit
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,55 @@
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 'tangerine_whistle'
20
+ require_relative 'spurious_dragon/transaction'
21
+ require_relative 'spurious_dragon/cost'
22
+
23
+ module Ciri
24
+ module Forks
25
+ # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md
26
+ module SpuriousDragon
27
+ class Schema < Forks::TangerineWhistle::Schema
28
+
29
+ CONTRACT_CODE_SIZE_LIMIT = 2 ** 14 + 2 ** 13
30
+
31
+ def initialize
32
+ super
33
+ @cost = Cost.new
34
+ end
35
+
36
+ def transaction_class
37
+ Transaction
38
+ end
39
+
40
+ def contract_code_size_limit
41
+ CONTRACT_CODE_SIZE_LIMIT
42
+ end
43
+
44
+ def contract_init_nonce
45
+ 1
46
+ end
47
+
48
+ def clean_empty_accounts?
49
+ true
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ require 'ciri/evm/op'
19
+ require 'ciri/forks/tangerine_whistle/cost'
20
+
21
+ module Ciri
22
+ module Forks
23
+ module SpuriousDragon
24
+
25
+ class Cost < TangerineWhistle::Cost
26
+
27
+ include Ciri::EVM::OP
28
+
29
+ # fee schedule, start with G
30
+ G_EXP = 10
31
+ G_EXPBYTE = 50
32
+ R_SELFDESTRUCT = 24000
33
+ G_SELFDESTRUCT = 5000
34
+ G_CALL = 700
35
+ G_NEWACCOUNT = 25000
36
+ G_CALLSTIPEND = 2300
37
+ G_CALLVALUE = 9000
38
+
39
+ # C(σ,μ,I)
40
+ # calculate cost of current operation
41
+ def gas_of_operation(vm)
42
+ ms = vm.machine_state
43
+ instruction = vm.instruction
44
+ w = instruction.get_op(vm.pc)
45
+
46
+ if w == CALL || w == CALLCODE || w == DELEGATECALL
47
+ G_CALL
48
+ elsif w == SELFDESTRUCT
49
+ cost_of_self_destruct(vm)
50
+ elsif w == EXP && ms.get_stack(1, Integer) == 0
51
+ G_EXP
52
+ elsif w == EXP && (x = ms.get_stack(1, Integer)) > 0
53
+ G_EXP + G_EXPBYTE * Utils.ceil_div(x.bit_length, 8)
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ def gas_of_call(vm:, gas:, to:, value:)
60
+ account_is_dead = vm.account_dead?(to)
61
+ value_exists = value > 0
62
+ transfer_gas_fee = value_exists ? G_CALLVALUE : 0
63
+ create_gas_fee = account_is_dead && value_exists ? G_NEWACCOUNT : 0
64
+ extra_gas = transfer_gas_fee + create_gas_fee
65
+
66
+ gas = [gas, max_child_gas_eip150(vm.remain_gas - extra_gas)].min
67
+ total_fee = gas + extra_gas
68
+ child_gas_limit = gas + (value_exists ? G_CALLSTIPEND : 0)
69
+ [child_gas_limit, total_fee]
70
+ end
71
+
72
+ private
73
+
74
+ def max_child_gas_eip150(gas)
75
+ gas - (gas / 64)
76
+ end
77
+
78
+ def cost_of_self_destruct(vm)
79
+ refund_address = vm.get_stack(0, Address)
80
+ if vm.account_exist?(refund_address)
81
+ G_SELFDESTRUCT
82
+ else
83
+ G_SELFDESTRUCT + G_NEWACCOUNT
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ require 'ciri/forks/homestead/transaction'
19
+
20
+ module Ciri
21
+ module Forks
22
+ module SpuriousDragon
23
+ class Transaction < Homestead::Transaction
24
+
25
+ def v_min
26
+ if eip_155_signed_transaction?
27
+ 35 + (2 * chain_id)
28
+ else
29
+ 27
30
+ end
31
+ end
32
+
33
+ def v_max
34
+ if eip_155_signed_transaction?
35
+ 36 + (2 * chain_id)
36
+ else
37
+ 28
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,37 @@
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
+ require_relative 'tangerine_whistle/cost'
21
+
22
+ module Ciri
23
+ module Forks
24
+ # Tangerine Whistle fork
25
+ # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-608.md
26
+ module TangerineWhistle
27
+ class Schema < Forks::Homestead::Schema
28
+
29
+ def initialize
30
+ super(support_dao_fork: false)
31
+ @cost = Cost.new
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2018 Jiang Jinyang <https://justjjy.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ require 'ciri/evm/op'
19
+ require 'ciri/forks/frontier/cost'
20
+
21
+ module Ciri
22
+ module Forks
23
+ module TangerineWhistle
24
+
25
+ class Cost < Frontier::Cost
26
+
27
+ include Ciri::EVM::OP
28
+
29
+ # fee schedule, start with G
30
+ G_EXTCODE = 700
31
+ G_BALANCE = 400
32
+ G_SLOAD = 200
33
+ R_SELFDESTRUCT = 24000
34
+ G_SELFDESTRUCT = 5000
35
+ G_CALL = 700
36
+ G_NEWACCOUNT = 25000
37
+ G_COPY = 3
38
+ G_CALLSTIPEND = 2300
39
+ G_CALLVALUE = 9000
40
+ W_EXTCODE = [EXTCODESIZE]
41
+
42
+ # C(σ,μ,I)
43
+ # calculate cost of current operation
44
+ def gas_of_operation(vm)
45
+ ms = vm.machine_state
46
+ instruction = vm.instruction
47
+ w = instruction.get_op(vm.pc)
48
+
49
+ if w == EXTCODECOPY
50
+ G_EXTCODE + G_COPY * Utils.ceil_div(ms.get_stack(3, Integer), 32)
51
+ elsif w == CALL || w == CALLCODE || w == DELEGATECALL
52
+ G_CALL
53
+ elsif w == SELFDESTRUCT
54
+ cost_of_self_destruct(vm)
55
+ elsif w == SLOAD
56
+ G_SLOAD
57
+ elsif W_EXTCODE.include? w
58
+ G_EXTCODE
59
+ elsif w == BALANCE
60
+ G_BALANCE
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ def gas_of_call(vm:, gas:, to:, value:)
67
+ account_exists = vm.account_exist?(to)
68
+ transfer_gas_fee = value > 0 ? G_CALLVALUE : 0
69
+ create_gas_fee = !account_exists ? G_NEWACCOUNT : 0
70
+ extra_gas = transfer_gas_fee + create_gas_fee
71
+
72
+ gas = [gas, max_child_gas_eip150(vm.remain_gas - extra_gas)].min
73
+ total_fee = gas + extra_gas
74
+ child_gas_limit = gas + (value > 0 ? G_CALLSTIPEND : 0)
75
+ [child_gas_limit, total_fee]
76
+ end
77
+
78
+ private
79
+
80
+ def max_child_gas_eip150(gas)
81
+ gas - (gas / 64)
82
+ end
83
+
84
+ def cost_of_self_destruct(vm)
85
+ balance_is_zero = vm.find_account(vm.instruction.address).balance == 0
86
+ refund_address = vm.get_stack(0, Address)
87
+ if vm.account_exist?(refund_address) || balance_is_zero
88
+ G_SELFDESTRUCT
89
+ else
90
+ G_SELFDESTRUCT + G_NEWACCOUNT
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -44,7 +44,7 @@ module Ciri
44
44
  if type == Integer
45
45
  item = s.read(1)
46
46
  if item.nil?
47
- raise InvalidValueError.new "invalid bool value nil"
47
+ raise InvalidError.new "invalid bool value nil"
48
48
  elsif item == "\x80".b || item.empty?
49
49
  0
50
50
  elsif item.ord < 0x80
@@ -60,7 +60,7 @@ module Ciri
60
60
  elsif item == Bool::ENCODED_FALSE
61
61
  false
62
62
  else
63
- raise InvalidValueError.new "invalid bool value #{item}"
63
+ raise InvalidError.new "invalid bool value #{item}"
64
64
  end
65
65
  elsif type.is_a?(Class) && type.respond_to?(:rlp_decode)
66
66
  type.rlp_decode(s)
@@ -76,7 +76,7 @@ module Ciri
76
76
  elsif type == Raw
77
77
  decode_stream(s)
78
78
  else
79
- raise RLP::InvalidValueError.new "unknown type #{type}"
79
+ raise RLP::InvalidError.new "unknown type #{type}"
80
80
  end
81
81
  rescue
82
82
  STDERR.puts "when decoding #{s} into #{type}"
@@ -99,7 +99,7 @@ module Ciri
99
99
  length = int_from_binary(length_binary)
100
100
  s.read(length)
101
101
  else
102
- raise InvalidValueError.new("invalid char #{c}")
102
+ raise InvalidError.new("invalid char #{c}")
103
103
  end
104
104
 
105
105
  decoder.call(list, StringIO.new(sub_s))
@@ -70,12 +70,12 @@ module Ciri
70
70
  if type.size == 1 # array type
71
71
  encode_list(item) {|i| encode_with_type(i, type[0])}
72
72
  else # unknown
73
- raise RLP::InvalidValueError.new "type size should be 1, got #{type}"
73
+ raise RLP::InvalidError.new "type size should be 1, got #{type}"
74
74
  end
75
75
  elsif type == Raw
76
76
  encode_raw(item)
77
77
  else
78
- raise RLP::InvalidValueError.new "unknown type #{type}"
78
+ raise RLP::InvalidError.new "unknown type #{type}"
79
79
  end
80
80
  rescue
81
81
  STDERR.puts "when encoding #{Utils.to_hex item.to_s} into #{type}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ciri
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ciri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jiang Jinyang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-03 00:00:00.000000000 Z
11
+ date: 2018-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ciri-utils
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.0
19
+ version: 0.2.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.0
26
+ version: 0.2.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ciri-rlp
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.1.1
33
+ version: 0.2.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.1.1
40
+ version: 0.2.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: ciri-crypto
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -164,8 +164,8 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '3.0'
167
- description: Ciri aims to be a feature complete, long maintained and stable Ethereum
168
- client.
167
+ description: It aims to be a feature complete Ethereum implementation and expects
168
+ to achieve both research-friendly and high-performance.
169
169
  email:
170
170
  - jjyruby@gmail.com
171
171
  executables: []
@@ -260,6 +260,7 @@ files:
260
260
  - lib/ciri/chain/transaction.rb
261
261
  - lib/ciri/core_ext.rb
262
262
  - lib/ciri/db/account_db.rb
263
+ - lib/ciri/db/backend/errors.rb
263
264
  - lib/ciri/db/backend/memory.rb
264
265
  - lib/ciri/db/backend/rocks.rb
265
266
  - lib/ciri/db/backend/rocks_db.rb
@@ -291,6 +292,7 @@ files:
291
292
  - lib/ciri/evm/log_entry.rb
292
293
  - lib/ciri/evm/machine_state.rb
293
294
  - lib/ciri/evm/op.rb
295
+ - lib/ciri/evm/op/errors.rb
294
296
  - lib/ciri/evm/op_call.rb
295
297
  - lib/ciri/evm/precompile_contract.rb
296
298
  - lib/ciri/evm/state.rb
@@ -299,11 +301,21 @@ files:
299
301
  - lib/ciri/forks.rb
300
302
  - lib/ciri/forks/base.rb
301
303
  - lib/ciri/forks/byzantium.rb
304
+ - lib/ciri/forks/byzantium/opcodes.rb
302
305
  - lib/ciri/forks/config.rb
306
+ - lib/ciri/forks/constantinople.rb
303
307
  - lib/ciri/forks/frontier.rb
304
308
  - lib/ciri/forks/frontier/cost.rb
309
+ - lib/ciri/forks/frontier/opcodes.rb
310
+ - lib/ciri/forks/frontier/transaction.rb
305
311
  - lib/ciri/forks/homestead.rb
306
- - lib/ciri/forks/homestead/cost.rb
312
+ - lib/ciri/forks/homestead/opcodes.rb
313
+ - lib/ciri/forks/homestead/transaction.rb
314
+ - lib/ciri/forks/spurious_dragon.rb
315
+ - lib/ciri/forks/spurious_dragon/cost.rb
316
+ - lib/ciri/forks/spurious_dragon/transaction.rb
317
+ - lib/ciri/forks/tangerine_whistle.rb
318
+ - lib/ciri/forks/tangerine_whistle/cost.rb
307
319
  - lib/ciri/key.rb
308
320
  - lib/ciri/pow.rb
309
321
  - lib/ciri/rlp/decode.rb
@@ -342,5 +354,5 @@ rubyforge_project:
342
354
  rubygems_version: 2.7.3
343
355
  signing_key:
344
356
  specification_version: 4
345
- summary: Ciri project intent to implement a full feature set Ethereum client.
357
+ summary: Ciri is an ongoing Ethereum implementation.
346
358
  test_files: []