bitcoinrb 0.3.1 → 0.7.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +6 -3
  4. data/README.md +17 -6
  5. data/bitcoinrb.gemspec +9 -8
  6. data/exe/bitcoinrbd +5 -0
  7. data/lib/bitcoin.rb +35 -19
  8. data/lib/bitcoin/bip85_entropy.rb +111 -0
  9. data/lib/bitcoin/block_filter.rb +14 -0
  10. data/lib/bitcoin/block_header.rb +2 -0
  11. data/lib/bitcoin/chain_params.rb +9 -8
  12. data/lib/bitcoin/chainparams/regtest.yml +1 -1
  13. data/lib/bitcoin/chainparams/signet.yml +39 -0
  14. data/lib/bitcoin/chainparams/testnet.yml +1 -1
  15. data/lib/bitcoin/constants.rb +45 -12
  16. data/lib/bitcoin/descriptor.rb +1 -1
  17. data/lib/bitcoin/errors.rb +19 -0
  18. data/lib/bitcoin/ext.rb +5 -0
  19. data/lib/bitcoin/ext/ecdsa.rb +31 -0
  20. data/lib/bitcoin/ext/json_parser.rb +46 -0
  21. data/lib/bitcoin/ext_key.rb +50 -19
  22. data/lib/bitcoin/key.rb +46 -29
  23. data/lib/bitcoin/key_path.rb +12 -5
  24. data/lib/bitcoin/message.rb +79 -0
  25. data/lib/bitcoin/message/addr_v2.rb +34 -0
  26. data/lib/bitcoin/message/base.rb +17 -0
  27. data/lib/bitcoin/message/cf_parser.rb +16 -0
  28. data/lib/bitcoin/message/cfcheckpt.rb +36 -0
  29. data/lib/bitcoin/message/cfheaders.rb +40 -0
  30. data/lib/bitcoin/message/cfilter.rb +35 -0
  31. data/lib/bitcoin/message/fee_filter.rb +1 -1
  32. data/lib/bitcoin/message/filter_load.rb +3 -3
  33. data/lib/bitcoin/message/get_cfcheckpt.rb +29 -0
  34. data/lib/bitcoin/message/get_cfheaders.rb +24 -0
  35. data/lib/bitcoin/message/get_cfilters.rb +25 -0
  36. data/lib/bitcoin/message/header_and_short_ids.rb +1 -1
  37. data/lib/bitcoin/message/inventory.rb +1 -1
  38. data/lib/bitcoin/message/merkle_block.rb +1 -1
  39. data/lib/bitcoin/message/network_addr.rb +141 -18
  40. data/lib/bitcoin/message/ping.rb +1 -1
  41. data/lib/bitcoin/message/pong.rb +1 -1
  42. data/lib/bitcoin/message/send_addr_v2.rb +13 -0
  43. data/lib/bitcoin/message/send_cmpct.rb +2 -2
  44. data/lib/bitcoin/message/version.rb +7 -0
  45. data/lib/bitcoin/mnemonic.rb +7 -7
  46. data/lib/bitcoin/network/peer.rb +9 -4
  47. data/lib/bitcoin/network/peer_discovery.rb +1 -1
  48. data/lib/bitcoin/node/cli.rb +14 -10
  49. data/lib/bitcoin/node/configuration.rb +3 -1
  50. data/lib/bitcoin/node/spv.rb +9 -1
  51. data/lib/bitcoin/opcodes.rb +14 -1
  52. data/lib/bitcoin/out_point.rb +7 -0
  53. data/lib/bitcoin/payment_code.rb +92 -0
  54. data/lib/bitcoin/psbt/hd_key_path.rb +1 -1
  55. data/lib/bitcoin/psbt/input.rb +8 -17
  56. data/lib/bitcoin/psbt/output.rb +1 -1
  57. data/lib/bitcoin/psbt/tx.rb +11 -16
  58. data/lib/bitcoin/rpc/bitcoin_core_client.rb +22 -12
  59. data/lib/bitcoin/rpc/request_handler.rb +3 -3
  60. data/lib/bitcoin/script/script.rb +68 -28
  61. data/lib/bitcoin/script/script_error.rb +27 -1
  62. data/lib/bitcoin/script/script_interpreter.rb +164 -67
  63. data/lib/bitcoin/script/tx_checker.rb +64 -14
  64. data/lib/bitcoin/secp256k1.rb +1 -0
  65. data/lib/bitcoin/secp256k1/native.rb +138 -25
  66. data/lib/bitcoin/secp256k1/rfc6979.rb +43 -0
  67. data/lib/bitcoin/secp256k1/ruby.rb +82 -54
  68. data/lib/bitcoin/sighash_generator.rb +156 -0
  69. data/lib/bitcoin/store.rb +2 -1
  70. data/lib/bitcoin/store/chain_entry.rb +1 -0
  71. data/lib/bitcoin/store/db/level_db.rb +2 -2
  72. data/lib/bitcoin/store/utxo_db.rb +226 -0
  73. data/lib/bitcoin/tx.rb +17 -88
  74. data/lib/bitcoin/tx_in.rb +4 -5
  75. data/lib/bitcoin/tx_out.rb +2 -3
  76. data/lib/bitcoin/util.rb +34 -6
  77. data/lib/bitcoin/version.rb +1 -1
  78. data/lib/bitcoin/wallet.rb +1 -0
  79. data/lib/bitcoin/wallet/account.rb +2 -1
  80. data/lib/bitcoin/wallet/base.rb +3 -3
  81. data/lib/bitcoin/wallet/db.rb +1 -1
  82. data/lib/bitcoin/wallet/master_key.rb +1 -0
  83. data/lib/bitcoin/wallet/utxo.rb +37 -0
  84. metadata +66 -32
data/lib/bitcoin/store.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'leveldb'
1
+ require 'leveldb-native'
2
2
 
3
3
  module Bitcoin
4
4
  module Store
@@ -6,6 +6,7 @@ module Bitcoin
6
6
  autoload :DB, 'bitcoin/store/db'
7
7
  autoload :SPVChain, 'bitcoin/store/spv_chain'
8
8
  autoload :ChainEntry, 'bitcoin/store/chain_entry'
9
+ autoload :UtxoDB, 'bitcoin/store/utxo_db'
9
10
 
10
11
  end
11
12
  end
@@ -3,6 +3,7 @@ module Bitcoin
3
3
 
4
4
  # wrap a block header object with extra data.
5
5
  class ChainEntry
6
+ include Bitcoin::HexConverter
6
7
 
7
8
  attr_reader :header
8
9
  attr_reader :height
@@ -1,4 +1,4 @@
1
- require 'leveldb'
1
+ require 'leveldb-native'
2
2
 
3
3
  module Bitcoin
4
4
  module Store
@@ -12,7 +12,7 @@ module Bitcoin
12
12
  def initialize(path = "#{Bitcoin.base_dir}/db/spv")
13
13
  # @logger = Bitcoin::Logger.create(:debug)
14
14
  FileUtils.mkdir_p(path)
15
- @db = ::LevelDB::DB.new(path)
15
+ @db = ::LevelDBNative::DB.new(path)
16
16
  # logger.debug 'Opened LevelDB successfully.'
17
17
  end
18
18
 
@@ -0,0 +1,226 @@
1
+ require 'leveldb-native'
2
+
3
+ module Bitcoin
4
+ module Store
5
+ class UtxoDB
6
+
7
+ KEY_PREFIX = {
8
+ out_point: 'o', # key: out_point(tx_hash and index), value: Utxo
9
+ script: 's', # key: script_pubkey and out_point(tx_hash and index), value: Utxo
10
+ height: 'h', # key: block_height and out_point, value: Utxo
11
+ tx_hash: 't', # key: tx_hash of transaction, value: [block_height, tx_index]
12
+ block: 'b', # key: block_height and tx_index, value: tx_hash
13
+ tx_payload: 'p', # key: tx_hash, value: Tx
14
+ }
15
+
16
+ attr_reader :level_db, :logger
17
+
18
+ def initialize(path = "#{Bitcoin.base_dir}/db/utxo")
19
+ FileUtils.mkdir_p(path)
20
+ @level_db = ::LevelDBNative::DB.new(path)
21
+ @logger = Bitcoin::Logger.create(:debug)
22
+ end
23
+
24
+ def close
25
+ level_db.close
26
+ end
27
+
28
+ # Save payload of a transaction into db
29
+ #
30
+ # @param [String] tx_hash
31
+ # @param [String] tx_payload
32
+ def save_tx(tx_hash, tx_payload)
33
+ logger.info("UtxoDB#save_tx:#{[tx_hash, tx_payload]}")
34
+ level_db.batch do
35
+ # tx_hash -> [block_height, tx_index]
36
+ key = KEY_PREFIX[:tx_payload] + tx_hash
37
+ level_db.put(key, tx_payload)
38
+ end
39
+ end
40
+
41
+ # Save tx position (block height and index in the block) into db
42
+ # When node receives `header` message, node should call save_tx_position to store block height and its index.
43
+ #
44
+ # @param [String] tx_hash
45
+ # @param [Integer] block_height
46
+ # @param [Integer] tx_index
47
+ def save_tx_position(tx_hash, block_height, tx_index)
48
+ logger.info("UtxoDB#save_tx_position:#{[tx_hash, block_height, tx_index]}")
49
+ level_db.batch do
50
+ # tx_hash -> [block_height, tx_index]
51
+ key = KEY_PREFIX[:tx_hash] + tx_hash
52
+ level_db.put(key, [block_height, tx_index].pack('N2').bth)
53
+
54
+ # block_hash and tx_index -> tx_hash
55
+ key = KEY_PREFIX[:block] + [block_height, tx_index].pack('N2').bth
56
+ level_db.put(key, tx_hash)
57
+ end
58
+ end
59
+
60
+ # Save utxo into db
61
+ #
62
+ # @param [Bitcoin::OutPoint] out_point
63
+ # @param [Double] value
64
+ # @param [Bitcoin::Script] script_pubkey
65
+ # @param [Integer] block_height
66
+ def save_utxo(out_point, value, script_pubkey, block_height=nil)
67
+ logger.info("UtxoDB#save_utxo:#{[out_point, value, script_pubkey, block_height]}")
68
+ level_db.batch do
69
+ utxo = Bitcoin::Wallet::Utxo.new(out_point.tx_hash, out_point.index, value, script_pubkey, block_height)
70
+ payload = utxo.to_payload
71
+
72
+ # out_point
73
+ key = KEY_PREFIX[:out_point] + out_point.to_hex
74
+ return if level_db.contains?(key)
75
+ level_db.put(key, payload)
76
+
77
+ # script_pubkey
78
+ if script_pubkey
79
+ key = KEY_PREFIX[:script] + script_pubkey.to_hex + out_point.to_hex
80
+ level_db.put(key, payload)
81
+ end
82
+
83
+ # height
84
+ unless block_height.nil?
85
+ key = KEY_PREFIX[:height] + [block_height].pack('N').bth + out_point.to_hex
86
+ level_db.put(key, payload)
87
+ end
88
+
89
+ utxo
90
+ end
91
+ end
92
+
93
+ # Get transaction stored via save_tx and save_tx_position
94
+ #
95
+ # @param [string] tx_hash
96
+ # @return [block_height, tx_index, tx_payload]
97
+ def get_tx(tx_hash)
98
+ key = KEY_PREFIX[:tx_hash] + tx_hash
99
+ return [] unless level_db.contains?(key)
100
+ block_height, tx_index = level_db.get(key).htb.unpack('N2')
101
+ key = KEY_PREFIX[:tx_payload] + tx_hash
102
+ tx_payload = level_db.get(key)
103
+ [block_height, tx_index, tx_payload]
104
+ end
105
+
106
+ # Delete utxo from db
107
+ #
108
+ # @param [Bitcoin::Outpoint] out_point
109
+ # @return [Bitcoin::Wallet::Utxo]
110
+ def delete_utxo(out_point)
111
+ level_db.batch do
112
+ # [:out_point]
113
+ key = KEY_PREFIX[:out_point] + out_point.to_hex
114
+ return unless level_db.contains?(key)
115
+ utxo = Bitcoin::Wallet::Utxo.parse_from_payload(level_db.get(key))
116
+ level_db.delete(key)
117
+
118
+ # [:script]
119
+ if utxo.script_pubkey
120
+ key = KEY_PREFIX[:script] + utxo.script_pubkey.to_hex + out_point.to_hex
121
+ level_db.delete(key)
122
+ end
123
+
124
+ if utxo.block_height
125
+ # [:height]
126
+ key = KEY_PREFIX[:height] + [utxo.block_height].pack('N').bth + out_point.to_hex
127
+ level_db.delete(key)
128
+
129
+ # [:block]
130
+ key = KEY_PREFIX[:block] + [utxo.block_height, utxo.index].pack('N2').bth
131
+ level_db.delete(key)
132
+ end
133
+
134
+ # handles both [:tx_hash] and [:tx_payload]
135
+ if utxo.tx_hash
136
+ key = KEY_PREFIX[:tx_hash] + utxo.tx_hash
137
+ level_db.delete(key)
138
+
139
+ key = KEY_PREFIX[:tx_payload] + utxo.tx_hash
140
+ level_db.delete(key)
141
+ end
142
+
143
+ utxo
144
+ end
145
+ end
146
+
147
+ # Get utxo of the specified out point
148
+ #
149
+ # @param [Bitcoin::Outpoint] out_point
150
+ # @return [Bitcoin::Wallet::Utxo]
151
+ def get_utxo(out_point)
152
+ level_db.batch do
153
+ key = KEY_PREFIX[:out_point] + out_point.to_hex
154
+ return unless level_db.contains?(key)
155
+ return Bitcoin::Wallet::Utxo.parse_from_payload(level_db.get(key))
156
+ end
157
+ end
158
+
159
+ # return [Bitcoin::Wallet::Utxo ...]
160
+ def list_unspent(current_block_height: 9999999, min: 0, max: 9999999, addresses: nil)
161
+ if addresses
162
+ list_unspent_by_addresses(current_block_height, min: min, max: max, addresses: addresses)
163
+ else
164
+ list_unspent_by_block_height(current_block_height, min: min, max: max)
165
+ end
166
+ end
167
+
168
+ # @param [Bitcoin::Wallet::Account]
169
+ # return [Bitcoin::Wallet::Utxo ...]
170
+ def list_unspent_in_account(account, current_block_height: 9999999, min: 0, max: 9999999)
171
+ return [] unless account
172
+
173
+ script_pubkeys = case account.purpose
174
+ when Bitcoin::Wallet::Account::PURPOSE_TYPE[:legacy]
175
+ account.watch_targets.map { |t| Bitcoin::Script.to_p2pkh(t).to_hex }
176
+ when Bitcoin::Wallet::Account::PURPOSE_TYPE[:nested_witness]
177
+ account.watch_targets.map { |t| Bitcoin::Script.to_p2wpkh(t).to_p2sh.to_hex }
178
+ when Bitcoin::Wallet::Account::PURPOSE_TYPE[:native_segwit]
179
+ account.watch_targets.map { |t| Bitcoin::Script.to_p2wpkh(t).to_hex }
180
+ end
181
+ list_unspent_by_script_pubkeys(current_block_height, min: min, max: max, script_pubkeys: script_pubkeys)
182
+ end
183
+
184
+ # @param [Bitcoin::Wallet::Account]
185
+ # return [Bitcoin::Wallet::Utxo ...]
186
+ def get_balance(account, current_block_height: 9999999, min: 0, max: 9999999)
187
+ list_unspent_in_account(account, current_block_height: current_block_height, min: min, max: max).sum { |u| u.value }
188
+ end
189
+
190
+ private
191
+
192
+ def utxos_between(from, to)
193
+ level_db.each(from: from, to: to).map { |k, v| Bitcoin::Wallet::Utxo.parse_from_payload(v) }
194
+ end
195
+
196
+ class ::Array
197
+ def with_height(min, max)
198
+ select { |u| u.block_height >= min && u.block_height <= max }
199
+ end
200
+ end
201
+
202
+ def list_unspent_by_block_height(current_block_height, min: 0, max: 9999999)
203
+ max_height = [current_block_height - min, 0].max
204
+ min_height = [current_block_height - max, 0].max
205
+ from = KEY_PREFIX[:height] + [min_height].pack('N').bth + '000000000000000000000000000000000000000000000000000000000000000000000000'
206
+ to = KEY_PREFIX[:height] + [max_height].pack('N').bth + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
207
+ utxos_between(from, to)
208
+ end
209
+
210
+ def list_unspent_by_addresses(current_block_height, min: 0, max: 9999999, addresses: [])
211
+ script_pubkeys = addresses.map { |a| Bitcoin::Script.parse_from_addr(a).to_hex }
212
+ list_unspent_by_script_pubkeys(current_block_height, min: min, max: max, script_pubkeys: script_pubkeys)
213
+ end
214
+
215
+ def list_unspent_by_script_pubkeys(current_block_height, min: 0, max: 9999999, script_pubkeys: [])
216
+ max_height = current_block_height - min
217
+ min_height = current_block_height - max
218
+ script_pubkeys.map do |key|
219
+ from = KEY_PREFIX[:script] + key + '000000000000000000000000000000000000000000000000000000000000000000000000'
220
+ to = KEY_PREFIX[:script] + key + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
221
+ utxos_between(from, to).with_height(min_height, max_height)
222
+ end.flatten
223
+ end
224
+ end
225
+ end
226
+ end
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
@@ -34,13 +36,13 @@ module Bitcoin
34
36
  def self.parse_from_payload(payload, non_witness: 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
42
  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
@@ -64,13 +66,13 @@ module Bitcoin
64
66
  end
65
67
  end
66
68
 
67
- tx.lock_time = buf.read(4).unpack('V').first
69
+ tx.lock_time = buf.read(4).unpack1('V')
68
70
 
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,22 @@ 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],
195
+ def sighash_for_input(input_index, output_script = nil, opts: {}, hash_type: SIGHASH_TYPE[:all],
199
196
  sig_version: :base, amount: nil, skip_separator_index: 0)
200
197
  raise ArgumentError, 'input_index must be specified.' unless input_index
201
198
  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
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)
211
207
  end
212
208
 
213
209
  # verify input signature.
@@ -225,7 +221,7 @@ module Bitcoin
225
221
  script_pubkey = redeem_script if redeem_script.p2wpkh?
226
222
  end
227
223
 
228
- if has_witness || Bitcoin.chain_params.fork_chain?
224
+ if has_witness
229
225
  verify_input_sig_for_witness(input_index, script_pubkey, amount, flags)
230
226
  else
231
227
  verify_input_sig_for_legacy(input_index, script_pubkey, flags)
@@ -249,73 +245,6 @@ module Bitcoin
249
245
 
250
246
  private
251
247
 
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
248
  # verify input signature for legacy tx.
320
249
  def verify_input_sig_for_legacy(input_index, script_pubkey, flags)
321
250
  script_sig = inputs[input_index].script_sig
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