tapyrus 0.2.13 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -3
- data/.ruby-version +1 -1
- data/README.md +1 -1
- data/exe/tapyrus-script-debugger +131 -0
- data/lib/tapyrus/block_header.rb +1 -1
- data/lib/tapyrus/chain_params.rb +2 -1
- data/lib/tapyrus/constants.rb +0 -2
- data/lib/tapyrus/ext.rb +16 -0
- data/lib/tapyrus/network/message_handler.rb +2 -0
- data/lib/tapyrus/rpc/request_handler.rb +1 -1
- data/lib/tapyrus/script/script.rb +24 -22
- data/lib/tapyrus/script/script_interpreter.rb +441 -432
- data/lib/tapyrus/script/tx_checker.rb +5 -9
- data/lib/tapyrus/tx.rb +8 -17
- data/lib/tapyrus/tx_builder.rb +10 -5
- data/lib/tapyrus/version.rb +1 -1
- data/lib/tapyrus.rb +0 -16
- data/tapyrusrb.gemspec +2 -1
- metadata +26 -10
@@ -2,13 +2,19 @@ module Tapyrus
|
|
2
2
|
class ScriptInterpreter
|
3
3
|
include Tapyrus::Opcodes
|
4
4
|
|
5
|
-
|
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,
|
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,
|
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,
|
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,
|
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
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
115
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) unless @flow_stack.empty?
|
108
116
|
|
109
|
-
|
117
|
+
set_error(SCRIPT_ERR_OK)
|
118
|
+
true
|
119
|
+
end
|
110
120
|
|
111
|
-
|
112
|
-
|
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
|
-
|
124
|
+
return set_error(SCRIPT_ERR_PUSH_SIZE) if c.pushdata? && c.pushed_data.bytesize > MAX_SCRIPT_ELEMENT_SIZE
|
381
125
|
|
382
|
-
|
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
|
-
|
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
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
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
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
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
|
-
|
398
|
+
success = checker.check_sig(sig, pubkey, subscript)
|
426
399
|
|
427
|
-
|
428
|
-
|
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
|
-
|
403
|
+
push_int(success ? 1 : 0)
|
431
404
|
|
432
|
-
|
433
|
-
|
434
|
-
|
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
|
-
|
437
|
-
|
436
|
+
@op_count += pubkey_count
|
437
|
+
return set_error(SCRIPT_ERR_OP_COUNT) if @op_count > MAX_OPS_PER_SCRIPT
|
438
438
|
|
439
|
-
|
439
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
|
440
440
|
|
441
|
-
|
442
|
-
|
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
|
-
|
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
|
-
|
482
|
-
|
483
|
-
|
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
|
-
|
489
|
-
|
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
|
-
|
453
|
+
subscript = script.subscript(@last_code_separator_index..-1)
|
495
454
|
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
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
|
-
|
516
|
-
|
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
|
-
|
519
|
-
|
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
|
-
|
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
|
-
|
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(
|
513
|
+
return set_error(SCRIPT_ERR_CHECKMULTISIGVERIFY)
|
529
514
|
end
|
530
515
|
end
|
531
|
-
|
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
|
-
|
534
|
-
|
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
|
-
|
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
|
-
|
545
|
-
|
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)
|