bitcoinrb 0.3.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +37 -0
  3. data/.rspec_parallel +2 -0
  4. data/.ruby-version +1 -1
  5. data/README.md +17 -6
  6. data/bitcoinrb.gemspec +9 -8
  7. data/exe/bitcoinrbd +5 -0
  8. data/lib/bitcoin.rb +37 -19
  9. data/lib/bitcoin/bip85_entropy.rb +111 -0
  10. data/lib/bitcoin/block_filter.rb +14 -0
  11. data/lib/bitcoin/block_header.rb +2 -0
  12. data/lib/bitcoin/chain_params.rb +9 -8
  13. data/lib/bitcoin/chainparams/regtest.yml +1 -1
  14. data/lib/bitcoin/chainparams/signet.yml +39 -0
  15. data/lib/bitcoin/chainparams/testnet.yml +1 -1
  16. data/lib/bitcoin/constants.rb +44 -10
  17. data/lib/bitcoin/descriptor.rb +1 -1
  18. data/lib/bitcoin/errors.rb +19 -0
  19. data/lib/bitcoin/ext.rb +6 -0
  20. data/lib/bitcoin/ext/array_ext.rb +22 -0
  21. data/lib/bitcoin/ext/ecdsa.rb +36 -0
  22. data/lib/bitcoin/ext/json_parser.rb +46 -0
  23. data/lib/bitcoin/ext_key.rb +51 -20
  24. data/lib/bitcoin/key.rb +89 -30
  25. data/lib/bitcoin/key_path.rb +12 -5
  26. data/lib/bitcoin/message.rb +79 -0
  27. data/lib/bitcoin/message/addr_v2.rb +34 -0
  28. data/lib/bitcoin/message/base.rb +17 -0
  29. data/lib/bitcoin/message/cf_parser.rb +16 -0
  30. data/lib/bitcoin/message/cfcheckpt.rb +36 -0
  31. data/lib/bitcoin/message/cfheaders.rb +40 -0
  32. data/lib/bitcoin/message/cfilter.rb +35 -0
  33. data/lib/bitcoin/message/fee_filter.rb +1 -1
  34. data/lib/bitcoin/message/filter_load.rb +3 -3
  35. data/lib/bitcoin/message/get_cfcheckpt.rb +29 -0
  36. data/lib/bitcoin/message/get_cfheaders.rb +24 -0
  37. data/lib/bitcoin/message/get_cfilters.rb +25 -0
  38. data/lib/bitcoin/message/header_and_short_ids.rb +1 -1
  39. data/lib/bitcoin/message/inventory.rb +1 -1
  40. data/lib/bitcoin/message/merkle_block.rb +1 -1
  41. data/lib/bitcoin/message/network_addr.rb +141 -18
  42. data/lib/bitcoin/message/ping.rb +1 -1
  43. data/lib/bitcoin/message/pong.rb +1 -1
  44. data/lib/bitcoin/message/send_addr_v2.rb +13 -0
  45. data/lib/bitcoin/message/send_cmpct.rb +2 -2
  46. data/lib/bitcoin/message/tx.rb +1 -1
  47. data/lib/bitcoin/message/version.rb +7 -0
  48. data/lib/bitcoin/message_sign.rb +47 -0
  49. data/lib/bitcoin/mnemonic.rb +7 -7
  50. data/lib/bitcoin/network/peer.rb +9 -4
  51. data/lib/bitcoin/network/peer_discovery.rb +1 -1
  52. data/lib/bitcoin/node/cli.rb +14 -10
  53. data/lib/bitcoin/node/configuration.rb +3 -1
  54. data/lib/bitcoin/node/spv.rb +9 -1
  55. data/lib/bitcoin/opcodes.rb +14 -1
  56. data/lib/bitcoin/out_point.rb +2 -0
  57. data/lib/bitcoin/payment_code.rb +92 -0
  58. data/lib/bitcoin/payments/payment.pb.rb +1 -1
  59. data/lib/bitcoin/psbt/hd_key_path.rb +1 -1
  60. data/lib/bitcoin/psbt/input.rb +9 -18
  61. data/lib/bitcoin/psbt/output.rb +1 -1
  62. data/lib/bitcoin/psbt/tx.rb +12 -17
  63. data/lib/bitcoin/rpc/bitcoin_core_client.rb +22 -12
  64. data/lib/bitcoin/rpc/request_handler.rb +5 -5
  65. data/lib/bitcoin/script/script.rb +96 -39
  66. data/lib/bitcoin/script/script_error.rb +27 -1
  67. data/lib/bitcoin/script/script_interpreter.rb +166 -66
  68. data/lib/bitcoin/script/tx_checker.rb +62 -14
  69. data/lib/bitcoin/secp256k1.rb +1 -0
  70. data/lib/bitcoin/secp256k1/native.rb +184 -17
  71. data/lib/bitcoin/secp256k1/rfc6979.rb +43 -0
  72. data/lib/bitcoin/secp256k1/ruby.rb +112 -56
  73. data/lib/bitcoin/sighash_generator.rb +156 -0
  74. data/lib/bitcoin/store.rb +1 -0
  75. data/lib/bitcoin/store/chain_entry.rb +1 -0
  76. data/lib/bitcoin/store/utxo_db.rb +226 -0
  77. data/lib/bitcoin/taproot.rb +9 -0
  78. data/lib/bitcoin/taproot/leaf_node.rb +23 -0
  79. data/lib/bitcoin/taproot/simple_builder.rb +139 -0
  80. data/lib/bitcoin/tx.rb +34 -104
  81. data/lib/bitcoin/tx_in.rb +4 -5
  82. data/lib/bitcoin/tx_out.rb +2 -3
  83. data/lib/bitcoin/util.rb +22 -6
  84. data/lib/bitcoin/version.rb +1 -1
  85. data/lib/bitcoin/wallet.rb +1 -0
  86. data/lib/bitcoin/wallet/account.rb +2 -1
  87. data/lib/bitcoin/wallet/base.rb +2 -2
  88. data/lib/bitcoin/wallet/master_key.rb +1 -0
  89. data/lib/bitcoin/wallet/utxo.rb +37 -0
  90. metadata +86 -32
  91. data/.travis.yml +0 -11
data/lib/bitcoin/tx.rb CHANGED
@@ -6,6 +6,8 @@ module Bitcoin
6
6
  # Transaction class
7
7
  class Tx
8
8
 
9
+ include Bitcoin::HexConverter
10
+
9
11
  MAX_STANDARD_VERSION = 2
10
12
 
11
13
  # The maximum weight for transactions we're willing to relay/mine
@@ -31,21 +33,21 @@ module Bitcoin
31
33
  alias_method :in, :inputs
32
34
  alias_method :out, :outputs
33
35
 
34
- def self.parse_from_payload(payload, non_witness: false)
36
+ def self.parse_from_payload(payload, non_witness: false, strict: false)
35
37
  buf = payload.is_a?(String) ? StringIO.new(payload) : payload
36
38
  tx = new
37
- tx.version = buf.read(4).unpack('V').first
39
+ tx.version = buf.read(4).unpack1('V')
38
40
 
39
41
  in_count = Bitcoin.unpack_var_int_from_io(buf)
40
- witness = false
42
+ has_witness = false
41
43
  if in_count.zero? && !non_witness
42
44
  tx.marker = 0
43
- tx.flag = buf.read(1).unpack('c').first
45
+ tx.flag = buf.read(1).unpack1('c')
44
46
  if tx.flag.zero?
45
47
  buf.pos -= 1
46
48
  else
47
49
  in_count = Bitcoin.unpack_var_int_from_io(buf)
48
- witness = true
50
+ has_witness = true
49
51
  end
50
52
  end
51
53
 
@@ -58,19 +60,19 @@ module Bitcoin
58
60
  tx.outputs << TxOut.parse_from_payload(buf)
59
61
  end
60
62
 
61
- if witness
63
+ if has_witness
62
64
  in_count.times do |i|
63
65
  tx.inputs[i].script_witness = Bitcoin::ScriptWitness.parse_from_payload(buf)
64
66
  end
65
67
  end
66
68
 
67
- tx.lock_time = buf.read(4).unpack('V').first
68
-
69
+ raise ArgumentError, 'Transaction has unexpected data.' if strict && (buf.pos + 4) != buf.length
70
+ tx.lock_time = buf.read(4).unpack1('V')
69
71
  tx
70
72
  end
71
73
 
72
74
  def hash
73
- to_payload.bth.to_i(16)
75
+ to_hex.to_i(16)
74
76
  end
75
77
 
76
78
  def tx_hash
@@ -104,12 +106,6 @@ module Bitcoin
104
106
  witness? ? serialize_witness_format : serialize_old_format
105
107
  end
106
108
 
107
- # convert tx to hex format.
108
- # @return [String] tx with hex format.
109
- def to_hex
110
- to_payload.bth
111
- end
112
-
113
109
  def coinbase_tx?
114
110
  inputs.length == 1 && inputs.first.coinbase?
115
111
  end
@@ -192,22 +188,26 @@ module Bitcoin
192
188
  # @param [Integer] input_index input index.
193
189
  # @param [Integer] hash_type signature hash type
194
190
  # @param [Bitcoin::Script] output_script script pubkey or script code. if script pubkey is P2WSH, set witness script to this.
191
+ # @param [Hash] opts Data required for each sig version (amount and skip_separator_index params can also be set to this parameter)
195
192
  # @param [Integer] amount bitcoin amount locked in input. required for witness input only.
196
193
  # @param [Integer] skip_separator_index If output_script is P2WSH and output_script contains any OP_CODESEPARATOR,
197
194
  # the script code needs is the witnessScript but removing everything up to and including the last executed OP_CODESEPARATOR before the signature checking opcode being executed.
198
- def sighash_for_input(input_index, output_script, hash_type: SIGHASH_TYPE[:all],
199
- sig_version: :base, amount: nil, skip_separator_index: 0)
195
+ # @param [Array[Bitcoin::TxOut] prevouts Previous outputs referenced by all Tx inputs, required for taproot.
196
+ # @return [String] signature hash with binary format.
197
+ def sighash_for_input(input_index, output_script = nil, opts: {}, hash_type: SIGHASH_TYPE[:all],
198
+ sig_version: :base, amount: nil, skip_separator_index: 0, prevouts: [])
200
199
  raise ArgumentError, 'input_index must be specified.' unless input_index
201
200
  raise ArgumentError, 'does not exist input corresponding to input_index.' if input_index >= inputs.size
202
- raise ArgumentError, 'script_pubkey must be specified.' unless output_script
203
- raise ArgumentError, 'unsupported sig version specified.' unless SIG_VERSION.include?(sig_version)
204
-
205
- if sig_version == :witness_v0 || Bitcoin.chain_params.fork_chain?
206
- raise ArgumentError, 'amount must be specified.' unless amount
207
- sighash_for_witness(input_index, output_script, hash_type, amount, skip_separator_index)
208
- else
209
- sighash_for_legacy(input_index, output_script, hash_type)
210
- end
201
+ raise ArgumentError, 'script_pubkey must be specified.' if [:base, :witness_v0].include?(sig_version) && output_script.nil?
202
+
203
+ opts[:amount] = amount if amount
204
+ opts[:skip_separator_index] = skip_separator_index
205
+ opts[:sig_version] = sig_version
206
+ opts[:script_code] = output_script
207
+ opts[:prevouts] = prevouts
208
+ opts[:last_code_separator_pos] ||= 0xffffffff
209
+ sig_hash_gen = SigHashGenerator.load(sig_version)
210
+ sig_hash_gen.generate(self, input_index, hash_type, opts)
211
211
  end
212
212
 
213
213
  # verify input signature.
@@ -215,7 +215,9 @@ module Bitcoin
215
215
  # @param [Bitcoin::Script] script_pubkey the script pubkey for target input.
216
216
  # @param [Integer] amount the amount of bitcoin, require for witness program only.
217
217
  # @param [Array] flags the flags used when execute script interpreter.
218
- def verify_input_sig(input_index, script_pubkey, amount: nil, flags: STANDARD_SCRIPT_VERIFY_FLAGS)
218
+ # @param [Array[Bitcoin::TxOut]] prevouts Previous outputs referenced by all Tx inputs, required for taproot.
219
+ # @return [Boolean] result
220
+ def verify_input_sig(input_index, script_pubkey, amount: nil, flags: STANDARD_SCRIPT_VERIFY_FLAGS, prevouts: [])
219
221
  script_sig = inputs[input_index].script_sig
220
222
  has_witness = inputs[input_index].has_witness?
221
223
 
@@ -225,8 +227,8 @@ module Bitcoin
225
227
  script_pubkey = redeem_script if redeem_script.p2wpkh?
226
228
  end
227
229
 
228
- if has_witness || Bitcoin.chain_params.fork_chain?
229
- verify_input_sig_for_witness(input_index, script_pubkey, amount, flags)
230
+ if has_witness
231
+ verify_input_sig_for_witness(input_index, script_pubkey, amount, flags, prevouts)
230
232
  else
231
233
  verify_input_sig_for_legacy(input_index, script_pubkey, flags)
232
234
  end
@@ -249,73 +251,6 @@ module Bitcoin
249
251
 
250
252
  private
251
253
 
252
- # generate sighash with legacy format
253
- def sighash_for_legacy(index, script_code, hash_type)
254
- ins = inputs.map.with_index do |i, idx|
255
- if idx == index
256
- i.to_payload(script_code.delete_opcode(Bitcoin::Opcodes::OP_CODESEPARATOR))
257
- else
258
- case hash_type & 0x1f
259
- when SIGHASH_TYPE[:none], SIGHASH_TYPE[:single]
260
- i.to_payload(Bitcoin::Script.new, 0)
261
- else
262
- i.to_payload(Bitcoin::Script.new)
263
- end
264
- end
265
- end
266
-
267
- outs = outputs.map(&:to_payload)
268
- out_size = Bitcoin.pack_var_int(outputs.size)
269
-
270
- case hash_type & 0x1f
271
- when SIGHASH_TYPE[:none]
272
- outs = ''
273
- out_size = Bitcoin.pack_var_int(0)
274
- when SIGHASH_TYPE[:single]
275
- return "\x01".ljust(32, "\x00") if index >= outputs.size
276
- outs = outputs[0...(index + 1)].map.with_index { |o, idx| (idx == index) ? o.to_payload : o.to_empty_payload }.join
277
- out_size = Bitcoin.pack_var_int(index + 1)
278
- end
279
-
280
- if hash_type & SIGHASH_TYPE[:anyonecanpay] != 0
281
- ins = [ins[index]]
282
- end
283
-
284
- buf = [[version].pack('V'), Bitcoin.pack_var_int(ins.size),
285
- ins, out_size, outs, [lock_time, hash_type].pack('VV')].join
286
-
287
- Bitcoin.double_sha256(buf)
288
- end
289
-
290
- # generate sighash with BIP-143 format
291
- # https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
292
- def sighash_for_witness(index, script_pubkey_or_script_code, hash_type, amount, skip_separator_index)
293
- hash_prevouts = Bitcoin.double_sha256(inputs.map{|i|i.out_point.to_payload}.join)
294
- hash_sequence = Bitcoin.double_sha256(inputs.map{|i|[i.sequence].pack('V')}.join)
295
- outpoint = inputs[index].out_point.to_payload
296
- amount = [amount].pack('Q')
297
- nsequence = [inputs[index].sequence].pack('V')
298
- hash_outputs = Bitcoin.double_sha256(outputs.map{|o|o.to_payload}.join)
299
-
300
- script_code = script_pubkey_or_script_code.to_script_code(skip_separator_index)
301
-
302
- case (hash_type & 0x1f)
303
- when SIGHASH_TYPE[:single]
304
- hash_outputs = index >= outputs.size ? "\x00".ljust(32, "\x00") : Bitcoin.double_sha256(outputs[index].to_payload)
305
- hash_sequence = "\x00".ljust(32, "\x00")
306
- when SIGHASH_TYPE[:none]
307
- hash_sequence = hash_outputs = "\x00".ljust(32, "\x00")
308
- end
309
-
310
- if (hash_type & SIGHASH_TYPE[:anyonecanpay]) != 0
311
- hash_prevouts = hash_sequence ="\x00".ljust(32, "\x00")
312
- end
313
- hash_type |= (Bitcoin.chain_params.fork_id << 8) if Bitcoin.chain_params.fork_chain?
314
- buf = [ [version].pack('V'), hash_prevouts, hash_sequence, outpoint,
315
- script_code ,amount, nsequence, hash_outputs, [@lock_time, hash_type].pack('VV')].join
316
- Bitcoin.double_sha256(buf)
317
- end
318
-
319
254
  # verify input signature for legacy tx.
320
255
  def verify_input_sig_for_legacy(input_index, script_pubkey, flags)
321
256
  script_sig = inputs[input_index].script_sig
@@ -326,16 +261,11 @@ module Bitcoin
326
261
  end
327
262
 
328
263
  # verify input signature for witness tx.
329
- def verify_input_sig_for_witness(input_index, script_pubkey, amount, flags)
330
- flags |= SCRIPT_VERIFY_WITNESS
331
- flags |= SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
332
- checker = Bitcoin::TxChecker.new(tx: self, input_index: input_index, amount: amount)
264
+ def verify_input_sig_for_witness(input_index, script_pubkey, amount, flags, prevouts)
265
+ checker = Bitcoin::TxChecker.new(tx: self, input_index: input_index, amount: amount, prevouts: prevouts)
333
266
  interpreter = Bitcoin::ScriptInterpreter.new(checker: checker, flags: flags)
334
267
  i = inputs[input_index]
335
-
336
- script_sig = i.script_sig
337
- witness = i.script_witness
338
- interpreter.verify_script(script_sig, script_pubkey, witness)
268
+ interpreter.verify_script(i.script_sig, script_pubkey, i.script_witness)
339
269
  end
340
270
 
341
271
  end
data/lib/bitcoin/tx_in.rb CHANGED
@@ -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
data/lib/bitcoin/util.rb CHANGED
@@ -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,7 @@ 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
83
  end
84
84
 
85
85
  # padding zero to the left of binary string until bytesize.
@@ -96,6 +96,15 @@ module Bitcoin
96
96
  Digest::RMD160.hexdigest(Digest::SHA256.digest(hex.htb))
97
97
  end
98
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
+
99
108
  # encode Base58 check address.
100
109
  # @param [String] hex the address payload.
101
110
  # @param [String] addr_version the address version for P2PKH and P2SH.
@@ -142,4 +151,11 @@ module Bitcoin
142
151
 
143
152
  end
144
153
 
154
+ module HexConverter
155
+
156
+ def to_hex
157
+ to_payload.bth
158
+ end
159
+
160
+ end
145
161
  end
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "0.3.2"
2
+ VERSION = "0.8.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
@@ -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
 
@@ -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.2
4
+ version: 0.8.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-12-14 00:00:00.000000000 Z
11
+ date: 2021-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 1.0.3
61
+ version: 1.1.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 1.0.3
68
+ version: 1.1.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: daemon-spawn
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +137,7 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: rest-client
140
+ name: iniparse
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
@@ -151,7 +151,7 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
- name: iniparse
154
+ name: siphash
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - ">="
@@ -165,61 +165,61 @@ dependencies:
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  - !ruby/object:Gem::Dependency
168
- name: siphash
168
+ name: protobuf
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - ">="
171
+ - - '='
172
172
  - !ruby/object:Gem::Version
173
- version: '0'
173
+ version: 3.8.5
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - ">="
178
+ - - '='
179
179
  - !ruby/object:Gem::Version
180
- version: '0'
180
+ version: 3.8.5
181
181
  - !ruby/object:Gem::Dependency
182
- name: protobuf
182
+ name: json_pure
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - '='
185
+ - - ">="
186
186
  - !ruby/object:Gem::Version
187
- version: 3.8.5
187
+ version: 2.3.1
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
- - - '='
192
+ - - ">="
193
193
  - !ruby/object:Gem::Version
194
- version: 3.8.5
194
+ version: 2.3.1
195
195
  - !ruby/object:Gem::Dependency
196
- name: scrypt
196
+ name: bip-schnorr
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
199
  - - ">="
200
200
  - !ruby/object:Gem::Version
201
- version: '0'
201
+ version: 0.4.0
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - ">="
207
207
  - !ruby/object:Gem::Version
208
- version: '0'
208
+ version: 0.4.0
209
209
  - !ruby/object:Gem::Dependency
210
- name: activesupport
210
+ name: base32
211
211
  requirement: !ruby/object:Gem::Requirement
212
212
  requirements:
213
- - - "~>"
213
+ - - ">="
214
214
  - !ruby/object:Gem::Version
215
- version: 5.2.3
215
+ version: 0.3.4
216
216
  type: :runtime
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
- - - "~>"
220
+ - - ">="
221
221
  - !ruby/object:Gem::Version
222
- version: 5.2.3
222
+ version: 0.3.4
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: leveldb-native
225
225
  requirement: !ruby/object:Gem::Requirement
@@ -252,16 +252,16 @@ dependencies:
252
252
  name: rake
253
253
  requirement: !ruby/object:Gem::Requirement
254
254
  requirements:
255
- - - "~>"
255
+ - - ">="
256
256
  - !ruby/object:Gem::Version
257
- version: '10.0'
257
+ version: 12.3.3
258
258
  type: :development
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
- - - "~>"
262
+ - - ">="
263
263
  - !ruby/object:Gem::Version
264
- version: '10.0'
264
+ version: 12.3.3
265
265
  - !ruby/object:Gem::Dependency
266
266
  name: rspec
267
267
  requirement: !ruby/object:Gem::Requirement
@@ -290,7 +290,35 @@ dependencies:
290
290
  - - ">="
291
291
  - !ruby/object:Gem::Version
292
292
  version: '0'
293
- description: "[WIP]The implementation of Bitcoin Protocol for Ruby."
293
+ - !ruby/object:Gem::Dependency
294
+ name: webmock
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - ">="
298
+ - !ruby/object:Gem::Version
299
+ version: 3.11.1
300
+ type: :development
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - ">="
305
+ - !ruby/object:Gem::Version
306
+ version: 3.11.1
307
+ - !ruby/object:Gem::Dependency
308
+ name: parallel
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - ">="
312
+ - !ruby/object:Gem::Version
313
+ version: 1.20.1
314
+ type: :development
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - ">="
319
+ - !ruby/object:Gem::Version
320
+ version: 1.20.1
321
+ description: The implementation of Bitcoin Protocol for Ruby.
294
322
  email:
295
323
  - azuchi@chaintope.com
296
324
  executables:
@@ -299,11 +327,12 @@ executables:
299
327
  extensions: []
300
328
  extra_rdoc_files: []
301
329
  files:
330
+ - ".github/workflows/ruby.yml"
302
331
  - ".gitignore"
303
332
  - ".rspec"
333
+ - ".rspec_parallel"
304
334
  - ".ruby-gemset"
305
335
  - ".ruby-version"
306
- - ".travis.yml"
307
336
  - CODE_OF_CONDUCT.md
308
337
  - Gemfile
309
338
  - LICENSE.txt
@@ -317,6 +346,7 @@ files:
317
346
  - exe/bitcoinrbd
318
347
  - lib/bitcoin.rb
319
348
  - lib/bitcoin/base58.rb
349
+ - lib/bitcoin/bip85_entropy.rb
320
350
  - lib/bitcoin/bit_stream.rb
321
351
  - lib/bitcoin/block.rb
322
352
  - lib/bitcoin/block_filter.rb
@@ -325,9 +355,15 @@ files:
325
355
  - lib/bitcoin/chain_params.rb
326
356
  - lib/bitcoin/chainparams/mainnet.yml
327
357
  - lib/bitcoin/chainparams/regtest.yml
358
+ - lib/bitcoin/chainparams/signet.yml
328
359
  - lib/bitcoin/chainparams/testnet.yml
329
360
  - lib/bitcoin/constants.rb
330
361
  - lib/bitcoin/descriptor.rb
362
+ - lib/bitcoin/errors.rb
363
+ - lib/bitcoin/ext.rb
364
+ - lib/bitcoin/ext/array_ext.rb
365
+ - lib/bitcoin/ext/ecdsa.rb
366
+ - lib/bitcoin/ext/json_parser.rb
331
367
  - lib/bitcoin/ext_key.rb
332
368
  - lib/bitcoin/gcs_filter.rb
333
369
  - lib/bitcoin/key.rb
@@ -336,11 +372,16 @@ files:
336
372
  - lib/bitcoin/merkle_tree.rb
337
373
  - lib/bitcoin/message.rb
338
374
  - lib/bitcoin/message/addr.rb
375
+ - lib/bitcoin/message/addr_v2.rb
339
376
  - lib/bitcoin/message/base.rb
340
377
  - lib/bitcoin/message/block.rb
341
378
  - lib/bitcoin/message/block_transaction_request.rb
342
379
  - lib/bitcoin/message/block_transactions.rb
343
380
  - lib/bitcoin/message/block_txn.rb
381
+ - lib/bitcoin/message/cf_parser.rb
382
+ - lib/bitcoin/message/cfcheckpt.rb
383
+ - lib/bitcoin/message/cfheaders.rb
384
+ - lib/bitcoin/message/cfilter.rb
344
385
  - lib/bitcoin/message/cmpct_block.rb
345
386
  - lib/bitcoin/message/error.rb
346
387
  - lib/bitcoin/message/fee_filter.rb
@@ -350,6 +391,9 @@ files:
350
391
  - lib/bitcoin/message/get_addr.rb
351
392
  - lib/bitcoin/message/get_block_txn.rb
352
393
  - lib/bitcoin/message/get_blocks.rb
394
+ - lib/bitcoin/message/get_cfcheckpt.rb
395
+ - lib/bitcoin/message/get_cfheaders.rb
396
+ - lib/bitcoin/message/get_cfilters.rb
353
397
  - lib/bitcoin/message/get_data.rb
354
398
  - lib/bitcoin/message/get_headers.rb
355
399
  - lib/bitcoin/message/header_and_short_ids.rb
@@ -366,11 +410,13 @@ files:
366
410
  - lib/bitcoin/message/pong.rb
367
411
  - lib/bitcoin/message/prefilled_tx.rb
368
412
  - lib/bitcoin/message/reject.rb
413
+ - lib/bitcoin/message/send_addr_v2.rb
369
414
  - lib/bitcoin/message/send_cmpct.rb
370
415
  - lib/bitcoin/message/send_headers.rb
371
416
  - lib/bitcoin/message/tx.rb
372
417
  - lib/bitcoin/message/ver_ack.rb
373
418
  - lib/bitcoin/message/version.rb
419
+ - lib/bitcoin/message_sign.rb
374
420
  - lib/bitcoin/mnemonic.rb
375
421
  - lib/bitcoin/mnemonic/wordlist/chinese_simplified.txt
376
422
  - lib/bitcoin/mnemonic/wordlist/chinese_traditional.txt
@@ -391,6 +437,7 @@ files:
391
437
  - lib/bitcoin/node/spv.rb
392
438
  - lib/bitcoin/opcodes.rb
393
439
  - lib/bitcoin/out_point.rb
440
+ - lib/bitcoin/payment_code.rb
394
441
  - lib/bitcoin/payments.rb
395
442
  - lib/bitcoin/payments/output.pb.rb
396
443
  - lib/bitcoin/payments/payment.pb.rb
@@ -416,7 +463,9 @@ files:
416
463
  - lib/bitcoin/script_witness.rb
417
464
  - lib/bitcoin/secp256k1.rb
418
465
  - lib/bitcoin/secp256k1/native.rb
466
+ - lib/bitcoin/secp256k1/rfc6979.rb
419
467
  - lib/bitcoin/secp256k1/ruby.rb
468
+ - lib/bitcoin/sighash_generator.rb
420
469
  - lib/bitcoin/slip39.rb
421
470
  - lib/bitcoin/slip39/share.rb
422
471
  - lib/bitcoin/slip39/sss.rb
@@ -426,6 +475,10 @@ files:
426
475
  - lib/bitcoin/store/db.rb
427
476
  - lib/bitcoin/store/db/level_db.rb
428
477
  - lib/bitcoin/store/spv_chain.rb
478
+ - lib/bitcoin/store/utxo_db.rb
479
+ - lib/bitcoin/taproot.rb
480
+ - lib/bitcoin/taproot/leaf_node.rb
481
+ - lib/bitcoin/taproot/simple_builder.rb
429
482
  - lib/bitcoin/tx.rb
430
483
  - lib/bitcoin/tx_in.rb
431
484
  - lib/bitcoin/tx_out.rb
@@ -437,6 +490,7 @@ files:
437
490
  - lib/bitcoin/wallet/base.rb
438
491
  - lib/bitcoin/wallet/db.rb
439
492
  - lib/bitcoin/wallet/master_key.rb
493
+ - lib/bitcoin/wallet/utxo.rb
440
494
  - lib/openassets.rb
441
495
  - lib/openassets/marker_output.rb
442
496
  - lib/openassets/payload.rb
@@ -460,8 +514,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
460
514
  - !ruby/object:Gem::Version
461
515
  version: '0'
462
516
  requirements: []
463
- rubygems_version: 3.0.3
517
+ rubygems_version: 3.2.3
464
518
  signing_key:
465
519
  specification_version: 4
466
- summary: "[WIP]The implementation of Bitcoin Protocol for Ruby."
520
+ summary: The implementation of Bitcoin Protocol for Ruby.
467
521
  test_files: []