ciri-p2p 0.1.0 → 0.2.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/.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
|
-
}
|