bitcoinrb 0.3.0 → 0.6.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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +5 -3
  4. data/README.md +17 -6
  5. data/bitcoinrb.gemspec +7 -7
  6. data/exe/bitcoinrbd +5 -0
  7. data/lib/bitcoin.rb +34 -11
  8. data/lib/bitcoin/bip85_entropy.rb +111 -0
  9. data/lib/bitcoin/block_filter.rb +14 -0
  10. data/lib/bitcoin/block_header.rb +2 -0
  11. data/lib/bitcoin/chain_params.rb +9 -8
  12. data/lib/bitcoin/chainparams/regtest.yml +1 -1
  13. data/lib/bitcoin/chainparams/signet.yml +39 -0
  14. data/lib/bitcoin/chainparams/testnet.yml +1 -1
  15. data/lib/bitcoin/constants.rb +45 -12
  16. data/lib/bitcoin/descriptor.rb +1 -1
  17. data/lib/bitcoin/errors.rb +19 -0
  18. data/lib/bitcoin/ext.rb +5 -0
  19. data/lib/bitcoin/ext/ecdsa.rb +31 -0
  20. data/lib/bitcoin/ext/json_parser.rb +46 -0
  21. data/lib/bitcoin/ext_key.rb +50 -19
  22. data/lib/bitcoin/key.rb +46 -29
  23. data/lib/bitcoin/key_path.rb +12 -5
  24. data/lib/bitcoin/message.rb +7 -0
  25. data/lib/bitcoin/message/base.rb +1 -0
  26. data/lib/bitcoin/message/cf_parser.rb +16 -0
  27. data/lib/bitcoin/message/cfcheckpt.rb +36 -0
  28. data/lib/bitcoin/message/cfheaders.rb +40 -0
  29. data/lib/bitcoin/message/cfilter.rb +35 -0
  30. data/lib/bitcoin/message/fee_filter.rb +1 -1
  31. data/lib/bitcoin/message/filter_load.rb +3 -3
  32. data/lib/bitcoin/message/get_cfcheckpt.rb +29 -0
  33. data/lib/bitcoin/message/get_cfheaders.rb +24 -0
  34. data/lib/bitcoin/message/get_cfilters.rb +25 -0
  35. data/lib/bitcoin/message/header_and_short_ids.rb +1 -1
  36. data/lib/bitcoin/message/inventory.rb +1 -1
  37. data/lib/bitcoin/message/merkle_block.rb +1 -1
  38. data/lib/bitcoin/message/network_addr.rb +3 -3
  39. data/lib/bitcoin/message/ping.rb +1 -1
  40. data/lib/bitcoin/message/pong.rb +1 -1
  41. data/lib/bitcoin/message/send_cmpct.rb +2 -2
  42. data/lib/bitcoin/message/version.rb +7 -0
  43. data/lib/bitcoin/mnemonic.rb +7 -7
  44. data/lib/bitcoin/network/peer.rb +9 -4
  45. data/lib/bitcoin/network/peer_discovery.rb +1 -1
  46. data/lib/bitcoin/node/cli.rb +14 -10
  47. data/lib/bitcoin/node/configuration.rb +3 -1
  48. data/lib/bitcoin/node/spv.rb +9 -1
  49. data/lib/bitcoin/opcodes.rb +14 -1
  50. data/lib/bitcoin/out_point.rb +7 -0
  51. data/lib/bitcoin/payment_code.rb +92 -0
  52. data/lib/bitcoin/psbt/hd_key_path.rb +1 -1
  53. data/lib/bitcoin/psbt/input.rb +8 -17
  54. data/lib/bitcoin/psbt/output.rb +1 -1
  55. data/lib/bitcoin/psbt/tx.rb +11 -16
  56. data/lib/bitcoin/rpc/bitcoin_core_client.rb +22 -12
  57. data/lib/bitcoin/rpc/request_handler.rb +2 -2
  58. data/lib/bitcoin/script/script.rb +68 -28
  59. data/lib/bitcoin/script/script_error.rb +27 -1
  60. data/lib/bitcoin/script/script_interpreter.rb +164 -67
  61. data/lib/bitcoin/script/tx_checker.rb +64 -14
  62. data/lib/bitcoin/secp256k1.rb +1 -0
  63. data/lib/bitcoin/secp256k1/native.rb +138 -25
  64. data/lib/bitcoin/secp256k1/rfc6979.rb +43 -0
  65. data/lib/bitcoin/secp256k1/ruby.rb +82 -54
  66. data/lib/bitcoin/sighash_generator.rb +156 -0
  67. data/lib/bitcoin/slip39/sss.rb +5 -2
  68. data/lib/bitcoin/store.rb +2 -1
  69. data/lib/bitcoin/store/chain_entry.rb +1 -0
  70. data/lib/bitcoin/store/db/level_db.rb +2 -2
  71. data/lib/bitcoin/store/utxo_db.rb +226 -0
  72. data/lib/bitcoin/tx.rb +17 -88
  73. data/lib/bitcoin/tx_in.rb +4 -5
  74. data/lib/bitcoin/tx_out.rb +2 -3
  75. data/lib/bitcoin/util.rb +43 -6
  76. data/lib/bitcoin/version.rb +1 -1
  77. data/lib/bitcoin/wallet.rb +1 -0
  78. data/lib/bitcoin/wallet/account.rb +2 -1
  79. data/lib/bitcoin/wallet/base.rb +3 -3
  80. data/lib/bitcoin/wallet/db.rb +1 -1
  81. data/lib/bitcoin/wallet/master_key.rb +1 -0
  82. data/lib/bitcoin/wallet/utxo.rb +37 -0
  83. metadata +50 -32
@@ -37,13 +37,12 @@ module Bitcoin
37
37
  hash, index = buf.read(36).unpack('a32V')
38
38
  i.out_point = OutPoint.new(hash.bth, index)
39
39
  sig_length = Bitcoin.unpack_var_int_from_io(buf)
40
- sig = buf.read(sig_length)
41
- if i.coinbase?
42
- i.script_sig.chunks[0] = sig
40
+ if sig_length == 0
41
+ i.script_sig = Bitcoin::Script.new
43
42
  else
44
- i.script_sig = Script.parse_from_payload(sig)
43
+ i.script_sig = Script.parse_from_payload(buf.read(sig_length))
45
44
  end
46
- i.sequence = buf.read(4).unpack('V').first
45
+ i.sequence = buf.read(4).unpack1('V')
47
46
  i
48
47
  end
49
48
 
@@ -18,14 +18,13 @@ module Bitcoin
18
18
 
19
19
  def self.parse_from_payload(payload)
20
20
  buf = payload.is_a?(String) ? StringIO.new(payload) : payload
21
- value = buf.read(8).unpack('q').first
21
+ value = buf.read(8).unpack1('q')
22
22
  script_size = Bitcoin.unpack_var_int_from_io(buf)
23
23
  new(value: value, script_pubkey: Script.parse_from_payload(buf.read(script_size)))
24
24
  end
25
25
 
26
26
  def to_payload
27
- s = script_pubkey.to_payload
28
- [value].pack('Q') << Bitcoin.pack_var_int(s.length) << s
27
+ [value].pack('Q') << script_pubkey.to_payload(true)
29
28
  end
30
29
 
31
30
  def to_empty_payload
@@ -33,7 +33,7 @@ module Bitcoin
33
33
 
34
34
  # @return an integer for a valid payload, otherwise nil
35
35
  def unpack_var_int(payload)
36
- case payload.unpack('C').first
36
+ case payload.unpack1('C')
37
37
  when 0xfd
38
38
  payload.unpack('xva*')
39
39
  when 0xfe
@@ -47,14 +47,14 @@ module Bitcoin
47
47
 
48
48
  # @return an integer for a valid payload, otherwise nil
49
49
  def unpack_var_int_from_io(buf)
50
- uchar = buf.read(1)&.unpack('C')&.first
50
+ uchar = buf.read(1)&.unpack1('C')
51
51
  case uchar
52
52
  when 0xfd
53
- buf.read(2)&.unpack('v')&.first
53
+ buf.read(2)&.unpack1('v')
54
54
  when 0xfe
55
- buf.read(4)&.unpack('V')&.first
55
+ buf.read(4)&.unpack1('V')
56
56
  when 0xff
57
- buf.read(8)&.unpack('Q')&.first
57
+ buf.read(8)&.unpack1('Q')
58
58
  else
59
59
  uchar
60
60
  end
@@ -79,7 +79,16 @@ module Bitcoin
79
79
 
80
80
  # byte convert to the sequence of bits packed eight in a byte with the least significant bit first.
81
81
  def byte_to_bit(byte)
82
- byte.unpack('b*').first
82
+ byte.unpack1('b*')
83
+ end
84
+
85
+ # padding zero to the left of binary string until bytesize.
86
+ # @param [String] binary string
87
+ # @param [Integer] bytesize total bytesize.
88
+ # @return [String] padded binary string.
89
+ def padding_zero(binary, bytesize)
90
+ return binary unless binary.bytesize < bytesize
91
+ ('00' * (bytesize - binary.bytesize)).htb + binary
83
92
  end
84
93
 
85
94
  # generate sha256-ripemd160 hash for value
@@ -87,6 +96,15 @@ module Bitcoin
87
96
  Digest::RMD160.hexdigest(Digest::SHA256.digest(hex.htb))
88
97
  end
89
98
 
99
+ # Generate tagged hash value.
100
+ # @param [String] tag tag value.
101
+ # @param [String] msg the message to be hashed.
102
+ # @return [String] the hash value with binary format.
103
+ def tagged_hash(tag, msg)
104
+ tag_hash = Digest::SHA256.digest(tag)
105
+ Digest::SHA256.digest(tag_hash + tag_hash + msg)
106
+ end
107
+
90
108
  # encode Base58 check address.
91
109
  # @param [String] hex the address payload.
92
110
  # @param [String] addr_version the address version for P2PKH and P2SH.
@@ -119,6 +137,25 @@ module Bitcoin
119
137
  OpenSSL::HMAC.digest(DIGEST_NAME_SHA256, key, data)
120
138
  end
121
139
 
140
+ # check whether +addr+ is valid address.
141
+ # @param [String] addr an address
142
+ # @return [Boolean] if valid address return true, otherwise false.
143
+ def valid_address?(addr)
144
+ begin
145
+ Bitcoin::Script.parse_from_addr(addr)
146
+ true
147
+ rescue Exception
148
+ false
149
+ end
150
+ end
151
+
122
152
  end
123
153
 
154
+ module HexConverter
155
+
156
+ def to_hex
157
+ to_payload.bth
158
+ end
159
+
160
+ end
124
161
  end
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "0.3.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -4,5 +4,6 @@ module Bitcoin
4
4
  autoload :Account, 'bitcoin/wallet/account'
5
5
  autoload :DB, 'bitcoin/wallet/db'
6
6
  autoload :MasterKey, 'bitcoin/wallet/master_key'
7
+ autoload :Utxo, 'bitcoin/wallet/utxo'
7
8
  end
8
9
  end
@@ -3,6 +3,7 @@ module Bitcoin
3
3
 
4
4
  # the account in BIP-44
5
5
  class Account
6
+ include Bitcoin::HexConverter
6
7
 
7
8
  PURPOSE_TYPE = {legacy: 44, nested_witness: 49, native_segwit: 84}
8
9
 
@@ -42,7 +43,7 @@ module Bitcoin
42
43
 
43
44
  def to_payload
44
45
  payload = account_key.to_payload
45
- payload << Bitcoin.pack_var_string(name.unpack('H*').first.htb)
46
+ payload << Bitcoin.pack_var_string(name.unpack1('H*').htb)
46
47
  payload << [purpose, index, receive_depth, change_depth, lookahead].pack('I*')
47
48
  payload
48
49
  end
@@ -1,4 +1,4 @@
1
- require 'leveldb'
1
+ require 'leveldb-native'
2
2
  module Bitcoin
3
3
  module Wallet
4
4
 
@@ -20,14 +20,14 @@ module Bitcoin
20
20
  # @param [String] wallet_id new wallet id.
21
21
  # @param [String] path_prefix wallet file path prefix.
22
22
  # @return [Bitcoin::Wallet::Base] the wallet
23
- def self.create(wallet_id = 1, path_prefix = default_path_prefix)
23
+ def self.create(wallet_id = 1, path_prefix = default_path_prefix, purpose = Account::PURPOSE_TYPE[:native_segwit])
24
24
  raise ArgumentError, "wallet_id : #{wallet_id} already exist." if self.exist?(wallet_id, path_prefix)
25
25
  w = self.new(wallet_id, path_prefix)
26
26
  # generate seed
27
27
  raise RuntimeError, 'the seed already exist.' if w.db.registered_master?
28
28
  master = Bitcoin::Wallet::MasterKey.generate
29
29
  w.db.register_master_key(master)
30
- w.create_account('Default')
30
+ w.create_account(purpose, 'Default')
31
31
  w
32
32
  end
33
33
 
@@ -15,7 +15,7 @@ module Bitcoin
15
15
 
16
16
  def initialize(path = "#{Bitcoin.base_dir}/db/wallet")
17
17
  FileUtils.mkdir_p(path)
18
- @level_db = ::LevelDB::DB.new(path)
18
+ @level_db = ::LevelDBNative::DB.new(path)
19
19
  end
20
20
 
21
21
  # close database
@@ -3,6 +3,7 @@ module Bitcoin
3
3
 
4
4
  # HD Wallet master seed
5
5
  class MasterKey
6
+ include Bitcoin::HexConverter
6
7
  extend Bitcoin::Util
7
8
  include Bitcoin::Util
8
9
  include Bitcoin::KeyPath
@@ -0,0 +1,37 @@
1
+ module Bitcoin
2
+ module Wallet
3
+ class Utxo
4
+ attr_reader :tx_hash
5
+ attr_reader :index
6
+ attr_reader :block_height
7
+ attr_reader :value
8
+ attr_reader :script_pubkey
9
+
10
+ def initialize(tx_hash, index, value, script_pubkey, block_height = nil)
11
+ @tx_hash = tx_hash
12
+ @index = index
13
+ @block_height = block_height
14
+ @value = value
15
+ @script_pubkey = script_pubkey
16
+ end
17
+
18
+ def self.parse_from_payload(payload)
19
+ return nil if payload.nil?
20
+
21
+ tx_hash, index, block_height, value, payload = payload.unpack('H64VVQa*')
22
+
23
+ buf = StringIO.new(payload)
24
+ script_size = Bitcoin.unpack_var_int_from_io(buf)
25
+ script_pubkey = Bitcoin::Script.parse_from_payload(buf.read(script_size));
26
+ new(tx_hash, index, value, script_pubkey, block_height == 0 ? nil : block_height )
27
+ end
28
+
29
+ def to_payload
30
+ payload = [tx_hash, index, block_height.nil? ? 0 : block_height, value].pack('H64VVQ')
31
+ s = script_pubkey.to_payload
32
+ payload << Bitcoin.pack_var_int(s.length) << s
33
+ payload
34
+ end
35
+ end
36
+ end
37
+ 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.3.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-30 00:00:00.000000000 Z
11
+ date: 2021-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa
@@ -136,20 +136,6 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: rest-client
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :runtime
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: iniparse
155
141
  requirement: !ruby/object:Gem::Requirement
@@ -193,35 +179,35 @@ dependencies:
193
179
  - !ruby/object:Gem::Version
194
180
  version: 3.8.5
195
181
  - !ruby/object:Gem::Dependency
196
- name: scrypt
182
+ name: json_pure
197
183
  requirement: !ruby/object:Gem::Requirement
198
184
  requirements:
199
185
  - - ">="
200
186
  - !ruby/object:Gem::Version
201
- version: '0'
187
+ version: 2.3.1
202
188
  type: :runtime
203
189
  prerelease: false
204
190
  version_requirements: !ruby/object:Gem::Requirement
205
191
  requirements:
206
192
  - - ">="
207
193
  - !ruby/object:Gem::Version
208
- version: '0'
194
+ version: 2.3.1
209
195
  - !ruby/object:Gem::Dependency
210
- name: activesupport
196
+ name: bip-schnorr
211
197
  requirement: !ruby/object:Gem::Requirement
212
198
  requirements:
213
- - - "~>"
199
+ - - ">="
214
200
  - !ruby/object:Gem::Version
215
- version: 5.2.3
201
+ version: 0.3.2
216
202
  type: :runtime
217
203
  prerelease: false
218
204
  version_requirements: !ruby/object:Gem::Requirement
219
205
  requirements:
220
- - - "~>"
206
+ - - ">="
221
207
  - !ruby/object:Gem::Version
222
- version: 5.2.3
208
+ version: 0.3.2
223
209
  - !ruby/object:Gem::Dependency
224
- name: leveldb-ruby
210
+ name: leveldb-native
225
211
  requirement: !ruby/object:Gem::Requirement
226
212
  requirements:
227
213
  - - ">="
@@ -252,16 +238,16 @@ dependencies:
252
238
  name: rake
253
239
  requirement: !ruby/object:Gem::Requirement
254
240
  requirements:
255
- - - "~>"
241
+ - - ">="
256
242
  - !ruby/object:Gem::Version
257
- version: '10.0'
243
+ version: 12.3.3
258
244
  type: :development
259
245
  prerelease: false
260
246
  version_requirements: !ruby/object:Gem::Requirement
261
247
  requirements:
262
- - - "~>"
248
+ - - ">="
263
249
  - !ruby/object:Gem::Version
264
- version: '10.0'
250
+ version: 12.3.3
265
251
  - !ruby/object:Gem::Dependency
266
252
  name: rspec
267
253
  requirement: !ruby/object:Gem::Requirement
@@ -290,7 +276,21 @@ dependencies:
290
276
  - - ">="
291
277
  - !ruby/object:Gem::Version
292
278
  version: '0'
293
- description: "[WIP]The implementation of Bitcoin Protocol for Ruby."
279
+ - !ruby/object:Gem::Dependency
280
+ name: webmock
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: 3.11.1
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: 3.11.1
293
+ description: The implementation of Bitcoin Protocol for Ruby.
294
294
  email:
295
295
  - azuchi@chaintope.com
296
296
  executables:
@@ -317,6 +317,7 @@ files:
317
317
  - exe/bitcoinrbd
318
318
  - lib/bitcoin.rb
319
319
  - lib/bitcoin/base58.rb
320
+ - lib/bitcoin/bip85_entropy.rb
320
321
  - lib/bitcoin/bit_stream.rb
321
322
  - lib/bitcoin/block.rb
322
323
  - lib/bitcoin/block_filter.rb
@@ -325,9 +326,14 @@ files:
325
326
  - lib/bitcoin/chain_params.rb
326
327
  - lib/bitcoin/chainparams/mainnet.yml
327
328
  - lib/bitcoin/chainparams/regtest.yml
329
+ - lib/bitcoin/chainparams/signet.yml
328
330
  - lib/bitcoin/chainparams/testnet.yml
329
331
  - lib/bitcoin/constants.rb
330
332
  - lib/bitcoin/descriptor.rb
333
+ - lib/bitcoin/errors.rb
334
+ - lib/bitcoin/ext.rb
335
+ - lib/bitcoin/ext/ecdsa.rb
336
+ - lib/bitcoin/ext/json_parser.rb
331
337
  - lib/bitcoin/ext_key.rb
332
338
  - lib/bitcoin/gcs_filter.rb
333
339
  - lib/bitcoin/key.rb
@@ -341,6 +347,10 @@ files:
341
347
  - lib/bitcoin/message/block_transaction_request.rb
342
348
  - lib/bitcoin/message/block_transactions.rb
343
349
  - lib/bitcoin/message/block_txn.rb
350
+ - lib/bitcoin/message/cf_parser.rb
351
+ - lib/bitcoin/message/cfcheckpt.rb
352
+ - lib/bitcoin/message/cfheaders.rb
353
+ - lib/bitcoin/message/cfilter.rb
344
354
  - lib/bitcoin/message/cmpct_block.rb
345
355
  - lib/bitcoin/message/error.rb
346
356
  - lib/bitcoin/message/fee_filter.rb
@@ -350,6 +360,9 @@ files:
350
360
  - lib/bitcoin/message/get_addr.rb
351
361
  - lib/bitcoin/message/get_block_txn.rb
352
362
  - lib/bitcoin/message/get_blocks.rb
363
+ - lib/bitcoin/message/get_cfcheckpt.rb
364
+ - lib/bitcoin/message/get_cfheaders.rb
365
+ - lib/bitcoin/message/get_cfilters.rb
353
366
  - lib/bitcoin/message/get_data.rb
354
367
  - lib/bitcoin/message/get_headers.rb
355
368
  - lib/bitcoin/message/header_and_short_ids.rb
@@ -391,6 +404,7 @@ files:
391
404
  - lib/bitcoin/node/spv.rb
392
405
  - lib/bitcoin/opcodes.rb
393
406
  - lib/bitcoin/out_point.rb
407
+ - lib/bitcoin/payment_code.rb
394
408
  - lib/bitcoin/payments.rb
395
409
  - lib/bitcoin/payments/output.pb.rb
396
410
  - lib/bitcoin/payments/payment.pb.rb
@@ -416,7 +430,9 @@ files:
416
430
  - lib/bitcoin/script_witness.rb
417
431
  - lib/bitcoin/secp256k1.rb
418
432
  - lib/bitcoin/secp256k1/native.rb
433
+ - lib/bitcoin/secp256k1/rfc6979.rb
419
434
  - lib/bitcoin/secp256k1/ruby.rb
435
+ - lib/bitcoin/sighash_generator.rb
420
436
  - lib/bitcoin/slip39.rb
421
437
  - lib/bitcoin/slip39/share.rb
422
438
  - lib/bitcoin/slip39/sss.rb
@@ -426,6 +442,7 @@ files:
426
442
  - lib/bitcoin/store/db.rb
427
443
  - lib/bitcoin/store/db/level_db.rb
428
444
  - lib/bitcoin/store/spv_chain.rb
445
+ - lib/bitcoin/store/utxo_db.rb
429
446
  - lib/bitcoin/tx.rb
430
447
  - lib/bitcoin/tx_in.rb
431
448
  - lib/bitcoin/tx_out.rb
@@ -437,6 +454,7 @@ files:
437
454
  - lib/bitcoin/wallet/base.rb
438
455
  - lib/bitcoin/wallet/db.rb
439
456
  - lib/bitcoin/wallet/master_key.rb
457
+ - lib/bitcoin/wallet/utxo.rb
440
458
  - lib/openassets.rb
441
459
  - lib/openassets/marker_output.rb
442
460
  - lib/openassets/payload.rb
@@ -460,8 +478,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
460
478
  - !ruby/object:Gem::Version
461
479
  version: '0'
462
480
  requirements: []
463
- rubygems_version: 3.0.3
481
+ rubygems_version: 3.2.3
464
482
  signing_key:
465
483
  specification_version: 4
466
- summary: "[WIP]The implementation of Bitcoin Protocol for Ruby."
484
+ summary: The implementation of Bitcoin Protocol for Ruby.
467
485
  test_files: []