bitcoin-ruby 0.0.14 → 0.0.15
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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -3
- data/COPYING +1 -1
- data/Gemfile.lock +1 -1
- data/README.rdoc +11 -29
- data/lib/bitcoin.rb +83 -11
- data/lib/bitcoin/bech32.rb +172 -0
- data/lib/bitcoin/builder.rb +25 -7
- data/lib/bitcoin/ffi/secp256k1.rb +12 -12
- data/lib/bitcoin/protocol/txout.rb +7 -1
- data/lib/bitcoin/script.rb +25 -8
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/bech32_spec.rb +160 -0
- data/spec/bitcoin/bitcoin_spec.rb +60 -0
- data/spec/bitcoin/builder_spec.rb +33 -0
- data/spec/bitcoin/fixtures/base58_keys_invalid.json +182 -0
- data/spec/bitcoin/fixtures/base58_keys_valid.json +488 -0
- data/spec/bitcoin/protocol/txout_spec.rb +6 -0
- data/spec/bitcoin/script/script_spec.rb +4 -0
- data/spec/bitcoin/secp256k1_spec.rb +1 -1
- metadata +9 -2
data/lib/bitcoin/builder.rb
CHANGED
@@ -237,7 +237,7 @@ module Bitcoin
|
|
237
237
|
@tx.in[i].sig_address = Script.new(@prev_script).get_address if @prev_script
|
238
238
|
end
|
239
239
|
|
240
|
-
def get_script_sig(inc)
|
240
|
+
def get_script_sig(inc, hash_type)
|
241
241
|
if inc.has_multiple_keys?
|
242
242
|
# multiple keys given, generate signature for each one
|
243
243
|
sigs = inc.sign(@sig_hash)
|
@@ -251,7 +251,7 @@ module Bitcoin
|
|
251
251
|
else
|
252
252
|
# only one key given, generate signature and script_sig
|
253
253
|
sig = inc.sign(@sig_hash)
|
254
|
-
script_sig = Script.to_signature_pubkey_script(sig, [inc.key.pub].pack("H*"))
|
254
|
+
script_sig = Script.to_signature_pubkey_script(sig, [inc.key.pub].pack("H*"), hash_type)
|
255
255
|
end
|
256
256
|
return script_sig
|
257
257
|
end
|
@@ -268,13 +268,28 @@ module Bitcoin
|
|
268
268
|
sig_script = inc.instance_eval { @redeem_script }
|
269
269
|
sig_script ||= @prev_script
|
270
270
|
|
271
|
+
hash_type = if inc.prev_out_forkid
|
272
|
+
Script::SIGHASH_TYPE[:all] | Script::SIGHASH_TYPE[:forkid]
|
273
|
+
else
|
274
|
+
Script::SIGHASH_TYPE[:all]
|
275
|
+
end
|
276
|
+
|
271
277
|
# when a sig_script was found, generate the sig_hash to be signed
|
272
278
|
if sig_script
|
273
279
|
script = Script.new(sig_script)
|
274
280
|
if script.is_witness_v0_keyhash?
|
275
281
|
@sig_hash = @tx.signature_hash_for_witness_input(i, sig_script, inc.value)
|
276
282
|
else
|
277
|
-
@sig_hash =
|
283
|
+
@sig_hash = if inc.prev_out_forkid
|
284
|
+
@tx.signature_hash_for_input(
|
285
|
+
i,
|
286
|
+
sig_script,
|
287
|
+
hash_type,
|
288
|
+
inc.value,
|
289
|
+
inc.prev_out_forkid)
|
290
|
+
else
|
291
|
+
@tx.signature_hash_for_input(i, sig_script)
|
292
|
+
end
|
278
293
|
end
|
279
294
|
end
|
280
295
|
|
@@ -285,10 +300,12 @@ module Bitcoin
|
|
285
300
|
@tx.in[i].script_witness.stack << inc.sign(@sig_hash) + [Script::SIGHASH_TYPE[:all]].pack("C")
|
286
301
|
@tx.in[i].script_witness.stack << inc.key.pub.htb
|
287
302
|
else
|
288
|
-
@tx.in[i].script_sig = get_script_sig(inc)
|
303
|
+
@tx.in[i].script_sig = get_script_sig(inc, hash_type)
|
289
304
|
end
|
290
305
|
# double-check that the script_sig is valid to spend the given prev_script
|
291
|
-
|
306
|
+
if @prev_script && !inc.prev_out_forkid && !@tx.verify_input_signature(i, @prev_script)
|
307
|
+
raise "Signature error"
|
308
|
+
end
|
292
309
|
elsif inc.has_multiple_keys?
|
293
310
|
raise "Keys missing for multisig signing"
|
294
311
|
else
|
@@ -329,7 +346,7 @@ module Bitcoin
|
|
329
346
|
#
|
330
347
|
# If you want to spend a multisig output, just provide an array of keys to #signature_key.
|
331
348
|
class TxInBuilder
|
332
|
-
attr_reader :prev_tx, :prev_script, :redeem_script, :key, :coinbase_data, :prev_out_value
|
349
|
+
attr_reader :prev_tx, :prev_script, :redeem_script, :key, :coinbase_data, :prev_out_value, :prev_out_forkid
|
333
350
|
|
334
351
|
def initialize
|
335
352
|
@txin = P::TxIn.new
|
@@ -341,7 +358,8 @@ module Bitcoin
|
|
341
358
|
# You can either pass the transaction, or just the tx hash.
|
342
359
|
# If you pass only the hash, you need to pass the previous outputs
|
343
360
|
# +script+ separately if you want the txin to be signed.
|
344
|
-
def prev_out tx, idx = nil, script = nil, prev_value = nil
|
361
|
+
def prev_out tx, idx = nil, script = nil, prev_value = nil, prev_forkid = nil
|
362
|
+
@prev_out_forkid = prev_forkid
|
345
363
|
if tx.is_a?(Bitcoin::P::Tx)
|
346
364
|
@prev_tx = tx
|
347
365
|
@prev_out_hash = tx.binary_hash
|
@@ -134,7 +134,7 @@ module Bitcoin
|
|
134
134
|
|
135
135
|
internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
|
136
136
|
result = secp256k1_ec_pubkey_create(context, internal_pubkey, seckey)
|
137
|
-
raise "error creating pubkey" unless result
|
137
|
+
raise "error creating pubkey" unless result == 1
|
138
138
|
|
139
139
|
pubkey, pubkey_len = FFI::MemoryPointer.new(:uchar, 65), FFI::MemoryPointer.new(:uint64)
|
140
140
|
result = if compressed
|
@@ -144,7 +144,7 @@ module Bitcoin
|
|
144
144
|
pubkey_len.put_uint64(0, 65)
|
145
145
|
secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_UNCOMPRESSED)
|
146
146
|
end
|
147
|
-
raise "error serialize pubkey" unless result || pubkey_len.read_uint64 > 0
|
147
|
+
raise "error serialize pubkey" unless (result == 1) || pubkey_len.read_uint64 > 0
|
148
148
|
|
149
149
|
[ seckey.read_string(32), pubkey.read_string(pubkey_len.read_uint64) ]
|
150
150
|
end
|
@@ -158,7 +158,7 @@ module Bitcoin
|
|
158
158
|
def self.sign(data, priv_key)
|
159
159
|
with_context do |context|
|
160
160
|
seckey = FFI::MemoryPointer.new(:uchar, priv_key.bytesize).put_bytes(0, priv_key)
|
161
|
-
raise "priv_key invalid" unless secp256k1_ec_seckey_verify(context, seckey)
|
161
|
+
raise "priv_key invalid" unless secp256k1_ec_seckey_verify(context, seckey) == 1
|
162
162
|
|
163
163
|
internal_signature = FFI::MemoryPointer.new(:uchar, 64)
|
164
164
|
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
|
@@ -173,7 +173,7 @@ module Bitcoin
|
|
173
173
|
|
174
174
|
signature, signature_len = FFI::MemoryPointer.new(:uchar, 72), FFI::MemoryPointer.new(:uint64).put_uint64(0, 72)
|
175
175
|
result = secp256k1_ecdsa_signature_serialize_der(context, signature, signature_len, internal_signature)
|
176
|
-
raise "secp256k1_ecdsa_signature_serialize_der failed" unless result
|
176
|
+
raise "secp256k1_ecdsa_signature_serialize_der failed" unless result == 1
|
177
177
|
|
178
178
|
signature.read_string(signature_len.read_uint64)
|
179
179
|
end
|
@@ -186,13 +186,13 @@ module Bitcoin
|
|
186
186
|
pubkey = FFI::MemoryPointer.new(:uchar, pub_key.bytesize).put_bytes(0, pub_key)
|
187
187
|
internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
|
188
188
|
result = secp256k1_ec_pubkey_parse(context, internal_pubkey, pubkey, pubkey.size)
|
189
|
-
return false unless result
|
189
|
+
return false unless result == 1
|
190
190
|
|
191
191
|
signature = FFI::MemoryPointer.new(:uchar, sig.bytesize).put_bytes(0, sig)
|
192
192
|
internal_signature = FFI::MemoryPointer.new(:uchar, 64)
|
193
193
|
result = secp256k1_ecdsa_signature_parse_der(context, internal_signature, signature, signature.size)
|
194
194
|
#result = ecdsa_signature_parse_der_lax(context, internal_signature, signature, signature.size)
|
195
|
-
return false unless result
|
195
|
+
return false unless result == 1
|
196
196
|
|
197
197
|
# libsecp256k1's ECDSA verification requires lower-S signatures, which have not historically been enforced in Bitcoin, so normalize them first.
|
198
198
|
secp256k1_ecdsa_signature_normalize(context, internal_signature, internal_signature)
|
@@ -200,14 +200,14 @@ module Bitcoin
|
|
200
200
|
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, data)
|
201
201
|
result = secp256k1_ecdsa_verify(context, internal_signature, msg32, internal_pubkey)
|
202
202
|
|
203
|
-
return result
|
203
|
+
return result == 1
|
204
204
|
end
|
205
205
|
end
|
206
206
|
|
207
207
|
def self.sign_compact(message, priv_key, compressed=true)
|
208
208
|
with_context do |context|
|
209
209
|
seckey = FFI::MemoryPointer.new(:uchar, priv_key.bytesize).put_bytes(0, priv_key)
|
210
|
-
raise "priv_key invalid" unless secp256k1_ec_seckey_verify(context, seckey)
|
210
|
+
raise "priv_key invalid" unless secp256k1_ec_seckey_verify(context, seckey) == 1
|
211
211
|
|
212
212
|
msg32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, message)
|
213
213
|
internal_recoverable_signature = FFI::MemoryPointer.new(:uchar, 65)
|
@@ -223,7 +223,7 @@ module Bitcoin
|
|
223
223
|
|
224
224
|
recoverable_signature = FFI::MemoryPointer.new(:uchar, 64)
|
225
225
|
result = secp256k1_ecdsa_recoverable_signature_serialize_compact(context, recoverable_signature, rec_id, internal_recoverable_signature)
|
226
|
-
raise "secp256k1_ecdsa_recoverable_signature_serialize_compact failed" unless result
|
226
|
+
raise "secp256k1_ecdsa_recoverable_signature_serialize_compact failed" unless result == 1
|
227
227
|
raise "secp256k1_ecdsa_recoverable_signature_serialize_compact failed" unless rec_id.read_int != -1
|
228
228
|
|
229
229
|
header = [27 + rec_id.read_int + (compressed ? 4 : 0)].pack("C")
|
@@ -248,15 +248,15 @@ module Bitcoin
|
|
248
248
|
|
249
249
|
internal_recoverable_signature = FFI::MemoryPointer.new(:uchar, 65)
|
250
250
|
result = secp256k1_ecdsa_recoverable_signature_parse_compact(context, internal_recoverable_signature, recoverable_signature, recid)
|
251
|
-
return nil unless result
|
251
|
+
return nil unless result == 1
|
252
252
|
|
253
253
|
internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
|
254
254
|
result = secp256k1_ecdsa_recover(context, internal_pubkey, internal_recoverable_signature, msg32)
|
255
|
-
return nil unless result
|
255
|
+
return nil unless result == 1
|
256
256
|
|
257
257
|
pubkey, pubkey_len = FFI::MemoryPointer.new(:uchar, 65), FFI::MemoryPointer.new(:uint64).put_uint64(0, 65)
|
258
258
|
result = secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, flag)
|
259
|
-
raise "error serialize pubkey" unless result || pubkey_len.read_uint64 > 0
|
259
|
+
raise "error serialize pubkey" unless (result == 1) || pubkey_len.read_uint64 > 0
|
260
260
|
|
261
261
|
pubkey.read_string(pubkey_len.read_uint64)
|
262
262
|
end
|
@@ -9,7 +9,7 @@ module Bitcoin
|
|
9
9
|
attr_accessor :value
|
10
10
|
|
11
11
|
# pk_script output Script
|
12
|
-
|
12
|
+
attr_reader :pk_script, :pk_script_length
|
13
13
|
|
14
14
|
# p2sh redeem script (optional, not included in the serialized binary format)
|
15
15
|
attr_accessor :redeem_script
|
@@ -39,6 +39,7 @@ module Bitcoin
|
|
39
39
|
|
40
40
|
# parse raw binary data for transaction output
|
41
41
|
def parse_data_from_io(buf)
|
42
|
+
clear_parsed_script_cache
|
42
43
|
@value = buf.read(8).unpack("Q")[0]
|
43
44
|
@pk_script_length = Protocol.unpack_var_int_from_io(buf)
|
44
45
|
@pk_script = buf.read(@pk_script_length)
|
@@ -50,6 +51,10 @@ module Bitcoin
|
|
50
51
|
@parsed_script ||= Bitcoin::Script.new(pk_script)
|
51
52
|
end
|
52
53
|
|
54
|
+
def clear_parsed_script_cache
|
55
|
+
remove_instance_variable(:@parsed_script) if defined?(@parsed_script)
|
56
|
+
end
|
57
|
+
|
53
58
|
def to_payload
|
54
59
|
[@value].pack("Q") << Protocol.pack_var_int(@pk_script_length) << @pk_script
|
55
60
|
end
|
@@ -73,6 +78,7 @@ module Bitcoin
|
|
73
78
|
|
74
79
|
# set pk_script and pk_script_length
|
75
80
|
def pk_script=(pk_script)
|
81
|
+
clear_parsed_script_cache
|
76
82
|
@pk_script_length, @pk_script = pk_script.bytesize, pk_script
|
77
83
|
end
|
78
84
|
|
data/lib/bitcoin/script.rb
CHANGED
@@ -599,19 +599,19 @@ class Bitcoin::Script
|
|
599
599
|
@chunks[0] == OP_RETURN && @chunks.size <= 2
|
600
600
|
end
|
601
601
|
|
602
|
-
# is this a witness script
|
602
|
+
# is this a witness script
|
603
603
|
def is_witness?
|
604
|
-
|
604
|
+
@chunks.length == 2 && (0..16).include?(@chunks[0]) && @chunks[1].is_a?(String)
|
605
605
|
end
|
606
606
|
|
607
607
|
# is this a witness pubkey script
|
608
608
|
def is_witness_v0_keyhash?
|
609
|
-
|
609
|
+
is_witness? && @chunks[0] == 0 && @chunks[1].bytesize == 20
|
610
610
|
end
|
611
611
|
|
612
612
|
# is this a witness script hash
|
613
613
|
def is_witness_v0_scripthash?
|
614
|
-
|
614
|
+
is_witness? && @chunks[0] == 0 && @chunks[1].bytesize == 32
|
615
615
|
end
|
616
616
|
|
617
617
|
# Verify the script is only pushing data onto the stack
|
@@ -731,6 +731,12 @@ class Bitcoin::Script
|
|
731
731
|
return [get_hash160_address] if is_hash160?
|
732
732
|
return get_multisig_addresses if is_multisig?
|
733
733
|
return [get_p2sh_address] if is_p2sh?
|
734
|
+
|
735
|
+
if is_witness_v0_keyhash? || is_witness_v0_scripthash?
|
736
|
+
program_hex = chunks[1].unpack("H*").first
|
737
|
+
return Bitcoin.encode_segwit_address(0, program_hex)
|
738
|
+
end
|
739
|
+
|
734
740
|
[]
|
735
741
|
end
|
736
742
|
|
@@ -762,20 +768,28 @@ class Bitcoin::Script
|
|
762
768
|
[ ["a9", "14", p2sh, "87"].join ].pack("H*")
|
763
769
|
end
|
764
770
|
|
771
|
+
# generate pay-to-witness output script for given +witness_version+ and
|
772
|
+
# +witness_program+. returns a raw binary script of the form:
|
773
|
+
# <witness_version> <witness_program>
|
774
|
+
def self.to_witness_script(witness_version, witness_program_hex)
|
775
|
+
return nil unless (0..16).include?(witness_version)
|
776
|
+
return nil unless witness_program_hex
|
777
|
+
version = witness_version != 0 ? 0x50 + witness_version : 0 # 0x50 for OP_1.. codes
|
778
|
+
[version].pack('C') + pack_pushdata(witness_program_hex.htb)
|
779
|
+
end
|
780
|
+
|
765
781
|
# generate p2wpkh tx for given +address+. returns a raw binary script of the form:
|
766
782
|
# 0 <hash160>
|
767
783
|
def self.to_witness_hash160_script(hash160)
|
768
784
|
return nil unless hash160
|
769
|
-
|
770
|
-
[ ["00", "14", hash160].join ].pack("H*")
|
785
|
+
to_witness_script(0, hash160)
|
771
786
|
end
|
772
787
|
|
773
788
|
# generate p2wsh output script for given +p2sh+ sha256. returns a raw binary script of the form:
|
774
789
|
# 0 <p2sh>
|
775
790
|
def self.to_witness_p2sh_script(p2sh)
|
776
791
|
return nil unless p2sh
|
777
|
-
|
778
|
-
[ [ "00", "20", p2sh].join].pack("H*")
|
792
|
+
to_witness_script(0, p2sh)
|
779
793
|
end
|
780
794
|
|
781
795
|
# generate hash160 or p2sh output script, depending on the type of the given +address+.
|
@@ -785,6 +799,9 @@ class Bitcoin::Script
|
|
785
799
|
case Bitcoin.address_type(address)
|
786
800
|
when :hash160; to_hash160_script(hash160)
|
787
801
|
when :p2sh; to_p2sh_script(hash160)
|
802
|
+
when :witness_v0_keyhash, :witness_v0_scripthash
|
803
|
+
witness_version, witness_program_hex = Bitcoin.decode_segwit_address(address)
|
804
|
+
to_witness_script(witness_version, witness_program_hex)
|
788
805
|
end
|
789
806
|
end
|
790
807
|
|
data/lib/bitcoin/version.rb
CHANGED
@@ -0,0 +1,160 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require_relative 'spec_helper'
|
4
|
+
|
5
|
+
describe Bitcoin::Bech32 do
|
6
|
+
before do
|
7
|
+
Bitcoin.network = :bitcoin
|
8
|
+
|
9
|
+
@invalid_address_enc = [
|
10
|
+
["BC", 0, 20],
|
11
|
+
["bc", 0, 21],
|
12
|
+
["bc", 17, 32],
|
13
|
+
["bc", 1, 1],
|
14
|
+
["bc", 16, 41],
|
15
|
+
]
|
16
|
+
|
17
|
+
@valid_address = [
|
18
|
+
[
|
19
|
+
"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
|
20
|
+
22, [
|
21
|
+
0x00, 0x14, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
22
|
+
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6
|
23
|
+
]
|
24
|
+
],
|
25
|
+
[
|
26
|
+
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
|
27
|
+
34, [
|
28
|
+
0x00, 0x20, 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, 0x04,
|
29
|
+
0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, 0x6c, 0x98, 0x56, 0x78,
|
30
|
+
0xcd, 0x4d, 0x27, 0xa1, 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32,
|
31
|
+
0x62
|
32
|
+
]
|
33
|
+
],
|
34
|
+
[
|
35
|
+
"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx",
|
36
|
+
42, [
|
37
|
+
0x51, 0x28, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
38
|
+
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6,
|
39
|
+
0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c,
|
40
|
+
0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6
|
41
|
+
]
|
42
|
+
],
|
43
|
+
[
|
44
|
+
"BC1SW50QA3JX3S",
|
45
|
+
4, [
|
46
|
+
0x60, 0x02, 0x75, 0x1e
|
47
|
+
]
|
48
|
+
],
|
49
|
+
[
|
50
|
+
"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
|
51
|
+
18, [
|
52
|
+
0x52, 0x10, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
53
|
+
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23
|
54
|
+
]
|
55
|
+
],
|
56
|
+
[
|
57
|
+
"tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
|
58
|
+
34, [
|
59
|
+
0x00, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21,
|
60
|
+
0xb2, 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5,
|
61
|
+
0xe9, 0x1c, 0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64,
|
62
|
+
0x33
|
63
|
+
]
|
64
|
+
]
|
65
|
+
]
|
66
|
+
|
67
|
+
@valid_checksum = [
|
68
|
+
"A12UEL5L",
|
69
|
+
"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs",
|
70
|
+
"abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw",
|
71
|
+
"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j",
|
72
|
+
"split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w",
|
73
|
+
]
|
74
|
+
|
75
|
+
@invalid_checksum = [
|
76
|
+
" 1nwldj5",
|
77
|
+
"\x7f""1axkwrx",
|
78
|
+
"an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx",
|
79
|
+
"pzry9x0s0muk",
|
80
|
+
"1pzry9x0s0muk",
|
81
|
+
"x1b4n0q5v",
|
82
|
+
"li1dgmt3",
|
83
|
+
"de1lg7wt\xff",
|
84
|
+
]
|
85
|
+
|
86
|
+
@invalid_address = [
|
87
|
+
"tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty",
|
88
|
+
"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5",
|
89
|
+
"BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2",
|
90
|
+
"bc1rw5uspcuh",
|
91
|
+
"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90",
|
92
|
+
"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
|
93
|
+
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7",
|
94
|
+
"bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du",
|
95
|
+
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv",
|
96
|
+
"bc1gmk9yu",
|
97
|
+
]
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#decode and #encode' do
|
101
|
+
it "test vectors" do
|
102
|
+
@valid_checksum.each do |testdata|
|
103
|
+
hrp, data = Bitcoin::Bech32.decode(testdata)
|
104
|
+
newdata = Bitcoin::Bech32.encode(hrp, data)
|
105
|
+
newdata.should == testdata.downcase
|
106
|
+
end
|
107
|
+
|
108
|
+
@invalid_checksum.each do |testdata|
|
109
|
+
hrp, data = Bitcoin::Bech32.decode(testdata)
|
110
|
+
hrp.should == nil
|
111
|
+
end
|
112
|
+
|
113
|
+
@valid_address.each do |testdata, _, _|
|
114
|
+
hrp, data = Bitcoin::Bech32.decode(testdata)
|
115
|
+
newdata = Bitcoin::Bech32.encode(hrp, data)
|
116
|
+
newdata.should == testdata.downcase
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#decode_segwit_address and #encode_segwit_address' do
|
122
|
+
it "test vectors" do
|
123
|
+
@valid_address.each do |testaddress, _, testscript|
|
124
|
+
Bitcoin.network = :bitcoin
|
125
|
+
version, program = Bitcoin.decode_segwit_address(testaddress)
|
126
|
+
if version.nil?
|
127
|
+
Bitcoin.network = :testnet3
|
128
|
+
version, program = Bitcoin.decode_segwit_address(testaddress)
|
129
|
+
end
|
130
|
+
version.should != nil
|
131
|
+
|
132
|
+
script = Bitcoin::Script.to_witness_script(version, program)
|
133
|
+
script.should == testscript.pack("C*")
|
134
|
+
|
135
|
+
newaddress = Bitcoin.encode_segwit_address(version, program)
|
136
|
+
newaddress.should != nil
|
137
|
+
newaddress.should == testaddress.downcase
|
138
|
+
end
|
139
|
+
|
140
|
+
@invalid_address.each do |testaddress|
|
141
|
+
Bitcoin.network = :bitcoin
|
142
|
+
version, program = Bitcoin.decode_segwit_address(testaddress)
|
143
|
+
if version.nil?
|
144
|
+
Bitcoin.network = :testnet3
|
145
|
+
version, program = Bitcoin.decode_segwit_address(testaddress)
|
146
|
+
end
|
147
|
+
version.should == nil
|
148
|
+
end
|
149
|
+
|
150
|
+
Bitcoin.network = :bitcoin
|
151
|
+
@invalid_address_enc.each do |testhrp, testversion, testlength|
|
152
|
+
Bitcoin.network[:bech32_hrp] = testhrp
|
153
|
+
program_hex = Array.new(testlength){ 0 }.pack("C*").unpack("H*").first
|
154
|
+
newaddress = Bitcoin.encode_segwit_address(testversion, program_hex)
|
155
|
+
newaddress.should == nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|