4"""Test the Iguana Script debugger."""
9from test_framework.hash
import hash160
10from test_framework.key
import ECKey
11from test_framework.messages
import COutPoint, CTransaction, CTxIn
12from test_framework.script
import (
28from test_framework.signature_hash
import (
35def iguana(*args, expected_stderr="", expected_returncode=None):
36 if expected_returncode
is None:
37 expected_returncode = 255
if expected_stderr
else 0
39 command = [os.environ[
"IGUANA_BIN"], *args]
40 if emulator := os.environ.get(
"EMULATOR",
None):
41 command.insert(0, emulator)
43 child = subprocess.Popen(
45 stdout=subprocess.PIPE,
46 stderr=subprocess.PIPE,
48 actual_stdout, actual_stderr = child.communicate()
49 assert actual_stderr.decode() == expected_stderr
50 assert child.returncode == expected_returncode
51 return actual_stdout.decode()
55 assert iguana(
"-version").startswith(
56 f
"Iguana v{os.environ['CMAKE_PROJECT_VERSION']}"
61 assert iguana(
"-?").startswith(
"Usage: iguana")
67 expected_stderr=
"Error parsing command line arguments: Invalid parameter -invalidarg\n",
73 "-format=doesntexist",
74 expected_stderr=
"Unsupported output format doesntexist\n",
83 expected_stderr=
"Error deserializing transaction\n",
90 "-tx=" + tx.serialize().hex(),
94 expected_stderr=
"Transaction doesn't have input index 0\n",
100 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31", OP_DUP]))]
102 def run(fmt, expected_stderr):
104 "-tx=" + tx.serialize().hex(),
109 expected_stderr=expected_stderr,
110 expected_returncode=255,
116 expected_stderr=
"scriptSig failed execution: Only push operators allowed in signatures\n",
119======= scriptSig =======
120 Stack (0 items): (empty stack)
130scriptName,index,opcode,stack 0,
131scriptSig,0,0x31,"31",
133scriptSig failed execution: Only push operators allowed in signatures
140 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
144 "-tx=" + tx.serialize().hex(),
154======= scriptSig =======
155 Stack (0 items): (empty stack)
157======= scriptPubKey =======
160Script executed without errors
166scriptName,index,opcode,stack 0,
167scriptSig,0,0x31,"31",
169Script executed without errors
176 tx.vin = [CTxIn(COutPoint(), CScript(b
"\x01"))]
178 def run(fmt, expected_stderr):
180 "-tx=" + tx.serialize().hex(),
185 expected_stderr=expected_stderr,
186 expected_returncode=255,
192 expected_stderr=
"scriptSig failed execution: Invalidly encoded opcode\n",
195======= scriptSig =======
196 Stack (0 items): (empty stack)
202scriptName,index,opcode,
203scriptSig failed execution: Invalidly encoded opcode
210 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31", b
"\x32"]))]
211 script_pub_key = CScript([OP_ADD, b
"\x63", OP_EQUAL])
215 "-tx=" + tx.serialize().hex(),
217 "-scriptpubkey=" + script_pub_key.hex(),
225======= scriptSig =======
226 Stack (0 items): (empty stack)
231======= scriptPubKey =======
245Script executed without errors
251scriptName,index,opcode,stack 0,stack 1,
252scriptSig,0,0x31,"31",
253scriptSig,1,0x32,"31","32",
254scriptPubKey,0,OP_ADD,"63",
255scriptPubKey,1,0x63,"63","63",
256scriptPubKey,2,OP_EQUAL,"01",
258Script executed without errors
265 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
266 script_pub_key = CScript([OP_EQUAL])
268 "-tx=" + tx.serialize().hex(),
270 "-scriptpubkey=" + script_pub_key.hex(),
272 expected_stderr=
"scriptPubKey failed execution: Operation not valid with the current stack size\n",
277======= scriptSig =======
278 Stack (0 items): (empty stack)
280======= scriptPubKey =======
290 tx.vin = [CTxIn(COutPoint(), CScript())]
291 script_pub_key = CScript([OP_1, OP_IF, OP_1])
293 "-tx=" + tx.serialize().hex(),
295 "-scriptpubkey=" + script_pub_key.hex(),
297 expected_stderr=
"scriptPubKey failed execution: Invalid OP_IF construction\n",
302======= scriptSig =======
303 Stack (0 items): (empty stack)
304======= scriptPubKey =======
305 Stack (0 items): (empty stack)
310 Stack (0 items): (empty stack)
318 tx.vin = [CTxIn(COutPoint(), CScript())]
319 script_pub_key = CScript([OP_NOP] * 10001)
321 "-tx=" + tx.serialize().hex(),
323 "-scriptpubkey=" + script_pub_key.hex(),
325 expected_stderr=
"scriptPubKey failed execution: Script is too big\n",
330======= scriptSig =======
331 Stack (0 items): (empty stack)
332======= scriptPubKey =======
333 Stack (0 items): (empty stack)
340 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
341 script_pub_key = CScript([OP_DROP])
343 "-tx=" + tx.serialize().hex(),
345 "-scriptpubkey=" + script_pub_key.hex(),
347 expected_stderr=
"scriptPubKey failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
352======= scriptSig =======
353 Stack (0 items): (empty stack)
355======= scriptPubKey =======
365 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
366 script_pub_key = CScript([OP_NOT])
368 "-tx=" + tx.serialize().hex(),
370 "-scriptpubkey=" + script_pub_key.hex(),
372 expected_stderr=
"scriptPubKey failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
377======= scriptSig =======
378 Stack (0 items): (empty stack)
380======= scriptPubKey =======
390 script_pub_key = CScript([1])
391 tx.vin = [CTxIn(COutPoint(), CScript([0]))]
393 "-tx=" + tx.serialize().hex(),
395 "-scriptpubkey=" + script_pub_key.hex(),
397 expected_stderr=
"scriptPubKey failed execution: Stack size must be exactly one after execution\n",
402======= scriptSig =======
403 Stack (0 items): (empty stack)
405======= scriptPubKey =======
417 redeem_script = CScript([OP_TOALTSTACK, b
"\x63", OP_EQUAL])
419 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x63", b
"alt!", bytes(redeem_script)]))]
420 script_hash = hash160(redeem_script)
421 script_pub_key = CScript([OP_HASH160, script_hash, OP_EQUAL])
425 "-tx=" + tx.serialize().hex(),
427 "-scriptpubkey=" + script_pub_key.hex(),
435======= scriptSig =======
436 Stack (0 items): (empty stack)
440OP 1: 0x04 {b"alt!".hex()}
444OP 2: 0x04 {redeem_script.hex()}
445======= scriptPubKey =======
449 2: {redeem_script.hex()}
454 2: {script_hash.hex()}
455OP 1: 0x14 {script_hash.hex()}
459 2: {script_hash.hex()}
460 3: {script_hash.hex()}
466======= redeemScript =======
486Script executed without errors
492scriptName,index,opcode,stack 0,stack 1,stack 2,stack 3,altstack 0,
493scriptSig,0,0x63,"63",
494scriptSig,1,0x{b"alt!".hex()},"63","{b"alt!".hex()}",
495scriptSig,2,0x{redeem_script.hex()},"63","{b"alt!".hex()}","{redeem_script.hex()}",
496scriptPubKey,0,OP_HASH160,"63","{b"alt!".hex()}","{script_hash.hex()}",
497scriptPubKey,1,0x{script_hash.hex()},"63","{b"alt!".hex()}","{script_hash.hex()}","{script_hash.hex()}",
498scriptPubKey,2,OP_EQUAL,"63","{b"alt!".hex()}","01",
499redeemScript,0,OP_TOALTSTACK,"63",,,,"{b"alt!".hex()}",
500redeemScript,1,0x63,"63","63",,,"{b"alt!".hex()}",
501redeemScript,2,OP_EQUAL,"01",,,,"{b"alt!".hex()}",
503Script executed without errors
509 redeem_script = CScript([OP_CHECKSIG])
511 tx.vin = [CTxIn(COutPoint(), CScript([b
"wrong", b
"sig", bytes(redeem_script)]))]
512 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
514 "-tx=" + tx.serialize().hex(),
516 "-scriptpubkey=" + script_pub_key.hex(),
518 expected_stderr=
"redeemScript failed execution: Non-canonical DER signature\n",
523======= scriptSig =======
524 Stack (0 items): (empty stack)
533======= scriptPubKey =======
542 2: 17be79cf51aa88feebb0a25e9d6a153ead585e59
543OP 1: 0x14 17be79cf51aa88feebb0a25e9d6a153ead585e59
547 2: 17be79cf51aa88feebb0a25e9d6a153ead585e59
548 3: 17be79cf51aa88feebb0a25e9d6a153ead585e59
554======= redeemScript =======
564 redeem_script = CScript([OP_ADD])
567 CTxIn(COutPoint(), CScript([b
"111111111", b
"222222222", bytes(redeem_script)]))
569 script_hash = hash160(redeem_script)
570 script_pub_key = CScript([OP_HASH160, script_hash, OP_EQUAL])
572 "-tx=" + tx.serialize().hex(),
574 "-scriptpubkey=" + script_pub_key.hex(),
576 expected_stderr=
"redeemScript failed execution: Integer overflow\n",
581======= scriptSig =======
582 Stack (0 items): (empty stack)
583OP 0: 0x09 313131313131313131
585 0: 313131313131313131
586OP 1: 0x09 323232323232323232
588 0: 313131313131313131
589 1: 323232323232323232
591======= scriptPubKey =======
593 0: 313131313131313131
594 1: 323232323232323232
598 0: 313131313131313131
599 1: 323232323232323232
600 2: {script_hash.hex()}
601OP 1: 0x14 {script_hash.hex()}
603 0: 313131313131313131
604 1: 323232323232323232
605 2: {script_hash.hex()}
606 3: {script_hash.hex()}
609 0: 313131313131313131
610 1: 323232323232323232
612======= redeemScript =======
614 0: 313131313131313131
615 1: 323232323232323232
622 redeem_script = CScript([OP_NOP])
624 tx.vin = [CTxIn(COutPoint(), CScript([bytes(redeem_script)]))]
625 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
627 "-tx=" + tx.serialize().hex(),
629 "-scriptpubkey=" + script_pub_key.hex(),
631 expected_stderr=
"redeemScript failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
636======= scriptSig =======
637 Stack (0 items): (empty stack)
639======= scriptPubKey =======
644 0: 994355199e516ff76c4fa4aab39337b9d84cf12b
645OP 1: 0x14 994355199e516ff76c4fa4aab39337b9d84cf12b
647 0: 994355199e516ff76c4fa4aab39337b9d84cf12b
648 1: 994355199e516ff76c4fa4aab39337b9d84cf12b
652======= redeemScript =======
653 Stack (0 items): (empty stack)
660 redeem_script = CScript([0])
662 tx.vin = [CTxIn(COutPoint(), CScript([bytes(redeem_script)]))]
663 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
665 "-tx=" + tx.serialize().hex(),
667 "-scriptpubkey=" + script_pub_key.hex(),
669 expected_stderr=
"redeemScript failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
674======= scriptSig =======
675 Stack (0 items): (empty stack)
677======= scriptPubKey =======
682 0: 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
683OP 1: 0x14 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
685 0: 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
686 1: 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
690======= redeemScript =======
691 Stack (0 items): (empty stack)
698 redeem_script = CScript([0, 1])
700 tx.vin = [CTxIn(COutPoint(), CScript([bytes(redeem_script)]))]
701 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
703 "-tx=" + tx.serialize().hex(),
705 "-scriptpubkey=" + script_pub_key.hex(),
707 expected_stderr=
"redeemScript failed execution: Stack size must be exactly one after execution\n",
712======= scriptSig =======
713 Stack (0 items): (empty stack)
715======= scriptPubKey =======
720 0: 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
721OP 1: 0x14 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
723 0: 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
724 1: 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
728======= redeemScript =======
729 Stack (0 items): (empty stack)
743 key.set(b
"12345678" * 4,
True)
744 redeem_script = CScript([OP_2DUP, OP_CHECKSIGVERIFY] * 3 + [OP_CHECKSIG])
745 script_hash = hash160(redeem_script)
746 script_pub_key = CScript([OP_HASH160, script_hash, OP_EQUAL])
748 tx.vin = [CTxIn(COutPoint())]
750 sighash = SignatureHashForkId(
751 redeem_script, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, amount
753 sig = key.sign_schnorr(sighash) + b
"\x41"
754 pubkey = key.get_pubkey().get_bytes()
755 tx.vin[0].scriptSig = CScript([sig, pubkey, bytes(redeem_script)])
757 "-tx=" + tx.serialize().hex(),
759 "-scriptpubkey=" + script_pub_key.hex(),
761 expected_stderr=
"redeemScript failed execution: Input SigChecks limit exceeded\n",
766======= scriptSig =======
767 Stack (0 items): (empty stack)
768OP 0: 0x41 {sig.hex()}
771OP 1: 0x21 {pubkey.hex()}
775OP 2: 0x07 {redeem_script.hex()}
776======= scriptPubKey =======
780 2: {redeem_script.hex()}
785 2: {script_hash.hex()}
786OP 1: 0x14 {script_hash.hex()}
790 2: {script_hash.hex()}
791 3: {script_hash.hex()}
797======= redeemScript =======
807OP 1: OP_CHECKSIGVERIFY
817OP 3: OP_CHECKSIGVERIFY
827OP 5: OP_CHECKSIGVERIFY
834Number of sigChecks: 4
def test_script_pub_key_empty_stack()
def test_script_pub_key_unbalanced_conditional()
def test_script_sig_invalid_opcode_encoding()
def test_script_pub_key_false_stack()
def test_redeem_script_false()
def test_script_pub_key_success()
def test_redeem_script_error()
def test_redeem_script_success()
def test_redeem_script_cleanstack()
def test_invalid_format()
def test_script_pub_key_too_big()
def test_redeem_script_exception()
def test_script_sig_success()
def test_redeem_script_input_sigchecks()
def test_script_pub_key_failure()
def test_script_pub_key_cleanstack()
def test_invalid_inputindex()
def test_redeem_script_empty_stack()
def iguana(*args, expected_stderr="", expected_returncode=None)