ciri 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +14 -0
  3. data/.rspec +2 -1
  4. data/.travis.yml +11 -4
  5. data/Gemfile.lock +3 -0
  6. data/README.md +44 -34
  7. data/Rakefile +47 -4
  8. data/ciri.gemspec +13 -12
  9. data/docker/Base +34 -0
  10. data/lib/ciri/actor.rb +223 -0
  11. data/lib/ciri/chain.rb +293 -0
  12. data/lib/ciri/chain/block.rb +47 -0
  13. data/lib/ciri/chain/header.rb +62 -0
  14. data/lib/ciri/chain/transaction.rb +145 -0
  15. data/lib/ciri/crypto.rb +58 -5
  16. data/lib/ciri/db/backend/memory.rb +68 -0
  17. data/lib/ciri/db/backend/rocks.rb +104 -0
  18. data/lib/ciri/db/backend/rocks_db.rb +278 -0
  19. data/lib/ciri/devp2p/peer.rb +10 -2
  20. data/lib/ciri/devp2p/protocol.rb +11 -3
  21. data/lib/ciri/devp2p/protocol_io.rb +6 -3
  22. data/lib/ciri/devp2p/rlpx.rb +1 -0
  23. data/lib/ciri/devp2p/rlpx/encryption_handshake.rb +1 -1
  24. data/lib/ciri/devp2p/rlpx/frame_io.rb +1 -1
  25. data/lib/ciri/devp2p/rlpx/message.rb +4 -4
  26. data/lib/ciri/devp2p/server.rb +14 -13
  27. data/lib/ciri/eth.rb +33 -0
  28. data/lib/ciri/eth/peer.rb +64 -0
  29. data/lib/ciri/eth/protocol_manage.rb +122 -0
  30. data/lib/ciri/eth/protocol_messages.rb +158 -0
  31. data/lib/ciri/eth/synchronizer.rb +188 -0
  32. data/lib/ciri/ethash.rb +123 -0
  33. data/lib/ciri/evm.rb +140 -0
  34. data/lib/ciri/evm/account.rb +50 -0
  35. data/lib/ciri/evm/block_info.rb +31 -0
  36. data/lib/ciri/evm/forks/frontier.rb +183 -0
  37. data/lib/ciri/evm/instruction.rb +92 -0
  38. data/lib/ciri/evm/machine_state.rb +81 -0
  39. data/lib/ciri/evm/op.rb +536 -0
  40. data/lib/ciri/evm/serialize.rb +60 -0
  41. data/lib/ciri/evm/sub_state.rb +64 -0
  42. data/lib/ciri/evm/vm.rb +379 -0
  43. data/lib/ciri/forks.rb +38 -0
  44. data/lib/ciri/forks/frontier.rb +43 -0
  45. data/lib/ciri/key.rb +7 -1
  46. data/lib/ciri/pow.rb +95 -0
  47. data/lib/ciri/rlp.rb +3 -53
  48. data/lib/ciri/rlp/decode.rb +100 -40
  49. data/lib/ciri/rlp/encode.rb +95 -34
  50. data/lib/ciri/rlp/serializable.rb +61 -91
  51. data/lib/ciri/types/address.rb +70 -0
  52. data/lib/ciri/types/errors.rb +36 -0
  53. data/lib/ciri/utils.rb +45 -13
  54. data/lib/ciri/utils/lib_c.rb +46 -0
  55. data/lib/ciri/utils/logger.rb +99 -0
  56. data/lib/ciri/utils/number.rb +67 -0
  57. data/lib/ciri/version.rb +1 -1
  58. metadata +67 -7
  59. data/lib/ciri/devp2p/actor.rb +0 -224
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
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:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
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.
22
+
23
+
24
+ require 'logger'
25
+
26
+ module Ciri
27
+ module Utils
28
+
29
+ # Logger
30
+ # Example:
31
+ #
32
+ # class A
33
+ # include Logger
34
+ #
35
+ # def initialize(name)
36
+ # @name = name
37
+ # debug("initial with name")
38
+ # end
39
+ #
40
+ # def greet
41
+ # puts "hello"
42
+ # debug("greeting hello")
43
+ # end
44
+ #
45
+ # # customize logging name
46
+ # def logging_name
47
+ # "#{super}:#{@name}"
48
+ # end
49
+ # end
50
+ #
51
+ # # don't forget initialize global logger
52
+ # Ciri::Utils::Logger.setup(level: :debug)
53
+ #
54
+ module Logger
55
+
56
+ class << self
57
+ attr_reader :global_logger
58
+
59
+ def setup(level:)
60
+ @global_logger = ::Logger.new(STDERR, level: level)
61
+ global_logger.datetime_format = '%Y-%m-%d %H:%M:%S'
62
+ set_concurrent_logger(level: global_logger.level)
63
+ end
64
+
65
+ private
66
+
67
+ def set_concurrent_logger(level:)
68
+ require 'concurrent'
69
+ Concurrent.use_simple_logger(level = level)
70
+ rescue LoadError
71
+ nil
72
+ end
73
+ end
74
+
75
+ def debug(message)
76
+ add(::Logger::DEBUG, message)
77
+ end
78
+
79
+ def info(message)
80
+ add(::Logger::INFO, message)
81
+ end
82
+
83
+ def error(message)
84
+ add(::Logger::ERROR, message)
85
+ end
86
+
87
+ def logging_name
88
+ self.class.to_s
89
+ end
90
+
91
+ private
92
+
93
+ def add(severity, message = nil, progname = logging_name)
94
+ Logger.global_logger.add(severity, message, progname)
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
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:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
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.
22
+
23
+
24
+ module Ciri
25
+ module Utils
26
+ module Number
27
+ extend self
28
+
29
+ def big_endian_encode(n, zero = ''.b)
30
+ if n == 0
31
+ zero
32
+ elsif n > 0
33
+ big_endian_encode(n / 256) + (n % 256).chr
34
+ else
35
+ raise ArgumentError.new("can't encode negative number #{n}")
36
+ end
37
+ end
38
+
39
+ def big_endian_encode_to_size(n, zero = ''.b, size:)
40
+ big_endian_encode(n, zero).rjust(size, "\x00".b)
41
+ end
42
+
43
+ def big_endian_decode(input)
44
+ input.each_byte.reduce(0) {|s, i| s * 256 + i}
45
+ end
46
+
47
+ UINT_256_MAX = 2 ** 256 - 1
48
+ UINT_256_CEILING = 2 ** 256
49
+ UINT_255_MAX = 2 ** 255 - 1
50
+ UINT_255_CEILING = 2 ** 255
51
+
52
+ def unsigned_to_signed(n)
53
+ n <= UINT_255_MAX ? n : n - UINT_256_CEILING
54
+ end
55
+
56
+ def signed_to_unsigned(n)
57
+ n >= 0 ? n : n + UINT_256_CEILING
58
+ end
59
+
60
+ def ceil_div(n, ceil)
61
+ size, m = n.divmod ceil
62
+ m.zero? ? size : size + 1
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ciri
4
- VERSION = "0.0.0"
4
+ VERSION = "0.0.1"
5
5
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ciri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
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-05-18 00:00:00.000000000 Z
11
+ date: 2018-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.23
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.9.23
27
+ - !ruby/object:Gem::Dependency
28
+ name: lru_redux
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.1.0
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: digest-sha3
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -108,8 +136,7 @@ dependencies:
108
136
  - - "~>"
109
137
  - !ruby/object:Gem::Version
110
138
  version: '3.0'
111
- description: Ciri project intent to implement full feature set of ethereum in pure
112
- ruby, to provide both usable cli and well documented ruby library.
139
+ description: Ciri project intent to implement a full feature set ethereum client.
113
140
  email:
114
141
  - jjyruby@gmail.com
115
142
  executables: []
@@ -117,6 +144,7 @@ extensions: []
117
144
  extra_rdoc_files: []
118
145
  files:
119
146
  - ".gitignore"
147
+ - ".gitmodules"
120
148
  - ".rspec"
121
149
  - ".travis.yml"
122
150
  - CODE_OF_CONDUCT.md
@@ -128,9 +156,17 @@ files:
128
156
  - bin/console
129
157
  - bin/setup
130
158
  - ciri.gemspec
159
+ - docker/Base
131
160
  - lib/ciri.rb
161
+ - lib/ciri/actor.rb
162
+ - lib/ciri/chain.rb
163
+ - lib/ciri/chain/block.rb
164
+ - lib/ciri/chain/header.rb
165
+ - lib/ciri/chain/transaction.rb
132
166
  - lib/ciri/crypto.rb
133
- - lib/ciri/devp2p/actor.rb
167
+ - lib/ciri/db/backend/memory.rb
168
+ - lib/ciri/db/backend/rocks.rb
169
+ - lib/ciri/db/backend/rocks_db.rb
134
170
  - lib/ciri/devp2p/peer.rb
135
171
  - lib/ciri/devp2p/protocol.rb
136
172
  - lib/ciri/devp2p/protocol_io.rb
@@ -145,14 +181,38 @@ files:
145
181
  - lib/ciri/devp2p/rlpx/protocol_messages.rb
146
182
  - lib/ciri/devp2p/rlpx/secrets.rb
147
183
  - lib/ciri/devp2p/server.rb
184
+ - lib/ciri/eth.rb
185
+ - lib/ciri/eth/peer.rb
186
+ - lib/ciri/eth/protocol_manage.rb
187
+ - lib/ciri/eth/protocol_messages.rb
188
+ - lib/ciri/eth/synchronizer.rb
189
+ - lib/ciri/ethash.rb
190
+ - lib/ciri/evm.rb
191
+ - lib/ciri/evm/account.rb
192
+ - lib/ciri/evm/block_info.rb
193
+ - lib/ciri/evm/forks/frontier.rb
194
+ - lib/ciri/evm/instruction.rb
195
+ - lib/ciri/evm/machine_state.rb
196
+ - lib/ciri/evm/op.rb
197
+ - lib/ciri/evm/serialize.rb
198
+ - lib/ciri/evm/sub_state.rb
199
+ - lib/ciri/evm/vm.rb
200
+ - lib/ciri/forks.rb
201
+ - lib/ciri/forks/frontier.rb
148
202
  - lib/ciri/key.rb
203
+ - lib/ciri/pow.rb
149
204
  - lib/ciri/rlp.rb
150
205
  - lib/ciri/rlp/decode.rb
151
206
  - lib/ciri/rlp/encode.rb
152
207
  - lib/ciri/rlp/serializable.rb
208
+ - lib/ciri/types/address.rb
209
+ - lib/ciri/types/errors.rb
153
210
  - lib/ciri/utils.rb
211
+ - lib/ciri/utils/lib_c.rb
212
+ - lib/ciri/utils/logger.rb
213
+ - lib/ciri/utils/number.rb
154
214
  - lib/ciri/version.rb
155
- homepage: https://github.com/ruby-ethereum/ethereum
215
+ homepage: https://github.com/ciri-ethereum/ciri
156
216
  licenses:
157
217
  - MIT
158
218
  metadata: {}
@@ -175,5 +235,5 @@ rubyforge_project:
175
235
  rubygems_version: 2.7.3
176
236
  signing_key:
177
237
  specification_version: 4
178
- summary: Ruby implementation of the ethereum
238
+ summary: Ciri ethereum client.
179
239
  test_files: []
@@ -1,224 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
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:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
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.
22
-
23
-
24
- require 'logger'
25
-
26
- module Ciri
27
- module DevP2P
28
-
29
- # simple actor model implementation
30
- # Example:
31
- #
32
- # class Hello
33
- # include Actor
34
- #
35
- # def say_hello
36
- # puts 'hello world'
37
- # 'hello world'
38
- # end
39
- # end
40
- #
41
- # actor = Hello.new
42
- # # start actor loop
43
- # actor.start
44
- # # push message to actor inbox
45
- # actor << :say_hello
46
- # # push message and wait until get response
47
- # actor.call(:say_hello).value
48
- #
49
- # # raise error
50
- # actor.call(:hello).value # NoMethodError
51
- #
52
- # # stop actor
53
- # actor.send_stop
54
- # actor.wait
55
- #
56
- module Actor
57
-
58
- LOGGER = Logger.new(STDERR, datetime_format: '%Y-%m-%d %H:%M:%S', level: Logger::INFO)
59
-
60
- # future, use this to wait actor msg respond
61
- class Future
62
- def initialize
63
- @value = nil
64
- @done = false
65
- end
66
-
67
- def value=(val)
68
- if @done
69
- raise RuntimeError.new('future value duplicated set')
70
- end
71
- @done = true
72
- @queue << :done if @queue
73
- @value = val
74
- end
75
-
76
- def value
77
- loop do
78
- if @done
79
- return @value
80
- elsif @error
81
- raise @error
82
- else
83
- queue.pop
84
- end
85
- end
86
- end
87
-
88
- def raise_error(error)
89
- error.set_backtrace(caller) if error.backtrace.nil?
90
- @error = error
91
- @queue << :error if @queue
92
- end
93
-
94
- private
95
- def queue
96
- @queue ||= Queue.new
97
- end
98
- end
99
-
100
- class Error < StandardError
101
- end
102
-
103
- # stop actor
104
- class StopError < Error
105
- end
106
-
107
- class StateError < Error
108
- end
109
-
110
- attr_accessor :executor
111
-
112
- def initialize(executor: nil)
113
- @inbox = Queue.new
114
- @executor = executor
115
- @future = Future.new
116
- @running = false
117
- end
118
-
119
- # async call
120
- def enqueue(method, *args)
121
- self << [method, *args]
122
- end
123
-
124
- def <<(args)
125
- @inbox << args
126
- end
127
-
128
- # sync call, push msg to inbox, and return future
129
- #
130
- # Example:
131
- # future = actor.call(:result) # future
132
- # future.value # blocking and wait for result
133
- #
134
- def call(method, *args)
135
- future = Future.new
136
- self << [future, method, *args]
137
- future
138
- end
139
-
140
- # start actor
141
- def start
142
- raise Error.new("must set executor before start") unless executor
143
-
144
- @running = true
145
- executor.post do
146
- start_loop
147
- end
148
- end
149
-
150
- # send stop to actor
151
- #
152
- # Example:
153
- # actor.send_stop
154
- # # wait for actor actually stopped
155
- # actor.wait
156
- #
157
- def send_stop
158
- self << [:raise_error, StopError.new]
159
- end
160
-
161
- # wait until an error occurs
162
- def wait
163
- raise StateError.new('actor not running!') unless @running
164
- @future.value
165
- end
166
-
167
- # start loop
168
- def start_loop
169
- loop_callback do |wait_message: true|
170
- # check inbox
171
- next Thread.pass if @inbox.empty? && !wait_message
172
- msg = @inbox.pop
173
-
174
- # extract sync or async call
175
- future = nil
176
- method, *args = msg
177
- if method.is_a?(Future)
178
- future = method
179
- method, *args = args
180
- end
181
- begin
182
- val = send(method, *args)
183
- rescue StandardError => e
184
- future.raise_error(e) if future
185
- raise
186
- end
187
- # if future not nil, set value
188
- future.value = val if future
189
- end while true
190
-
191
- rescue StopError
192
- # actor stop
193
- @future.value = nil
194
- rescue StandardError => e
195
- @future.raise_error e
196
- LOGGER.error("Actor #{self}") {"#{e}\n#{e.backtrace.join("\n")}"}
197
- ensure
198
- @running = false
199
- end
200
-
201
- # allow inject callback into actor loop
202
- # Example:
203
- #
204
- # class A
205
- # include Actor
206
- #
207
- # def loop_callback
208
- # # before handle msg
209
- # yield
210
- # # after handle msg
211
- # end
212
- # end
213
- #
214
- def loop_callback
215
- yield
216
- end
217
-
218
- def raise_error(e)
219
- raise e
220
- end
221
- end
222
-
223
- end
224
- end