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 (
26from test_framework.signature_hash
import (
33def iguana(*args, expected_stderr="", expected_returncode=None):
34 if expected_returncode
is None:
35 expected_returncode = 255
if expected_stderr
else 0
37 command = [os.environ[
"IGUANA_BIN"], *args]
38 if emulator := os.environ.get(
"EMULATOR",
None):
39 command.insert(0, emulator)
41 child = subprocess.Popen(
43 stdout=subprocess.PIPE,
44 stderr=subprocess.PIPE,
46 actual_stdout, actual_stderr = child.communicate()
47 assert actual_stderr.decode() == expected_stderr
48 assert child.returncode == expected_returncode
49 return actual_stdout.decode()
53 assert iguana(
"-version").startswith(
54 f
"Iguana v{os.environ['CMAKE_PROJECT_VERSION']}"
59 assert iguana(
"-?").startswith(
"Usage: iguana")
65 expected_stderr=
"Error parsing command line arguments: Invalid parameter -invalidarg\n",
71 "-format=doesntexist",
72 expected_stderr=
"Unsupported output format doesntexist\n",
79 "-tx=" + tx.serialize().hex(),
83 expected_stderr=
"Transaction doesn't have input index 0\n",
89 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31", OP_DUP]))]
91 def run(fmt, expected_stderr):
93 "-tx=" + tx.serialize().hex(),
98 expected_stderr=expected_stderr,
99 expected_returncode=255,
105 expected_stderr=
"scriptSig failed execution: Only push operators allowed in signatures\n",
108======= scriptSig =======
109 Stack (0 items): (empty stack)
119scriptName,index,opcode,stack 0,
120scriptSig,0,0x31,"31",
122scriptSig failed execution: Only push operators allowed in signatures
129 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
133 "-tx=" + tx.serialize().hex(),
143======= scriptSig =======
144 Stack (0 items): (empty stack)
146======= scriptPubKey =======
149Script executed without errors
155scriptName,index,opcode,stack 0,
156scriptSig,0,0x31,"31",
158Script executed without errors
165 tx.vin = [CTxIn(COutPoint(), CScript(b
"\x01"))]
167 def run(fmt, expected_stderr):
169 "-tx=" + tx.serialize().hex(),
174 expected_stderr=expected_stderr,
175 expected_returncode=255,
181 expected_stderr=
"scriptSig failed execution: Invalidly encoded opcode\n",
184======= scriptSig =======
185 Stack (0 items): (empty stack)
191scriptName,index,opcode,
192scriptSig failed execution: Invalidly encoded opcode
199 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31", b
"\x32"]))]
200 script_pub_key = CScript([OP_ADD, b
"\x63", OP_EQUAL])
204 "-tx=" + tx.serialize().hex(),
206 "-scriptpubkey=" + script_pub_key.hex(),
214======= scriptSig =======
215 Stack (0 items): (empty stack)
220======= scriptPubKey =======
234Script executed without errors
240scriptName,index,opcode,stack 0,stack 1,
241scriptSig,0,0x31,"31",
242scriptSig,1,0x32,"31","32",
243scriptPubKey,0,OP_ADD,"63",
244scriptPubKey,1,0x63,"63","63",
245scriptPubKey,2,OP_EQUAL,"01",
247Script executed without errors
254 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
255 script_pub_key = CScript([OP_EQUAL])
257 "-tx=" + tx.serialize().hex(),
259 "-scriptpubkey=" + script_pub_key.hex(),
261 expected_stderr=
"scriptPubKey failed execution: Operation not valid with the current stack size\n",
266======= scriptSig =======
267 Stack (0 items): (empty stack)
269======= scriptPubKey =======
279 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
280 script_pub_key = CScript([OP_DROP])
282 "-tx=" + tx.serialize().hex(),
284 "-scriptpubkey=" + script_pub_key.hex(),
286 expected_stderr=
"scriptPubKey failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
291======= scriptSig =======
292 Stack (0 items): (empty stack)
294======= scriptPubKey =======
304 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x31"]))]
305 script_pub_key = CScript([OP_NOT])
307 "-tx=" + tx.serialize().hex(),
309 "-scriptpubkey=" + script_pub_key.hex(),
311 expected_stderr=
"scriptPubKey failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
316======= scriptSig =======
317 Stack (0 items): (empty stack)
319======= scriptPubKey =======
329 script_pub_key = CScript([1])
330 tx.vin = [CTxIn(COutPoint(), CScript([0]))]
332 "-tx=" + tx.serialize().hex(),
334 "-scriptpubkey=" + script_pub_key.hex(),
336 expected_stderr=
"scriptPubKey failed execution: Stack size must be exactly one after execution\n",
341======= scriptSig =======
342 Stack (0 items): (empty stack)
344======= scriptPubKey =======
356 redeem_script = CScript([OP_TOALTSTACK, b
"\x63", OP_EQUAL])
358 tx.vin = [CTxIn(COutPoint(), CScript([b
"\x63", b
"alt!", bytes(redeem_script)]))]
359 script_hash = hash160(redeem_script)
360 script_pub_key = CScript([OP_HASH160, script_hash, OP_EQUAL])
364 "-tx=" + tx.serialize().hex(),
366 "-scriptpubkey=" + script_pub_key.hex(),
374======= scriptSig =======
375 Stack (0 items): (empty stack)
379OP 1: 0x04 {b"alt!".hex()}
383OP 2: 0x04 {redeem_script.hex()}
384======= scriptPubKey =======
388 2: {redeem_script.hex()}
393 2: {script_hash.hex()}
394OP 1: 0x14 {script_hash.hex()}
398 2: {script_hash.hex()}
399 3: {script_hash.hex()}
405======= redeemScript =======
425Script executed without errors
431scriptName,index,opcode,stack 0,stack 1,stack 2,stack 3,altstack 0,
432scriptSig,0,0x63,"63",
433scriptSig,1,0x{b"alt!".hex()},"63","{b"alt!".hex()}",
434scriptSig,2,0x{redeem_script.hex()},"63","{b"alt!".hex()}","{redeem_script.hex()}",
435scriptPubKey,0,OP_HASH160,"63","{b"alt!".hex()}","{script_hash.hex()}",
436scriptPubKey,1,0x{script_hash.hex()},"63","{b"alt!".hex()}","{script_hash.hex()}","{script_hash.hex()}",
437scriptPubKey,2,OP_EQUAL,"63","{b"alt!".hex()}","01",
438redeemScript,0,OP_TOALTSTACK,"63",,,,"{b"alt!".hex()}",
439redeemScript,1,0x63,"63","63",,,"{b"alt!".hex()}",
440redeemScript,2,OP_EQUAL,"01",,,,"{b"alt!".hex()}",
442Script executed without errors
448 redeem_script = CScript([OP_CHECKSIG])
450 tx.vin = [CTxIn(COutPoint(), CScript([b
"wrong", b
"sig", bytes(redeem_script)]))]
451 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
453 "-tx=" + tx.serialize().hex(),
455 "-scriptpubkey=" + script_pub_key.hex(),
457 expected_stderr=
"redeemScript failed execution: Non-canonical DER signature\n",
462======= scriptSig =======
463 Stack (0 items): (empty stack)
472======= scriptPubKey =======
481 2: 17be79cf51aa88feebb0a25e9d6a153ead585e59
482OP 1: 0x14 17be79cf51aa88feebb0a25e9d6a153ead585e59
486 2: 17be79cf51aa88feebb0a25e9d6a153ead585e59
487 3: 17be79cf51aa88feebb0a25e9d6a153ead585e59
493======= redeemScript =======
503 redeem_script = CScript([OP_ADD])
505 tx.vin = [CTxIn(COutPoint(), CScript([b
"111111", b
"222222", bytes(redeem_script)]))]
506 script_hash = hash160(redeem_script)
507 script_pub_key = CScript([OP_HASH160, script_hash, OP_EQUAL])
509 "-tx=" + tx.serialize().hex(),
511 "-scriptpubkey=" + script_pub_key.hex(),
513 expected_stderr=
"redeemScript failed execution: Exception: script number overflow\n",
518======= scriptSig =======
519 Stack (0 items): (empty stack)
520OP 0: 0x06 313131313131
523OP 1: 0x06 323232323232
528======= scriptPubKey =======
537 2: {script_hash.hex()}
538OP 1: 0x14 {script_hash.hex()}
542 2: {script_hash.hex()}
543 3: {script_hash.hex()}
549======= redeemScript =======
559 redeem_script = CScript([OP_NOP])
561 tx.vin = [CTxIn(COutPoint(), CScript([bytes(redeem_script)]))]
562 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
564 "-tx=" + tx.serialize().hex(),
566 "-scriptpubkey=" + script_pub_key.hex(),
568 expected_stderr=
"redeemScript failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
573======= scriptSig =======
574 Stack (0 items): (empty stack)
576======= scriptPubKey =======
581 0: 994355199e516ff76c4fa4aab39337b9d84cf12b
582OP 1: 0x14 994355199e516ff76c4fa4aab39337b9d84cf12b
584 0: 994355199e516ff76c4fa4aab39337b9d84cf12b
585 1: 994355199e516ff76c4fa4aab39337b9d84cf12b
589======= redeemScript =======
590 Stack (0 items): (empty stack)
597 redeem_script = CScript([0])
599 tx.vin = [CTxIn(COutPoint(), CScript([bytes(redeem_script)]))]
600 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
602 "-tx=" + tx.serialize().hex(),
604 "-scriptpubkey=" + script_pub_key.hex(),
606 expected_stderr=
"redeemScript failed execution: Script evaluated without error but finished with a false/empty top stack element\n",
611======= scriptSig =======
612 Stack (0 items): (empty stack)
614======= scriptPubKey =======
619 0: 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
620OP 1: 0x14 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
622 0: 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
623 1: 9f7fd096d37ed2c0e3f7f0cfc924beef4ffceb68
627======= redeemScript =======
628 Stack (0 items): (empty stack)
635 redeem_script = CScript([0, 1])
637 tx.vin = [CTxIn(COutPoint(), CScript([bytes(redeem_script)]))]
638 script_pub_key = CScript([OP_HASH160, hash160(redeem_script), OP_EQUAL])
640 "-tx=" + tx.serialize().hex(),
642 "-scriptpubkey=" + script_pub_key.hex(),
644 expected_stderr=
"redeemScript failed execution: Stack size must be exactly one after execution\n",
649======= scriptSig =======
650 Stack (0 items): (empty stack)
652======= scriptPubKey =======
657 0: 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
658OP 1: 0x14 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
660 0: 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
661 1: 5cbe818a2be9df5479d201af59df9c0bdfaaf21e
665======= redeemScript =======
666 Stack (0 items): (empty stack)
680 key.set(b
"12345678" * 4,
True)
681 redeem_script = CScript([OP_2DUP, OP_CHECKSIGVERIFY] * 3 + [OP_CHECKSIG])
682 script_hash = hash160(redeem_script)
683 script_pub_key = CScript([OP_HASH160, script_hash, OP_EQUAL])
685 tx.vin = [CTxIn(COutPoint())]
687 sighash = SignatureHashForkId(
688 redeem_script, tx, 0, SIGHASH_ALL | SIGHASH_FORKID, amount
690 sig = key.sign_schnorr(sighash) + b
"\x41"
691 pubkey = key.get_pubkey().get_bytes()
692 tx.vin[0].scriptSig = CScript([sig, pubkey, bytes(redeem_script)])
694 "-tx=" + tx.serialize().hex(),
696 "-scriptpubkey=" + script_pub_key.hex(),
698 expected_stderr=
"redeemScript failed execution: Input SigChecks limit exceeded\n",
703======= scriptSig =======
704 Stack (0 items): (empty stack)
705OP 0: 0x41 {sig.hex()}
708OP 1: 0x21 {pubkey.hex()}
712OP 2: 0x07 {redeem_script.hex()}
713======= scriptPubKey =======
717 2: {redeem_script.hex()}
722 2: {script_hash.hex()}
723OP 1: 0x14 {script_hash.hex()}
727 2: {script_hash.hex()}
728 3: {script_hash.hex()}
734======= redeemScript =======
744OP 1: OP_CHECKSIGVERIFY
754OP 3: OP_CHECKSIGVERIFY
764OP 5: OP_CHECKSIGVERIFY
771Number of sigChecks: 4
def test_script_pub_key_empty_stack()
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_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)