bitcoinrb 0.3.2 → 0.8.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 (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: []