bitcoinrb 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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