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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/bitcoinrb.gemspec +7 -3
  4. data/exe/bitcoinrb-cli +1 -1
  5. data/exe/bitcoinrbd +9 -23
  6. data/lib/bitcoin/block.rb +66 -0
  7. data/lib/bitcoin/block_header.rb +33 -1
  8. data/lib/bitcoin/chain_params.rb +11 -4
  9. data/lib/bitcoin/chainparams/mainnet.yml +9 -2
  10. data/lib/bitcoin/chainparams/regtest.yml +9 -1
  11. data/lib/bitcoin/chainparams/testnet.yml +9 -1
  12. data/lib/bitcoin/constants.rb +13 -0
  13. data/lib/bitcoin/ext_key.rb +2 -1
  14. data/lib/bitcoin/merkle_tree.rb +50 -51
  15. data/lib/bitcoin/message/block.rb +5 -0
  16. data/lib/bitcoin/message.rb +5 -5
  17. data/lib/bitcoin/network/connection.rb +58 -0
  18. data/lib/bitcoin/network/message_handler.rb +192 -0
  19. data/lib/bitcoin/network/peer.rb +55 -0
  20. data/lib/bitcoin/network/peer_discovery.rb +34 -0
  21. data/lib/bitcoin/network/pool.rb +74 -0
  22. data/lib/bitcoin/network.rb +14 -0
  23. data/lib/bitcoin/node/spv.rb +39 -0
  24. data/lib/bitcoin/node/spv_block_chain.rb +15 -0
  25. data/lib/bitcoin/node.rb +6 -0
  26. data/lib/bitcoin/script/script.rb +13 -0
  27. data/lib/bitcoin/store/spv_block_store.rb +11 -0
  28. data/lib/bitcoin/store.rb +7 -0
  29. data/lib/bitcoin/tx.rb +11 -0
  30. data/lib/bitcoin/tx_out.rb +2 -0
  31. data/lib/bitcoin/validation.rb +33 -11
  32. data/lib/bitcoin/version.rb +1 -1
  33. data/lib/bitcoin.rb +5 -2
  34. data/lib/openassets/marker_output.rb +14 -0
  35. data/lib/openassets/payload.rb +45 -0
  36. data/lib/openassets.rb +8 -0
  37. metadata +59 -8
  38. data/lib/bitcoin/connection.rb +0 -68
  39. data/lib/bitcoin/message/handler.rb +0 -183
  40. data/lib/bitcoin/nodes/spv/cli.rb +0 -12
  41. data/lib/bitcoin/nodes/spv/daemon.rb +0 -21
  42. data/lib/bitcoin/nodes/spv.rb +0 -13
  43. 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
@@ -0,0 +1,8 @@
1
+ require 'leb128'
2
+
3
+ module OpenAssets
4
+
5
+ autoload :MarkerOutput, 'openassets/marker_output'
6
+ autoload :Payload, 'openassets/payload'
7
+
8
+ end
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.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-09-08 00:00:00.000000000 Z
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/nodes.rb
229
- - lib/bitcoin/nodes/spv.rb
230
- - lib/bitcoin/nodes/spv/cli.rb
231
- - lib/bitcoin/nodes/spv/daemon.rb
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
@@ -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
@@ -1,12 +0,0 @@
1
- require 'thor'
2
-
3
- module Bitcoin
4
- module Nodes
5
- module SPV
6
-
7
- class CLI < Thor
8
-
9
- end
10
- end
11
- end
12
- end
@@ -1,21 +0,0 @@
1
- require 'daemon_spawn'
2
- module Bitcoin
3
- module Nodes
4
- module SPV
5
-
6
- # SPV node daemon
7
- class Daemon < DaemonSpawn::Base
8
-
9
- def start(args)
10
-
11
- end
12
-
13
- def stop
14
-
15
- end
16
-
17
- end
18
-
19
- end
20
- end
21
- end
@@ -1,13 +0,0 @@
1
- module Bitcoin
2
- module Nodes
3
-
4
- # SPV module
5
- module SPV
6
-
7
- autoload :CLI, 'bitcoin/nodes/spv/cli'
8
- autoload :Daemon, 'bitcoin/nodes/spv/daemon'
9
-
10
- end
11
-
12
- end
13
- end
data/lib/bitcoin/nodes.rb DELETED
@@ -1,5 +0,0 @@
1
- module Bitcoin
2
- module Nodes
3
- autoload :SPV, 'bitcoin/nodes/spv'
4
- end
5
- end