tapyrus 0.2.13 → 0.3.2

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.
@@ -2,13 +2,19 @@ module Tapyrus
2
2
  class ScriptInterpreter
3
3
  include Tapyrus::Opcodes
4
4
 
5
- attr_reader :stack
5
+ attr_accessor :stack
6
6
  attr_reader :debug
7
7
  attr_reader :flags
8
8
  attr_accessor :error
9
9
  attr_reader :checker
10
10
  attr_reader :require_minimal
11
11
 
12
+ attr_accessor :flow_stack
13
+ attr_accessor :alt_stack
14
+ attr_accessor :last_code_separator_index
15
+ attr_accessor :op_count
16
+ attr_accessor :color_id
17
+
12
18
  DISABLE_OPCODES = [
13
19
  OP_CAT,
14
20
  OP_SUBSTR,
@@ -51,11 +57,11 @@ module Tapyrus
51
57
 
52
58
  stack_copy = nil
53
59
 
54
- return false unless eval_script(script_sig, :base, false)
60
+ return false unless eval_script(script_sig, false)
55
61
 
56
62
  stack_copy = stack.dup if flag?(SCRIPT_VERIFY_P2SH)
57
63
 
58
- return false unless eval_script(script_pubkey, :base, false)
64
+ return false unless eval_script(script_pubkey, false)
59
65
 
60
66
  return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last.htb)
61
67
 
@@ -70,7 +76,7 @@ module Tapyrus
70
76
  rescue Exception => e
71
77
  return set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
72
78
  end
73
- return false unless eval_script(redeem_script, :base, true)
79
+ return false unless eval_script(redeem_script, true)
74
80
  return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)
75
81
  end
76
82
 
@@ -92,457 +98,473 @@ module Tapyrus
92
98
  false
93
99
  end
94
100
 
95
- def eval_script(script, sig_version, is_redeem_script)
101
+ def eval_script(script, is_redeem_script)
96
102
  return set_error(SCRIPT_ERR_SCRIPT_SIZE) if script.size > MAX_SCRIPT_SIZE
97
103
  begin
98
- flow_stack = []
99
- alt_stack = []
100
- last_code_separator_index = 0
101
- op_count = 0
102
- color_id = nil
103
-
104
- script.chunks.each_with_index do |c, index|
105
- need_exec = !flow_stack.include?(false)
104
+ reset_params
105
+ script.chunks.each_with_index do |chunk, index|
106
+ result = next_step(script, chunk, index, is_redeem_script)
107
+ return result if result.is_a?(FalseClass)
108
+ end
109
+ rescue Exception => e
110
+ puts e
111
+ puts e.backtrace
112
+ return set_error(SCRIPT_ERR_UNKNOWN_ERROR, e.message)
113
+ end
106
114
 
107
- return set_error(SCRIPT_ERR_PUSH_SIZE) if c.pushdata? && c.pushed_data.bytesize > MAX_SCRIPT_ELEMENT_SIZE
115
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) unless @flow_stack.empty?
108
116
 
109
- opcode = c.opcode
117
+ set_error(SCRIPT_ERR_OK)
118
+ true
119
+ end
110
120
 
111
- if need_exec && c.pushdata?
112
- return set_error(SCRIPT_ERR_MINIMALDATA) if require_minimal && !minimal_push?(c.pushed_data, opcode)
113
- return set_error(SCRIPT_ERR_BAD_OPCODE) unless verify_pushdata_length(c)
114
- stack << c.pushed_data.bth
115
- else
116
- if opcode > OP_16 && (op_count += 1) > MAX_OPS_PER_SCRIPT
117
- return set_error(SCRIPT_ERR_OP_COUNT)
118
- end
119
- return set_error(SCRIPT_ERR_DISABLED_OPCODE) if DISABLE_OPCODES.include?(opcode)
120
- if opcode == OP_CODESEPARATOR && sig_version == :base && flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE)
121
- return set_error(SCRIPT_ERR_OP_CODESEPARATOR)
122
- end
123
- next unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
124
- small_int = Opcodes.opcode_to_small_int(opcode)
125
- if small_int && opcode != OP_0
126
- push_int(small_int)
127
- else
128
- case opcode
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)
143
- 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)
170
- end
171
- end
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)
318
- 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)
367
- end
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
121
+ def next_step(script, c, index, is_redeem_script)
122
+ need_exec = !@flow_stack.include?(false)
379
123
 
380
- success = checker.check_sig(sig, pubkey, subscript, sig_version)
124
+ return set_error(SCRIPT_ERR_PUSH_SIZE) if c.pushdata? && c.pushed_data.bytesize > MAX_SCRIPT_ELEMENT_SIZE
381
125
 
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
126
+ opcode = c.opcode
386
127
 
387
- push_int(success ? 1 : 0)
128
+ if need_exec && c.pushdata?
129
+ return set_error(SCRIPT_ERR_MINIMALDATA) if require_minimal && !minimal_push?(c.pushed_data, opcode)
130
+ return set_error(SCRIPT_ERR_BAD_OPCODE) unless verify_pushdata_length(c)
131
+ stack << c.pushed_data.bth
132
+ else
133
+ if opcode > OP_16 && (@op_count += 1) > MAX_OPS_PER_SCRIPT
134
+ return set_error(SCRIPT_ERR_OP_COUNT)
135
+ end
136
+ return set_error(SCRIPT_ERR_DISABLED_OPCODE) if DISABLE_OPCODES.include?(opcode)
137
+ if opcode == OP_CODESEPARATOR && flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE)
138
+ return set_error(SCRIPT_ERR_OP_CODESEPARATOR)
139
+ end
388
140
 
389
- if opcode == OP_CHECKSIGVERIFY
390
- if success
391
- stack.pop
392
- else
393
- return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
394
- end
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
141
+ # next unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
142
+ return unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
143
+ small_int = Opcodes.opcode_to_small_int(opcode)
144
+ if small_int && opcode != OP_0
145
+ push_int(small_int)
146
+ else
147
+ case opcode
148
+ when OP_0
149
+ stack << ''
150
+ when OP_DEPTH
151
+ push_int(stack.size)
152
+ when OP_EQUAL, OP_EQUALVERIFY
153
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
154
+ a, b = pop_string(2)
155
+ result = a == b
156
+ push_int(result ? 1 : 0)
157
+ if opcode == OP_EQUALVERIFY
158
+ if result
159
+ stack.pop
160
+ else
161
+ return set_error(SCRIPT_ERR_EQUALVERIFY)
162
+ end
163
+ end
164
+ when OP_0NOTEQUAL
165
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
166
+ push_int(pop_int == 0 ? 0 : 1)
167
+ when OP_ADD
168
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
169
+ a, b = pop_int(2)
170
+ push_int(a + b)
171
+ when OP_1ADD
172
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
173
+ push_int(pop_int + 1)
174
+ when OP_SUB
175
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
176
+ a, b = pop_int(2)
177
+ push_int(a - b)
178
+ when OP_1SUB
179
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
180
+ push_int(pop_int - 1)
181
+ when OP_IF, OP_NOTIF
182
+ result = false
183
+ if need_exec
184
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
185
+ value = pop_string.htb
186
+ if flag?(SCRIPT_VERIFY_MINIMALIF)
187
+ if value.bytesize > 1 || (value.bytesize == 1 && value[0].unpack('C').first != 1)
188
+ return set_error(SCRIPT_ERR_MINIMALIF)
416
189
  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
190
+ end
191
+ result = cast_to_bool(value)
192
+ result = !result if opcode == OP_NOTIF
193
+ end
194
+ @flow_stack << result
195
+ when OP_ELSE
196
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if @flow_stack.size < 1
197
+ @flow_stack << !@flow_stack.pop
198
+ when OP_ENDIF
199
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if @flow_stack.empty?
200
+ @flow_stack.pop
201
+ when OP_NOP
202
+ when OP_NOP1, OP_NOP4..OP_NOP10
203
+ return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
204
+ when OP_CHECKLOCKTIMEVERIFY
205
+ # next unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
206
+ return unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
207
+
208
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
209
+
210
+ # Note that elsewhere numeric opcodes are limited to operands in the range -2**31+1 to 2**31-1,
211
+ # however it is legal for opcodes to produce results exceeding that range.
212
+ # This limitation is implemented by CScriptNum's default 4-byte limit.
213
+ # If we kept to that limit we'd have a year 2038 problem,
214
+ # even though the nLockTime field in transactions themselves is uint32 which only becomes meaningless after the year 2106.
215
+ # Thus as a special case we tell CScriptNum to accept up to 5-byte bignums,
216
+ # which are good until 2**39-1, well beyond the 2**32-1 limit of the nLockTime field itself.
217
+ locktime = cast_to_int(stack.last, 5)
218
+ return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if locktime < 0
219
+ return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_locktime(locktime)
220
+ when OP_CHECKSEQUENCEVERIFY
221
+ # next unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
222
+ return unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
223
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
224
+
225
+ # nSequence, like nLockTime, is a 32-bit unsigned integer field.
226
+ # See the comment in CHECKLOCKTIMEVERIFY regarding 5-byte numeric operands.
227
+ sequence = cast_to_int(stack.last, 5)
228
+
229
+ # In the rare event that the argument may be < 0 due to some arithmetic being done first,
230
+ # you can always use 0 MAX CHECKSEQUENCEVERIFY.
231
+ return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if sequence < 0
232
+
233
+ # To provide for future soft-fork extensibility,
234
+ # if the operand has the disabled lock-time flag set, CHECKSEQUENCEVERIFY behaves as a NOP.
235
+ # next if (sequence & Tapyrus::TxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0
236
+ return if (sequence & Tapyrus::TxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0
237
+
238
+ # Compare the specified sequence number with the input.
239
+ return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_sequence(sequence)
240
+ when OP_DUP
241
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
242
+ stack << stack.last
243
+ when OP_2DUP
244
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
245
+ 2.times { stack << stack[-2] }
246
+ when OP_3DUP
247
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
248
+ 3.times { stack << stack[-3] }
249
+ when OP_IFDUP
250
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
251
+ stack << stack.last if cast_to_bool(stack.last)
252
+ when OP_RIPEMD160
253
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
254
+ stack << Digest::RMD160.hexdigest(pop_string.htb)
255
+ when OP_SHA1
256
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
257
+ stack << Digest::SHA1.hexdigest(pop_string.htb)
258
+ when OP_SHA256
259
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
260
+ stack << Digest::SHA256.hexdigest(pop_string.htb)
261
+ when OP_HASH160
262
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
263
+ stack << Tapyrus.hash160(pop_string)
264
+ when OP_HASH256
265
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
266
+ stack << Tapyrus.double_sha256(pop_string.htb).bth
267
+ when OP_VERIFY
268
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
269
+ return set_error(SCRIPT_ERR_VERIFY) unless pop_bool
270
+ when OP_TOALTSTACK
271
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
272
+ @alt_stack << stack.pop
273
+ when OP_FROMALTSTACK
274
+ return set_error(SCRIPT_ERR_INVALID_ALTSTACK_OPERATION) if @alt_stack.size < 1
275
+ stack << @alt_stack.pop
276
+ when OP_DROP
277
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
278
+ stack.pop
279
+ when OP_2DROP
280
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
281
+ 2.times { stack.pop }
282
+ when OP_NIP
283
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
284
+ stack.delete_at(-2)
285
+ when OP_OVER
286
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
287
+ stack << stack[-2]
288
+ when OP_2OVER
289
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
290
+ 2.times { stack << stack[-4] }
291
+ when OP_PICK, OP_ROLL
292
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
293
+ pos = pop_int
294
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
295
+ stack << stack[-pos - 1]
296
+ stack.delete_at(-pos - 2) if opcode == OP_ROLL
297
+ when OP_ROT
298
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
299
+ stack << stack[-3]
300
+ stack.delete_at(-4)
301
+ when OP_2ROT
302
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
303
+ 2.times { stack << stack[-6] }
304
+ 2.times { stack.delete_at(-7) }
305
+ when OP_SWAP
306
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
307
+ tmp = stack.last
308
+ stack[-1] = stack[-2]
309
+ stack[-2] = tmp
310
+ when OP_2SWAP
311
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
312
+ 2.times { stack << stack[-4] }
313
+ 2.times { stack.delete_at(-5) }
314
+ when OP_TUCK
315
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
316
+ stack.insert(-3, stack.last)
317
+ when OP_ABS
318
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
319
+ v = pop_int
320
+ push_int(v.abs)
321
+ when OP_BOOLAND
322
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
323
+ a, b = pop_int(2)
324
+ push_int((!a.zero? && !b.zero?) ? 1 : 0)
325
+ when OP_BOOLOR
326
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
327
+ a, b = pop_int(2)
328
+ push_int((!a.zero? || !b.zero?) ? 1 : 0)
329
+ when OP_NUMEQUAL, OP_NUMEQUALVERIFY
330
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
331
+ a, b = pop_int(2)
332
+ result = a == b
333
+ push_int(result ? 1 : 0)
334
+ if opcode == OP_NUMEQUALVERIFY
335
+ if result
336
+ stack.pop
337
+ else
338
+ return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
339
+ end
340
+ end
341
+ when OP_LESSTHAN, OP_LESSTHANOREQUAL
342
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
343
+ a, b = pop_int(2)
344
+ push_int(a < b ? 1 : 0) if opcode == OP_LESSTHAN
345
+ push_int(a <= b ? 1 : 0) if opcode == OP_LESSTHANOREQUAL
346
+ when OP_GREATERTHAN, OP_GREATERTHANOREQUAL
347
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
348
+ a, b = pop_int(2)
349
+ push_int(a > b ? 1 : 0) if opcode == OP_GREATERTHAN
350
+ push_int(a >= b ? 1 : 0) if opcode == OP_GREATERTHANOREQUAL
351
+ when OP_MIN
352
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
353
+ push_int(pop_int(2).min)
354
+ when OP_MAX
355
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
356
+ push_int(pop_int(2).max)
357
+ when OP_WITHIN
358
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
359
+ x, a, b = pop_int(3)
360
+ push_int((a <= x && x < b) ? 1 : 0)
361
+ when OP_NOT
362
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
363
+ push_int(pop_int == 0 ? 1 : 0)
364
+ when OP_SIZE
365
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
366
+ item = stack.last
367
+ item = Tapyrus::Script.encode_number(item) if item.is_a?(Numeric)
368
+ size = item.htb.bytesize
369
+ push_int(size)
370
+ when OP_NEGATE
371
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
372
+ push_int(-pop_int)
373
+ when OP_NUMNOTEQUAL
374
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
375
+ a, b = pop_int(2)
376
+ push_int(a == b ? 0 : 1)
377
+ when OP_CODESEPARATOR
378
+ @last_code_separator_index = index + 1
379
+ when OP_CHECKSIG, OP_CHECKSIGVERIFY
380
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
381
+ sig, pubkey = pop_string(2)
382
+
383
+ subscript = script.subscript(@last_code_separator_index..-1)
384
+ tmp = subscript.find_and_delete(Script.new << sig)
385
+ return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
386
+ subscript = tmp
387
+
388
+ if (
389
+ if sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE
390
+ !check_schnorr_signature_encoding(sig)
391
+ else
392
+ !check_ecdsa_signature_encoding(sig)
393
+ end
394
+ ) || !check_pubkey_encoding(pubkey)
395
+ return false
396
+ end
424
397
 
425
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
398
+ success = checker.check_sig(sig, pubkey, subscript)
426
399
 
427
- pubkeys = pop_string(pubkey_count)
428
- pubkeys = [pubkeys] if pubkeys.is_a?(String)
400
+ # https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL
401
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL) if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
429
402
 
430
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
403
+ push_int(success ? 1 : 0)
431
404
 
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)
405
+ if opcode == OP_CHECKSIGVERIFY
406
+ if success
407
+ stack.pop
408
+ else
409
+ return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
410
+ end
411
+ end
412
+ when OP_CHECKDATASIG, OP_CHECKDATASIGVERIFY
413
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
414
+ sig, msg, pubkey = pop_string(3)
415
+
416
+ # check signature encoding without hashtype byte
417
+ if (
418
+ sig.htb.bytesize != (Tapyrus::Key::COMPACT_SIGNATURE_SIZE - 1) &&
419
+ !check_ecdsa_signature_encoding(sig, true)
420
+ ) || !check_pubkey_encoding(pubkey)
421
+ return false
422
+ end
423
+ digest = Tapyrus.sha256(msg)
424
+ success = checker.verify_sig(sig, pubkey, digest)
425
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL) if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
426
+ push_int(success ? 1 : 0)
427
+ if opcode == OP_CHECKDATASIGVERIFY
428
+ stack.pop if success
429
+ return set_error(SCRIPT_ERR_CHECKDATASIGVERIFY) unless success
430
+ end
431
+ when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
432
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
433
+ pubkey_count = pop_int
434
+ return set_error(SCRIPT_ERR_PUBKEY_COUNT) unless (0..MAX_PUBKEYS_PER_MULTISIG).include?(pubkey_count)
435
435
 
436
- sigs = pop_string(sig_count)
437
- sigs = [sigs] if sigs.is_a?(String)
436
+ @op_count += pubkey_count
437
+ return set_error(SCRIPT_ERR_OP_COUNT) if @op_count > MAX_OPS_PER_SCRIPT
438
438
 
439
- subscript = script.subscript(last_code_separator_index..-1)
439
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
440
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)
446
- end
447
- subscript = tmp
448
- end
449
- end
441
+ pubkeys = pop_string(pubkey_count)
442
+ pubkeys = [pubkeys] if pubkeys.is_a?(String)
450
443
 
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
476
- end
477
- pubkey_count -= 1
478
- success = false if sig_count > pubkey_count
479
- end
444
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
480
445
 
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
485
- end
486
- end
446
+ sig_count = pop_int
447
+ return set_error(SCRIPT_ERR_SIG_COUNT) if sig_count < 0 || sig_count > pubkey_count
448
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
487
449
 
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
450
+ sigs = pop_string(sig_count)
451
+ sigs = [sigs] if sigs.is_a?(String)
493
452
 
494
- stack.pop
453
+ subscript = script.subscript(@last_code_separator_index..-1)
495
454
 
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)
502
- end
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
509
-
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
455
+ sigs.each do |sig|
456
+ tmp = subscript.find_and_delete(Script.new << sig)
457
+ if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
458
+ return set_error(SCRIPT_ERR_SIG_FINDANDDELETE)
459
+ end
460
+ subscript = tmp
461
+ end
514
462
 
515
- # color id is not allowed inside OP_IF
516
- return set_error(SCRIPT_ERR_OP_COLOR_IN_BRANCH) unless flow_stack.empty?
463
+ success = true
464
+ current_sig_scheme = nil
465
+ while success && sig_count > 0
466
+ sig = sigs.pop
467
+ pubkey = pubkeys.pop
468
+ sig_scheme = sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE ? :schnorr : :ecdsa
469
+ current_sig_scheme = sig_scheme if current_sig_scheme.nil?
470
+
471
+ if (
472
+ if sig_scheme == :schnorr
473
+ !check_schnorr_signature_encoding(sig)
474
+ else
475
+ !check_ecdsa_signature_encoding(sig)
476
+ end
477
+ ) || !check_pubkey_encoding(pubkey)
478
+ return false
479
+ end # error already set.
480
+
481
+ return set_error(SCRIPT_ERR_MIXED_SCHEME_MULTISIG) unless sig_scheme == current_sig_scheme
482
+
483
+ ok = checker.check_sig(sig, pubkey, subscript)
484
+ if ok
485
+ sig_count -= 1
486
+ else
487
+ sigs << sig
488
+ end
489
+ pubkey_count -= 1
490
+ success = false if sig_count > pubkey_count
491
+ end
517
492
 
518
- # pop one stack element and verify that it exists
519
- return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
493
+ if !success && flag?(SCRIPT_VERIFY_NULLFAIL)
494
+ sigs.each do |sig|
495
+ # If the operation failed, we require that all signatures must be empty vector
496
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL) if sig.bytesize > 0
497
+ end
498
+ end
520
499
 
521
- color_id = Tapyrus::Color::ColorIdentifier.parse_from_payload(stack.last.htb)
500
+ # A bug causes CHECKMULTISIG to consume one extra argument whose contents were not checked in any way.
501
+ # Unfortunately this is a potential source of mutability,
502
+ # so optionally verify it is exactly equal to zero prior to removing it from the stack.
503
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
504
+ return set_error(SCRIPT_ERR_SIG_NULLDUMMY) if stack[-1].size > 0
522
505
 
523
- # check ColorIdentifier is valid
524
- return set_error(SCRIPT_ERR_OP_COLOR_ID_INVALID) unless color_id.valid?
506
+ stack.pop
525
507
 
508
+ push_int(success ? 1 : 0)
509
+ if opcode == OP_CHECKMULTISIGVERIFY
510
+ if success
526
511
  stack.pop
527
512
  else
528
- return set_error(SCRIPT_ERR_BAD_OPCODE)
513
+ return set_error(SCRIPT_ERR_CHECKMULTISIGVERIFY)
529
514
  end
530
515
  end
531
- end
516
+ when OP_RETURN
517
+ return set_error(SCRIPT_ERR_OP_RETURN)
518
+ when OP_COLOR
519
+ # Color id is not permitted in p2sh redeem script
520
+ return set_error(SCRIPT_ERR_OP_COLOR_UNEXPECTED) if is_redeem_script
521
+
522
+ # if Color id is already initialized this must be an extra
523
+ if @color_id && @color_id.type != Tapyrus::Color::TokenTypes::NONE
524
+ return set_error(SCRIPT_ERR_OP_COLOR_MULTIPLE)
525
+ end
526
+
527
+ # color id is not allowed inside OP_IF
528
+ return set_error(SCRIPT_ERR_OP_COLOR_IN_BRANCH) unless @flow_stack.empty?
532
529
 
533
- # max stack size check
534
- return set_error(SCRIPT_ERR_STACK_SIZE) if stack.size + alt_stack.size > MAX_STACK_SIZE
530
+ # pop one stack element and verify that it exists
531
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
532
+
533
+ @color_id = Tapyrus::Color::ColorIdentifier.parse_from_payload(stack.last.htb)
534
+
535
+ # check ColorIdentifier is valid
536
+ return set_error(SCRIPT_ERR_OP_COLOR_ID_INVALID) unless @color_id.valid?
537
+
538
+ stack.pop
539
+ else
540
+ return set_error(SCRIPT_ERR_BAD_OPCODE)
541
+ end
535
542
  end
536
- rescue Exception => e
537
- puts e
538
- puts e.backtrace
539
- return set_error(SCRIPT_ERR_UNKNOWN_ERROR, e.message)
540
543
  end
541
544
 
542
- return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) unless flow_stack.empty?
545
+ # max stack size check
546
+ return set_error(SCRIPT_ERR_STACK_SIZE) if stack.size + @alt_stack.size > MAX_STACK_SIZE
547
+ end
543
548
 
544
- set_error(SCRIPT_ERR_OK)
545
- true
549
+ def reset_params
550
+ @flow_stack = []
551
+ @alt_stack = []
552
+ @last_code_separator_index = 0
553
+ @op_count = 0
554
+ @color_id = nil
555
+ end
556
+
557
+ # see https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L36-L49
558
+ def cast_to_bool(v)
559
+ case v
560
+ when Numeric
561
+ return v != 0
562
+ when String
563
+ v.each_byte.with_index { |b, i| return !(i == (v.bytesize - 1) && b == 0x80) unless b == 0 }
564
+ false
565
+ else
566
+ false
567
+ end
546
568
  end
547
569
 
548
570
  private
@@ -595,19 +617,6 @@ module Tapyrus
595
617
  cast_to_bool(pop_string.htb)
596
618
  end
597
619
 
598
- # see https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L36-L49
599
- def cast_to_bool(v)
600
- case v
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
608
- end
609
- end
610
-
611
620
  def check_ecdsa_signature_encoding(sig, data_sig = false)
612
621
  return true if sig.size.zero?
613
622
  if !Key.valid_signature_encoding?(sig.htb, data_sig)