ciri-p2p 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/.travis.yml +2 -2
- data/Dockerfile +21 -0
- data/Gemfile.lock +1 -1
- data/README.md +29 -2
- data/Rakefile +74 -3
- data/ciri-p2p.gemspec +1 -1
- data/lib/ciri/p2p/dial_scheduler.rb +2 -2
- data/lib/ciri/p2p/network_state.rb +40 -26
- data/lib/ciri/p2p/peer.rb +6 -6
- data/lib/ciri/p2p/server.rb +1 -1
- data/lib/ciri/p2p/version.rb +3 -2
- metadata +4 -3
- data/.vscode/launch.json +0 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84a78196ee2a9a850e3f893c8f3f7a4a30eae83eb9cde69537020215723b9a8e
|
4
|
+
data.tar.gz: '09e75872015ea1b557150db5650f4ef2ccd7bcd180b6fbfa2caa78eae705a769'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: adb6135d935ee3ec9e4aa77c65a0aa44d741481acc44b30d6c880f6a9e35732243fdb9e318fee7a99efaab4d3370c3bfdb31d1a9d3bd2a2729e74a501f3b1b4a
|
7
|
+
data.tar.gz: ce7fcafe49551d9a0cbb9d62496395524d21507053f48add1f9d06101ee123930e2d09d6c082b0c671f3edeb46fe4fd37832513b6c9198fb45e15ff760ecee05
|
data/.gitmodules
ADDED
data/.travis.yml
CHANGED
@@ -8,8 +8,8 @@ install:
|
|
8
8
|
- echo "install nothing"
|
9
9
|
|
10
10
|
before_install:
|
11
|
-
- docker pull ciriethereum/ciri:latest
|
11
|
+
- docker pull ciriethereum/ciri-p2p-test:latest
|
12
12
|
|
13
13
|
script:
|
14
|
-
- docker run -v `pwd`:/app --rm ciriethereum/ciri:latest bash -c 'bundle install && bundle exec
|
14
|
+
- docker run -v `pwd`:/app --rm ciriethereum/ciri-p2p-test:latest bash -c 'bundle install && bundle exec rake'
|
15
15
|
|
data/Dockerfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
FROM ruby:2.6.0-preview2 AS build
|
2
|
+
|
3
|
+
LABEL maintainer="Jiang Jinyang <jjyruby@gmail.com>"
|
4
|
+
|
5
|
+
# install bitcoin secp256k1
|
6
|
+
COPY . /app
|
7
|
+
WORKDIR /app
|
8
|
+
RUN rake install:secp256k1
|
9
|
+
|
10
|
+
# Runtime image
|
11
|
+
FROM ruby:2.6.0-preview2
|
12
|
+
|
13
|
+
# install runtime dependencies libraries
|
14
|
+
RUN apt-get update && apt-get install -y libsnappy-dev libgflags-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev
|
15
|
+
|
16
|
+
# copy header files and shared libraries
|
17
|
+
COPY --from=build /usr/local/include /usr/local/include
|
18
|
+
COPY --from=build /usr/local/lib/ /usr/local/lib
|
19
|
+
|
20
|
+
WORKDIR /app
|
21
|
+
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -3,10 +3,37 @@
|
|
3
3
|
|
4
4
|
P2P network implementation for [Ciri Ethereum](https://github.com/ciri-ethereum/ciri).
|
5
5
|
|
6
|
-
`ciri-p2p` is a DevP2P implementation, we also seek to implement LibP2P components upon ciri-p2p codebase in the future.
|
6
|
+
`ciri-p2p` is a [DevP2P](https://github.com/ethereum/devp2p) implementation, we also seek to implement [LibP2P](https://github.com/libp2p/libp2p) components upon ciri-p2p codebase in the future.
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
10
|
+
### Install dependencies
|
11
|
+
|
12
|
+
Ciri P2P depend on `secp256k1` to handle crypto signature and depend on `snappy` to compress data.
|
13
|
+
|
14
|
+
Build and install `secp256k1`
|
15
|
+
|
16
|
+
``` bash
|
17
|
+
cd ciri
|
18
|
+
git submodule init && git submodule update
|
19
|
+
rake install:secp256k1
|
20
|
+
```
|
21
|
+
|
22
|
+
On Mac you can install `snappy` with homebrew
|
23
|
+
|
24
|
+
``` bash
|
25
|
+
brew install snappy
|
26
|
+
```
|
27
|
+
|
28
|
+
For linux users, remember to check [Dockerfile](/docker) instructions for hint.
|
29
|
+
|
30
|
+
then run tests:
|
31
|
+
``` bash
|
32
|
+
bundle exec rake spec
|
33
|
+
```
|
34
|
+
|
35
|
+
### Install as Gem
|
36
|
+
|
10
37
|
Add this line to your application's Gemfile:
|
11
38
|
|
12
39
|
```ruby
|
@@ -23,7 +50,7 @@ Or install it yourself as:
|
|
23
50
|
|
24
51
|
## Usage
|
25
52
|
|
26
|
-
Check spec directory.
|
53
|
+
Check [spec](https://github.com/ciri-ethereum/ciri-p2p/tree/master/spec) directory.
|
27
54
|
|
28
55
|
## Development
|
29
56
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,77 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tmpdir'
|
3
4
|
|
4
|
-
|
5
|
+
begin
|
6
|
+
require "rspec/core/rake_task"
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
task :default => :spec
|
9
|
+
rescue LoadError
|
10
|
+
warn("rspec not installed, use `gem install rspec-core` to install")
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :install do
|
14
|
+
desc "Build and install secp256k1 shared library"
|
15
|
+
task :secp256k1 do
|
16
|
+
Dir.mktmpdir do |path|
|
17
|
+
source_dir = "secp256k1"
|
18
|
+
build_dir = "#{path}/#{source_dir}"
|
19
|
+
FileUtils.copy_entry source_dir, build_dir
|
20
|
+
Dir.chdir(build_dir)
|
21
|
+
run("./autogen.sh")
|
22
|
+
run("./configure --enable-module-recovery --enable-experimental --enable-module-ecdh")
|
23
|
+
run("make")
|
24
|
+
run("make install")
|
25
|
+
end
|
26
|
+
puts "Success installed secp256k1"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Build and install all"
|
30
|
+
task all: [:secp256k1, :install]
|
31
|
+
end
|
32
|
+
|
33
|
+
namespace :docker do
|
34
|
+
base_image = 'ciriethereum/ciri-p2p-test'
|
35
|
+
|
36
|
+
desc 'pull docker image'
|
37
|
+
task :pull do
|
38
|
+
run("docker pull #{base_image}:latest")
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'build docker image, rerun this task after updated Gemfile or Dockerfile'
|
42
|
+
task :build do
|
43
|
+
system("git submodule init && git submodule update")
|
44
|
+
run("docker build . -f Dockerfile -t #{base_image}:latest")
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'push docker image'
|
48
|
+
task :push do
|
49
|
+
run("docker push #{base_image}:latest")
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'open Ciri P2P develop container shell'
|
53
|
+
task :shell do
|
54
|
+
container_name = 'ciri-p2p-develop'
|
55
|
+
if system("docker inspect #{container_name} > /dev/null")
|
56
|
+
system("docker start -i #{container_name}")
|
57
|
+
else
|
58
|
+
puts "start a new develop container: #{container_name}"
|
59
|
+
system("docker run -v `pwd`:/app -it --name #{container_name} #{base_image}:latest bash")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'run spec in docker'
|
64
|
+
task :spec do |task, args|
|
65
|
+
run("docker run -v `pwd`:/app --rm #{base_image}:latest rake")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def run(cmd)
|
72
|
+
puts "$ #{cmd}"
|
73
|
+
pid = spawn(cmd)
|
74
|
+
Process.wait(pid)
|
75
|
+
exit $?.exitstatus unless $?.success?
|
76
|
+
end
|
5
77
|
|
6
|
-
task :default => :spec
|
data/ciri-p2p.gemspec
CHANGED
@@ -54,7 +54,7 @@ module Ciri
|
|
54
54
|
def dial_bootnodes
|
55
55
|
@network_state.peer_store.find_bootnodes(@network_state.number_of_attemp_outgoing).each do |node|
|
56
56
|
conn, handshake = @dialer.dial(node)
|
57
|
-
@network_state.new_peer_connected(conn, handshake,
|
57
|
+
@network_state.new_peer_connected(conn, handshake, direction: Peer::OUTGOING)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -63,7 +63,7 @@ module Ciri
|
|
63
63
|
# avoid dial self or connected peers
|
64
64
|
next if @network_state.peers.include?(node.raw_node_id) || node.raw_node_id == @network_state.local_node_id
|
65
65
|
conn, handshake = @dialer.dial(node)
|
66
|
-
@network_state.new_peer_connected(conn, handshake,
|
66
|
+
@network_state.new_peer_connected(conn, handshake, direction: Peer::OUTGOING)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -23,6 +23,7 @@
|
|
23
23
|
|
24
24
|
|
25
25
|
require 'async'
|
26
|
+
require 'async/semaphore'
|
26
27
|
require 'ciri/utils/logger'
|
27
28
|
require_relative 'peer'
|
28
29
|
require_relative 'errors'
|
@@ -40,6 +41,7 @@ module Ciri
|
|
40
41
|
|
41
42
|
def initialize(protocols:, peer_store:, local_node_id:, max_outgoing: 10, max_incoming: 10, ping_interval_secs: 15)
|
42
43
|
@peers = {}
|
44
|
+
@peers_lock = Async::Semaphore.new
|
43
45
|
@peer_store = peer_store
|
44
46
|
@protocols = protocols
|
45
47
|
@local_node_id = local_node_id
|
@@ -60,35 +62,41 @@ module Ciri
|
|
60
62
|
@max_outgoing - @peers.values.select(&:outgoing?).count
|
61
63
|
end
|
62
64
|
|
63
|
-
def new_peer_connected(connection, handshake,
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
65
|
+
def new_peer_connected(connection, handshake, direction:, task: Async::Task.current)
|
66
|
+
@peers_lock.acquire do
|
67
|
+
peer = Peer.new(connection, handshake, @protocols, direction: direction)
|
68
|
+
# disconnect already connected peers
|
69
|
+
if @peers.include?(peer.raw_node_id)
|
70
|
+
debug("[#{local_node_id.short_hex}] peer #{peer.inspect} is already connected")
|
71
|
+
# disconnect duplicate connection
|
72
|
+
peer.disconnect
|
73
|
+
return
|
74
|
+
end
|
75
|
+
# check peers
|
76
|
+
protocol_handshake_checks(handshake)
|
77
|
+
@peers[peer.raw_node_id] = peer
|
78
|
+
debug "[#{local_node_id.short_hex}] connect to new peer #{peer.inspect}"
|
79
|
+
@peer_store.update_peer_status(peer.raw_node_id, PeerStore::Status::CONNECTED)
|
80
|
+
# run peer logic
|
81
|
+
task.async do
|
82
|
+
register_peer_protocols(peer)
|
83
|
+
handling_peer(peer)
|
84
|
+
end
|
78
85
|
end
|
79
86
|
end
|
80
87
|
|
81
|
-
def remove_peer(peer)
|
82
|
-
@peers.delete(peer.raw_node_id)
|
83
|
-
deregister_peer_protocols(peer)
|
84
|
-
end
|
85
|
-
|
86
88
|
def disconnect_peer(peer, reason: nil)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
@peers_lock.acquire do
|
90
|
+
# only disconnect from peers if direction correct to avoiding delete peer by mistake
|
91
|
+
if (exist_peer = @peers[peer.raw_node_id]) && exist_peer.direction == peer.direction
|
92
|
+
debug("[#{local_node_id.short_hex}] disconnect peer: #{peer.inspect}, reason: #{reason}")
|
93
|
+
remove_peer(peer)
|
94
|
+
peer.disconnect
|
95
|
+
@peer_store.update_peer_status(peer.raw_node_id, PeerStore::Status::DISCONNECTED)
|
96
|
+
else
|
97
|
+
debug("[#{local_node_id.short_hex}] Ignoring: disconnect peer: #{peer.inspect}, reason: #{reason}")
|
98
|
+
end
|
99
|
+
end
|
92
100
|
end
|
93
101
|
|
94
102
|
def disconnect_all
|
@@ -100,6 +108,12 @@ module Ciri
|
|
100
108
|
|
101
109
|
private
|
102
110
|
|
111
|
+
def remove_peer(peer)
|
112
|
+
@peers.delete(peer.raw_node_id)
|
113
|
+
deregister_peer_protocols(peer)
|
114
|
+
end
|
115
|
+
|
116
|
+
|
103
117
|
def register_peer_protocols(peer, task: Async::Task.current)
|
104
118
|
peer.protocol_ios.dup.each do |protocol_io|
|
105
119
|
task.async do
|
@@ -107,7 +121,7 @@ module Ciri
|
|
107
121
|
context = ProtocolContext.new(self, peer: peer, protocol: protocol_io.protocol, protocol_io: protocol_io)
|
108
122
|
context.protocol.connected(context)
|
109
123
|
rescue StandardError => e
|
110
|
-
error("Protocol#connected error: {e}\nbacktrace: #{e.backtrace.join "\n"}")
|
124
|
+
error("Protocol#connected error: #{e}\nbacktrace: #{e.backtrace.join "\n"}")
|
111
125
|
disconnect_peer(peer, reason: "Protocol#connected callback error: #{e}")
|
112
126
|
end
|
113
127
|
end
|
data/lib/ciri/p2p/peer.rb
CHANGED
@@ -35,22 +35,22 @@ module Ciri
|
|
35
35
|
OUTGOING = :outgoing
|
36
36
|
INCOMING = :incoming
|
37
37
|
|
38
|
-
attr_reader :connection
|
38
|
+
attr_reader :connection, :direction
|
39
39
|
|
40
|
-
def initialize(connection, handshake, protocols,
|
40
|
+
def initialize(connection, handshake, protocols, direction:)
|
41
41
|
@connection = connection
|
42
42
|
@handshake = handshake
|
43
43
|
@protocols = protocols
|
44
44
|
@protocol_io_hash = make_protocol_io_hash(protocols, handshake.caps, connection)
|
45
|
-
@
|
45
|
+
@direction = direction
|
46
46
|
end
|
47
47
|
|
48
48
|
def outgoing?
|
49
|
-
@
|
49
|
+
@direction == OUTGOING
|
50
50
|
end
|
51
51
|
|
52
52
|
def incoming?
|
53
|
-
@
|
53
|
+
@direction == INCOMING
|
54
54
|
end
|
55
55
|
|
56
56
|
def to_s
|
@@ -60,7 +60,7 @@ module Ciri
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def inspect
|
63
|
-
"<Peer:#{to_s}>"
|
63
|
+
"<Peer:#{to_s} direction: #{@direction}>"
|
64
64
|
end
|
65
65
|
|
66
66
|
def hash
|
data/lib/ciri/p2p/server.rb
CHANGED
@@ -148,7 +148,7 @@ module Ciri
|
|
148
148
|
c = Connection.new(client)
|
149
149
|
c.encryption_handshake!(private_key: @private_key)
|
150
150
|
remote_handshake = c.protocol_handshake!(handshake)
|
151
|
-
@network_state.new_peer_connected(c, remote_handshake,
|
151
|
+
@network_state.new_peer_connected(c, remote_handshake, direction: Peer::INCOMING)
|
152
152
|
end
|
153
153
|
end
|
154
154
|
end
|
data/lib/ciri/p2p/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ciri-p2p
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jjy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ciri-utils
|
@@ -159,10 +159,11 @@ extensions: []
|
|
159
159
|
extra_rdoc_files: []
|
160
160
|
files:
|
161
161
|
- ".gitignore"
|
162
|
+
- ".gitmodules"
|
162
163
|
- ".rspec"
|
163
164
|
- ".travis.yml"
|
164
|
-
- ".vscode/launch.json"
|
165
165
|
- CODE_OF_CONDUCT.md
|
166
|
+
- Dockerfile
|
166
167
|
- Gemfile
|
167
168
|
- Gemfile.lock
|
168
169
|
- LICENSE.txt
|
data/.vscode/launch.json
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
{
|
2
|
-
// Use IntelliSense to learn about possible attributes.
|
3
|
-
// Hover to view descriptions of existing attributes.
|
4
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
5
|
-
"version": "0.2.0",
|
6
|
-
"configurations": [
|
7
|
-
{
|
8
|
-
"name": "Debug Local File",
|
9
|
-
"type": "Ruby",
|
10
|
-
"request": "launch",
|
11
|
-
"cwd": "${workspaceRoot}",
|
12
|
-
"program": "${workspaceRoot}/main.rb"
|
13
|
-
},
|
14
|
-
{
|
15
|
-
"name": "Listen for rdebug-ide",
|
16
|
-
"type": "Ruby",
|
17
|
-
"request": "attach",
|
18
|
-
"cwd": "${workspaceRoot}",
|
19
|
-
"remoteHost": "127.0.0.1",
|
20
|
-
"remotePort": "1234",
|
21
|
-
"remoteWorkspaceRoot": "${workspaceRoot}"
|
22
|
-
},
|
23
|
-
{
|
24
|
-
"name": "Rails server",
|
25
|
-
"type": "Ruby",
|
26
|
-
"request": "launch",
|
27
|
-
"cwd": "${workspaceRoot}",
|
28
|
-
"program": "${workspaceRoot}/bin/rails",
|
29
|
-
"args": [
|
30
|
-
"server"
|
31
|
-
]
|
32
|
-
},
|
33
|
-
{
|
34
|
-
"name": "RSpec - all",
|
35
|
-
"type": "Ruby",
|
36
|
-
"request": "launch",
|
37
|
-
"cwd": "${workspaceRoot}",
|
38
|
-
"program": "${workspaceRoot}/bin/rspec",
|
39
|
-
"args": [
|
40
|
-
"-I",
|
41
|
-
"${workspaceRoot}"
|
42
|
-
]
|
43
|
-
},
|
44
|
-
{
|
45
|
-
"name": "RSpec - quick",
|
46
|
-
"type": "Ruby",
|
47
|
-
"request": "launch",
|
48
|
-
"cwd": "${workspaceRoot}",
|
49
|
-
"program": "${workspaceRoot}/bin/rake",
|
50
|
-
"args": [
|
51
|
-
"test"
|
52
|
-
]
|
53
|
-
},
|
54
|
-
{
|
55
|
-
"name": "RSpec - BlockChainSpec",
|
56
|
-
"type": "Ruby",
|
57
|
-
"request": "launch",
|
58
|
-
"cwd": "${workspaceRoot}",
|
59
|
-
"program": "${workspaceRoot}/bin/rspec",
|
60
|
-
"args": [
|
61
|
-
"-t",
|
62
|
-
"~slow_tests",
|
63
|
-
"spec/ciri/fixtures_tests/block_chain_spec.rb"
|
64
|
-
],
|
65
|
-
"env": {
|
66
|
-
"DEBUG": true,
|
67
|
-
"RUBY_THREAD_VM_STACK_SIZE": 52428800
|
68
|
-
}
|
69
|
-
},
|
70
|
-
{
|
71
|
-
"name": "RSpec - active spec file only",
|
72
|
-
"type": "Ruby",
|
73
|
-
"request": "launch",
|
74
|
-
"cwd": "${workspaceRoot}",
|
75
|
-
"program": "${workspaceRoot}/bin/rspec",
|
76
|
-
"args": [
|
77
|
-
"-I",
|
78
|
-
"${workspaceRoot}",
|
79
|
-
"${file}"
|
80
|
-
]
|
81
|
-
},
|
82
|
-
{
|
83
|
-
"name": "Cucumber",
|
84
|
-
"type": "Ruby",
|
85
|
-
"request": "launch",
|
86
|
-
"cwd": "${workspaceRoot}",
|
87
|
-
"program": "${workspaceRoot}/bin/cucumber"
|
88
|
-
}
|
89
|
-
]
|
90
|
-
}
|