|
67 | 67 | OP_EQUAL, |
68 | 68 | OP_EQUALVERIFY, |
69 | 69 | OP_IF, |
| 70 | + OP_INTERNALKEY, |
70 | 71 | OP_NOP, |
71 | 72 | OP_NOT, |
72 | 73 | OP_NOTIF, |
@@ -666,6 +667,22 @@ def byte_popper(expr): |
666 | 667 |
|
667 | 668 | # === Actual test cases === |
668 | 669 |
|
| 670 | +def spenders_internalkey_active(): |
| 671 | + |
| 672 | + secs = [generate_privkey() for _ in range(8)] |
| 673 | + pubs = [compute_xonly_pubkey(sec)[0] for sec in secs] |
| 674 | + |
| 675 | + spenders = [] |
| 676 | + |
| 677 | + scripts = [ |
| 678 | + ("ik", CScript([OP_INTERNALKEY, OP_EQUAL])), |
| 679 | + ] |
| 680 | + |
| 681 | + tap = taproot_construct(pubs[0], scripts) |
| 682 | + |
| 683 | + add_spender(spenders, "ik/success", tap=tap, leaf="ik", inputs=[pubs[0]], failure={"inputs": [pubs[1]]}) |
| 684 | + |
| 685 | + return spenders |
669 | 686 |
|
670 | 687 | def spenders_taproot_active(): |
671 | 688 | """Return a list of Spenders for testing post-Taproot activation behavior.""" |
@@ -1255,7 +1272,7 @@ def predict_sigops_ratio(n, dummy_size): |
1255 | 1272 | # For the standard non-witness p2sh case, we need inputs to be minimal push opcodes (not witness stack elements) |
1256 | 1273 | # so we use arb non-0 byte push via valid pubkey |
1257 | 1274 | add_spender(spenders, "compat/nocsfs", p2sh=p2sh, witv0=witv0, standard=p2sh or witv0, script=CScript([OP_IF, b'', b'', pubs[0], OP_CHECKSIGFROMSTACK, OP_DROP, OP_ENDIF]), inputs=[pubs[0], b''], failure={"inputs": [pubs[0], pubs[0]]}, **ERR_UNDECODABLE) |
1258 | | - |
| 1275 | + add_spender(spenders, "compat/noik", p2sh=p2sh, witv0=witv0, standard=p2sh or witv0, script=CScript([OP_IF, OP_INTERNALKEY, OP_RETURN, OP_ENDIF]), inputs=[pubs[0], b''], failure={"inputs": [pubs[0], pubs[0]]}, **ERR_UNDECODABLE) |
1259 | 1276 | return spenders |
1260 | 1277 |
|
1261 | 1278 |
|
@@ -1299,6 +1316,25 @@ def bip348_csfs_spenders_nonstandard(): |
1299 | 1316 |
|
1300 | 1317 | return spenders |
1301 | 1318 |
|
| 1319 | +def bip349_ik_spenders_nonstandard(): |
| 1320 | + """Spenders for testing that pre-active INTERNALKEY usage is discouraged but valid""" |
| 1321 | + |
| 1322 | + spenders = [] |
| 1323 | + |
| 1324 | + sec = generate_privkey() |
| 1325 | + pub, _ = compute_xonly_pubkey(sec) |
| 1326 | + scripts = [ |
| 1327 | + ("stilltrue", CScript([OP_INTERNALKEY])), |
| 1328 | + ("still_opsuccess", CScript([OP_RETURN, OP_INTERNALKEY])), |
| 1329 | + ] |
| 1330 | + tap = taproot_construct(pub, scripts) |
| 1331 | + |
| 1332 | + # Valid prior to activation but nonstandard |
| 1333 | + add_spender(spenders, "discouraged_ik/stilltrue", tap=tap, leaf="stilltrue", standard=False) |
| 1334 | + add_spender(spenders, "discouraged_ik/still_opsuccess", tap=tap, leaf="still_opsuccess", standard=False) |
| 1335 | + |
| 1336 | + return spenders |
| 1337 | + |
1302 | 1338 | def bip348_csfs_spenders(): |
1303 | 1339 | secs = [generate_privkey() for _ in range(2)] |
1304 | 1340 | pubs = [compute_xonly_pubkey(sec)[0] for sec in secs] |
@@ -1417,7 +1453,8 @@ def skip_test_if_missing_module(self): |
1417 | 1453 |
|
1418 | 1454 | def set_test_params(self): |
1419 | 1455 | self.num_nodes = 1 |
1420 | | - self.extra_args = [["-vbparams=checksigfromstack:0:3999999999"]] |
| 1456 | + self.extra_args = [["-vbparams=checksigfromstack:0:3999999999", |
| 1457 | + "-vbparams=internalkey:0:3999999999"]] |
1421 | 1458 | self.setup_clean_chain = True |
1422 | 1459 |
|
1423 | 1460 | def block_submit(self, node, txs, msg, err_msg, cb_pubkey=None, fees=0, sigops_weight=0, witness=False, accept=False): |
@@ -1890,25 +1927,31 @@ def pr(node): |
1890 | 1927 | def run_test(self): |
1891 | 1928 | self.gen_test_vectors() |
1892 | 1929 |
|
1893 | | - self.log.info("CSFS Pre-activation tests...") |
| 1930 | + self.log.info("CSFS and IK Pre-activation tests...") |
1894 | 1931 | assert_equal(self.nodes[0].getdeploymentinfo()["deployments"]["checksigfromstack"]["heretical"]["status"],"defined") |
| 1932 | + assert_equal(self.nodes[0].getdeploymentinfo()["deployments"]["internalkey"]["heretical"]["status"],"defined") |
1895 | 1933 | self.generate(self.nodes[0], 144) |
1896 | 1934 | assert_equal(self.nodes[0].getdeploymentinfo()["deployments"]["checksigfromstack"]["heretical"]["status"],"started") |
1897 | | - signal_ver = int(self.nodes[0].getdeploymentinfo()["deployments"]["checksigfromstack"]["heretical"]["signal_activate"], 16) |
| 1935 | + assert_equal(self.nodes[0].getdeploymentinfo()["deployments"]["internalkey"]["heretical"]["status"],"started") |
| 1936 | + signal_ver_csfs = int(self.nodes[0].getdeploymentinfo()["deployments"]["checksigfromstack"]["heretical"]["signal_activate"], 16) |
| 1937 | + signal_ver_ik = int(self.nodes[0].getdeploymentinfo()["deployments"]["internalkey"]["heretical"]["signal_activate"], 16) |
1898 | 1938 |
|
1899 | | - self.test_spenders(self.nodes[0], bip348_csfs_spenders_nonstandard(), input_counts=[1, 2]) |
| 1939 | + self.test_spenders(self.nodes[0], bip348_csfs_spenders_nonstandard() + bip349_ik_spenders_nonstandard(), input_counts=[1, 2]) |
1900 | 1940 |
|
1901 | | - self.log.info("Activating CSFS") |
| 1941 | + self.log.info("Activating CSFS and IK") |
1902 | 1942 | now = self.nodes[0].getblock(self.nodes[0].getbestblockhash())["time"] |
1903 | | - coinbase_tx = create_coinbase(self.nodes[0].getblockcount() + 1) |
1904 | | - block = create_block(hashprev=int(self.nodes[0].getbestblockhash(), 16), ntime=now, coinbase=coinbase_tx, version=signal_ver) |
1905 | | - block.solve() |
1906 | | - self.nodes[0].submitblock(block.serialize().hex()) |
| 1943 | + for signal in [signal_ver_csfs, signal_ver_ik]: |
| 1944 | + coinbase_tx = create_coinbase(self.nodes[0].getblockcount() + 1) |
| 1945 | + block = create_block(hashprev=int(self.nodes[0].getbestblockhash(), 16), ntime=now, coinbase=coinbase_tx, version=signal) |
| 1946 | + block.solve() |
| 1947 | + self.nodes[0].submitblock(block.serialize().hex()) |
| 1948 | + now += 1 |
1907 | 1949 | self.generate(self.nodes[0], 288) |
1908 | 1950 | assert_equal(self.nodes[0].getdeploymentinfo()["deployments"]["checksigfromstack"]["heretical"]["status"],"active") |
| 1951 | + assert_equal(self.nodes[0].getdeploymentinfo()["deployments"]["internalkey"]["heretical"]["status"],"active") |
1909 | 1952 |
|
1910 | 1953 | self.log.info("Post-activation tests...") |
1911 | | - consensus_spenders = spenders_taproot_active() + bip348_csfs_spenders() |
| 1954 | + consensus_spenders = spenders_taproot_active() + bip348_csfs_spenders() + spenders_internalkey_active() |
1912 | 1955 | self.test_spenders(self.nodes[0], consensus_spenders, input_counts=[1, 2, 2, 2, 2, 3]) |
1913 | 1956 | # Run each test twice; once in isolation, and once combined with others. Testing in isolation |
1914 | 1957 | # means that the standardness is verified in every test (as combined transactions are only standard |
|
0 commit comments