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.
- 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)
|