bitcoinrb 0.2.5 → 0.2.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 895222030c0d0673f1524e112cf42d8cbb8e248558ba356e156a92b7482d4344
4
- data.tar.gz: cca9f6a8777925fcf39c47a835549b1894554e2d3c67400ba330487731677a89
3
+ metadata.gz: 2dea1d2e52223f2754f748f612c5d3df9606988476ee0c1f5b1ad03e71ba0ead
4
+ data.tar.gz: baedfcc44fdacd0c2c46766a360fb76404630bd01dbaf034664d358f5564d5b8
5
5
  SHA512:
6
- metadata.gz: cbb089fdfa71ac6a9c60591789c18b78af3fac81e6ba82ac264a50cd1d464b814f8989ca62fdde78910640e241f2b7e8c516b20b9e67eb979efae86c43b9b0ab
7
- data.tar.gz: bf0b6f27f6e4819569f3d814194b202f18d829bf315591ce8fa75db0846b2ef372ca45294537918ff7d161b37947f91be05562200d7028bc39b598ec83f01b26
6
+ metadata.gz: 851b762a403ebd8a0f175171e000650b76b5380522c174cbea3c03817477aa89e98b8a3e204c0cc3c223fb281dfbc75ae936cd1b1fe6e6f6b06ae5aeca74b335
7
+ data.tar.gz: 75fd1e350ab651a01b1eae0d0b6885ca933a60efcfc237ad75de55002777806aaf805c4a724430535521c421a10111871838d97bfaf94d93766f93e433e33160
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.0
1
+ 2.6.2
data/.travis.yml CHANGED
@@ -1,9 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3.8
4
3
  - 2.4.5
5
- - 2.5.3
6
- - 2.6.0
4
+ - 2.5.5
5
+ - 2.6.2
7
6
  addons:
8
7
  apt:
9
8
  packages:
data/README.md CHANGED
@@ -46,7 +46,7 @@ gem leveldb-ruby
46
46
  Add this line to your application's Gemfile:
47
47
 
48
48
  ```ruby
49
- gem 'bitcoinrb'
49
+ gem 'bitcoinrb', require: 'bitcoin'
50
50
  ```
51
51
 
52
52
  And then execute:
@@ -57,6 +57,9 @@ Or install it yourself as:
57
57
 
58
58
  $ gem install bitcoinrb
59
59
 
60
+ And then add to your .rb file:
61
+
62
+ require 'bitcoin'
60
63
 
61
64
  ## Usage
62
65
 
data/bitcoinrb.gemspec CHANGED
@@ -32,13 +32,13 @@ Gem::Specification.new do |spec|
32
32
  spec.add_runtime_dependency 'rest-client'
33
33
  spec.add_runtime_dependency 'iniparse'
34
34
  spec.add_runtime_dependency 'siphash'
35
- spec.add_runtime_dependency 'protobuf'
35
+ spec.add_runtime_dependency 'protobuf', '3.8.5'
36
36
  spec.add_runtime_dependency 'scrypt'
37
37
 
38
38
  # for options
39
39
  spec.add_development_dependency 'leveldb-ruby'
40
40
 
41
- spec.add_development_dependency 'bundler', '~> 1.11'
41
+ spec.add_development_dependency 'bundler'
42
42
  spec.add_development_dependency 'rake', '~> 10.0'
43
43
  spec.add_development_dependency 'rspec', '~> 3.0'
44
44
  spec.add_development_dependency 'timecop'
@@ -25,7 +25,7 @@ module Bitcoin
25
25
  int_val = 0
26
26
  base58_val.reverse.split(//).each_with_index do |char,index|
27
27
  raise ArgumentError, 'Value passed not a valid Base58 String.' if (char_index = ALPHABET.index(char)).nil?
28
- int_val += char_index * (SIZE**index)
28
+ int_val += char_index * (SIZE ** index)
29
29
  end
30
30
  s = int_val.to_even_length_hex
31
31
  s = '' if s == '00'
@@ -2,7 +2,7 @@ module Bitcoin
2
2
 
3
3
  class BitStreamWriter
4
4
 
5
- MAX_BIT = 2**64
5
+ MAX_BIT = 4611686018427387904 # 2**64
6
6
 
7
7
  attr_reader :stream
8
8
  attr_accessor :buffer
@@ -28,7 +28,7 @@ module Bitcoin
28
28
 
29
29
  def flush
30
30
  return if offset == 0
31
- self.stream << [buffer.to_even_length_hex].pack('H*')
31
+ self.stream << buffer.itb
32
32
  self.offset = 0
33
33
  self.buffer = 0
34
34
  end
@@ -70,7 +70,7 @@ module Bitcoin
70
70
  def work
71
71
  target = difficulty_target
72
72
  return 0 if target < 1
73
- (2**256) / (target + 1)
73
+ 115792089237316195423570985008687907853269984665640564039457584007913129639936.div(target + 1) # 115792089237316195423570985008687907853269984665640564039457584007913129639936 is 2**256
74
74
  end
75
75
 
76
76
  def ==(other)
@@ -3,6 +3,8 @@ module Bitcoin
3
3
  # Integers modulo the order of the curve(secp256k1)
4
4
  CURVE_ORDER = ECDSA::Group::Secp256k1.order
5
5
 
6
+ HARDENED_THRESHOLD = 2147483648 # 2**31
7
+
6
8
  # BIP32 Extended private key
7
9
  class ExtKey
8
10
 
@@ -83,7 +85,7 @@ module Bitcoin
83
85
 
84
86
  # whether hardened key.
85
87
  def hardened?
86
- number >= 2**31
88
+ number >= HARDENED_THRESHOLD
87
89
  end
88
90
 
89
91
  # derive new key
@@ -91,12 +93,12 @@ module Bitcoin
91
93
  # @param [Boolean] harden whether hardened key or not. If true, 2^31 is added to +number+.
92
94
  # @return [Bitcoin::ExtKey] derived new key.
93
95
  def derive(number, harden = false)
94
- number += 2**31 if harden
96
+ number += HARDENED_THRESHOLD if harden
95
97
  new_key = ExtKey.new
96
98
  new_key.depth = depth + 1
97
99
  new_key.number = number
98
100
  new_key.parent_fingerprint = fingerprint
99
- if number > (2**31 -1)
101
+ if number > (HARDENED_THRESHOLD - 1)
100
102
  data = [0x00].pack('C') << key.priv_key.htb << [number].pack('N')
101
103
  else
102
104
  data = key.pubkey.htb << [number].pack('N')
@@ -153,7 +155,7 @@ module Bitcoin
153
155
 
154
156
  # get version bytes from purpose' value.
155
157
  def self.version_from_purpose(purpose)
156
- v = purpose - 2**31
158
+ v = purpose - HARDENED_THRESHOLD
157
159
  case v
158
160
  when 49
159
161
  Bitcoin.chain_params.bip49_privkey_p2wpkh_p2sh_version
@@ -245,7 +247,7 @@ module Bitcoin
245
247
 
246
248
  # whether hardened key.
247
249
  def hardened?
248
- number >= 2**31
250
+ number >= HARDENED_THRESHOLD
249
251
  end
250
252
 
251
253
  # derive child key
@@ -254,7 +256,7 @@ module Bitcoin
254
256
  new_key.depth = depth + 1
255
257
  new_key.number = number
256
258
  new_key.parent_fingerprint = fingerprint
257
- raise 'hardened key is not support' if number > (2**31 -1)
259
+ raise 'hardened key is not support' if number > (HARDENED_THRESHOLD - 1)
258
260
  data = pub.htb << [number].pack('N')
259
261
  l = Bitcoin.hmac_sha512(chain_code, data)
260
262
  left = l[0..31].bth.to_i(16)
@@ -306,7 +308,7 @@ module Bitcoin
306
308
 
307
309
  # get version bytes from purpose' value.
308
310
  def self.version_from_purpose(purpose)
309
- v = purpose - 2**31
311
+ v = purpose - HARDENED_THRESHOLD
310
312
  case v
311
313
  when 49
312
314
  Bitcoin.chain_params.bip49_pubkey_p2wpkh_p2sh_version
@@ -6,6 +6,8 @@ module Bitcoin
6
6
  # see https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
7
7
  class GCSFilter
8
8
 
9
+ MAX_ELEMENTS_SIZE = 4294967296 # 2**32
10
+
9
11
  attr_reader :p # Golomb-Rice coding parameter
10
12
  attr_reader :m # Inverse false positive rate
11
13
  attr_reader :n # Number of elements in the filter
@@ -26,7 +28,7 @@ module Bitcoin
26
28
  @p = p
27
29
  @m = m
28
30
  if elements
29
- raise 'elements size must be < 2**32.' if elements.size >= (2**32)
31
+ raise 'elements size must be < 2**32.' if elements.size >= MAX_ELEMENTS_SIZE
30
32
  @n = elements.size
31
33
  encoded = Bitcoin.pack_var_int(@n)
32
34
  bit_writer = Bitcoin::BitStreamWriter.new
data/lib/bitcoin/key.rb CHANGED
@@ -18,7 +18,7 @@ module Bitcoin
18
18
 
19
19
  TYPES = {uncompressed: 0x00, compressed: 0x01, p2pkh: 0x10, p2wpkh: 0x11, pw2pkh_p2sh: 0x12}
20
20
 
21
- MIN_PRIV_KEy_MOD_ORDER = 0x01
21
+ MIN_PRIV_KEY_MOD_ORDER = 0x01
22
22
  # Order of secp256k1's generator minus 1.
23
23
  MAX_PRIV_KEY_MOD_ORDER = ECDSA::Group::Secp256k1.order - 1
24
24
 
@@ -253,15 +253,13 @@ module Bitcoin
253
253
  # @param [Boolean] compressed pubkey compressed?
254
254
  # @return [String] a pubkey which generate from privkey
255
255
  def generate_pubkey(privkey, compressed: true)
256
- public_key = ECDSA::Group::Secp256k1.generator.multiply_by_scalar(privkey.to_i(16))
257
- pubkey = ECDSA::Format::PointOctetString.encode(public_key, compression: compressed)
258
- pubkey.bth
256
+ @secp256k1_module.generate_pubkey(privkey, compressed: compressed)
259
257
  end
260
258
 
261
259
  # check private key range.
262
260
  def validate_private_key_range(private_key)
263
261
  value = private_key.to_i(16)
264
- MIN_PRIV_KEy_MOD_ORDER <= value && value <= MAX_PRIV_KEY_MOD_ORDER
262
+ MIN_PRIV_KEY_MOD_ORDER <= value && value <= MAX_PRIV_KEY_MOD_ORDER
265
263
  end
266
264
 
267
265
  # Supported violations include negative integers, excessive padding, garbage
@@ -100,11 +100,12 @@ module Bitcoin
100
100
  payload << PSBT.serialize_to_vector(PSBT_IN_TYPES[:script_sig], value: final_script_sig.to_payload) if final_script_sig
101
101
  payload << PSBT.serialize_to_vector(PSBT_IN_TYPES[:script_witness], value: final_script_witness.to_payload) if final_script_witness
102
102
  payload << unknowns.map {|k,v|Bitcoin.pack_var_int(k.htb.bytesize) << k.htb << Bitcoin.pack_var_int(v.bytesize) << v}.join
103
- payload << PSBT_SEPARATOR.to_even_length_hex.htb
103
+ payload << PSBT_SEPARATOR.itb
104
104
  payload
105
105
  end
106
106
 
107
107
  # Sanity check
108
+ # @return [Boolean]
108
109
  def sane?
109
110
  return false if non_witness_utxo && witness_utxo
110
111
  return false if witness_script && witness_utxo.nil?
@@ -112,6 +113,33 @@ module Bitcoin
112
113
  true
113
114
  end
114
115
 
116
+ # Check whether input's scriptPubkey is correct witness.
117
+ # @return [Boolean]
118
+ def valid_witness_input?
119
+ return true if witness_utxo.script_pubkey.p2wpkh? # P2WPKH
120
+ return true if witness_utxo.script_pubkey.p2wsh? && witness_utxo.script_pubkey == redeem_script.to_p2wsh # P2WSH
121
+ return true if witness_utxo.script_pubkey.p2sh? && redeem_script&.witness_program? && # segwit nested in P2SH
122
+ redeem_script.to_p2sh == witness_utxo.script_pubkey && witness_script&.to_sha256 == redeem_script.witness_data[1].bth
123
+ false
124
+ end
125
+
126
+ # Check whether input's scriptPubkey is correct witness.
127
+ # @return [Boolean]
128
+ def valid_non_witness_input?
129
+ non_witness_utxo.outputs.each do |o|
130
+ return true if o.script_pubkey.p2sh? && redeem_script.to_p2sh == o.script_pubkey
131
+ end
132
+ false
133
+ end
134
+
135
+ # Check whether the signer can sign this input.
136
+ # @return [Boolean]
137
+ def ready_to_sign?
138
+ return false unless sane?
139
+ return valid_witness_input? if witness_utxo
140
+ valid_non_witness_input? # non_witness_utxo
141
+ end
142
+
115
143
  # add signature as partial sig.
116
144
  # @param [String] pubkey a public key with hex format.
117
145
  # @param [String] sig a signature.
@@ -132,7 +160,7 @@ module Bitcoin
132
160
  raise ArgumentError, 'The Partially Signed Input\'s redeem_script are different.' unless redeem_script == psbi.redeem_script
133
161
  raise ArgumentError, 'The Partially Signed Input\'s witness_script are different.' unless witness_script == psbi.witness_script
134
162
  combined = Bitcoin::PSBT::Input.new(non_witness_utxo: non_witness_utxo, witness_utxo: witness_utxo)
135
- combined.unknowns = unknowns.merge(psbi.unknowns)
163
+ combined.unknowns = Hash[unknowns.merge(psbi.unknowns).sort]
136
164
  combined.redeem_script = redeem_script
137
165
  combined.witness_script = witness_script
138
166
  combined.sighash_type = sighash_type
@@ -52,7 +52,7 @@ module Bitcoin
52
52
  payload << PSBT.serialize_to_vector(PSBT_OUT_TYPES[:witness_script], value: witness_script) if witness_script
53
53
  payload << hd_key_paths.values.map{|v|v.to_payload(PSBT_OUT_TYPES[:bip32_derivation])}.join
54
54
  payload << unknowns.map {|k,v|Bitcoin.pack_var_int(k.htb.bytesize) << k.htb << Bitcoin.pack_var_int(v.bytesize) << v}.join
55
- payload << PSBT_SEPARATOR.to_even_length_hex.htb
55
+ payload << PSBT_SEPARATOR.itb
56
56
  payload
57
57
  end
58
58
 
@@ -66,7 +66,7 @@ module Bitcoin
66
66
  combined = Bitcoin::PSBT::Output.new
67
67
  combined.redeem_script = redeem_script
68
68
  combined.witness_script = witness_script
69
- combined.unknowns = unknowns.merge(psbo.unknowns)
69
+ combined.unknowns = Hash[unknowns.merge(psbo.unknowns).sort]
70
70
  combined.hd_key_paths = hd_key_paths.merge(psbo.hd_key_paths)
71
71
  combined
72
72
  end
@@ -86,13 +86,13 @@ module Bitcoin
86
86
  # generate payload.
87
87
  # @return [String] a payload with binary format.
88
88
  def to_payload
89
- payload = PSBT_MAGIC_BYTES.to_even_length_hex.htb << 0xff.to_even_length_hex.htb
89
+ payload = PSBT_MAGIC_BYTES.itb << 0xff.itb
90
90
 
91
91
  payload << PSBT.serialize_to_vector(PSBT_GLOBAL_TYPES[:unsigned_tx], value: tx.to_payload)
92
92
 
93
93
  payload << unknowns.map {|k,v|Bitcoin.pack_var_int(k.htb.bytesize) << k.htb << Bitcoin.pack_var_int(v.bytesize) << v}.join
94
94
 
95
- payload << PSBT_SEPARATOR.to_even_length_hex.htb
95
+ payload << PSBT_SEPARATOR.itb
96
96
 
97
97
  payload << inputs.map(&:to_payload).join
98
98
  payload << outputs.map(&:to_payload).join
@@ -129,6 +129,16 @@ module Bitcoin
129
129
  end
130
130
  end
131
131
 
132
+ # Check whether the signer can sign. Specifically, check the following.
133
+ # * If a non-witness UTXO is provided, its hash must match the hash specified in the prevout
134
+ # * If a witness UTXO is provided, no non-witness signature may be created
135
+ # * If a redeemScript is provided, the scriptPubKey must be for that redeemScript
136
+ # * If a witnessScript is provided, the scriptPubKey or the redeemScript must be for that witnessScript
137
+ # @return [Boolean]
138
+ def ready_to_sign?
139
+ inputs.all?(&:ready_to_sign?)
140
+ end
141
+
132
142
  # get signature script of input specified by +index+
133
143
  # @param [Integer] index input index.
134
144
  # @return [Bitcoin::Script]
@@ -158,7 +168,8 @@ module Bitcoin
158
168
  outputs.each_with_index do |o, index|
159
169
  combined.outputs[index] = o.merge(psbt.outputs[index])
160
170
  end
161
- combined.unknowns = unknowns.merge(psbt.unknowns)
171
+
172
+ combined.unknowns = Hash[unknowns.merge(psbt.unknowns).sort]
162
173
  combined
163
174
  end
164
175
 
data/lib/bitcoin/psbt.rb CHANGED
@@ -21,7 +21,7 @@ module Bitcoin
21
21
  module_function
22
22
 
23
23
  def self.serialize_to_vector(key_type, key: nil, value: nil)
24
- key_len = key_type.to_even_length_hex.htb.bytesize
24
+ key_len = key_type.itb.bytesize
25
25
  key_len += key.bytesize if key
26
26
  s = Bitcoin.pack_var_int(key_len) << Bitcoin.pack_var_int(key_type)
27
27
  s << key if key
@@ -26,6 +26,7 @@ module Bitcoin
26
26
  def getblockheader(block_id, verbose)
27
27
  block_hash = block_id.rhex
28
28
  entry = node.chain.find_entry_by_hash(block_hash)
29
+ raise ArgumentError.new('Block not found') unless entry
29
30
  if verbose
30
31
  {
31
32
  hash: block_id,
@@ -78,23 +78,8 @@ module Bitcoin
78
78
  priv_key = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, SecureRandom.random_bytes(32))
79
79
  ret = secp256k1_ec_seckey_verify(context, priv_key)
80
80
  end
81
-
82
- internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
83
- result = secp256k1_ec_pubkey_create(context, internal_pubkey, priv_key)
84
- raise 'error creating pubkey' unless result
85
-
86
- pubkey = FFI::MemoryPointer.new(:uchar, 65)
87
- pubkey_len = FFI::MemoryPointer.new(:uint64)
88
- result = if compressed
89
- pubkey_len.put_uint64(0, 33)
90
- secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_COMPRESSED)
91
- else
92
- pubkey_len.put_uint64(0, 65)
93
- secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_UNCOMPRESSED)
94
- end
95
- raise 'error serialize pubkey' unless result || pubkey_len.read_uint64 > 0
96
-
97
- [ priv_key.read_string(32).bth, pubkey.read_string(pubkey_len.read_uint64).bth ]
81
+ private_key = priv_key.read_string(32).bth
82
+ [private_key , generate_pubkey_in_context(context, private_key, compressed: compressed) ]
98
83
  end
99
84
  end
100
85
 
@@ -104,6 +89,12 @@ module Bitcoin
104
89
  Bitcoin::Key.new(priv_key: privkey, pubkey: pubkey, compressed: compressed)
105
90
  end
106
91
 
92
+ def generate_pubkey(priv_key, compressed: true)
93
+ with_context do |context|
94
+ generate_pubkey_in_context(context, priv_key, compressed: compressed)
95
+ end
96
+ end
97
+
107
98
  # sign data.
108
99
  # @param [String] data a data to be signed with binary format
109
100
  # @param [String] privkey a private key using sign
@@ -159,7 +150,25 @@ module Bitcoin
159
150
  end
160
151
  end
161
152
 
153
+ private
154
+
155
+ def generate_pubkey_in_context(context, privkey, compressed: true)
156
+ internal_pubkey = FFI::MemoryPointer.new(:uchar, 64)
157
+ result = secp256k1_ec_pubkey_create(context, internal_pubkey, privkey.htb)
158
+ raise 'error creating pubkey' unless result
159
+
160
+ pubkey = FFI::MemoryPointer.new(:uchar, 65)
161
+ pubkey_len = FFI::MemoryPointer.new(:uint64)
162
+ result = if compressed
163
+ pubkey_len.put_uint64(0, 33)
164
+ secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_COMPRESSED)
165
+ else
166
+ pubkey_len.put_uint64(0, 65)
167
+ secp256k1_ec_pubkey_serialize(context, pubkey, pubkey_len, internal_pubkey, SECP256K1_EC_UNCOMPRESSED)
168
+ end
169
+ raise 'error serialize pubkey' unless result || pubkey_len.read_uint64 > 0
170
+ pubkey.read_string(pubkey_len.read_uint64).bth
171
+ end
162
172
  end
163
-
164
173
  end
165
174
  end
@@ -22,6 +22,11 @@ module Bitcoin
22
22
  Bitcoin::Key.new(priv_key: privkey, pubkey: pubkey, compressed: compressed)
23
23
  end
24
24
 
25
+ def generate_pubkey(privkey, compressed: true)
26
+ public_key = ECDSA::Group::Secp256k1.generator.multiply_by_scalar(privkey.to_i(16))
27
+ ECDSA::Format::PointOctetString.encode(public_key, compression: compressed).bth
28
+ end
29
+
25
30
  # sign data.
26
31
  # @param [String] data a data to be signed with binary format
27
32
  # @param [String] privkey a private key using sign
@@ -36,6 +36,7 @@ module Bitcoin
36
36
  # find block entry with the specified hash
37
37
  def find_entry_by_hash(hash)
38
38
  payload = db.get_entry_payload_from_hash(hash)
39
+ return nil unless payload
39
40
  ChainEntry.parse_from_payload(payload)
40
41
  end
41
42
 
data/lib/bitcoin/util.rb CHANGED
@@ -31,6 +31,7 @@ module Bitcoin
31
31
  end
32
32
  end
33
33
 
34
+ # @return an integer for a valid payload, otherwise nil
34
35
  def unpack_var_int(payload)
35
36
  case payload.unpack('C').first
36
37
  when 0xfd
@@ -44,15 +45,16 @@ module Bitcoin
44
45
  end
45
46
  end
46
47
 
48
+ # @return an integer for a valid payload, otherwise nil
47
49
  def unpack_var_int_from_io(buf)
48
- uchar = buf.read(1).unpack('C').first
50
+ uchar = buf.read(1)&.unpack('C')&.first
49
51
  case uchar
50
52
  when 0xfd
51
- buf.read(2).unpack('v').first
53
+ buf.read(2)&.unpack('v')&.first
52
54
  when 0xfe
53
- buf.read(4).unpack('V').first
55
+ buf.read(4)&.unpack('V')&.first
54
56
  when 0xff
55
- buf.read(8).unpack('Q').first
57
+ buf.read(8)&.unpack('Q')&.first
56
58
  else
57
59
  uchar
58
60
  end
@@ -1,3 +1,3 @@
1
1
  module Bitcoin
2
- VERSION = "0.2.5"
2
+ VERSION = "0.2.6"
3
3
  end
@@ -140,8 +140,8 @@ module Bitcoin
140
140
 
141
141
  def validate_params!(account_key, purpose, index)
142
142
  raise 'account_key must be an instance of Bitcoin::ExtPubkey.' unless account_key.is_a?(Bitcoin::ExtPubkey)
143
- raise 'Account key and index does not match.' unless account_key.number == (index + 2**31)
144
- version_bytes = Bitcoin::ExtPubkey.version_from_purpose(purpose + 2**31)
143
+ raise 'Account key and index does not match.' unless account_key.number == (index + Bitcoin::HARDENED_THRESHOLD)
144
+ version_bytes = Bitcoin::ExtPubkey.version_from_purpose(purpose + Bitcoin::HARDENED_THRESHOLD)
145
145
  raise 'The purpose and the account key do not match.' unless account_key.version == version_bytes
146
146
  end
147
147
 
@@ -71,7 +71,7 @@ module Bitcoin
71
71
  next
72
72
  end
73
73
  raise ArgumentError.new("#{path} is invalid format.") unless p.delete("'") =~ /^[0-9]+$/
74
- num = (p[-1] == "'" ? p.delete("'").to_i + 2**31 : p.to_i)
74
+ num = (p[-1] == "'" ? p.delete("'").to_i + Bitcoin::HARDENED_THRESHOLD : p.to_i)
75
75
  derived_key = derived_key.derive(num)
76
76
  end
77
77
  derived_key
data/lib/bitcoin.rb CHANGED
@@ -186,6 +186,10 @@ module Bitcoin
186
186
  hex = to_s(16)
187
187
  hex.rjust((hex.length / 2.0).ceil * 2, '0')
188
188
  end
189
+
190
+ def itb
191
+ to_even_length_hex.htb
192
+ end
189
193
  end
190
194
 
191
195
  class ::ECDSA::Signature
@@ -24,14 +24,19 @@ module OpenAssets
24
24
  version = buf.read(2)
25
25
  return nil if marker != MARKER || version != VERSION
26
26
  count = Bitcoin.unpack_var_int_from_io(buf)
27
+ return nil unless count
27
28
  quantities = []
28
29
  count.times do
29
30
  quantities << LEB128.decode_unsigned(buf, buf.pos)
30
31
  end
31
32
  metadata_length = Bitcoin.unpack_var_int_from_io(buf)
32
- return nil if buf.length < metadata_length + buf.pos
33
+ return nil if metadata_length.nil? || buf.length < metadata_length + buf.pos
33
34
  metadata = buf.read(metadata_length).each_byte.map(&:chr).join
34
35
  new(quantities, metadata)
36
+ rescue
37
+ # LEB128#decode_unsigned raise 'undefined method `unpack' for nil:NilClass'
38
+ # for invalid format such as "018f8f" (the most significant bit of the last byte should be 0)
39
+ nil
35
40
  end
36
41
 
37
42
  # generate binary payload
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.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - azuchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-14 00:00:00.000000000 Z
11
+ date: 2019-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ecdsa
@@ -182,16 +182,16 @@ dependencies:
182
182
  name: protobuf
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - ">="
185
+ - - '='
186
186
  - !ruby/object:Gem::Version
187
- version: '0'
187
+ version: 3.8.5
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: '0'
194
+ version: 3.8.5
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: scrypt
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -224,16 +224,16 @@ dependencies:
224
224
  name: bundler
225
225
  requirement: !ruby/object:Gem::Requirement
226
226
  requirements:
227
- - - "~>"
227
+ - - ">="
228
228
  - !ruby/object:Gem::Version
229
- version: '1.11'
229
+ version: '0'
230
230
  type: :development
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
233
233
  requirements:
234
- - - "~>"
234
+ - - ">="
235
235
  - !ruby/object:Gem::Version
236
- version: '1.11'
236
+ version: '0'
237
237
  - !ruby/object:Gem::Dependency
238
238
  name: rake
239
239
  requirement: !ruby/object:Gem::Requirement
@@ -439,7 +439,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
439
439
  - !ruby/object:Gem::Version
440
440
  version: '0'
441
441
  requirements: []
442
- rubygems_version: 3.0.1
442
+ rubygems_version: 3.0.3
443
443
  signing_key:
444
444
  specification_version: 4
445
445
  summary: "[WIP]The implementation of Bitcoin Protocol for Ruby."