bitcoinrb 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +5 -4
- data/README.md +10 -0
- data/bitcoinrb.gemspec +4 -4
- data/lib/bitcoin.rb +29 -16
- data/lib/bitcoin/block_filter.rb +14 -0
- data/lib/bitcoin/chain_params.rb +9 -0
- data/lib/bitcoin/chainparams/signet.yml +39 -0
- data/lib/bitcoin/constants.rb +43 -3
- data/lib/bitcoin/descriptor.rb +1 -1
- data/lib/bitcoin/errors.rb +19 -0
- data/lib/bitcoin/ext/ecdsa.rb +31 -0
- data/lib/bitcoin/ext_key.rb +35 -19
- data/lib/bitcoin/key.rb +43 -26
- data/lib/bitcoin/message/cfcheckpt.rb +2 -2
- data/lib/bitcoin/message/cfheaders.rb +1 -1
- data/lib/bitcoin/message/cfilter.rb +1 -1
- data/lib/bitcoin/message/fee_filter.rb +1 -1
- data/lib/bitcoin/message/filter_load.rb +3 -3
- 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 +3 -3
- data/lib/bitcoin/message/ping.rb +1 -1
- data/lib/bitcoin/message/pong.rb +1 -1
- data/lib/bitcoin/message/send_cmpct.rb +2 -2
- data/lib/bitcoin/mnemonic.rb +2 -2
- data/lib/bitcoin/network/peer_discovery.rb +1 -3
- data/lib/bitcoin/node/configuration.rb +3 -1
- data/lib/bitcoin/node/spv.rb +8 -0
- data/lib/bitcoin/opcodes.rb +14 -1
- data/lib/bitcoin/payment_code.rb +2 -2
- data/lib/bitcoin/psbt/hd_key_path.rb +1 -1
- data/lib/bitcoin/psbt/input.rb +3 -3
- data/lib/bitcoin/psbt/output.rb +1 -1
- data/lib/bitcoin/psbt/tx.rb +4 -4
- data/lib/bitcoin/rpc/bitcoin_core_client.rb +1 -1
- data/lib/bitcoin/script/script.rb +52 -19
- data/lib/bitcoin/script/script_error.rb +27 -1
- data/lib/bitcoin/script/script_interpreter.rb +161 -62
- data/lib/bitcoin/script/tx_checker.rb +64 -14
- data/lib/bitcoin/secp256k1/native.rb +138 -25
- data/lib/bitcoin/secp256k1/ruby.rb +78 -19
- data/lib/bitcoin/sighash_generator.rb +156 -0
- data/lib/bitcoin/tx.rb +13 -80
- data/lib/bitcoin/tx_in.rb +1 -1
- data/lib/bitcoin/tx_out.rb +2 -3
- data/lib/bitcoin/util.rb +15 -6
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin/wallet/account.rb +1 -1
- metadata +19 -15
data/lib/bitcoin/tx.rb
CHANGED
@@ -36,13 +36,13 @@ module Bitcoin
|
|
36
36
|
def self.parse_from_payload(payload, non_witness: false)
|
37
37
|
buf = payload.is_a?(String) ? StringIO.new(payload) : payload
|
38
38
|
tx = new
|
39
|
-
tx.version = buf.read(4).
|
39
|
+
tx.version = buf.read(4).unpack1('V')
|
40
40
|
|
41
41
|
in_count = Bitcoin.unpack_var_int_from_io(buf)
|
42
42
|
witness = false
|
43
43
|
if in_count.zero? && !non_witness
|
44
44
|
tx.marker = 0
|
45
|
-
tx.flag = buf.read(1).
|
45
|
+
tx.flag = buf.read(1).unpack1('c')
|
46
46
|
if tx.flag.zero?
|
47
47
|
buf.pos -= 1
|
48
48
|
else
|
@@ -66,7 +66,7 @@ module Bitcoin
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
tx.lock_time = buf.read(4).
|
69
|
+
tx.lock_time = buf.read(4).unpack1('V')
|
70
70
|
|
71
71
|
tx
|
72
72
|
end
|
@@ -188,22 +188,22 @@ module Bitcoin
|
|
188
188
|
# @param [Integer] input_index input index.
|
189
189
|
# @param [Integer] hash_type signature hash type
|
190
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)
|
191
192
|
# @param [Integer] amount bitcoin amount locked in input. required for witness input only.
|
192
193
|
# @param [Integer] skip_separator_index If output_script is P2WSH and output_script contains any OP_CODESEPARATOR,
|
193
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.
|
194
|
-
def sighash_for_input(input_index, output_script, hash_type: SIGHASH_TYPE[:all],
|
195
|
+
def sighash_for_input(input_index, output_script = nil, opts: {}, hash_type: SIGHASH_TYPE[:all],
|
195
196
|
sig_version: :base, amount: nil, skip_separator_index: 0)
|
196
197
|
raise ArgumentError, 'input_index must be specified.' unless input_index
|
197
198
|
raise ArgumentError, 'does not exist input corresponding to input_index.' if input_index >= inputs.size
|
198
|
-
raise ArgumentError, 'script_pubkey must be specified.'
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
end
|
199
|
+
raise ArgumentError, 'script_pubkey must be specified.' if [:base, :witness_v0].include?(sig_version) && output_script.nil?
|
200
|
+
|
201
|
+
opts[:amount] = amount if amount
|
202
|
+
opts[:skip_separator_index] = skip_separator_index
|
203
|
+
opts[:sig_version] = sig_version
|
204
|
+
opts[:script_code] = output_script
|
205
|
+
sig_hash_gen = SigHashGenerator.load(sig_version)
|
206
|
+
sig_hash_gen.generate(self, input_index, hash_type, opts)
|
207
207
|
end
|
208
208
|
|
209
209
|
# verify input signature.
|
@@ -245,73 +245,6 @@ module Bitcoin
|
|
245
245
|
|
246
246
|
private
|
247
247
|
|
248
|
-
# generate sighash with legacy format
|
249
|
-
def sighash_for_legacy(index, script_code, hash_type)
|
250
|
-
ins = inputs.map.with_index do |i, idx|
|
251
|
-
if idx == index
|
252
|
-
i.to_payload(script_code.delete_opcode(Bitcoin::Opcodes::OP_CODESEPARATOR))
|
253
|
-
else
|
254
|
-
case hash_type & 0x1f
|
255
|
-
when SIGHASH_TYPE[:none], SIGHASH_TYPE[:single]
|
256
|
-
i.to_payload(Bitcoin::Script.new, 0)
|
257
|
-
else
|
258
|
-
i.to_payload(Bitcoin::Script.new)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
outs = outputs.map(&:to_payload)
|
264
|
-
out_size = Bitcoin.pack_var_int(outputs.size)
|
265
|
-
|
266
|
-
case hash_type & 0x1f
|
267
|
-
when SIGHASH_TYPE[:none]
|
268
|
-
outs = ''
|
269
|
-
out_size = Bitcoin.pack_var_int(0)
|
270
|
-
when SIGHASH_TYPE[:single]
|
271
|
-
return "\x01".ljust(32, "\x00") if index >= outputs.size
|
272
|
-
outs = outputs[0...(index + 1)].map.with_index { |o, idx| (idx == index) ? o.to_payload : o.to_empty_payload }.join
|
273
|
-
out_size = Bitcoin.pack_var_int(index + 1)
|
274
|
-
end
|
275
|
-
|
276
|
-
if hash_type & SIGHASH_TYPE[:anyonecanpay] != 0
|
277
|
-
ins = [ins[index]]
|
278
|
-
end
|
279
|
-
|
280
|
-
buf = [[version].pack('V'), Bitcoin.pack_var_int(ins.size),
|
281
|
-
ins, out_size, outs, [lock_time, hash_type].pack('VV')].join
|
282
|
-
|
283
|
-
Bitcoin.double_sha256(buf)
|
284
|
-
end
|
285
|
-
|
286
|
-
# generate sighash with BIP-143 format
|
287
|
-
# https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
|
288
|
-
def sighash_for_witness(index, script_pubkey_or_script_code, hash_type, amount, skip_separator_index)
|
289
|
-
hash_prevouts = Bitcoin.double_sha256(inputs.map{|i|i.out_point.to_payload}.join)
|
290
|
-
hash_sequence = Bitcoin.double_sha256(inputs.map{|i|[i.sequence].pack('V')}.join)
|
291
|
-
outpoint = inputs[index].out_point.to_payload
|
292
|
-
amount = [amount].pack('Q')
|
293
|
-
nsequence = [inputs[index].sequence].pack('V')
|
294
|
-
hash_outputs = Bitcoin.double_sha256(outputs.map{|o|o.to_payload}.join)
|
295
|
-
|
296
|
-
script_code = script_pubkey_or_script_code.to_script_code(skip_separator_index)
|
297
|
-
|
298
|
-
case (hash_type & 0x1f)
|
299
|
-
when SIGHASH_TYPE[:single]
|
300
|
-
hash_outputs = index >= outputs.size ? "\x00".ljust(32, "\x00") : Bitcoin.double_sha256(outputs[index].to_payload)
|
301
|
-
hash_sequence = "\x00".ljust(32, "\x00")
|
302
|
-
when SIGHASH_TYPE[:none]
|
303
|
-
hash_sequence = hash_outputs = "\x00".ljust(32, "\x00")
|
304
|
-
end
|
305
|
-
|
306
|
-
if (hash_type & SIGHASH_TYPE[:anyonecanpay]) != 0
|
307
|
-
hash_prevouts = hash_sequence ="\x00".ljust(32, "\x00")
|
308
|
-
end
|
309
|
-
|
310
|
-
buf = [ [version].pack('V'), hash_prevouts, hash_sequence, outpoint,
|
311
|
-
script_code ,amount, nsequence, hash_outputs, [@lock_time, hash_type].pack('VV')].join
|
312
|
-
Bitcoin.double_sha256(buf)
|
313
|
-
end
|
314
|
-
|
315
248
|
# verify input signature for legacy tx.
|
316
249
|
def verify_input_sig_for_legacy(input_index, script_pubkey, flags)
|
317
250
|
script_sig = inputs[input_index].script_sig
|
data/lib/bitcoin/tx_in.rb
CHANGED
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.
|
data/lib/bitcoin/version.rb
CHANGED
@@ -43,7 +43,7 @@ module Bitcoin
|
|
43
43
|
|
44
44
|
def to_payload
|
45
45
|
payload = account_key.to_payload
|
46
|
-
payload << Bitcoin.pack_var_string(name.
|
46
|
+
payload << Bitcoin.pack_var_string(name.unpack1('H*').htb)
|
47
47
|
payload << [purpose, index, receive_depth, change_depth, lookahead].pack('I*')
|
48
48
|
payload
|
49
49
|
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ecdsa
|
@@ -179,33 +179,33 @@ dependencies:
|
|
179
179
|
- !ruby/object:Gem::Version
|
180
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:
|
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:
|
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.3.2
|
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.3.2
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
210
|
name: leveldb-native
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -280,17 +280,17 @@ dependencies:
|
|
280
280
|
name: webmock
|
281
281
|
requirement: !ruby/object:Gem::Requirement
|
282
282
|
requirements:
|
283
|
-
- - "
|
283
|
+
- - ">="
|
284
284
|
- !ruby/object:Gem::Version
|
285
|
-
version:
|
285
|
+
version: 3.11.1
|
286
286
|
type: :development
|
287
287
|
prerelease: false
|
288
288
|
version_requirements: !ruby/object:Gem::Requirement
|
289
289
|
requirements:
|
290
|
-
- - "
|
290
|
+
- - ">="
|
291
291
|
- !ruby/object:Gem::Version
|
292
|
-
version:
|
293
|
-
description:
|
292
|
+
version: 3.11.1
|
293
|
+
description: The implementation of Bitcoin Protocol for Ruby.
|
294
294
|
email:
|
295
295
|
- azuchi@chaintope.com
|
296
296
|
executables:
|
@@ -326,10 +326,13 @@ files:
|
|
326
326
|
- lib/bitcoin/chain_params.rb
|
327
327
|
- lib/bitcoin/chainparams/mainnet.yml
|
328
328
|
- lib/bitcoin/chainparams/regtest.yml
|
329
|
+
- lib/bitcoin/chainparams/signet.yml
|
329
330
|
- lib/bitcoin/chainparams/testnet.yml
|
330
331
|
- lib/bitcoin/constants.rb
|
331
332
|
- lib/bitcoin/descriptor.rb
|
333
|
+
- lib/bitcoin/errors.rb
|
332
334
|
- lib/bitcoin/ext.rb
|
335
|
+
- lib/bitcoin/ext/ecdsa.rb
|
333
336
|
- lib/bitcoin/ext/json_parser.rb
|
334
337
|
- lib/bitcoin/ext_key.rb
|
335
338
|
- lib/bitcoin/gcs_filter.rb
|
@@ -429,6 +432,7 @@ files:
|
|
429
432
|
- lib/bitcoin/secp256k1/native.rb
|
430
433
|
- lib/bitcoin/secp256k1/rfc6979.rb
|
431
434
|
- lib/bitcoin/secp256k1/ruby.rb
|
435
|
+
- lib/bitcoin/sighash_generator.rb
|
432
436
|
- lib/bitcoin/slip39.rb
|
433
437
|
- lib/bitcoin/slip39/share.rb
|
434
438
|
- lib/bitcoin/slip39/sss.rb
|
@@ -474,8 +478,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
474
478
|
- !ruby/object:Gem::Version
|
475
479
|
version: '0'
|
476
480
|
requirements: []
|
477
|
-
rubygems_version: 3.
|
481
|
+
rubygems_version: 3.2.3
|
478
482
|
signing_key:
|
479
483
|
specification_version: 4
|
480
|
-
summary:
|
484
|
+
summary: The implementation of Bitcoin Protocol for Ruby.
|
481
485
|
test_files: []
|