| 1367 | |
| 1368 | |
| 1369 | class TaprootTest(BitcoinTestFramework): |
| 1370 | def add_options(self, parser): |
| 1371 | parser.add_argument("--dumptests", dest="dump_tests", default=False, action="store_true", |
| 1372 | help="Dump generated test cases to directory set by TEST_DUMP_DIR environment variable") |
| 1373 | parser.add_argument("--previous_release", dest="previous_release", default=False, action="store_true", |
| 1374 | help="Use a previous release as taproot-inactive node") |
| 1375 | |
| 1376 | def skip_test_if_missing_module(self): |
| 1377 | self.skip_if_no_wallet() |
| 1378 | if self.options.previous_release: |
| 1379 | self.skip_if_no_previous_releases() |
| 1380 | |
| 1381 | def set_test_params(self): |
| 1382 | self.num_nodes = 2 |
| 1383 | self.setup_clean_chain = True |
| 1384 | # Node 0 has Taproot inactive, Node 1 active. |
| 1385 | # ELEMENTS: to preserve tests which depend on the exact number of outputs, |
| 1386 | # we turn one of the original outputs into a fee output, which routinely |
| 1387 | # results in us burning massive amounts of coin. Hence -maxtxfee. |
| 1388 | self.extra_args = [["-par=1"], ["-par=1", "-maxtxfee=100.0"]] |
| 1389 | if self.options.previous_release: |
| 1390 | self.wallet_names = [None, self.default_wallet_name] |
| 1391 | else: |
| 1392 | self.extra_args[0].append("-vbparams=taproot:1:1") |
| 1393 | # ELEMENTS: both nodes have Simplicity active. We activate one with evbparams |
| 1394 | # and the other with vbparams to check that both work. |
| 1395 | self.extra_args[0].append("-vbparams=simplicity:-1:1") |
| 1396 | self.extra_args[1].append("-evbparams=simplicity:-1:::") |
| 1397 | |
| 1398 | def setup_nodes(self): |
| 1399 | self.add_nodes(self.num_nodes, self.extra_args, versions=[ |
| 1400 | 200100 if self.options.previous_release else None, |
| 1401 | None, |
| 1402 | ]) |
| 1403 | self.start_nodes() |
| 1404 | self.import_deterministic_coinbase_privkeys() |
| 1405 | |
| 1406 | def block_submit(self, node, txs, msg, err_msg, cb_pubkey=None, fees=0, sigops_weight=0, witness=False, accept=False): |
| 1407 | |
| 1408 | # Deplete block of any non-tapscript sigops using a single additional 0-value coinbase output. |
| 1409 | # It is not impossible to fit enough tapscript sigops to hit the old 80k limit without |
| 1410 | # busting txin-level limits. We simply have to account for the p2pk outputs in all |
| 1411 | # transactions. |
| 1412 | extra_output_script = CScript([OP_CHECKSIG]*((MAX_BLOCK_SIGOPS_WEIGHT - sigops_weight) // WITNESS_SCALE_FACTOR)) |
| 1413 | if extra_output_script == CScript(): |
| 1414 | extra_output_script = None ## ELEMENTS: an explicitly empty coinbase scriptpubkey would be rejected with bad-cb-fee |
| 1415 | |
| 1416 | coinbase_tx = create_coinbase(self.lastblockheight + 1, pubkey=cb_pubkey, extra_output_script=extra_output_script, fees=fees) |
| 1417 | block = create_block(self.tip, coinbase_tx, self.lastblocktime + 1, txlist=txs) |
| 1418 | witness and add_witness_commitment(block) |
| 1419 | block.solve() |
| 1420 | block_response = node.submitblock(block.serialize().hex()) |
| 1421 | if err_msg is not None: |
| 1422 | assert block_response is not None |
| 1423 | assert block_response is not None and err_msg in block_response, "Missing error message '%s' from block response '%s': %s" % (err_msg, "(None)" if block_response is None else block_response, msg) |
| 1424 | if accept: |
| 1425 | assert node.getbestblockhash() == block.hash, "Failed to accept: %s (response: %s)" % (msg, block_response) |
| 1426 | self.tip = block.sha256 |