devp2p 0.1.0
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +22 -0
- data/lib/devp2p.rb +57 -0
- data/lib/devp2p/app_helper.rb +85 -0
- data/lib/devp2p/base_app.rb +80 -0
- data/lib/devp2p/base_protocol.rb +136 -0
- data/lib/devp2p/base_service.rb +55 -0
- data/lib/devp2p/command.rb +82 -0
- data/lib/devp2p/configurable.rb +32 -0
- data/lib/devp2p/connection_monitor.rb +77 -0
- data/lib/devp2p/control.rb +32 -0
- data/lib/devp2p/crypto.rb +73 -0
- data/lib/devp2p/crypto/ecc_x.rb +133 -0
- data/lib/devp2p/crypto/ecies.rb +134 -0
- data/lib/devp2p/discovery.rb +118 -0
- data/lib/devp2p/discovery/address.rb +83 -0
- data/lib/devp2p/discovery/kademlia_protocol_adapter.rb +11 -0
- data/lib/devp2p/discovery/node.rb +32 -0
- data/lib/devp2p/discovery/protocol.rb +342 -0
- data/lib/devp2p/discovery/transport.rb +105 -0
- data/lib/devp2p/exception.rb +30 -0
- data/lib/devp2p/frame.rb +197 -0
- data/lib/devp2p/kademlia.rb +48 -0
- data/lib/devp2p/kademlia/k_bucket.rb +178 -0
- data/lib/devp2p/kademlia/node.rb +40 -0
- data/lib/devp2p/kademlia/protocol.rb +284 -0
- data/lib/devp2p/kademlia/routing_table.rb +131 -0
- data/lib/devp2p/kademlia/wire_interface.rb +30 -0
- data/lib/devp2p/multiplexed_session.rb +110 -0
- data/lib/devp2p/multiplexer.rb +358 -0
- data/lib/devp2p/p2p_protocol.rb +170 -0
- data/lib/devp2p/packet.rb +35 -0
- data/lib/devp2p/peer.rb +329 -0
- data/lib/devp2p/peer_errors.rb +35 -0
- data/lib/devp2p/peer_manager.rb +274 -0
- data/lib/devp2p/rlpx_session.rb +434 -0
- data/lib/devp2p/sync_queue.rb +76 -0
- data/lib/devp2p/utils.rb +106 -0
- data/lib/devp2p/version.rb +13 -0
- data/lib/devp2p/wired_service.rb +30 -0
- metadata +227 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# A naive synchronized queue for Celluloid actors.
|
5
|
+
#
|
6
|
+
class SyncQueue
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@queue = []
|
10
|
+
@num_waiting = 0
|
11
|
+
@cond = Celluloid::Condition.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def enq(obj)
|
15
|
+
@queue.push obj
|
16
|
+
@cond.signal
|
17
|
+
end
|
18
|
+
alias << enq
|
19
|
+
|
20
|
+
def deq(non_block=false)
|
21
|
+
loop do
|
22
|
+
if @queue.empty?
|
23
|
+
if non_block
|
24
|
+
raise ThreadError, 'queue empty'
|
25
|
+
else
|
26
|
+
begin
|
27
|
+
@num_waiting += 1
|
28
|
+
@cond.wait
|
29
|
+
ensure
|
30
|
+
@num_waiting -= 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
else
|
34
|
+
return @queue.shift
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Same as pop except it will not remove the element from queue, just peek.
|
40
|
+
def peek(non_block=false)
|
41
|
+
loop do
|
42
|
+
if @queue.empty?
|
43
|
+
if non_block
|
44
|
+
raise ThreadError, 'queue empty'
|
45
|
+
else
|
46
|
+
begin
|
47
|
+
@num_waiting += 1
|
48
|
+
@cond.wait
|
49
|
+
ensure
|
50
|
+
@num_waiting -= 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
return @queue[0]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def empty?
|
60
|
+
@queue.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
def clear
|
64
|
+
@queue.clear
|
65
|
+
end
|
66
|
+
|
67
|
+
def length
|
68
|
+
@queue.length
|
69
|
+
end
|
70
|
+
alias size length
|
71
|
+
|
72
|
+
# Returns the number of threads waiting on the queue.
|
73
|
+
def num_waiting
|
74
|
+
@num_waiting
|
75
|
+
end
|
76
|
+
end
|
data/lib/devp2p/utils.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
|
3
|
+
module DEVp2p
|
4
|
+
module Utils
|
5
|
+
|
6
|
+
BYTE_ZERO = "\x00".freeze
|
7
|
+
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def encode_hex(b)
|
11
|
+
RLP::Utils.encode_hex b
|
12
|
+
end
|
13
|
+
|
14
|
+
def decode_hex(s)
|
15
|
+
RLP::Utils.decode_hex s
|
16
|
+
end
|
17
|
+
|
18
|
+
def int_to_big_endian(i)
|
19
|
+
RLP::Sedes.big_endian_int.serialize(i)
|
20
|
+
end
|
21
|
+
|
22
|
+
def big_endian_to_int(s)
|
23
|
+
RLP::Sedes.big_endian_int.deserialize s.sub(/\A(\x00)+/, '')
|
24
|
+
end
|
25
|
+
|
26
|
+
# 4 bytes big endian integer
|
27
|
+
def int_to_big_endian4(i)
|
28
|
+
[i].pack('I>')
|
29
|
+
end
|
30
|
+
|
31
|
+
def ceil16(x)
|
32
|
+
x % 16 == 0 ? x : (x + 16 - (x%16))
|
33
|
+
end
|
34
|
+
|
35
|
+
def lpad(x, symbol, l)
|
36
|
+
return x if x.size >= l
|
37
|
+
symbol * (l - x.size) + x
|
38
|
+
end
|
39
|
+
|
40
|
+
def zpad(x, l)
|
41
|
+
lpad x, BYTE_ZERO, l
|
42
|
+
end
|
43
|
+
|
44
|
+
def bpad(x, l)
|
45
|
+
lpad x.to_s(2), '0', l
|
46
|
+
end
|
47
|
+
|
48
|
+
def rzpad16(data)
|
49
|
+
extra = data.size % 16
|
50
|
+
data += "\x00" * (16 - extra) if extra != 0
|
51
|
+
data
|
52
|
+
end
|
53
|
+
|
54
|
+
def zpad_int(i, l=32)
|
55
|
+
Utils.zpad Utils.int_to_big_endian(i), l
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# String xor.
|
60
|
+
#
|
61
|
+
def sxor(s1, s2)
|
62
|
+
raise ArgumentError, "strings must have equal size" unless s1.size == s2.size
|
63
|
+
|
64
|
+
s1.bytes.zip(s2.bytes).map {|a, b| (a ^ b).chr }.join
|
65
|
+
end
|
66
|
+
|
67
|
+
def update_config_with_defaults(config, default_config)
|
68
|
+
default_config.each do |k, v|
|
69
|
+
if v.is_a?(Hash)
|
70
|
+
config[k] = update_config_with_defaults(config.fetch(k, {}), v)
|
71
|
+
elsif !config.has_key?(k)
|
72
|
+
config[k] = default_config[k]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
config
|
77
|
+
end
|
78
|
+
|
79
|
+
def host_port_pubkey_from_uri(uri)
|
80
|
+
raise ArgumentError, 'invalid uri' unless uri =~ /\A#{NODE_URI_SCHEME}.+@.+:.+$/
|
81
|
+
|
82
|
+
pubkey_hex, ip_port = uri[NODE_URI_SCHEME.size..-1].split('@')
|
83
|
+
raise ArgumentError, 'invalid pubkey length' unless pubkey_hex.size == 2 * Kademlia::PUBKEY_SIZE / 8
|
84
|
+
|
85
|
+
ip, port = ip_port.split(':')
|
86
|
+
return ip, port, Utils.decode_hex(pubkey_hex)
|
87
|
+
end
|
88
|
+
|
89
|
+
def host_port_pubkey_to_uri(host, port, pubkey)
|
90
|
+
raise ArgumentError, 'invalid pubkey length' unless pubkey.size == Kademlia::PUBKEY_SIZE / 8
|
91
|
+
|
92
|
+
"#{NODE_URI_SCHEME}#{encode_hex pubkey}@#{host}:#{port}"
|
93
|
+
end
|
94
|
+
|
95
|
+
DOUBLE_COLON = '::'.freeze
|
96
|
+
def underscore(s)
|
97
|
+
word = s.split(DOUBLE_COLON).last
|
98
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
99
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
100
|
+
word.tr!("-", "_")
|
101
|
+
word.downcase!
|
102
|
+
word
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
module DEVp2p
|
3
|
+
VERSION = '0.1.0'
|
4
|
+
|
5
|
+
VersionString = begin
|
6
|
+
git_describe_re = /^(?<version>v\d+\.\d+\.\d+)-(?<git>\d+-g[a-fA-F0-9]+(?:-dirty)?)$/
|
7
|
+
|
8
|
+
rev = `git describe --tags --dirty`
|
9
|
+
m = rev.match git_describe_re
|
10
|
+
|
11
|
+
ver = m ? "#{m[:version]}+git-#{m[:git]}" : VERSION
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
module DEVp2p
|
3
|
+
|
4
|
+
##
|
5
|
+
# A service which has an associated WireProtocol.
|
6
|
+
#
|
7
|
+
# peermanager checks all services registered with app.services
|
8
|
+
# if service is instance of WiredService
|
9
|
+
# add WiredService.wire_protocol to announced capabilities
|
10
|
+
# if a peer with the same protocol is connected
|
11
|
+
# a WiredService.wire_protocol instance is created
|
12
|
+
# with instances of Peer and WiredService
|
13
|
+
# WiredService.wire_protocol(Peer.new, WiredService.new)
|
14
|
+
#
|
15
|
+
class WiredService < BaseService
|
16
|
+
name 'wired'
|
17
|
+
|
18
|
+
attr_accessor :wire_protocol
|
19
|
+
|
20
|
+
def on_wire_protocol_start(proto)
|
21
|
+
raise ArgumentError, "argument is not a protocol" unless proto.is_a?(BaseProtocol)
|
22
|
+
end
|
23
|
+
|
24
|
+
def on_wire_protocol_stop(proto)
|
25
|
+
raise ArgumentError, "argument is not a protocol" unless proto.is_a?(BaseProtocol)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: devp2p
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan Xie
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hashie
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: block_logger
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: celluloid
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.17'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.17'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: celluloid-io
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.17.3
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.17.3
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: digest-sha3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bitcoin-secp256k1
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.3.1
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.3.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rlp
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.7.1
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.7.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '10.5'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '10.5'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: minitest
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 5.8.3
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 5.8.3
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: yard
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.8.7.6
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.8.7.6
|
153
|
+
description: DEVp2p aims to provide a lightweight abstraction layer that provides
|
154
|
+
these low-level algorithms, protocols and services in a transparent framework without
|
155
|
+
predetermining the eventual transmission-use-cases of the protocols.
|
156
|
+
email:
|
157
|
+
- jan.h.xie@gmail.com
|
158
|
+
executables: []
|
159
|
+
extensions: []
|
160
|
+
extra_rdoc_files: []
|
161
|
+
files:
|
162
|
+
- LICENSE
|
163
|
+
- README.md
|
164
|
+
- lib/devp2p.rb
|
165
|
+
- lib/devp2p/app_helper.rb
|
166
|
+
- lib/devp2p/base_app.rb
|
167
|
+
- lib/devp2p/base_protocol.rb
|
168
|
+
- lib/devp2p/base_service.rb
|
169
|
+
- lib/devp2p/command.rb
|
170
|
+
- lib/devp2p/configurable.rb
|
171
|
+
- lib/devp2p/connection_monitor.rb
|
172
|
+
- lib/devp2p/control.rb
|
173
|
+
- lib/devp2p/crypto.rb
|
174
|
+
- lib/devp2p/crypto/ecc_x.rb
|
175
|
+
- lib/devp2p/crypto/ecies.rb
|
176
|
+
- lib/devp2p/discovery.rb
|
177
|
+
- lib/devp2p/discovery/address.rb
|
178
|
+
- lib/devp2p/discovery/kademlia_protocol_adapter.rb
|
179
|
+
- lib/devp2p/discovery/node.rb
|
180
|
+
- lib/devp2p/discovery/protocol.rb
|
181
|
+
- lib/devp2p/discovery/transport.rb
|
182
|
+
- lib/devp2p/exception.rb
|
183
|
+
- lib/devp2p/frame.rb
|
184
|
+
- lib/devp2p/kademlia.rb
|
185
|
+
- lib/devp2p/kademlia/k_bucket.rb
|
186
|
+
- lib/devp2p/kademlia/node.rb
|
187
|
+
- lib/devp2p/kademlia/protocol.rb
|
188
|
+
- lib/devp2p/kademlia/routing_table.rb
|
189
|
+
- lib/devp2p/kademlia/wire_interface.rb
|
190
|
+
- lib/devp2p/multiplexed_session.rb
|
191
|
+
- lib/devp2p/multiplexer.rb
|
192
|
+
- lib/devp2p/p2p_protocol.rb
|
193
|
+
- lib/devp2p/packet.rb
|
194
|
+
- lib/devp2p/peer.rb
|
195
|
+
- lib/devp2p/peer_errors.rb
|
196
|
+
- lib/devp2p/peer_manager.rb
|
197
|
+
- lib/devp2p/rlpx_session.rb
|
198
|
+
- lib/devp2p/sync_queue.rb
|
199
|
+
- lib/devp2p/utils.rb
|
200
|
+
- lib/devp2p/version.rb
|
201
|
+
- lib/devp2p/wired_service.rb
|
202
|
+
homepage: https://github.com/janx/ruby-devp2p
|
203
|
+
licenses:
|
204
|
+
- MIT
|
205
|
+
metadata: {}
|
206
|
+
post_install_message:
|
207
|
+
rdoc_options: []
|
208
|
+
require_paths:
|
209
|
+
- lib
|
210
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
requirements: []
|
221
|
+
rubyforge_project:
|
222
|
+
rubygems_version: 2.4.5.1
|
223
|
+
signing_key:
|
224
|
+
specification_version: 4
|
225
|
+
summary: A ruby implementation of Ethereum's DEVp2p framework.
|
226
|
+
test_files: []
|
227
|
+
has_rdoc:
|