ciri 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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: []