bitcoinrb 0.1.1 → 0.1.2
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/.gitignore +1 -0
- data/bitcoinrb.gemspec +7 -3
- data/exe/bitcoinrb-cli +1 -1
- data/exe/bitcoinrbd +9 -23
- data/lib/bitcoin/block.rb +66 -0
- data/lib/bitcoin/block_header.rb +33 -1
- data/lib/bitcoin/chain_params.rb +11 -4
- data/lib/bitcoin/chainparams/mainnet.yml +9 -2
- data/lib/bitcoin/chainparams/regtest.yml +9 -1
- data/lib/bitcoin/chainparams/testnet.yml +9 -1
- data/lib/bitcoin/constants.rb +13 -0
- data/lib/bitcoin/ext_key.rb +2 -1
- data/lib/bitcoin/merkle_tree.rb +50 -51
- data/lib/bitcoin/message/block.rb +5 -0
- data/lib/bitcoin/message.rb +5 -5
- data/lib/bitcoin/network/connection.rb +58 -0
- data/lib/bitcoin/network/message_handler.rb +192 -0
- data/lib/bitcoin/network/peer.rb +55 -0
- data/lib/bitcoin/network/peer_discovery.rb +34 -0
- data/lib/bitcoin/network/pool.rb +74 -0
- data/lib/bitcoin/network.rb +14 -0
- data/lib/bitcoin/node/spv.rb +39 -0
- data/lib/bitcoin/node/spv_block_chain.rb +15 -0
- data/lib/bitcoin/node.rb +6 -0
- data/lib/bitcoin/script/script.rb +13 -0
- data/lib/bitcoin/store/spv_block_store.rb +11 -0
- data/lib/bitcoin/store.rb +7 -0
- data/lib/bitcoin/tx.rb +11 -0
- data/lib/bitcoin/tx_out.rb +2 -0
- data/lib/bitcoin/validation.rb +33 -11
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin.rb +5 -2
- data/lib/openassets/marker_output.rb +14 -0
- data/lib/openassets/payload.rb +45 -0
- data/lib/openassets.rb +8 -0
- metadata +59 -8
- data/lib/bitcoin/connection.rb +0 -68
- data/lib/bitcoin/message/handler.rb +0 -183
- data/lib/bitcoin/nodes/spv/cli.rb +0 -12
- data/lib/bitcoin/nodes/spv/daemon.rb +0 -21
- data/lib/bitcoin/nodes/spv.rb +0 -13
- data/lib/bitcoin/nodes.rb +0 -5
@@ -0,0 +1,45 @@
|
|
1
|
+
module OpenAssets
|
2
|
+
|
3
|
+
MARKER = "\x4f\x41"
|
4
|
+
VERSION = "\x01\x00"
|
5
|
+
|
6
|
+
# the open assets payload
|
7
|
+
class Payload
|
8
|
+
|
9
|
+
attr_accessor :quantities
|
10
|
+
attr_accessor :metadata
|
11
|
+
|
12
|
+
def initialize(quantities = [], metadata = '')
|
13
|
+
@quantities = quantities
|
14
|
+
@metadata = metadata
|
15
|
+
end
|
16
|
+
|
17
|
+
# parse open assets payload
|
18
|
+
# @return [Payload] a open assets payload object, if payload is invalid, return nil.
|
19
|
+
def self.parse_from_payload(payload)
|
20
|
+
buf = StringIO.new(payload)
|
21
|
+
marker = buf.read(2)
|
22
|
+
version = buf.read(2)
|
23
|
+
return nil if marker != MARKER || version != VERSION
|
24
|
+
count = Bitcoin.unpack_var_int_from_io(buf)
|
25
|
+
quantities = []
|
26
|
+
count.times do
|
27
|
+
quantities << LEB128.decode_unsigned(buf, buf.pos)
|
28
|
+
end
|
29
|
+
metadata_length = Bitcoin.unpack_var_int_from_io(buf)
|
30
|
+
return nil if buf.length < metadata_length + buf.pos
|
31
|
+
metadata = buf.read(metadata_length).each_byte.map(&:chr).join
|
32
|
+
new(quantities, metadata)
|
33
|
+
end
|
34
|
+
|
35
|
+
# generate binary payload
|
36
|
+
def to_payload
|
37
|
+
payload = MARKER << VERSION
|
38
|
+
payload << Bitcoin.pack_var_int(quantities.size) << quantities.map{|q| LEB128.encode_unsigned(q).read }.join
|
39
|
+
payload << Bitcoin.pack_var_int(metadata.length) << metadata.bytes.map{|b|b.to_s(16)}.join.htb
|
40
|
+
payload
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/openassets.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitcoinrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ecdsa
|
@@ -108,6 +108,34 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: parallel
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: leb128
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.0.0
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.0.0
|
111
139
|
- !ruby/object:Gem::Dependency
|
112
140
|
name: bundler
|
113
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +178,20 @@ dependencies:
|
|
150
178
|
- - "~>"
|
151
179
|
- !ruby/object:Gem::Version
|
152
180
|
version: '3.0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: timecop
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
153
195
|
description: "[WIP]The implementation of Bitcoin Protocol for Ruby."
|
154
196
|
email:
|
155
197
|
- azuchi@haw.co.jp
|
@@ -176,12 +218,12 @@ files:
|
|
176
218
|
- exe/bitcoinrbd
|
177
219
|
- lib/bitcoin.rb
|
178
220
|
- lib/bitcoin/base58.rb
|
221
|
+
- lib/bitcoin/block.rb
|
179
222
|
- lib/bitcoin/block_header.rb
|
180
223
|
- lib/bitcoin/chain_params.rb
|
181
224
|
- lib/bitcoin/chainparams/mainnet.yml
|
182
225
|
- lib/bitcoin/chainparams/regtest.yml
|
183
226
|
- lib/bitcoin/chainparams/testnet.yml
|
184
|
-
- lib/bitcoin/connection.rb
|
185
227
|
- lib/bitcoin/constants.rb
|
186
228
|
- lib/bitcoin/ext_key.rb
|
187
229
|
- lib/bitcoin/key.rb
|
@@ -200,7 +242,6 @@ files:
|
|
200
242
|
- lib/bitcoin/message/get_blocks.rb
|
201
243
|
- lib/bitcoin/message/get_data.rb
|
202
244
|
- lib/bitcoin/message/get_headers.rb
|
203
|
-
- lib/bitcoin/message/handler.rb
|
204
245
|
- lib/bitcoin/message/headers.rb
|
205
246
|
- lib/bitcoin/message/headers_parser.rb
|
206
247
|
- lib/bitcoin/message/inv.rb
|
@@ -225,10 +266,15 @@ files:
|
|
225
266
|
- lib/bitcoin/mnemonic/wordlist/italian.txt
|
226
267
|
- lib/bitcoin/mnemonic/wordlist/japanese.txt
|
227
268
|
- lib/bitcoin/mnemonic/wordlist/spanish.txt
|
228
|
-
- lib/bitcoin/
|
229
|
-
- lib/bitcoin/
|
230
|
-
- lib/bitcoin/
|
231
|
-
- lib/bitcoin/
|
269
|
+
- lib/bitcoin/network.rb
|
270
|
+
- lib/bitcoin/network/connection.rb
|
271
|
+
- lib/bitcoin/network/message_handler.rb
|
272
|
+
- lib/bitcoin/network/peer.rb
|
273
|
+
- lib/bitcoin/network/peer_discovery.rb
|
274
|
+
- lib/bitcoin/network/pool.rb
|
275
|
+
- lib/bitcoin/node.rb
|
276
|
+
- lib/bitcoin/node/spv.rb
|
277
|
+
- lib/bitcoin/node/spv_block_chain.rb
|
232
278
|
- lib/bitcoin/opcodes.rb
|
233
279
|
- lib/bitcoin/out_point.rb
|
234
280
|
- lib/bitcoin/script/script.rb
|
@@ -239,12 +285,17 @@ files:
|
|
239
285
|
- lib/bitcoin/secp256k1.rb
|
240
286
|
- lib/bitcoin/secp256k1/native.rb
|
241
287
|
- lib/bitcoin/secp256k1/ruby.rb
|
288
|
+
- lib/bitcoin/store.rb
|
289
|
+
- lib/bitcoin/store/spv_block_store.rb
|
242
290
|
- lib/bitcoin/tx.rb
|
243
291
|
- lib/bitcoin/tx_in.rb
|
244
292
|
- lib/bitcoin/tx_out.rb
|
245
293
|
- lib/bitcoin/util.rb
|
246
294
|
- lib/bitcoin/validation.rb
|
247
295
|
- lib/bitcoin/version.rb
|
296
|
+
- lib/openassets.rb
|
297
|
+
- lib/openassets/marker_output.rb
|
298
|
+
- lib/openassets/payload.rb
|
248
299
|
homepage: https://github.com/haw-itn/bitcoinrb
|
249
300
|
licenses:
|
250
301
|
- MIT
|
data/lib/bitcoin/connection.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
module Bitcoin
|
2
|
-
|
3
|
-
# Basic Bitcoin P2P connection class
|
4
|
-
class Connection < EM::Connection
|
5
|
-
|
6
|
-
attr_reader :host, :port, :handler, :logger
|
7
|
-
attr_accessor :connected
|
8
|
-
|
9
|
-
# if true, this peer send new block announcements using a headers message rather than an inv message.
|
10
|
-
attr_accessor :sendheaders
|
11
|
-
|
12
|
-
# minimum fee(in satoshis per kilobyte) for relay tx
|
13
|
-
attr_accessor :fee_rate
|
14
|
-
|
15
|
-
def initialize(host, port)
|
16
|
-
@host = host
|
17
|
-
@port = port
|
18
|
-
@logger = Bitcoin::Logger.create(:connection)
|
19
|
-
@handler = Message::Handler.new(self, @logger)
|
20
|
-
@connected = false
|
21
|
-
@sendheaders = false
|
22
|
-
@attr_accessor = 0
|
23
|
-
end
|
24
|
-
|
25
|
-
def post_init
|
26
|
-
logger.info "connected. #{remote_node}"
|
27
|
-
begin_handshake
|
28
|
-
end
|
29
|
-
|
30
|
-
# handle receiving data from remote node.
|
31
|
-
def receive_data(data)
|
32
|
-
logger.info "receive data from #{remote_node}"
|
33
|
-
handler.handle(data)
|
34
|
-
end
|
35
|
-
|
36
|
-
# close network connection.
|
37
|
-
def close(msg = '')
|
38
|
-
logger.info "close connection with #{remote_node}. #{msg}"
|
39
|
-
close_connection_after_writing
|
40
|
-
EM.stop
|
41
|
-
end
|
42
|
-
|
43
|
-
def handshake_done
|
44
|
-
logger.info 'handshake finished.'
|
45
|
-
@connected = true
|
46
|
-
end
|
47
|
-
|
48
|
-
def send_message(msg)
|
49
|
-
logger.info "send message #{msg.class::COMMAND}"
|
50
|
-
send_data(msg.to_pkt)
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def remote_node
|
56
|
-
"#{host}:#{port}"
|
57
|
-
end
|
58
|
-
|
59
|
-
# start handshake
|
60
|
-
def begin_handshake
|
61
|
-
logger.info "begin handshake with #{remote_node}"
|
62
|
-
ver = Bitcoin::Message::Version.new(remote_addr: remote_node, start_height: 0) # TODO use start_height in wallet
|
63
|
-
send_message(ver)
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
@@ -1,183 +0,0 @@
|
|
1
|
-
module Bitcoin
|
2
|
-
module Message
|
3
|
-
|
4
|
-
# Default P2P message handler.
|
5
|
-
class Handler
|
6
|
-
|
7
|
-
attr_reader :logger
|
8
|
-
attr_reader :conn
|
9
|
-
|
10
|
-
def initialize(conn, logger = Bitcoin::Logger.create(:parser))
|
11
|
-
@conn = conn
|
12
|
-
@logger = logger
|
13
|
-
@message = ""
|
14
|
-
end
|
15
|
-
|
16
|
-
# handle p2p message.
|
17
|
-
def handle(message)
|
18
|
-
logger.info "handle message #{message.bth}"
|
19
|
-
begin
|
20
|
-
parse(message)
|
21
|
-
rescue Error => e
|
22
|
-
logger.error("invalid header magic. #{e.message}")
|
23
|
-
conn.close
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def parse(message)
|
30
|
-
@message += message
|
31
|
-
command, payload, rest = parse_header
|
32
|
-
return unless command
|
33
|
-
|
34
|
-
handle_command(command, payload)
|
35
|
-
@message = ""
|
36
|
-
parse(rest) if rest && rest.bytesize > 0
|
37
|
-
end
|
38
|
-
|
39
|
-
def parse_header
|
40
|
-
head_magic = Bitcoin.chain_params.magic_head
|
41
|
-
return if @message.nil? || @message.size < HEADER_SIZE
|
42
|
-
|
43
|
-
magic, command, length, checksum = @message.unpack('a4A12Va4')
|
44
|
-
raise Error, "invalid header magic. #{magic.bth}" unless magic.bth == head_magic
|
45
|
-
|
46
|
-
payload = @message[HEADER_SIZE...(HEADER_SIZE + length)]
|
47
|
-
return if payload.size < length
|
48
|
-
raise Error, "header checksum mismatch. #{checksum.bth}" unless Bitcoin.double_sha256(payload)[0...4] == checksum
|
49
|
-
|
50
|
-
rest = @message[(HEADER_SIZE + length)..-1]
|
51
|
-
[command, payload, rest]
|
52
|
-
end
|
53
|
-
|
54
|
-
def handle_command(command, payload)
|
55
|
-
logger.info("process command #{command}. payload = #{payload.bth}")
|
56
|
-
case command
|
57
|
-
when Version::COMMAND
|
58
|
-
on_version(Version.parse_from_payload(payload))
|
59
|
-
when VerAck::COMMAND
|
60
|
-
on_ver_ack
|
61
|
-
when GetAddr::COMMAND
|
62
|
-
on_get_addr
|
63
|
-
when Addr::COMMAND
|
64
|
-
on_addr(Addr.parse_from_payload(payload))
|
65
|
-
when SendHeaders::COMMAND
|
66
|
-
on_send_headers
|
67
|
-
when FeeFilter::COMMAND
|
68
|
-
on_fee_filter(FeeFilter.parse_from_payload(payload))
|
69
|
-
when Ping::COMMAND
|
70
|
-
on_ping(Ping.parse_from_payload(payload))
|
71
|
-
when Pong::COMMAND
|
72
|
-
on_pong(Pong.parse_from_payload(payload))
|
73
|
-
when GetHeaders::COMMAND
|
74
|
-
on_get_headers(GetHeaders.parse_from_payload(payload))
|
75
|
-
when Headers::COMMAND
|
76
|
-
on_headers(Headers.parse_from_payload(payload))
|
77
|
-
when Block::COMMAND
|
78
|
-
on_block(Block.parse_from_payload(payload))
|
79
|
-
when Tx::COMMAND
|
80
|
-
on_tx(Tx.parse_from_payload(payload))
|
81
|
-
when NotFound::COMMAND
|
82
|
-
on_not_found(NotFound.parse_from_payload(payload))
|
83
|
-
when MemPool::COMMAND
|
84
|
-
on_mem_pool
|
85
|
-
when Reject::COMMAND
|
86
|
-
on_reject(Reject.parse_from_payload(payload))
|
87
|
-
when SendCmpct::COMMAND
|
88
|
-
on_send_cmpct(SendCmpct.parse_from_payload(payload))
|
89
|
-
when Inv::COMMAND
|
90
|
-
on_inv(Inv.parse_from_payload(payload))
|
91
|
-
else
|
92
|
-
logger.warn("unsupported command received. #{command}")
|
93
|
-
conn.close("with command #{command}")
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def on_version(version)
|
98
|
-
logger.info("receive version message. #{version.build_json}")
|
99
|
-
conn.send_message(VerAck.new)
|
100
|
-
end
|
101
|
-
|
102
|
-
def on_ver_ack
|
103
|
-
logger.info('receive verack message.')
|
104
|
-
conn.handshake_done
|
105
|
-
end
|
106
|
-
|
107
|
-
def on_get_addr
|
108
|
-
logger.info('receive getaddr message.')
|
109
|
-
end
|
110
|
-
|
111
|
-
def on_addr(addr)
|
112
|
-
logger.info("receive addr message. #{addr.build_json}")
|
113
|
-
# TODO
|
114
|
-
end
|
115
|
-
|
116
|
-
def on_send_headers
|
117
|
-
logger.info('receive sendheaders message.')
|
118
|
-
conn.sendheaders = true
|
119
|
-
end
|
120
|
-
|
121
|
-
def on_fee_filter(fee_filter)
|
122
|
-
logger.info("receive feefilter message. #{fee_filter.build_json}")
|
123
|
-
conn.fee_rate = fee_filter.fee_rate
|
124
|
-
end
|
125
|
-
|
126
|
-
def on_ping(ping)
|
127
|
-
logger.info("receive ping message. #{ping.build_json}")
|
128
|
-
conn.send_message(ping.to_response)
|
129
|
-
end
|
130
|
-
|
131
|
-
def on_pong(pong)
|
132
|
-
logger.info("receive pong message. #{pong.build_json}")
|
133
|
-
# TODO calculate response
|
134
|
-
end
|
135
|
-
|
136
|
-
def on_get_headers(headers)
|
137
|
-
logger.info("receive getheaders message. #{headers.build_json}")
|
138
|
-
# TODO
|
139
|
-
end
|
140
|
-
|
141
|
-
def on_headers(headers)
|
142
|
-
logger.info("receive headers message. #{headers.build_json}")
|
143
|
-
# TODO
|
144
|
-
end
|
145
|
-
|
146
|
-
def on_block(block)
|
147
|
-
logger.info("receive block message. #{block.build_json}")
|
148
|
-
# TODO
|
149
|
-
end
|
150
|
-
|
151
|
-
def on_tx(tx)
|
152
|
-
logger.info("receive tx message. #{tx.build_json}")
|
153
|
-
# TODO
|
154
|
-
end
|
155
|
-
|
156
|
-
def on_not_found(not_found)
|
157
|
-
logger.info("receive notfound message. #{not_found.build_json}")
|
158
|
-
# TODO
|
159
|
-
end
|
160
|
-
|
161
|
-
def on_mem_pool
|
162
|
-
logger.info('receive mempool message.')
|
163
|
-
# TODO return mempool tx
|
164
|
-
end
|
165
|
-
|
166
|
-
def on_reject(reject)
|
167
|
-
logger.warn("receive reject message. #{reject.build_json}")
|
168
|
-
# TODO
|
169
|
-
end
|
170
|
-
|
171
|
-
def on_send_cmpct(cmpct)
|
172
|
-
logger.info("receive sendcmpct message. #{cmpct.build_json}")
|
173
|
-
# TODO if mode is high and version is 1, relay block with cmpctblock message
|
174
|
-
end
|
175
|
-
|
176
|
-
def on_inv(inv)
|
177
|
-
logger.info("receive inv message. #{inv.build_json}")
|
178
|
-
# TODO
|
179
|
-
end
|
180
|
-
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
data/lib/bitcoin/nodes/spv.rb
DELETED