tapyrus 0.2.4 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +37 -0
  3. data/.prettierignore +3 -0
  4. data/.prettierrc.yaml +3 -0
  5. data/CODE_OF_CONDUCT.md +7 -7
  6. data/README.md +14 -17
  7. data/Rakefile +3 -3
  8. data/lib/openassets.rb +0 -2
  9. data/lib/openassets/marker_output.rb +0 -4
  10. data/lib/openassets/payload.rb +4 -10
  11. data/lib/schnorr.rb +14 -9
  12. data/lib/schnorr/sign_to_contract.rb +51 -0
  13. data/lib/schnorr/signature.rb +3 -6
  14. data/lib/tapyrus.rb +8 -30
  15. data/lib/tapyrus/base58.rb +7 -6
  16. data/lib/tapyrus/bip175.rb +67 -0
  17. data/lib/tapyrus/block.rb +1 -2
  18. data/lib/tapyrus/block_header.rb +15 -9
  19. data/lib/tapyrus/bloom_filter.rb +5 -3
  20. data/lib/tapyrus/chain_params.rb +1 -4
  21. data/lib/tapyrus/chainparams/dev.yml +3 -2
  22. data/lib/tapyrus/chainparams/prod.yml +3 -2
  23. data/lib/tapyrus/constants.rb +29 -23
  24. data/lib/tapyrus/errors.rb +1 -3
  25. data/lib/tapyrus/ext.rb +1 -1
  26. data/lib/tapyrus/ext/ecdsa.rb +4 -4
  27. data/lib/tapyrus/ext/json_parser.rb +1 -4
  28. data/lib/tapyrus/ext_key.rb +44 -32
  29. data/lib/tapyrus/key.rb +31 -35
  30. data/lib/tapyrus/key_path.rb +15 -12
  31. data/lib/tapyrus/logger.rb +20 -16
  32. data/lib/tapyrus/merkle_tree.rb +19 -20
  33. data/lib/tapyrus/message.rb +14 -16
  34. data/lib/tapyrus/message/addr.rb +1 -7
  35. data/lib/tapyrus/message/base.rb +0 -3
  36. data/lib/tapyrus/message/block.rb +2 -9
  37. data/lib/tapyrus/message/block_transaction_request.rb +3 -6
  38. data/lib/tapyrus/message/block_transactions.rb +2 -6
  39. data/lib/tapyrus/message/block_txn.rb +0 -4
  40. data/lib/tapyrus/message/cmpct_block.rb +1 -7
  41. data/lib/tapyrus/message/error.rb +1 -4
  42. data/lib/tapyrus/message/fee_filter.rb +1 -4
  43. data/lib/tapyrus/message/filter_add.rb +0 -4
  44. data/lib/tapyrus/message/filter_clear.rb +0 -4
  45. data/lib/tapyrus/message/filter_load.rb +2 -5
  46. data/lib/tapyrus/message/get_addr.rb +0 -4
  47. data/lib/tapyrus/message/get_block_txn.rb +0 -4
  48. data/lib/tapyrus/message/get_blocks.rb +0 -3
  49. data/lib/tapyrus/message/get_data.rb +1 -4
  50. data/lib/tapyrus/message/get_headers.rb +1 -3
  51. data/lib/tapyrus/message/header_and_short_ids.rb +3 -9
  52. data/lib/tapyrus/message/headers.rb +0 -4
  53. data/lib/tapyrus/message/headers_parser.rb +3 -8
  54. data/lib/tapyrus/message/inv.rb +1 -4
  55. data/lib/tapyrus/message/inventories_parser.rb +2 -7
  56. data/lib/tapyrus/message/inventory.rb +12 -5
  57. data/lib/tapyrus/message/mem_pool.rb +0 -4
  58. data/lib/tapyrus/message/merkle_block.rb +4 -9
  59. data/lib/tapyrus/message/network_addr.rb +7 -6
  60. data/lib/tapyrus/message/not_found.rb +0 -3
  61. data/lib/tapyrus/message/ping.rb +0 -3
  62. data/lib/tapyrus/message/pong.rb +0 -3
  63. data/lib/tapyrus/message/prefilled_tx.rb +0 -4
  64. data/lib/tapyrus/message/reject.rb +0 -3
  65. data/lib/tapyrus/message/send_cmpct.rb +1 -3
  66. data/lib/tapyrus/message/send_headers.rb +0 -3
  67. data/lib/tapyrus/message/tx.rb +0 -4
  68. data/lib/tapyrus/message/ver_ack.rb +1 -5
  69. data/lib/tapyrus/message/version.rb +2 -5
  70. data/lib/tapyrus/mnemonic.rb +17 -15
  71. data/lib/tapyrus/network.rb +0 -2
  72. data/lib/tapyrus/network/connection.rb +0 -3
  73. data/lib/tapyrus/network/message_handler.rb +61 -60
  74. data/lib/tapyrus/network/peer.rb +13 -12
  75. data/lib/tapyrus/network/peer_discovery.rb +3 -5
  76. data/lib/tapyrus/network/pool.rb +12 -12
  77. data/lib/tapyrus/node.rb +1 -1
  78. data/lib/tapyrus/node/cli.rb +12 -14
  79. data/lib/tapyrus/node/configuration.rb +1 -3
  80. data/lib/tapyrus/node/spv.rb +2 -3
  81. data/lib/tapyrus/opcodes.rb +9 -7
  82. data/lib/tapyrus/out_point.rb +5 -5
  83. data/lib/tapyrus/rpc.rb +1 -0
  84. data/lib/tapyrus/rpc/http_server.rb +21 -22
  85. data/lib/tapyrus/rpc/request_handler.rb +42 -44
  86. data/lib/tapyrus/rpc/tapyrus_core_client.rb +67 -25
  87. data/lib/tapyrus/script/color.rb +20 -2
  88. data/lib/tapyrus/script/multisig.rb +13 -12
  89. data/lib/tapyrus/script/script.rb +104 -67
  90. data/lib/tapyrus/script/script_error.rb +1 -4
  91. data/lib/tapyrus/script/script_interpreter.rb +439 -399
  92. data/lib/tapyrus/script/tx_checker.rb +20 -10
  93. data/lib/tapyrus/secp256k1.rb +0 -4
  94. data/lib/tapyrus/secp256k1/native.rb +14 -15
  95. data/lib/tapyrus/secp256k1/rfc6979.rb +7 -4
  96. data/lib/tapyrus/secp256k1/ruby.rb +10 -12
  97. data/lib/tapyrus/slip39.rb +20 -5
  98. data/lib/tapyrus/slip39/share.rb +41 -29
  99. data/lib/tapyrus/slip39/sss.rb +101 -57
  100. data/lib/tapyrus/store.rb +1 -3
  101. data/lib/tapyrus/store/chain_entry.rb +0 -4
  102. data/lib/tapyrus/store/db.rb +0 -2
  103. data/lib/tapyrus/store/db/level_db.rb +5 -9
  104. data/lib/tapyrus/store/spv_chain.rb +11 -17
  105. data/lib/tapyrus/tx.rb +45 -37
  106. data/lib/tapyrus/tx_builder.rb +158 -0
  107. data/lib/tapyrus/tx_in.rb +1 -6
  108. data/lib/tapyrus/tx_out.rb +2 -7
  109. data/lib/tapyrus/util.rb +20 -7
  110. data/lib/tapyrus/validation.rb +12 -11
  111. data/lib/tapyrus/version.rb +1 -1
  112. data/lib/tapyrus/wallet/account.rb +22 -18
  113. data/lib/tapyrus/wallet/base.rb +12 -9
  114. data/lib/tapyrus/wallet/db.rb +6 -9
  115. data/lib/tapyrus/wallet/master_key.rb +2 -4
  116. data/tapyrusrb.gemspec +13 -16
  117. metadata +22 -31
  118. data/.travis.yml +0 -12
@@ -1,11 +1,10 @@
1
1
  module Tapyrus
2
-
3
2
  # utility for multisig
4
3
  module Multisig
5
4
  include Tapyrus::Opcodes
6
5
 
7
6
  def self.prefix
8
- [OP_0].pack("C*")
7
+ [OP_0].pack('C*')
9
8
  end
10
9
 
11
10
  # generate input script sig spending a multisig output script.
@@ -23,7 +22,7 @@ module Tapyrus
23
22
  # multiple parties. Signatures must be in the same order as the
24
23
  # pubkeys in the output script being redeemed.
25
24
  def self.add_sig_to_multisig_script_sig(sig_to_add, script_sig, hash_type = SIGHASH_TYPE[:all])
26
- signature = sig_to_add + [hash_type].pack("C*")
25
+ signature = sig_to_add + [hash_type].pack('C*')
27
26
  offset = script_sig.empty? ? 0 : 1
28
27
  script_sig.insert(offset, Tapyrus::Script.pack_pushdata(signature))
29
28
  end
@@ -49,17 +48,19 @@ module Tapyrus
49
48
  pubkeys = redeem_script.get_multisig_pubkeys
50
49
 
51
50
  # find the pubkey for each signature by trying to verify it
52
- sigs = Hash[script.chunks[1...-1].map.with_index do |sig, idx|
53
- sig = sig.pushed_data
54
- pubkey = pubkeys.map do |key|
55
- Tapyrus::Key.new(pubkey: key.bth).verify(sig, sig_hash) ? key : nil
56
- end.compact.first
57
- raise "Key for signature ##{idx} not found in redeem script!" unless pubkey
58
- [pubkey, sig]
59
- end]
51
+ sigs =
52
+ Hash[
53
+ script.chunks[1...-1].map.with_index do |sig, idx|
54
+ sig = sig.pushed_data
55
+ pubkey =
56
+ pubkeys.map { |key| Tapyrus::Key.new(pubkey: key.bth).verify(sig, sig_hash) ? key : nil }.compact.first
57
+ raise "Key for signature ##{idx} not found in redeem script!" unless pubkey
58
+ [pubkey, sig]
59
+ end
60
+ ]
60
61
 
61
62
  prefix + pubkeys.map { |k| sigs[k] ? Tapyrus::Script.pack_pushdata(sigs[k]) : nil }.join +
62
63
  Tapyrus::Script.pack_pushdata(script.chunks[-1].pushed_data)
63
64
  end
64
65
  end
65
- end
66
+ end
@@ -2,7 +2,6 @@
2
2
  # https://github.com/lian/bitcoin-ruby/blob/master/COPYING
3
3
 
4
4
  module Tapyrus
5
-
6
5
  # tapyrus script
7
6
  class Script
8
7
  include Tapyrus::HexConverter
@@ -75,9 +74,19 @@ module Tapyrus
75
74
  end
76
75
  end
77
76
 
77
+ # Remove color identifier from cp2pkh or cp2sh
78
+ # @param [ColorIdentifier] color identifier
79
+ # @return [Script] P2PKH or P2SH script
80
+ # @raise [RuntimeError] if script is neither cp2pkh nor cp2sh
81
+ def remove_color
82
+ raise RuntimeError, 'Only cp2pkh and cp2sh can remove color' unless cp2pkh? or cp2sh?
83
+
84
+ Tapyrus::Script.new.tap { |s| s.chunks = self.chunks[2..-1] }
85
+ end
86
+
78
87
  def get_multisig_pubkeys
79
88
  num = Tapyrus::Opcodes.opcode_to_small_int(chunks[-2].bth.to_i(16))
80
- (1..num).map{ |i| chunks[i].pushed_data }
89
+ (1..num).map { |i| chunks[i].pushed_data }
81
90
  end
82
91
 
83
92
  # generate m of n multisig script
@@ -92,14 +101,16 @@ module Tapyrus
92
101
  # generate script from string.
93
102
  def self.from_string(string)
94
103
  script = new
95
- string.split(' ').each do |v|
96
- opcode = Opcodes.name_to_opcode(v)
97
- if opcode
98
- script << (v =~ /^\d/ && Opcodes.small_int_to_opcode(v.ord) ? v.ord : opcode)
99
- else
100
- script << (v =~ /^[0-9]+$/ ? v.to_i : v)
104
+ string
105
+ .split(' ')
106
+ .each do |v|
107
+ opcode = Opcodes.name_to_opcode(v)
108
+ if opcode
109
+ script << (v =~ /^\d/ && Opcodes.small_int_to_opcode(v.ord) ? v.ord : opcode)
110
+ else
111
+ script << (v =~ /^[0-9]+$/ ? v.to_i : v)
112
+ end
101
113
  end
102
- end
103
114
  script
104
115
  end
105
116
 
@@ -118,6 +129,12 @@ module Tapyrus
118
129
  Tapyrus::Script.to_p2pkh(hex)
119
130
  when Tapyrus.chain_params.p2sh_version
120
131
  Tapyrus::Script.to_p2sh(hex)
132
+ when Tapyrus.chain_params.cp2pkh_version
133
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
134
+ Tapyrus::Script.to_cp2pkh(color, hex[66..-1])
135
+ when Tapyrus.chain_params.cp2sh_version
136
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
137
+ Tapyrus::Script.to_cp2sh(color, hex[66..-1])
121
138
  else
122
139
  throw e
123
140
  end
@@ -132,19 +149,20 @@ module Tapyrus
132
149
  if opcode.pushdata?
133
150
  pushcode = opcode.ord
134
151
  packed_size = nil
135
- len = case pushcode
136
- when OP_PUSHDATA1
137
- packed_size = buf.read(1)
138
- packed_size.unpack('C').first
139
- when OP_PUSHDATA2
140
- packed_size = buf.read(2)
141
- packed_size.unpack('v').first
142
- when OP_PUSHDATA4
143
- packed_size = buf.read(4)
144
- packed_size.unpack('V').first
145
- else
146
- pushcode if pushcode < OP_PUSHDATA1
147
- end
152
+ len =
153
+ case pushcode
154
+ when OP_PUSHDATA1
155
+ packed_size = buf.read(1)
156
+ packed_size.unpack('C').first
157
+ when OP_PUSHDATA2
158
+ packed_size = buf.read(2)
159
+ packed_size.unpack('v').first
160
+ when OP_PUSHDATA4
161
+ packed_size = buf.read(4)
162
+ packed_size.unpack('V').first
163
+ else
164
+ pushcode if pushcode < OP_PUSHDATA1
165
+ end
148
166
  if len
149
167
  s.chunks << [len].pack('C') if buf.eof?
150
168
  unless buf.eof?
@@ -176,7 +194,7 @@ module Tapyrus
176
194
  return [p2sh_addr] if p2sh?
177
195
  return [cp2pkh_addr] if cp2pkh?
178
196
  return [cp2sh_addr] if cp2sh?
179
- return get_multisig_pubkeys.map{|pubkey| Tapyrus::Key.new(pubkey: pubkey.bth).to_p2pkh} if multisig?
197
+ return get_multisig_pubkeys.map { |pubkey| Tapyrus::Key.new(pubkey: pubkey.bth).to_p2pkh } if multisig?
180
198
  []
181
199
  end
182
200
 
@@ -188,8 +206,8 @@ module Tapyrus
188
206
  # whether this script is a P2PKH format script.
189
207
  def p2pkh?
190
208
  return false unless chunks.size == 5
191
- [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] ==
192
- (chunks[0..1]+ chunks[3..4]).map(&:ord) && chunks[2].bytesize == 21
209
+ [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] == (chunks[0..1] + chunks[3..4]).map(&:ord) &&
210
+ chunks[2].bytesize == 21
193
211
  end
194
212
 
195
213
  def p2sh?
@@ -210,19 +228,22 @@ module Tapyrus
210
228
  end
211
229
 
212
230
  def standard_op_return?
213
- op_return? && size <= MAX_OP_RETURN_RELAY &&
214
- (chunks.size == 1 || chunks[1].opcode <= OP_16)
231
+ op_return? && size <= MAX_OP_RETURN_RELAY && (chunks.size == 1 || chunks[1].opcode <= OP_16)
215
232
  end
216
233
 
234
+ # Return whether this script is a CP2PKH format script or not.
235
+ # @return [Boolean] true if this script is cp2pkh, otherwise false.
217
236
  def cp2pkh?
218
237
  return false unless chunks.size == 7
219
238
  return false unless chunks[0].bytesize == 34
220
239
  return false unless Tapyrus::Color::ColorIdentifier.parse_from_payload(chunks[0].pushed_data)&.valid?
221
240
  return false unless chunks[1].ord == OP_COLOR
222
- [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] ==
223
- (chunks[2..3]+ chunks[5..6]).map(&:ord) && chunks[4].bytesize == 21
241
+ [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] == (chunks[2..3] + chunks[5..6]).map(&:ord) &&
242
+ chunks[4].bytesize == 21
224
243
  end
225
244
 
245
+ # Return whether this script is a CP2SH format script or not.
246
+ # @return [Boolean] true if this script is cp2pkh, otherwise false.
226
247
  def cp2sh?
227
248
  return false unless chunks.size == 5
228
249
  return false unless chunks[0].bytesize == 34
@@ -231,6 +252,20 @@ module Tapyrus
231
252
  OP_HASH160 == chunks[2].ord && OP_EQUAL == chunks[4].ord && chunks[3].bytesize == 21
232
253
  end
233
254
 
255
+ # Return whether this script represents colored coin.
256
+ # @return [Boolean] true if this script is colored, otherwise false.
257
+ def colored?
258
+ cp2pkh? || cp2sh?
259
+ end
260
+
261
+ # Return color identifier for this script.
262
+ # @return [ColorIdentifer] color identifier for this script if this script is colored. return nil if this script is not colored.
263
+ def color_id
264
+ return nil unless colored?
265
+
266
+ Tapyrus::Color::ColorIdentifier.parse_from_payload(chunks[0].pushed_data)
267
+ end
268
+
234
269
  def op_return_data
235
270
  return nil unless op_return?
236
271
  return nil if chunks.size == 1
@@ -239,24 +274,23 @@ module Tapyrus
239
274
 
240
275
  # whether data push only script which dose not include other opcode
241
276
  def push_only?
242
- chunks.each do |c|
243
- return false if !c.opcode.nil? && c.opcode > OP_16
244
- end
277
+ chunks.each { |c| return false if !c.opcode.nil? && c.opcode > OP_16 }
245
278
  true
246
279
  end
247
280
 
248
281
  # get public keys in the stack.
249
282
  # @return[Array[String]] an array of the pubkeys with hex format.
250
283
  def get_pubkeys
251
- chunks.select{|c|c.pushdata? && [33, 65].include?(c.pushed_data.bytesize) && [2, 3, 4, 6, 7].include?(c.pushed_data[0].bth.to_i(16))}.map{|c|c.pushed_data.bth}
284
+ chunks.select do |c|
285
+ c.pushdata? && [33, 65].include?(c.pushed_data.bytesize) &&
286
+ [2, 3, 4, 6, 7].include?(c.pushed_data[0].bth.to_i(16))
287
+ end.map { |c| c.pushed_data.bth }
252
288
  end
253
289
 
254
290
  # returns the self payload. ScriptInterpreter does not use this.
255
291
  def to_script_code(skip_separator_index = 0)
256
292
  payload = to_payload
257
- if skip_separator_index > 0
258
- payload = subscript_codeseparator(skip_separator_index)
259
- end
293
+ payload = subscript_codeseparator(skip_separator_index) if skip_separator_index > 0
260
294
  Tapyrus.pack_var_string(payload)
261
295
  end
262
296
 
@@ -267,7 +301,7 @@ module Tapyrus
267
301
  elsif obj.is_a?(String)
268
302
  append_data(obj)
269
303
  elsif obj.is_a?(Array)
270
- obj.each { |o| self.<< o}
304
+ obj.each { |o| self.<< o }
271
305
  self
272
306
  end
273
307
  end
@@ -303,18 +337,19 @@ module Tapyrus
303
337
 
304
338
  # Check the item is in the chunk of the script.
305
339
  def include?(item)
306
- chunk_item = if item.is_a?(Integer)
307
- item.chr
308
- elsif item.is_a?(String)
309
- data = Encoding::ASCII_8BIT == item.encoding ? item : item.htb
310
- Tapyrus::Script.pack_pushdata(data)
311
- end
340
+ chunk_item =
341
+ if item.is_a?(Integer)
342
+ item.chr
343
+ elsif item.is_a?(String)
344
+ data = Encoding::ASCII_8BIT == item.encoding ? item : item.htb
345
+ Tapyrus::Script.pack_pushdata(data)
346
+ end
312
347
  return false unless chunk_item
313
348
  chunks.include?(chunk_item)
314
349
  end
315
350
 
316
351
  def to_s
317
- chunks.map { |c|
352
+ chunks.map do |c|
318
353
  case c
319
354
  when Integer
320
355
  opcode_to_name(c)
@@ -337,7 +372,7 @@ module Tapyrus
337
372
  opcode ? opcode : 'OP_UNKNOWN [error]'
338
373
  end
339
374
  end
340
- }.join(' ')
375
+ end.join(' ')
341
376
  end
342
377
 
343
378
  # generate sha-256 hash for payload
@@ -395,17 +430,18 @@ module Tapyrus
395
430
  # binary +data+ convert pushdata which contains data length and append PUSHDATA opcode if necessary.
396
431
  def self.pack_pushdata(data)
397
432
  size = data.bytesize
398
- header = if size < OP_PUSHDATA1
399
- [size].pack('C')
400
- elsif size < 0xff
401
- [OP_PUSHDATA1, size].pack('CC')
402
- elsif size < 0xffff
403
- [OP_PUSHDATA2, size].pack('Cv')
404
- elsif size < 0xffffffff
405
- [OP_PUSHDATA4, size].pack('CV')
406
- else
407
- raise ArgumentError, 'data size is too big.'
408
- end
433
+ header =
434
+ if size < OP_PUSHDATA1
435
+ [size].pack('C')
436
+ elsif size < 0xff
437
+ [OP_PUSHDATA1, size].pack('CC')
438
+ elsif size < 0xffff
439
+ [OP_PUSHDATA2, size].pack('Cv')
440
+ elsif size < 0xffffffff
441
+ [OP_PUSHDATA4, size].pack('CV')
442
+ else
443
+ raise ArgumentError, 'data size is too big.'
444
+ end
409
445
  header + data
410
446
  end
411
447
 
@@ -429,8 +465,12 @@ module Tapyrus
429
465
  if chunk == sub_chunk
430
466
  buf << chunk
431
467
  i += 1
432
- (i = 0; buf.clear) if i == subscript.chunks.size # matched the whole subscript
433
- else # matched the part of head
468
+ (
469
+ i = 0
470
+ buf.clear
471
+ ) if i == subscript.chunks.size # matched the whole subscript
472
+ else
473
+ # matched the part of head
434
474
  i = 0
435
475
  tmp = chunk.dup
436
476
  tmp.slice!(sub_chunk)
@@ -452,7 +492,7 @@ module Tapyrus
452
492
 
453
493
  # remove all occurences of opcode. Typically it's OP_CODESEPARATOR.
454
494
  def delete_opcode(opcode)
455
- @chunks = chunks.select{|chunk| chunk.ord != opcode}
495
+ @chunks = chunks.select { |chunk| chunk.ord != opcode }
456
496
  self
457
497
  end
458
498
 
@@ -460,12 +500,10 @@ module Tapyrus
460
500
  def subscript_codeseparator(separator_index)
461
501
  buf = []
462
502
  process_separator_index = 0
463
- chunks.each{|chunk|
503
+ chunks.each do |chunk|
464
504
  buf << chunk if process_separator_index == separator_index
465
- if chunk.ord == OP_CODESEPARATOR && process_separator_index < separator_index
466
- process_separator_index += 1
467
- end
468
- }
505
+ process_separator_index += 1 if chunk.ord == OP_CODESEPARATOR && process_separator_index < separator_index
506
+ end
469
507
  buf.join
470
508
  end
471
509
 
@@ -482,10 +520,10 @@ module Tapyrus
482
520
  end
483
521
 
484
522
  def to_h
485
- h = {asm: to_s, hex: to_hex, type: type}
523
+ h = { asm: to_s, hex: to_hex, type: type }
486
524
  addrs = addresses
487
525
  unless addrs.empty?
488
- h[:req_sigs] = multisig? ? Tapyrus::Opcodes.opcode_to_small_int(chunks[0].bth.to_i(16)) :addrs.size
526
+ h[:req_sigs] = multisig? ? Tapyrus::Opcodes.opcode_to_small_int(chunks[0].bth.to_i(16)) : addrs.size
489
527
  h[:addresses] = addrs
490
528
  end
491
529
  h
@@ -532,5 +570,4 @@ module Tapyrus
532
570
  Tapyrus.encode_base58_address(color_id + hash160, Tapyrus.chain_params.cp2sh_version)
533
571
  end
534
572
  end
535
-
536
573
  end
@@ -1,8 +1,6 @@
1
1
  module Tapyrus
2
-
3
2
  # tapyrus script error
4
3
  class ScriptError < Exception
5
-
6
4
  attr_accessor :code
7
5
  attr_accessor :extra_msg
8
6
 
@@ -100,6 +98,5 @@ module Tapyrus
100
98
  def self.name_to_code(name)
101
99
  NAME_MAP[name]
102
100
  end
103
-
104
101
  end
105
- end
102
+ end
@@ -1,7 +1,5 @@
1
1
  module Tapyrus
2
-
3
2
  class ScriptInterpreter
4
-
5
3
  include Tapyrus::Opcodes
6
4
 
7
5
  attr_reader :stack
@@ -11,8 +9,23 @@ module Tapyrus
11
9
  attr_reader :checker
12
10
  attr_reader :require_minimal
13
11
 
14
- DISABLE_OPCODES = [OP_CAT, OP_SUBSTR, OP_LEFT, OP_RIGHT, OP_INVERT, OP_AND, OP_OR, OP_XOR, OP_2MUL, OP_2DIV, OP_DIV, OP_MUL, OP_MOD, OP_LSHIFT, OP_RSHIFT]
15
-
12
+ DISABLE_OPCODES = [
13
+ OP_CAT,
14
+ OP_SUBSTR,
15
+ OP_LEFT,
16
+ OP_RIGHT,
17
+ OP_INVERT,
18
+ OP_AND,
19
+ OP_OR,
20
+ OP_XOR,
21
+ OP_2MUL,
22
+ OP_2DIV,
23
+ OP_DIV,
24
+ OP_MUL,
25
+ OP_MOD,
26
+ OP_LSHIFT,
27
+ OP_RSHIFT
28
+ ]
16
29
 
17
30
  # syntax sugar for simple evaluation for script.
18
31
  # @param [Tapyrus::Script] script_sig a scriptSig.
@@ -34,7 +47,6 @@ module Tapyrus
34
47
  # @param [Tapyrus::Script] script_pubkey a script pubkey (locking script)
35
48
  # @return [Boolean] result
36
49
  def verify_script(script_sig, script_pubkey)
37
-
38
50
  return set_error(SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.push_only?
39
51
 
40
52
  stack_copy = nil
@@ -97,9 +109,7 @@ module Tapyrus
97
109
  opcode = c.opcode
98
110
 
99
111
  if need_exec && c.pushdata?
100
- if require_minimal && !minimal_push?(c.pushed_data, opcode)
101
- return set_error(SCRIPT_ERR_MINIMALDATA)
102
- end
112
+ return set_error(SCRIPT_ERR_MINIMALDATA) if require_minimal && !minimal_push?(c.pushed_data, opcode)
103
113
  return set_error(SCRIPT_ERR_BAD_OPCODE) unless verify_pushdata_length(c)
104
114
  stack << c.pushed_data.bth
105
115
  else
@@ -107,385 +117,415 @@ module Tapyrus
107
117
  return set_error(SCRIPT_ERR_OP_COUNT)
108
118
  end
109
119
  return set_error(SCRIPT_ERR_DISABLED_OPCODE) if DISABLE_OPCODES.include?(opcode)
110
- return set_error(SCRIPT_ERR_OP_CODESEPARATOR) if opcode == OP_CODESEPARATOR && sig_version == :base && flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE)
120
+ if opcode == OP_CODESEPARATOR && sig_version == :base && flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE)
121
+ return set_error(SCRIPT_ERR_OP_CODESEPARATOR)
122
+ end
111
123
  next unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
112
124
  small_int = Opcodes.opcode_to_small_int(opcode)
113
125
  if small_int && opcode != OP_0
114
126
  push_int(small_int)
115
127
  else
116
128
  case opcode
117
- when OP_0
118
- stack << ''
119
- when OP_DEPTH
120
- push_int(stack.size)
121
- when OP_EQUAL, OP_EQUALVERIFY
122
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
123
- a, b = pop_string(2)
124
- result = a == b
125
- push_int(result ? 1 : 0)
126
- if opcode == OP_EQUALVERIFY
127
- if result
128
- stack.pop
129
- else
130
- return set_error(SCRIPT_ERR_EQUALVERIFY)
131
- end
129
+ when OP_0
130
+ stack << ''
131
+ when OP_DEPTH
132
+ push_int(stack.size)
133
+ when OP_EQUAL, OP_EQUALVERIFY
134
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
135
+ a, b = pop_string(2)
136
+ result = a == b
137
+ push_int(result ? 1 : 0)
138
+ if opcode == OP_EQUALVERIFY
139
+ if result
140
+ stack.pop
141
+ else
142
+ return set_error(SCRIPT_ERR_EQUALVERIFY)
132
143
  end
133
- when OP_0NOTEQUAL
134
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
135
- push_int(pop_int == 0 ? 0 : 1)
136
- when OP_ADD
137
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
138
- a, b = pop_int(2)
139
- push_int(a + b)
140
- when OP_1ADD
141
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
142
- push_int(pop_int + 1)
143
- when OP_SUB
144
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
145
- a, b = pop_int(2)
146
- push_int(a - b)
147
- when OP_1SUB
148
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
149
- push_int(pop_int - 1)
150
- when OP_IF, OP_NOTIF
151
- result = false
152
- if need_exec
153
- return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
154
- value = pop_string.htb
155
- if flag?(SCRIPT_VERIFY_MINIMALIF)
156
- if value.bytesize > 1 || (value.bytesize == 1 && value[0].unpack('C').first != 1)
157
- return set_error(SCRIPT_ERR_MINIMALIF)
158
- end
144
+ end
145
+ when OP_0NOTEQUAL
146
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
147
+ push_int(pop_int == 0 ? 0 : 1)
148
+ when OP_ADD
149
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
150
+ a, b = pop_int(2)
151
+ push_int(a + b)
152
+ when OP_1ADD
153
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
154
+ push_int(pop_int + 1)
155
+ when OP_SUB
156
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
157
+ a, b = pop_int(2)
158
+ push_int(a - b)
159
+ when OP_1SUB
160
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
161
+ push_int(pop_int - 1)
162
+ when OP_IF, OP_NOTIF
163
+ result = false
164
+ if need_exec
165
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
166
+ value = pop_string.htb
167
+ if flag?(SCRIPT_VERIFY_MINIMALIF)
168
+ if value.bytesize > 1 || (value.bytesize == 1 && value[0].unpack('C').first != 1)
169
+ return set_error(SCRIPT_ERR_MINIMALIF)
159
170
  end
160
- result = cast_to_bool(value)
161
- result = !result if opcode == OP_NOTIF
162
171
  end
163
- flow_stack << result
164
- when OP_ELSE
165
- return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.size < 1
166
- flow_stack << !flow_stack.pop
167
- when OP_ENDIF
168
- return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.empty?
169
- flow_stack.pop
170
- when OP_NOP
171
- when OP_NOP1, OP_NOP4..OP_NOP10
172
- return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
173
- when OP_CHECKLOCKTIMEVERIFY
174
- next unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
175
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
176
- # Note that elsewhere numeric opcodes are limited to operands in the range -2**31+1 to 2**31-1,
177
- # however it is legal for opcodes to produce results exceeding that range.
178
- # This limitation is implemented by CScriptNum's default 4-byte limit.
179
- # If we kept to that limit we'd have a year 2038 problem,
180
- # even though the nLockTime field in transactions themselves is uint32 which only becomes meaningless after the year 2106.
181
- # Thus as a special case we tell CScriptNum to accept up to 5-byte bignums,
182
- # which are good until 2**39-1, well beyond the 2**32-1 limit of the nLockTime field itself.
183
- locktime = cast_to_int(stack.last, 5)
184
- return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if locktime < 0
185
- return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_locktime(locktime)
186
- when OP_CHECKSEQUENCEVERIFY
187
- next unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
188
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
189
-
190
- # nSequence, like nLockTime, is a 32-bit unsigned integer field.
191
- # See the comment in CHECKLOCKTIMEVERIFY regarding 5-byte numeric operands.
192
- sequence = cast_to_int(stack.last, 5)
193
-
194
- # In the rare event that the argument may be < 0 due to some arithmetic being done first,
195
- # you can always use 0 MAX CHECKSEQUENCEVERIFY.
196
- return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if sequence < 0
197
-
198
- # To provide for future soft-fork extensibility,
199
- # if the operand has the disabled lock-time flag set, CHECKSEQUENCEVERIFY behaves as a NOP.
200
- next if (sequence & Tapyrus::TxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0
201
-
202
- # Compare the specified sequence number with the input.
203
- unless checker.check_sequence(sequence)
204
- return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME)
172
+ result = cast_to_bool(value)
173
+ result = !result if opcode == OP_NOTIF
174
+ end
175
+ flow_stack << result
176
+ when OP_ELSE
177
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.size < 1
178
+ flow_stack << !flow_stack.pop
179
+ when OP_ENDIF
180
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.empty?
181
+ flow_stack.pop
182
+ when OP_NOP
183
+ when OP_NOP1, OP_NOP4..OP_NOP10
184
+ if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
185
+ return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS)
186
+ end
187
+ when OP_CHECKLOCKTIMEVERIFY
188
+ next unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
189
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
190
+
191
+ # Note that elsewhere numeric opcodes are limited to operands in the range -2**31+1 to 2**31-1,
192
+ # however it is legal for opcodes to produce results exceeding that range.
193
+ # This limitation is implemented by CScriptNum's default 4-byte limit.
194
+ # If we kept to that limit we'd have a year 2038 problem,
195
+ # even though the nLockTime field in transactions themselves is uint32 which only becomes meaningless after the year 2106.
196
+ # Thus as a special case we tell CScriptNum to accept up to 5-byte bignums,
197
+ # which are good until 2**39-1, well beyond the 2**32-1 limit of the nLockTime field itself.
198
+ locktime = cast_to_int(stack.last, 5)
199
+ return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if locktime < 0
200
+ return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_locktime(locktime)
201
+ when OP_CHECKSEQUENCEVERIFY
202
+ next unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
203
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
204
+
205
+ # nSequence, like nLockTime, is a 32-bit unsigned integer field.
206
+ # See the comment in CHECKLOCKTIMEVERIFY regarding 5-byte numeric operands.
207
+ sequence = cast_to_int(stack.last, 5)
208
+
209
+ # In the rare event that the argument may be < 0 due to some arithmetic being done first,
210
+ # you can always use 0 MAX CHECKSEQUENCEVERIFY.
211
+ return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if sequence < 0
212
+
213
+ # To provide for future soft-fork extensibility,
214
+ # if the operand has the disabled lock-time flag set, CHECKSEQUENCEVERIFY behaves as a NOP.
215
+ next if (sequence & Tapyrus::TxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0
216
+
217
+ # Compare the specified sequence number with the input.
218
+ return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_sequence(sequence)
219
+ when OP_DUP
220
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
221
+ stack << stack.last
222
+ when OP_2DUP
223
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
224
+ 2.times { stack << stack[-2] }
225
+ when OP_3DUP
226
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
227
+ 3.times { stack << stack[-3] }
228
+ when OP_IFDUP
229
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
230
+ stack << stack.last if cast_to_bool(stack.last)
231
+ when OP_RIPEMD160
232
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
233
+ stack << Digest::RMD160.hexdigest(pop_string.htb)
234
+ when OP_SHA1
235
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
236
+ stack << Digest::SHA1.hexdigest(pop_string.htb)
237
+ when OP_SHA256
238
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
239
+ stack << Digest::SHA256.hexdigest(pop_string.htb)
240
+ when OP_HASH160
241
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
242
+ stack << Tapyrus.hash160(pop_string)
243
+ when OP_HASH256
244
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
245
+ stack << Tapyrus.double_sha256(pop_string.htb).bth
246
+ when OP_VERIFY
247
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
248
+ return set_error(SCRIPT_ERR_VERIFY) unless pop_bool
249
+ when OP_TOALTSTACK
250
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
251
+ alt_stack << stack.pop
252
+ when OP_FROMALTSTACK
253
+ return set_error(SCRIPT_ERR_INVALID_ALTSTACK_OPERATION) if alt_stack.size < 1
254
+ stack << alt_stack.pop
255
+ when OP_DROP
256
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
257
+ stack.pop
258
+ when OP_2DROP
259
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
260
+ 2.times { stack.pop }
261
+ when OP_NIP
262
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
263
+ stack.delete_at(-2)
264
+ when OP_OVER
265
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
266
+ stack << stack[-2]
267
+ when OP_2OVER
268
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
269
+ 2.times { stack << stack[-4] }
270
+ when OP_PICK, OP_ROLL
271
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
272
+ pos = pop_int
273
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
274
+ stack << stack[-pos - 1]
275
+ stack.delete_at(-pos - 2) if opcode == OP_ROLL
276
+ when OP_ROT
277
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
278
+ stack << stack[-3]
279
+ stack.delete_at(-4)
280
+ when OP_2ROT
281
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
282
+ 2.times { stack << stack[-6] }
283
+ 2.times { stack.delete_at(-7) }
284
+ when OP_SWAP
285
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
286
+ tmp = stack.last
287
+ stack[-1] = stack[-2]
288
+ stack[-2] = tmp
289
+ when OP_2SWAP
290
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
291
+ 2.times { stack << stack[-4] }
292
+ 2.times { stack.delete_at(-5) }
293
+ when OP_TUCK
294
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
295
+ stack.insert(-3, stack.last)
296
+ when OP_ABS
297
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
298
+ v = pop_int
299
+ push_int(v.abs)
300
+ when OP_BOOLAND
301
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
302
+ a, b = pop_int(2)
303
+ push_int((!a.zero? && !b.zero?) ? 1 : 0)
304
+ when OP_BOOLOR
305
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
306
+ a, b = pop_int(2)
307
+ push_int((!a.zero? || !b.zero?) ? 1 : 0)
308
+ when OP_NUMEQUAL, OP_NUMEQUALVERIFY
309
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
310
+ a, b = pop_int(2)
311
+ result = a == b
312
+ push_int(result ? 1 : 0)
313
+ if opcode == OP_NUMEQUALVERIFY
314
+ if result
315
+ stack.pop
316
+ else
317
+ return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
205
318
  end
206
- when OP_DUP
207
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
208
- stack << stack.last
209
- when OP_2DUP
210
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
211
- 2.times { stack << stack[-2] }
212
- when OP_3DUP
213
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
214
- 3.times { stack << stack[-3] }
215
- when OP_IFDUP
216
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
217
- stack << stack.last if cast_to_bool(stack.last)
218
- when OP_RIPEMD160
219
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
220
- stack << Digest::RMD160.hexdigest(pop_string.htb)
221
- when OP_SHA1
222
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
223
- stack << Digest::SHA1.hexdigest(pop_string.htb)
224
- when OP_SHA256
225
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
226
- stack << Digest::SHA256.hexdigest(pop_string.htb)
227
- when OP_HASH160
228
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
229
- stack << Tapyrus.hash160(pop_string)
230
- when OP_HASH256
231
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
232
- stack << Tapyrus.double_sha256(pop_string.htb).bth
233
- when OP_VERIFY
234
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
235
- return set_error(SCRIPT_ERR_VERIFY) unless pop_bool
236
- when OP_TOALTSTACK
237
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
238
- alt_stack << stack.pop
239
- when OP_FROMALTSTACK
240
- return set_error(SCRIPT_ERR_INVALID_ALTSTACK_OPERATION) if alt_stack.size < 1
241
- stack << alt_stack.pop
242
- when OP_DROP
243
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
244
- stack.pop
245
- when OP_2DROP
246
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
247
- 2.times { stack.pop }
248
- when OP_NIP
249
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
250
- stack.delete_at(-2)
251
- when OP_OVER
252
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
253
- stack << stack[-2]
254
- when OP_2OVER
255
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
256
- 2.times { stack << stack[-4]}
257
- when OP_PICK, OP_ROLL
258
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
259
- pos = pop_int
260
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
261
- stack << stack[-pos - 1]
262
- stack.delete_at(-pos - 2) if opcode == OP_ROLL
263
- when OP_ROT
264
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
265
- stack << stack[-3]
266
- stack.delete_at(-4)
267
- when OP_2ROT
268
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
269
- 2.times { stack << stack[-6] }
270
- 2.times { stack.delete_at(-7) }
271
- when OP_SWAP
272
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
273
- tmp = stack.last
274
- stack[-1] = stack[-2]
275
- stack[-2] = tmp
276
- when OP_2SWAP
277
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
278
- 2.times {stack << stack[-4]}
279
- 2.times {stack.delete_at(-5)}
280
- when OP_TUCK
281
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
282
- stack.insert(-3, stack.last)
283
- when OP_ABS
284
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
285
- v = pop_int
286
- push_int(v.abs)
287
- when OP_BOOLAND
288
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
289
- a, b = pop_int(2)
290
- push_int((!a.zero? && !b.zero?) ? 1 : 0)
291
- when OP_BOOLOR
292
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
293
- a, b = pop_int(2)
294
- push_int((!a.zero? || !b.zero?) ? 1 : 0)
295
- when OP_NUMEQUAL, OP_NUMEQUALVERIFY
296
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
297
- a, b = pop_int(2)
298
- result = a == b
299
- push_int(result ? 1 : 0)
300
- if opcode == OP_NUMEQUALVERIFY
301
- if result
302
- stack.pop
303
- else
304
- return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
305
- end
319
+ end
320
+ when OP_LESSTHAN, OP_LESSTHANOREQUAL
321
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
322
+ a, b = pop_int(2)
323
+ push_int(a < b ? 1 : 0) if opcode == OP_LESSTHAN
324
+ push_int(a <= b ? 1 : 0) if opcode == OP_LESSTHANOREQUAL
325
+ when OP_GREATERTHAN, OP_GREATERTHANOREQUAL
326
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
327
+ a, b = pop_int(2)
328
+ push_int(a > b ? 1 : 0) if opcode == OP_GREATERTHAN
329
+ push_int(a >= b ? 1 : 0) if opcode == OP_GREATERTHANOREQUAL
330
+ when OP_MIN
331
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
332
+ push_int(pop_int(2).min)
333
+ when OP_MAX
334
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
335
+ push_int(pop_int(2).max)
336
+ when OP_WITHIN
337
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
338
+ x, a, b = pop_int(3)
339
+ push_int((a <= x && x < b) ? 1 : 0)
340
+ when OP_NOT
341
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
342
+ push_int(pop_int == 0 ? 1 : 0)
343
+ when OP_SIZE
344
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
345
+ item = stack.last
346
+ item = Tapyrus::Script.encode_number(item) if item.is_a?(Numeric)
347
+ size = item.htb.bytesize
348
+ push_int(size)
349
+ when OP_NEGATE
350
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
351
+ push_int(-pop_int)
352
+ when OP_NUMNOTEQUAL
353
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
354
+ a, b = pop_int(2)
355
+ push_int(a == b ? 0 : 1)
356
+ when OP_CODESEPARATOR
357
+ last_code_separator_index = index + 1
358
+ when OP_CHECKSIG, OP_CHECKSIGVERIFY
359
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
360
+ sig, pubkey = pop_string(2)
361
+
362
+ subscript = script.subscript(last_code_separator_index..-1)
363
+ if sig_version == :base
364
+ tmp = subscript.find_and_delete(Script.new << sig)
365
+ if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
366
+ return set_error(SCRIPT_ERR_SIG_FINDANDDELETE)
306
367
  end
307
- when OP_LESSTHAN, OP_LESSTHANOREQUAL
308
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
309
- a, b = pop_int(2)
310
- push_int(a < b ? 1 : 0) if opcode == OP_LESSTHAN
311
- push_int(a <= b ? 1 : 0) if opcode == OP_LESSTHANOREQUAL
312
- when OP_GREATERTHAN, OP_GREATERTHANOREQUAL
313
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
314
- a, b = pop_int(2)
315
- push_int(a > b ? 1 : 0) if opcode == OP_GREATERTHAN
316
- push_int(a >= b ? 1 : 0) if opcode == OP_GREATERTHANOREQUAL
317
- when OP_MIN
318
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
319
- push_int(pop_int(2).min)
320
- when OP_MAX
321
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
322
- push_int(pop_int(2).max)
323
- when OP_WITHIN
324
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
325
- x, a, b = pop_int(3)
326
- push_int((a <= x && x < b) ? 1 : 0)
327
- when OP_NOT
328
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
329
- push_int(pop_int == 0 ? 1 : 0)
330
- when OP_SIZE
331
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
332
- item = stack.last
333
- item = Tapyrus::Script.encode_number(item) if item.is_a?(Numeric)
334
- size = item.htb.bytesize
335
- push_int(size)
336
- when OP_NEGATE
337
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
338
- push_int(-pop_int)
339
- when OP_NUMNOTEQUAL
340
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
341
- a, b = pop_int(2)
342
- push_int(a == b ? 0 : 1)
343
- when OP_CODESEPARATOR
344
- last_code_separator_index = index + 1
345
- when OP_CHECKSIG, OP_CHECKSIGVERIFY
346
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
347
- sig, pubkey = pop_string(2)
348
-
349
- subscript = script.subscript(last_code_separator_index..-1)
350
- if sig_version == :base
351
- tmp = subscript.find_and_delete(Script.new << sig)
352
- return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
353
- subscript = tmp
368
+ subscript = tmp
369
+ end
370
+ if (
371
+ if sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE
372
+ !check_schnorr_signature_encoding(sig)
373
+ else
374
+ !check_ecdsa_signature_encoding(sig)
375
+ end
376
+ ) || !check_pubkey_encoding(pubkey)
377
+ return false
378
+ end
379
+
380
+ success = checker.check_sig(sig, pubkey, subscript, sig_version)
381
+
382
+ # https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL
383
+ if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
384
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL)
385
+ end
386
+
387
+ push_int(success ? 1 : 0)
388
+
389
+ if opcode == OP_CHECKSIGVERIFY
390
+ if success
391
+ stack.pop
392
+ else
393
+ return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
354
394
  end
355
- return false if (sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE ?
356
- !check_schnorr_signature_encoding(sig) : !check_ecdsa_signature_encoding(sig)) || !check_pubkey_encoding(pubkey)
357
-
358
- success = checker.check_sig(sig, pubkey, subscript, sig_version)
359
-
360
- # https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL
361
- if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
362
- return set_error(SCRIPT_ERR_SIG_NULLFAIL)
363
- end
364
-
365
- push_int(success ? 1 : 0)
366
-
367
- if opcode == OP_CHECKSIGVERIFY
368
- if success
369
- stack.pop
370
- else
371
- return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
372
- end
373
- end
374
- when OP_CHECKDATASIG, OP_CHECKDATASIGVERIFY
375
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
376
- sig, msg, pubkey = pop_string(3)
377
- # check signature encoding without hashtype byte
378
- return false if (sig.htb.bytesize != (Tapyrus::Key::COMPACT_SIGNATURE_SIZE - 1) && !check_ecdsa_signature_encoding(sig, true)) || !check_pubkey_encoding(pubkey)
379
- digest = Tapyrus.sha256(msg)
380
- success = checker.verify_sig(sig, pubkey, digest)
381
- return set_error(SCRIPT_ERR_SIG_NULLFAIL) if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
382
- push_int(success ? 1 : 0)
383
- if opcode == OP_CHECKDATASIGVERIFY
384
- stack.pop if success
385
- return set_error(SCRIPT_ERR_CHECKDATASIGVERIFY) unless success
386
- end
387
- when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
388
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
389
- pubkey_count = pop_int
390
- unless (0..MAX_PUBKEYS_PER_MULTISIG).include?(pubkey_count)
391
- return set_error(SCRIPT_ERR_PUBKEY_COUNT)
392
- end
393
-
394
- op_count += pubkey_count
395
- return set_error(SCRIPT_ERR_OP_COUNT) if op_count > MAX_OPS_PER_SCRIPT
396
-
397
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
398
-
399
- pubkeys = pop_string(pubkey_count)
400
- pubkeys = [pubkeys] if pubkeys.is_a?(String)
401
-
402
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
403
-
404
- sig_count = pop_int
405
- return set_error(SCRIPT_ERR_SIG_COUNT) if sig_count < 0 || sig_count > pubkey_count
406
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
407
-
408
- sigs = pop_string(sig_count)
409
- sigs = [sigs] if sigs.is_a?(String)
410
-
411
- subscript = script.subscript(last_code_separator_index..-1)
412
-
413
- if sig_version == :base
414
- sigs.each do |sig|
415
- tmp = subscript.find_and_delete(Script.new << sig)
416
- return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
417
- subscript = tmp
395
+ end
396
+ when OP_CHECKDATASIG, OP_CHECKDATASIGVERIFY
397
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
398
+ sig, msg, pubkey = pop_string(3)
399
+
400
+ # check signature encoding without hashtype byte
401
+ if (
402
+ sig.htb.bytesize != (Tapyrus::Key::COMPACT_SIGNATURE_SIZE - 1) &&
403
+ !check_ecdsa_signature_encoding(sig, true)
404
+ ) || !check_pubkey_encoding(pubkey)
405
+ return false
406
+ end
407
+ digest = Tapyrus.sha256(msg)
408
+ success = checker.verify_sig(sig, pubkey, digest)
409
+ if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
410
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL)
411
+ end
412
+ push_int(success ? 1 : 0)
413
+ if opcode == OP_CHECKDATASIGVERIFY
414
+ stack.pop if success
415
+ return set_error(SCRIPT_ERR_CHECKDATASIGVERIFY) unless success
416
+ end
417
+ when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
418
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
419
+ pubkey_count = pop_int
420
+ return set_error(SCRIPT_ERR_PUBKEY_COUNT) unless (0..MAX_PUBKEYS_PER_MULTISIG).include?(pubkey_count)
421
+
422
+ op_count += pubkey_count
423
+ return set_error(SCRIPT_ERR_OP_COUNT) if op_count > MAX_OPS_PER_SCRIPT
424
+
425
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
426
+
427
+ pubkeys = pop_string(pubkey_count)
428
+ pubkeys = [pubkeys] if pubkeys.is_a?(String)
429
+
430
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
431
+
432
+ sig_count = pop_int
433
+ return set_error(SCRIPT_ERR_SIG_COUNT) if sig_count < 0 || sig_count > pubkey_count
434
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
435
+
436
+ sigs = pop_string(sig_count)
437
+ sigs = [sigs] if sigs.is_a?(String)
438
+
439
+ subscript = script.subscript(last_code_separator_index..-1)
440
+
441
+ if sig_version == :base
442
+ sigs.each do |sig|
443
+ tmp = subscript.find_and_delete(Script.new << sig)
444
+ if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
445
+ return set_error(SCRIPT_ERR_SIG_FINDANDDELETE)
418
446
  end
447
+ subscript = tmp
419
448
  end
420
-
421
- success = true
422
- current_sig_scheme = nil
423
- while success && sig_count > 0
424
- sig = sigs.pop
425
- pubkey = pubkeys.pop
426
- sig_scheme = sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE ? :schnorr : :ecdsa
427
- current_sig_scheme = sig_scheme if current_sig_scheme.nil?
428
-
429
- return false if (sig_scheme == :schnorr ? !check_schnorr_signature_encoding(sig) : !check_ecdsa_signature_encoding(sig)) || !check_pubkey_encoding(pubkey) # error already set.
430
-
431
- return set_error(SCRIPT_ERR_MIXED_SCHEME_MULTISIG) unless sig_scheme == current_sig_scheme
432
-
433
- ok = checker.check_sig(sig, pubkey, subscript, sig_version)
434
- if ok
435
- sig_count -= 1
436
- else
437
- sigs << sig
438
- end
439
- pubkey_count -= 1
440
- success = false if sig_count > pubkey_count
449
+ end
450
+
451
+ success = true
452
+ current_sig_scheme = nil
453
+ while success && sig_count > 0
454
+ sig = sigs.pop
455
+ pubkey = pubkeys.pop
456
+ sig_scheme = sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE ? :schnorr : :ecdsa
457
+ current_sig_scheme = sig_scheme if current_sig_scheme.nil?
458
+
459
+ if (
460
+ if sig_scheme == :schnorr
461
+ !check_schnorr_signature_encoding(sig)
462
+ else
463
+ !check_ecdsa_signature_encoding(sig)
464
+ end
465
+ ) || !check_pubkey_encoding(pubkey)
466
+ return false
467
+ end # error already set.
468
+
469
+ return set_error(SCRIPT_ERR_MIXED_SCHEME_MULTISIG) unless sig_scheme == current_sig_scheme
470
+
471
+ ok = checker.check_sig(sig, pubkey, subscript, sig_version)
472
+ if ok
473
+ sig_count -= 1
474
+ else
475
+ sigs << sig
441
476
  end
442
-
443
- if !success && flag?(SCRIPT_VERIFY_NULLFAIL)
444
- sigs.each do |sig|
445
- # If the operation failed, we require that all signatures must be empty vector
446
- return set_error(SCRIPT_ERR_SIG_NULLFAIL) if sig.bytesize > 0
447
- end
477
+ pubkey_count -= 1
478
+ success = false if sig_count > pubkey_count
479
+ end
480
+
481
+ if !success && flag?(SCRIPT_VERIFY_NULLFAIL)
482
+ sigs.each do |sig|
483
+ # If the operation failed, we require that all signatures must be empty vector
484
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL) if sig.bytesize > 0
448
485
  end
449
-
450
- # A bug causes CHECKMULTISIG to consume one extra argument whose contents were not checked in any way.
451
- # Unfortunately this is a potential source of mutability,
452
- # so optionally verify it is exactly equal to zero prior to removing it from the stack.
453
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
454
- return set_error(SCRIPT_ERR_SIG_NULLDUMMY) if stack[-1].size > 0
455
-
456
- stack.pop
457
-
458
- push_int(success ? 1 : 0)
459
- if opcode == OP_CHECKMULTISIGVERIFY
460
- if success
461
- stack.pop
462
- else
463
- return set_error(SCRIPT_ERR_CHECKMULTISIGVERIFY)
464
- end
486
+ end
487
+
488
+ # A bug causes CHECKMULTISIG to consume one extra argument whose contents were not checked in any way.
489
+ # Unfortunately this is a potential source of mutability,
490
+ # so optionally verify it is exactly equal to zero prior to removing it from the stack.
491
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
492
+ return set_error(SCRIPT_ERR_SIG_NULLDUMMY) if stack[-1].size > 0
493
+
494
+ stack.pop
495
+
496
+ push_int(success ? 1 : 0)
497
+ if opcode == OP_CHECKMULTISIGVERIFY
498
+ if success
499
+ stack.pop
500
+ else
501
+ return set_error(SCRIPT_ERR_CHECKMULTISIGVERIFY)
465
502
  end
466
- when OP_RETURN
467
- return set_error(SCRIPT_ERR_OP_RETURN)
468
- when OP_COLOR
469
- # Color id is not permitted in p2sh redeem script
470
- return set_error(SCRIPT_ERR_OP_COLOR_UNEXPECTED) if is_redeem_script
503
+ end
504
+ when OP_RETURN
505
+ return set_error(SCRIPT_ERR_OP_RETURN)
506
+ when OP_COLOR
507
+ # Color id is not permitted in p2sh redeem script
508
+ return set_error(SCRIPT_ERR_OP_COLOR_UNEXPECTED) if is_redeem_script
471
509
 
472
- # if Color id is already initialized this must be an extra
473
- return set_error(SCRIPT_ERR_OP_COLOR_MULTIPLE) if color_id && color_id.type != Tapyrus::Color::TokenTypes::NONE
510
+ # if Color id is already initialized this must be an extra
511
+ if color_id && color_id.type != Tapyrus::Color::TokenTypes::NONE
512
+ return set_error(SCRIPT_ERR_OP_COLOR_MULTIPLE)
513
+ end
474
514
 
475
- # color id is not allowed inside OP_IF
476
- return set_error(SCRIPT_ERR_OP_COLOR_IN_BRANCH) unless flow_stack.empty?
515
+ # color id is not allowed inside OP_IF
516
+ return set_error(SCRIPT_ERR_OP_COLOR_IN_BRANCH) unless flow_stack.empty?
477
517
 
478
- # pop one stack element and verify that it exists
479
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size() < 1
518
+ # pop one stack element and verify that it exists
519
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
480
520
 
481
- color_id = Tapyrus::Color::ColorIdentifier.parse_from_payload(stack.last.htb)
521
+ color_id = Tapyrus::Color::ColorIdentifier.parse_from_payload(stack.last.htb)
482
522
 
483
- # check ColorIdentifier is valid
484
- return set_error(SCRIPT_ERR_OP_COLOR_ID_INVALID) unless color_id.valid?
523
+ # check ColorIdentifier is valid
524
+ return set_error(SCRIPT_ERR_OP_COLOR_ID_INVALID) unless color_id.valid?
485
525
 
486
- stack.pop
487
- else
488
- return set_error(SCRIPT_ERR_BAD_OPCODE)
526
+ stack.pop
527
+ else
528
+ return set_error(SCRIPT_ERR_BAD_OPCODE)
489
529
  end
490
530
  end
491
531
  end
@@ -513,7 +553,7 @@ module Tapyrus
513
553
 
514
554
  # pop the item with the int value for the number specified by +count+ from the stack.
515
555
  def pop_int(count = 1)
516
- i = stack.pop(count).map{ |s| cast_to_int(s) }
556
+ i = stack.pop(count).map { |s| cast_to_int(s) }
517
557
  count == 1 ? i.first : i
518
558
  end
519
559
 
@@ -536,14 +576,17 @@ module Tapyrus
536
576
 
537
577
  # pop the item with the string(hex) value for the number specified by +count+ from the stack.
538
578
  def pop_string(count = 1)
539
- s = stack.pop(count).map do |s|
540
- case s
541
- when Numeric
542
- Script.encode_number(s)
543
- else
544
- s
545
- end
546
- end
579
+ s =
580
+ stack
581
+ .pop(count)
582
+ .map do |s|
583
+ case s
584
+ when Numeric
585
+ Script.encode_number(s)
586
+ else
587
+ s
588
+ end
589
+ end
547
590
  count == 1 ? s.first : s
548
591
  end
549
592
 
@@ -555,15 +598,13 @@ module Tapyrus
555
598
  # see https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L36-L49
556
599
  def cast_to_bool(v)
557
600
  case v
558
- when Numeric
559
- return v != 0
560
- when String
561
- v.each_byte.with_index do |b, i|
562
- return !(i == (v.bytesize - 1) && b == 0x80) unless b == 0
563
- end
564
- false
565
- else
566
- false
601
+ when Numeric
602
+ return v != 0
603
+ when String
604
+ v.each_byte.with_index { |b, i| return !(i == (v.bytesize - 1) && b == 0x80) unless b == 0 }
605
+ false
606
+ else
607
+ false
567
608
  end
568
609
  end
569
610
 
@@ -616,7 +657,7 @@ module Tapyrus
616
657
  return opcode == data.bytesize
617
658
  elsif data.bytesize <= 255
618
659
  return opcode == OP_PUSHDATA1
619
- elsif data.bytesize <= 65535
660
+ elsif data.bytesize <= 65_535
620
661
  return opcode == OP_PUSHDATA2
621
662
  end
622
663
  true
@@ -626,22 +667,21 @@ module Tapyrus
626
667
  buf = StringIO.new(chunk)
627
668
  opcode = buf.read(1).ord
628
669
  offset = 1
629
- len = case opcode
630
- when OP_PUSHDATA1
631
- offset += 1
632
- buf.read(1).unpack('C').first
633
- when OP_PUSHDATA2
634
- offset += 2
635
- buf.read(2).unpack('v').first
636
- when OP_PUSHDATA4
637
- offset += 4
638
- buf.read(4).unpack('V').first
639
- else
640
- opcode
641
- end
670
+ len =
671
+ case opcode
672
+ when OP_PUSHDATA1
673
+ offset += 1
674
+ buf.read(1).unpack('C').first
675
+ when OP_PUSHDATA2
676
+ offset += 2
677
+ buf.read(2).unpack('v').first
678
+ when OP_PUSHDATA4
679
+ offset += 4
680
+ buf.read(4).unpack('V').first
681
+ else
682
+ opcode
683
+ end
642
684
  chunk.bytesize == len + offset
643
685
  end
644
-
645
686
  end
646
-
647
- end
687
+ end