devp2p 0.2.0 → 0.3.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 +4 -4
- data/lib/devp2p.rb +14 -29
- data/lib/devp2p/app.rb +70 -0
- data/lib/devp2p/command.rb +1 -1
- data/lib/devp2p/connection_monitor.rb +27 -21
- data/lib/devp2p/discovery.rb +1 -1
- data/lib/devp2p/discovery/protocol.rb +2 -2
- data/lib/devp2p/discovery/service.rb +108 -49
- data/lib/devp2p/p2p_protocol.rb +9 -9
- data/lib/devp2p/peer.rb +53 -59
- data/lib/devp2p/peer_manager.rb +77 -39
- data/lib/devp2p/{base_protocol.rb → protocol.rb} +19 -17
- data/lib/devp2p/service.rb +50 -0
- data/lib/devp2p/sync_queue.rb +58 -45
- data/lib/devp2p/version.rb +2 -1
- data/lib/devp2p/wired_service.rb +3 -3
- metadata +19 -35
- data/lib/devp2p/app_helper.rb +0 -85
- data/lib/devp2p/base_app.rb +0 -88
- data/lib/devp2p/base_service.rb +0 -55
- data/lib/devp2p/control.rb +0 -32
@@ -20,9 +20,8 @@ module DEVp2p
|
|
20
20
|
# The default implementation of `command.receive` calls callbacks which can
|
21
21
|
# be registered in a list which is available as: `protocol.receive_X_callbacks`.
|
22
22
|
#
|
23
|
-
class
|
24
|
-
include
|
25
|
-
include Control
|
23
|
+
class Protocol
|
24
|
+
include Concurrent::Async
|
26
25
|
|
27
26
|
extend Configurable
|
28
27
|
add_config(
|
@@ -41,28 +40,31 @@ module DEVp2p
|
|
41
40
|
@peer = peer
|
42
41
|
@service = service
|
43
42
|
|
44
|
-
|
43
|
+
@stopped = false
|
45
44
|
|
46
45
|
setup
|
47
46
|
end
|
48
47
|
|
49
48
|
def start
|
50
|
-
logger.debug 'starting', proto:
|
51
|
-
service.on_wire_protocol_start
|
52
|
-
|
49
|
+
logger.debug 'starting', proto: self
|
50
|
+
service.async.on_wire_protocol_start self
|
51
|
+
rescue
|
52
|
+
puts $!
|
53
|
+
puts $!.backtrace[0,10].join("\n")
|
53
54
|
end
|
54
55
|
|
55
56
|
def stop
|
56
|
-
logger.debug 'stopping', proto:
|
57
|
-
service.on_wire_protocol_stop
|
57
|
+
logger.debug 'stopping', proto: self
|
58
|
+
service.async.on_wire_protocol_stop self
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
@stopped = true
|
61
|
+
rescue
|
62
|
+
puts $!
|
63
|
+
puts $!.backtrace[0,10].join("\n")
|
62
64
|
end
|
63
65
|
|
64
|
-
def
|
65
|
-
|
66
|
+
def stopped?
|
67
|
+
@stopped
|
66
68
|
end
|
67
69
|
|
68
70
|
def receive_packet(packet)
|
@@ -75,7 +77,7 @@ module DEVp2p
|
|
75
77
|
end
|
76
78
|
|
77
79
|
def send_packet(packet)
|
78
|
-
peer.send_packet packet
|
80
|
+
peer.async.send_packet packet
|
79
81
|
end
|
80
82
|
|
81
83
|
def to_s
|
@@ -98,14 +100,14 @@ module DEVp2p
|
|
98
100
|
|
99
101
|
raise DuplicatedCommand unless klasses.map(&:cmd_id).uniq.size == klasses.size
|
100
102
|
|
101
|
-
proto =
|
103
|
+
proto = self
|
102
104
|
|
103
105
|
klasses.each do |klass|
|
104
106
|
instance = klass.new
|
105
107
|
|
106
108
|
# decode rlp, create hash, call receive
|
107
109
|
receive = lambda do |packet|
|
108
|
-
raise ArgumentError unless packet.is_a?(Packet)
|
110
|
+
raise ArgumentError, "packet is not a Packet: #{packet.inspect}" unless packet.is_a?(Packet)
|
109
111
|
instance.receive proto, klass.decode_payload(packet.payload)
|
110
112
|
end
|
111
113
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
|
3
|
+
module DEVp2p
|
4
|
+
|
5
|
+
class Service
|
6
|
+
include Concurrent::Async
|
7
|
+
|
8
|
+
extend Configurable
|
9
|
+
add_config(
|
10
|
+
name: '',
|
11
|
+
default_config: {},
|
12
|
+
required_services: []
|
13
|
+
)
|
14
|
+
|
15
|
+
class <<self
|
16
|
+
def register_with_app(app)
|
17
|
+
app.register_service self, app
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
attr :app, :config
|
22
|
+
|
23
|
+
def initialize(app)
|
24
|
+
super()
|
25
|
+
|
26
|
+
@app = app
|
27
|
+
@config = app.config.reverse_merge(default_config)
|
28
|
+
|
29
|
+
available_services = app.services.each_value.map(&:class)
|
30
|
+
required_services.each do |r|
|
31
|
+
raise MissingRequiredServiceError, "require service #{r}" unless available_services.include?(r)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def start
|
36
|
+
raise NotImplemented
|
37
|
+
end
|
38
|
+
|
39
|
+
def stop
|
40
|
+
raise NotImplemented
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
"<Service #{name}##{object_id}>"
|
45
|
+
end
|
46
|
+
alias inspect to_s
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/lib/devp2p/sync_queue.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# -*- encoding : ascii-8bit -*-
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
#
|
3
|
+
require 'thread'
|
4
|
+
|
6
5
|
class SyncQueue
|
7
6
|
|
8
7
|
attr :queue, :max_size
|
@@ -12,69 +11,83 @@ class SyncQueue
|
|
12
11
|
@num_waiting = 0
|
13
12
|
|
14
13
|
@max_size = max_size
|
15
|
-
|
16
|
-
@
|
14
|
+
|
15
|
+
@mutex = Mutex.new
|
16
|
+
@cond_full = ConditionVariable.new
|
17
|
+
@cond_empty = ConditionVariable.new
|
17
18
|
end
|
18
19
|
|
19
20
|
def enq(obj, non_block=false)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
22
|
+
loop do
|
23
|
+
@mutex.synchronize do
|
24
|
+
if full?
|
25
|
+
if non_block
|
26
|
+
raise ThreadError, 'queue full'
|
27
|
+
else
|
28
|
+
begin
|
29
|
+
@num_waiting += 1
|
30
|
+
@cond_full.wait @mutex
|
31
|
+
ensure
|
32
|
+
@num_waiting -= 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
@queue.push obj
|
37
|
+
@cond_empty.signal
|
38
|
+
return obj
|
30
39
|
end
|
31
40
|
end
|
32
|
-
else
|
33
|
-
@queue.push obj
|
34
|
-
@cond_empty.signal
|
35
|
-
return obj
|
36
41
|
end
|
37
42
|
end
|
38
43
|
end
|
39
44
|
alias << enq
|
40
45
|
|
41
46
|
def deq(non_block=false)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
48
|
+
loop do
|
49
|
+
@mutex.synchronize do
|
50
|
+
if empty?
|
51
|
+
if non_block
|
52
|
+
raise ThreadError, 'queue empty'
|
53
|
+
else
|
54
|
+
begin
|
55
|
+
@num_waiting += 1
|
56
|
+
@cond_empty.wait @mutex
|
57
|
+
ensure
|
58
|
+
@num_waiting -= 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
else
|
62
|
+
obj = @queue.shift
|
63
|
+
@cond_full.signal
|
64
|
+
return obj
|
52
65
|
end
|
53
66
|
end
|
54
|
-
else
|
55
|
-
obj = @queue.shift
|
56
|
-
@cond_full.signal
|
57
|
-
return obj
|
58
67
|
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
62
71
|
# Same as pop except it will not remove the element from queue, just peek.
|
63
72
|
def peek(non_block=false)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
73
|
+
Thread.handle_interrupt(StandardError => :on_blocking) do
|
74
|
+
loop do
|
75
|
+
@mutex.synchronize do
|
76
|
+
if empty?
|
77
|
+
if non_block
|
78
|
+
raise ThreadError, 'queue empty'
|
79
|
+
else
|
80
|
+
begin
|
81
|
+
@num_waiting += 1
|
82
|
+
@cond_empty.wait @mutex
|
83
|
+
ensure
|
84
|
+
@num_waiting -= 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
else
|
88
|
+
return @queue[0]
|
74
89
|
end
|
75
90
|
end
|
76
|
-
else
|
77
|
-
return @queue[0]
|
78
91
|
end
|
79
92
|
end
|
80
93
|
end
|
data/lib/devp2p/version.rb
CHANGED
data/lib/devp2p/wired_service.rb
CHANGED
@@ -12,17 +12,17 @@ module DEVp2p
|
|
12
12
|
# with instances of Peer and WiredService
|
13
13
|
# WiredService.wire_protocol(Peer.new, WiredService.new)
|
14
14
|
#
|
15
|
-
class WiredService <
|
15
|
+
class WiredService < Service
|
16
16
|
name 'wired'
|
17
17
|
|
18
18
|
attr_accessor :wire_protocol
|
19
19
|
|
20
20
|
def on_wire_protocol_start(proto)
|
21
|
-
raise ArgumentError, "argument is not a protocol" unless proto.is_a?(
|
21
|
+
raise ArgumentError, "argument is not a protocol" unless proto.is_a?(::DEVp2p::Protocol)
|
22
22
|
end
|
23
23
|
|
24
24
|
def on_wire_protocol_stop(proto)
|
25
|
-
raise ArgumentError, "argument is not a protocol" unless proto.is_a?(
|
25
|
+
raise ArgumentError, "argument is not a protocol" unless proto.is_a?(::DEVp2p::Protocol)
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devp2p
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Xie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -38,34 +38,6 @@ dependencies:
|
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
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
41
|
- !ruby/object:Gem::Dependency
|
70
42
|
name: digest-sha3
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +80,20 @@ dependencies:
|
|
108
80
|
- - ">="
|
109
81
|
- !ruby/object:Gem::Version
|
110
82
|
version: 0.7.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: concurrent-ruby
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: rake
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,14 +148,10 @@ files:
|
|
162
148
|
- LICENSE
|
163
149
|
- README.md
|
164
150
|
- lib/devp2p.rb
|
165
|
-
- lib/devp2p/
|
166
|
-
- lib/devp2p/base_app.rb
|
167
|
-
- lib/devp2p/base_protocol.rb
|
168
|
-
- lib/devp2p/base_service.rb
|
151
|
+
- lib/devp2p/app.rb
|
169
152
|
- lib/devp2p/command.rb
|
170
153
|
- lib/devp2p/configurable.rb
|
171
154
|
- lib/devp2p/connection_monitor.rb
|
172
|
-
- lib/devp2p/control.rb
|
173
155
|
- lib/devp2p/crypto.rb
|
174
156
|
- lib/devp2p/crypto/ecc_x.rb
|
175
157
|
- lib/devp2p/crypto/ecies.rb
|
@@ -194,7 +176,9 @@ files:
|
|
194
176
|
- lib/devp2p/peer.rb
|
195
177
|
- lib/devp2p/peer_errors.rb
|
196
178
|
- lib/devp2p/peer_manager.rb
|
179
|
+
- lib/devp2p/protocol.rb
|
197
180
|
- lib/devp2p/rlpx_session.rb
|
181
|
+
- lib/devp2p/service.rb
|
198
182
|
- lib/devp2p/sync_queue.rb
|
199
183
|
- lib/devp2p/utils.rb
|
200
184
|
- lib/devp2p/version.rb
|
data/lib/devp2p/app_helper.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
# -*- encoding : ascii-8bit -*-
|
2
|
-
|
3
|
-
module DEVp2p
|
4
|
-
class AppHelper
|
5
|
-
|
6
|
-
def run(app_class, service_class, num_nodes: 3, seed: 0, min_peers: 2, max_peers: 2, random_port: false)
|
7
|
-
base_port = random_port ? SecureRandom.random_number(50000) + 10000 : 29870
|
8
|
-
|
9
|
-
bootstrap_node_privkey = Crypto.mk_privkey "#{seed}:udp:0"
|
10
|
-
bootstrap_node_pubkey = Crypto.privtopub bootstrap_node_privkey
|
11
|
-
enode = Utils.host_port_pubkey_to_uri "0.0.0.0", base_port, bootstrap_node_pubkey
|
12
|
-
|
13
|
-
services = [Discovery::Service, PeerManager]#, service_class]
|
14
|
-
|
15
|
-
base_config = {}
|
16
|
-
services.each {|s| Utils.update_config_with_defaults base_config, s.default_config }
|
17
|
-
|
18
|
-
base_config[:discovery][:bootstrap_nodes] = [enode]
|
19
|
-
base_config[:seed] = seed
|
20
|
-
base_config[:base_port] = base_port
|
21
|
-
base_config[:num_nodes] = num_nodes
|
22
|
-
base_config[:min_peers] = min_peers
|
23
|
-
base_config[:max_peers] = max_peers
|
24
|
-
|
25
|
-
apps = []
|
26
|
-
num_nodes.times do |node_num|
|
27
|
-
app = create_app node_num, base_config, services, app_class
|
28
|
-
apps.push app
|
29
|
-
end
|
30
|
-
|
31
|
-
serve_until_stopped apps
|
32
|
-
end
|
33
|
-
|
34
|
-
def create_app(node_num, config, services, app_class)
|
35
|
-
num_nodes = config[:num_nodes]
|
36
|
-
base_port = config[:base_port]
|
37
|
-
seed = config[:seed]
|
38
|
-
min_peers = config[:min_peers]
|
39
|
-
max_peers = config[:max_peers]
|
40
|
-
|
41
|
-
raise "invalid node_num" unless node_num < num_nodes
|
42
|
-
#raise "invalid min/max peers" unless min_peers <= max_peers && max_peers < num_nodes
|
43
|
-
|
44
|
-
config = Marshal.load Marshal.dump(config)
|
45
|
-
config[:node_num] = node_num
|
46
|
-
|
47
|
-
config[:node][:privkey_hex] = Utils.encode_hex Crypto.mk_privkey("#{seed}:udp:#{node_num}")
|
48
|
-
config[:discovery][:listen_port] = base_port + node_num
|
49
|
-
config[:p2p][:listen_port] = base_port + node_num
|
50
|
-
config[:p2p][:min_peers] = [min_peers, 10].min
|
51
|
-
config[:p2p][:max_peers] = max_peers
|
52
|
-
config[:client_version_string] = "NODE#{node_num}"
|
53
|
-
|
54
|
-
app = app_class.new config
|
55
|
-
|
56
|
-
services.each do |service|
|
57
|
-
raise "invalid service" unless service.instance_of?(Class) && service < BaseService
|
58
|
-
|
59
|
-
if !app.config[:deactivated_services].include?(service.name)
|
60
|
-
raise "service should not be active" if app.services.has_key?(service.name)
|
61
|
-
service.register_with_app app
|
62
|
-
raise "servier should be active" unless app.services.has_key?(service.name)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
app
|
67
|
-
end
|
68
|
-
|
69
|
-
def serve_until_stopped(apps)
|
70
|
-
apps.each do |app|
|
71
|
-
app.start
|
72
|
-
|
73
|
-
if app.config[:post_app_start_callback]
|
74
|
-
app.config[:post_app_start_callback].call(app)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
apps.each(&:join)
|
79
|
-
|
80
|
-
# finally stop
|
81
|
-
apps.each(&:stop)
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|