bitcoinrb 0.3.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +37 -0
- data/.rspec_parallel +2 -0
- data/.ruby-version +1 -1
- data/README.md +17 -6
- data/bitcoinrb.gemspec +9 -8
- data/exe/bitcoinrbd +5 -0
- data/lib/bitcoin.rb +37 -19
- data/lib/bitcoin/bip85_entropy.rb +111 -0
- data/lib/bitcoin/block_filter.rb +14 -0
- data/lib/bitcoin/block_header.rb +2 -0
- data/lib/bitcoin/chain_params.rb +9 -8
- data/lib/bitcoin/chainparams/regtest.yml +1 -1
- data/lib/bitcoin/chainparams/signet.yml +39 -0
- data/lib/bitcoin/chainparams/testnet.yml +1 -1
- data/lib/bitcoin/constants.rb +44 -10
- data/lib/bitcoin/descriptor.rb +1 -1
- data/lib/bitcoin/errors.rb +19 -0
- data/lib/bitcoin/ext.rb +6 -0
- data/lib/bitcoin/ext/array_ext.rb +22 -0
- data/lib/bitcoin/ext/ecdsa.rb +36 -0
- data/lib/bitcoin/ext/json_parser.rb +46 -0
- data/lib/bitcoin/ext_key.rb +51 -20
- data/lib/bitcoin/key.rb +89 -30
- data/lib/bitcoin/key_path.rb +12 -5
- data/lib/bitcoin/message.rb +79 -0
- data/lib/bitcoin/message/addr_v2.rb +34 -0
- data/lib/bitcoin/message/base.rb +17 -0
- data/lib/bitcoin/message/cf_parser.rb +16 -0
- data/lib/bitcoin/message/cfcheckpt.rb +36 -0
- data/lib/bitcoin/message/cfheaders.rb +40 -0
- data/lib/bitcoin/message/cfilter.rb +35 -0
- data/lib/bitcoin/message/fee_filter.rb +1 -1
- data/lib/bitcoin/message/filter_load.rb +3 -3
- data/lib/bitcoin/message/get_cfcheckpt.rb +29 -0
- data/lib/bitcoin/message/get_cfheaders.rb +24 -0
- data/lib/bitcoin/message/get_cfilters.rb +25 -0
- data/lib/bitcoin/message/header_and_short_ids.rb +1 -1
- data/lib/bitcoin/message/inventory.rb +1 -1
- data/lib/bitcoin/message/merkle_block.rb +1 -1
- data/lib/bitcoin/message/network_addr.rb +141 -18
- data/lib/bitcoin/message/ping.rb +1 -1
- data/lib/bitcoin/message/pong.rb +1 -1
- data/lib/bitcoin/message/send_addr_v2.rb +13 -0
- data/lib/bitcoin/message/send_cmpct.rb +2 -2
- data/lib/bitcoin/message/tx.rb +1 -1
- data/lib/bitcoin/message/version.rb +7 -0
- data/lib/bitcoin/message_sign.rb +47 -0
- data/lib/bitcoin/mnemonic.rb +7 -7
- data/lib/bitcoin/network/peer.rb +9 -4
- data/lib/bitcoin/network/peer_discovery.rb +1 -1
- data/lib/bitcoin/node/cli.rb +14 -10
- data/lib/bitcoin/node/configuration.rb +3 -1
- data/lib/bitcoin/node/spv.rb +9 -1
- data/lib/bitcoin/opcodes.rb +14 -1
- data/lib/bitcoin/out_point.rb +2 -0
- data/lib/bitcoin/payment_code.rb +92 -0
- data/lib/bitcoin/payments/payment.pb.rb +1 -1
- data/lib/bitcoin/psbt/hd_key_path.rb +1 -1
- data/lib/bitcoin/psbt/input.rb +9 -18
- data/lib/bitcoin/psbt/output.rb +1 -1
- data/lib/bitcoin/psbt/tx.rb +12 -17
- data/lib/bitcoin/rpc/bitcoin_core_client.rb +22 -12
- data/lib/bitcoin/rpc/request_handler.rb +5 -5
- data/lib/bitcoin/script/script.rb +96 -39
- data/lib/bitcoin/script/script_error.rb +27 -1
- data/lib/bitcoin/script/script_interpreter.rb +166 -66
- data/lib/bitcoin/script/tx_checker.rb +62 -14
- data/lib/bitcoin/secp256k1.rb +1 -0
- data/lib/bitcoin/secp256k1/native.rb +184 -17
- data/lib/bitcoin/secp256k1/rfc6979.rb +43 -0
- data/lib/bitcoin/secp256k1/ruby.rb +112 -56
- data/lib/bitcoin/sighash_generator.rb +156 -0
- data/lib/bitcoin/store.rb +1 -0
- data/lib/bitcoin/store/chain_entry.rb +1 -0
- data/lib/bitcoin/store/utxo_db.rb +226 -0
- data/lib/bitcoin/taproot.rb +9 -0
- data/lib/bitcoin/taproot/leaf_node.rb +23 -0
- data/lib/bitcoin/taproot/simple_builder.rb +139 -0
- data/lib/bitcoin/tx.rb +34 -104
- data/lib/bitcoin/tx_in.rb +4 -5
- data/lib/bitcoin/tx_out.rb +2 -3
- data/lib/bitcoin/util.rb +22 -6
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin/wallet.rb +1 -0
- data/lib/bitcoin/wallet/account.rb +2 -1
- data/lib/bitcoin/wallet/base.rb +2 -2
- data/lib/bitcoin/wallet/master_key.rb +1 -0
- data/lib/bitcoin/wallet/utxo.rb +37 -0
- metadata +86 -32
- 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).
|
39
|
+
tx.version = buf.read(4).unpack1('V')
|
38
40
|
|
39
41
|
in_count = Bitcoin.unpack_var_int_from_io(buf)
|
40
|
-
|
42
|
+
has_witness = false
|
41
43
|
if in_count.zero? && !non_witness
|
42
44
|
tx.marker = 0
|
43
|
-
tx.flag = buf.read(1).
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
199
|
-
|
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.'
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
41
|
-
|
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(
|
43
|
+
i.script_sig = Script.parse_from_payload(buf.read(sig_length))
|
45
44
|
end
|
46
|
-
i.sequence = buf.read(4).
|
45
|
+
i.sequence = buf.read(4).unpack1('V')
|
47
46
|
i
|
48
47
|
end
|
49
48
|
|
data/lib/bitcoin/tx_out.rb
CHANGED
@@ -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).
|
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
|
-
|
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.
|
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)&.
|
50
|
+
uchar = buf.read(1)&.unpack1('C')
|
51
51
|
case uchar
|
52
52
|
when 0xfd
|
53
|
-
buf.read(2)&.
|
53
|
+
buf.read(2)&.unpack1('v')
|
54
54
|
when 0xfe
|
55
|
-
buf.read(4)&.
|
55
|
+
buf.read(4)&.unpack1('V')
|
56
56
|
when 0xff
|
57
|
-
buf.read(8)&.
|
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.
|
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
|
data/lib/bitcoin/version.rb
CHANGED
data/lib/bitcoin/wallet.rb
CHANGED
@@ -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.
|
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
|
data/lib/bitcoin/wallet/base.rb
CHANGED
@@ -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
|
|
@@ -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.
|
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:
|
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
|
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
|
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:
|
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:
|
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:
|
168
|
+
name: protobuf
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- -
|
171
|
+
- - '='
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
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:
|
180
|
+
version: 3.8.5
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
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.
|
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.
|
194
|
+
version: 2.3.1
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
196
|
+
name: bip-schnorr
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
198
198
|
requirements:
|
199
199
|
- - ">="
|
200
200
|
- !ruby/object:Gem::Version
|
201
|
-
version:
|
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:
|
208
|
+
version: 0.4.0
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
|
-
name:
|
210
|
+
name: base32
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
212
212
|
requirements:
|
213
|
-
- - "
|
213
|
+
- - ">="
|
214
214
|
- !ruby/object:Gem::Version
|
215
|
-
version:
|
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:
|
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:
|
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:
|
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
|
-
|
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.
|
517
|
+
rubygems_version: 3.2.3
|
464
518
|
signing_key:
|
465
519
|
specification_version: 4
|
466
|
-
summary:
|
520
|
+
summary: The implementation of Bitcoin Protocol for Ruby.
|
467
521
|
test_files: []
|