v31.1-roots.1 · Commit 2: [PATCH 02/17] feat(policy): preserve Roots parsing and local transaction checks
test/functional/mempool_datacarrier.py
Before: test/functional/mempool_datacarrier.py · After: test/functional/mempool_datacarrier.py
File metadata
index 8e17d4a3ccdf405699a295d08f3886bcdfd22e40..09f48cd35f6b28156be3098b59660df4d6fe6df7 100755
Download original patch · Release notes
Diff rows 1–140 of 140. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
test/functional/mempool_datacarrier.py
CHANGED
|
@@ -1,15 +1,26 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
-
# Copyright (c) 2020-present The Bitcoin Core developers
|
| 3 |
# Distributed under the MIT software license, see the accompanying
|
| 4 |
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
| 5 |
"""Test datacarrier functionality"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
from test_framework.messages import (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
CTxOut,
|
| 8 |
-
MAX_OP_RETURN_RELAY,
|
| 9 |
)
|
| 10 |
from test_framework.script import (
|
| 11 |
CScript,
|
|
|
|
|
|
|
| 12 |
OP_RETURN,
|
|
|
|
|
|
|
| 13 |
)
|
| 14 |
from test_framework.test_framework import BitcoinTestFramework
|
| 15 |
from test_framework.test_node import TestNode
|
|
@@ -19,7 +30,6 @@ from test_framework.util import (
|
|
| 19 |
)
|
| 20 |
from test_framework.wallet import MiniWallet
|
| 21 |
|
| 22 |
-
from random import randbytes
|
| 23 |
|
| 24 |
# The historical maximum, now used to test coverage
|
| 25 |
CUSTOM_DATACARRIER_ARG = 83
|
|
@@ -28,13 +38,13 @@ class DataCarrierTest(BitcoinTestFramework):
|
|
| 28 |
def set_test_params(self):
|
| 29 |
self.num_nodes = 4
|
| 30 |
self.extra_args = [
|
| 31 |
-
[], # default is uncapped
|
| 32 |
["-datacarrier=0"], # no relay of datacarrier
|
| 33 |
["-datacarrier=1", f"-datacarriersize={CUSTOM_DATACARRIER_ARG}"],
|
| 34 |
["-datacarrier=1", "-datacarriersize=2"],
|
| 35 |
]
|
| 36 |
|
| 37 |
-
def test_null_data_transaction(self, node: TestNode, data, success: bool) -> None:
|
| 38 |
tx = self.wallet.create_self_transfer(fee_rate=0)["tx"]
|
| 39 |
data = [] if data is None else [data]
|
| 40 |
tx.vout.append(CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN] + data)))
|
|
@@ -47,31 +57,65 @@ class DataCarrierTest(BitcoinTestFramework):
|
|
| 47 |
assert tx.txid_hex in node.getrawmempool(True), f'{tx_hex} not in mempool'
|
| 48 |
else:
|
| 49 |
assert_raises_rpc_error(-26, "datacarrier", self.wallet.sendrawtransaction, from_node=node, tx_hex=tx_hex)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
def run_test(self):
|
| 52 |
self.wallet = MiniWallet(self.nodes[0])
|
| 53 |
|
| 54 |
-
# Test that bare multisig is allowed by default. Do it here rather than create a new test for it.
|
| 55 |
-
assert_equal(self.nodes[0].getmempoolinfo()["permitbaremultisig"], True)
|
| 56 |
|
| 57 |
-
assert_equal(self.nodes[0].getmempoolinfo()["maxdatacarriersize"], MAX_OP_RETURN_RELAY)
|
| 58 |
assert_equal(self.nodes[1].getmempoolinfo()["maxdatacarriersize"], 0)
|
| 59 |
assert_equal(self.nodes[2].getmempoolinfo()["maxdatacarriersize"], CUSTOM_DATACARRIER_ARG)
|
| 60 |
assert_equal(self.nodes[3].getmempoolinfo()["maxdatacarriersize"], 2)
|
| 61 |
|
| 62 |
-
# By default, any size is allowed.
|
| 63 |
|
| 64 |
# If it is custom set to 83, the historical value,
|
| 65 |
# only 80 bytes are used for data (+1 for OP_RETURN, +2 for the pushdata opcodes).
|
| 66 |
custom_size_data = randbytes(CUSTOM_DATACARRIER_ARG - 3)
|
| 67 |
too_long_data = randbytes(CUSTOM_DATACARRIER_ARG - 2)
|
| 68 |
-
extremely_long_data = randbytes(MAX_OP_RETURN_RELAY - 200)
|
| 69 |
one_byte = randbytes(1)
|
| 70 |
zero_bytes = randbytes(0)
|
| 71 |
|
| 72 |
-
self.log.info("Testing a null data transaction succeeds for default arg regardless of size.")
|
| 73 |
-
self.test_null_data_transaction(node=self.nodes[0], data=too_long_data, success=True)
|
| 74 |
-
self.test_null_data_transaction(node=self.nodes[0], data=extremely_long_data, success=True)
|
|
|
|
|
|
|
| 75 |
|
| 76 |
self.log.info("Testing a null data transaction with -datacarrier=false.")
|
| 77 |
self.test_null_data_transaction(node=self.nodes[1], data=custom_size_data, success=False)
|
|
@@ -100,5 +144,17 @@ class DataCarrierTest(BitcoinTestFramework):
|
|
| 100 |
self.test_null_data_transaction(node=self.nodes[2], data=one_byte, success=True)
|
| 101 |
self.test_null_data_transaction(node=self.nodes[3], data=one_byte, success=False)
|
| 102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
if __name__ == '__main__':
|
| 104 |
DataCarrierTest(__file__).main()
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
+
# Copyright (c) 2020-2022 The Bitcoin Core developers
|
| 3 |
# Distributed under the MIT software license, see the accompanying
|
| 4 |
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
| 5 |
"""Test datacarrier functionality"""
|
| 6 |
+
from random import randbytes
|
| 7 |
+
|
| 8 |
+
from test_framework.blocktools import MAX_STANDARD_TX_WEIGHT
|
| 9 |
+
from test_framework.key import compute_xonly_pubkey
|
| 10 |
from test_framework.messages import (
|
| 11 |
+
COutPoint,
|
| 12 |
+
CTransaction,
|
| 13 |
+
CTxIn,
|
| 14 |
+
CTxInWitness,
|
| 15 |
CTxOut,
|
|
|
|
| 16 |
)
|
| 17 |
from test_framework.script import (
|
| 18 |
CScript,
|
| 19 |
+
MAX_SCRIPT_ELEMENT_SIZE,
|
| 20 |
+
OP_DROP,
|
| 21 |
OP_RETURN,
|
| 22 |
+
OP_TRUE,
|
| 23 |
+
taproot_construct,
|
| 24 |
)
|
| 25 |
from test_framework.test_framework import BitcoinTestFramework
|
| 26 |
from test_framework.test_node import TestNode
|
|
|
|
| 30 |
)
|
| 31 |
from test_framework.wallet import MiniWallet
|
| 32 |
|
|
|
|
| 33 |
|
| 34 |
# The historical maximum, now used to test coverage
|
| 35 |
CUSTOM_DATACARRIER_ARG = 83
|
|
|
|
| 38 |
def set_test_params(self):
|
| 39 |
self.num_nodes = 4
|
| 40 |
self.extra_args = [
|
| 41 |
+
[], # default aggregate size is 83 bytes
|
| 42 |
["-datacarrier=0"], # no relay of datacarrier
|
| 43 |
["-datacarrier=1", f"-datacarriersize={CUSTOM_DATACARRIER_ARG}"],
|
| 44 |
["-datacarrier=1", "-datacarriersize=2"],
|
| 45 |
]
|
| 46 |
|
| 47 |
+
def test_null_data_transaction(self, node: TestNode, data, success: bool) -> str:
|
| 48 |
tx = self.wallet.create_self_transfer(fee_rate=0)["tx"]
|
| 49 |
data = [] if data is None else [data]
|
| 50 |
tx.vout.append(CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN] + data)))
|
|
|
|
| 57 |
assert tx.txid_hex in node.getrawmempool(True), f'{tx_hex} not in mempool'
|
| 58 |
else:
|
| 59 |
assert_raises_rpc_error(-26, "datacarrier", self.wallet.sendrawtransaction, from_node=node, tx_hex=tx_hex)
|
| 60 |
+
return tx_hex
|
| 61 |
+
|
| 62 |
+
def test_taproot_carrier(self):
|
| 63 |
+
# Match feature_taproot's pushmaxlimit pattern without randomized input grouping.
|
| 64 |
+
script = CScript([b"x" * MAX_SCRIPT_ELEMENT_SIZE, OP_DROP, OP_TRUE])
|
| 65 |
+
tap = taproot_construct(compute_xonly_pubkey((1).to_bytes(32, "big"))[0], [("carrier", script)])
|
| 66 |
+
funding = self.wallet.send_to(from_node=self.nodes[0], scriptPubKey=tap.scriptPubKey, amount=100000)
|
| 67 |
+
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
|
| 68 |
+
tx = CTransaction()
|
| 69 |
+
tx.vin = [CTxIn(COutPoint(int(funding["txid"], 16), funding["sent_vout"]))]
|
| 70 |
+
tx.vout = [CTxOut(90000, funding["tx"].vout[0].scriptPubKey)]
|
| 71 |
+
tx.wit.vtxinwit = [CTxInWitness()]
|
| 72 |
+
leaf = tap.leaves["carrier"]
|
| 73 |
+
control = bytes([leaf.version | tap.negflag]) + tap.internal_pubkey + leaf.merklebranch
|
| 74 |
+
tx.wit.vtxinwit[0].scriptWitness.stack = [script, control]
|
| 75 |
+
tx_hex = tx.serialize().hex()
|
| 76 |
+
|
| 77 |
+
self.log.info("Testing Taproot push/OP_DROP carrier policy independently of script validity.")
|
| 78 |
+
assert_raises_rpc_error(-26, "txn-datacarrier-nonstandard", self.nodes[0].sendrawtransaction, tx_hex)
|
| 79 |
+
# Disabling general standardness does not disable carrier recognition.
|
| 80 |
+
self.restart_node(0, extra_args=["-acceptnonstdtxn=1"])
|
| 81 |
+
assert_raises_rpc_error(-26, "txn-datacarrier-nonstandard", self.nodes[0].sendrawtransaction, tx_hex)
|
| 82 |
+
# Full-count disabling is separate from the nonstandard-carrier switch.
|
| 83 |
+
self.restart_node(0, extra_args=["-acceptnonstddatacarrier=1", "-datacarrierfullcount=0", "-datacarriersize=0"])
|
| 84 |
+
assert_equal(self.nodes[0].testmempoolaccept([tx_hex])[0]["allowed"], True)
|
| 85 |
+
carrier_size = len(CScript([b"x" * MAX_SCRIPT_ELEMENT_SIZE, OP_DROP]))
|
| 86 |
+
self.restart_node(0, extra_args=["-acceptnonstddatacarrier=1", f"-datacarriersize={carrier_size - 1}"])
|
| 87 |
+
assert_raises_rpc_error(-26, "txn-datacarrier-exceeded", self.nodes[0].sendrawtransaction, tx_hex)
|
| 88 |
+
# A local carrier rejection cannot invalidate this consensus-valid script.
|
| 89 |
+
self.generateblock(self.nodes[0], output="raw(42)", transactions=[tx_hex], sync_fun=self.no_op)
|
| 90 |
+
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
| 91 |
+
self.restart_node(0, extra_args=["-acceptnonstddatacarrier=1", f"-datacarriersize={carrier_size}"])
|
| 92 |
+
assert_equal(self.nodes[0].sendrawtransaction(tx_hex), tx.txid_hex)
|
| 93 |
+
assert tx.txid_hex in self.nodes[0].getrawmempool()
|
| 94 |
+
self.restart_node(0)
|
| 95 |
|
| 96 |
def run_test(self):
|
| 97 |
self.wallet = MiniWallet(self.nodes[0])
|
| 98 |
|
| 99 |
+
# Roots rejects bare multisig by default; report the actual configured policy.
|
|
|
|
| 100 |
|
| 101 |
+
assert_equal(self.nodes[0].getmempoolinfo()["maxdatacarriersize"], CUSTOM_DATACARRIER_ARG)
|
| 102 |
assert_equal(self.nodes[1].getmempoolinfo()["maxdatacarriersize"], 0)
|
| 103 |
assert_equal(self.nodes[2].getmempoolinfo()["maxdatacarriersize"], CUSTOM_DATACARRIER_ARG)
|
| 104 |
assert_equal(self.nodes[3].getmempoolinfo()["maxdatacarriersize"], 2)
|
| 105 |
|
|
|
|
| 106 |
|
| 107 |
# If it is custom set to 83, the historical value,
|
| 108 |
# only 80 bytes are used for data (+1 for OP_RETURN, +2 for the pushdata opcodes).
|
| 109 |
custom_size_data = randbytes(CUSTOM_DATACARRIER_ARG - 3)
|
| 110 |
too_long_data = randbytes(CUSTOM_DATACARRIER_ARG - 2)
|
|
|
|
| 111 |
one_byte = randbytes(1)
|
| 112 |
zero_bytes = randbytes(0)
|
| 113 |
|
| 114 |
+
self.log.info("Testing null data with the default 83-byte aggregate limit.")
|
| 115 |
+
self.test_null_data_transaction(node=self.nodes[0], data=custom_size_data, success=True)
|
| 116 |
+
rejected_tx = self.test_null_data_transaction(node=self.nodes[0], data=too_long_data, success=False)
|
| 117 |
+
# Relay limits do not alter block validity.
|
| 118 |
+
self.generateblock(self.nodes[0], output="raw(42)", transactions=[rejected_tx], sync_fun=self.no_op)
|
| 119 |
|
| 120 |
self.log.info("Testing a null data transaction with -datacarrier=false.")
|
| 121 |
self.test_null_data_transaction(node=self.nodes[1], data=custom_size_data, success=False)
|
|
|
|
| 144 |
self.test_null_data_transaction(node=self.nodes[2], data=one_byte, success=True)
|
| 145 |
self.test_null_data_transaction(node=self.nodes[3], data=one_byte, success=False)
|
| 146 |
|
| 147 |
+
self.log.info("Testing an explicit large data-carrier limit below the standard transaction weight boundary.")
|
| 148 |
+
self.restart_node(0, extra_args=["-datacarriersize=100000", "-maxscriptsize=100000"])
|
| 149 |
+
self.test_null_data_transaction(node=self.nodes[0], data=randbytes(MAX_STANDARD_TX_WEIGHT // 4 - 200), success=True)
|
| 150 |
+
|
| 151 |
+
# Extreme cost accounting/valid-block coverage follows in L8.
|
| 152 |
+
self.stop_node(0)
|
| 153 |
+
for cost in ["-1", "1073741823.76", "1e999", "invalid"]:
|
| 154 |
+
self.nodes[0].assert_start_raises_init_error(
|
| 155 |
+
[f"-datacarriercost={cost}"], f"Error: Invalid -datacarriercost value: '{cost}' (expected a value from 0 to 1073741823.75 exactly representable in hundredths)")
|
| 156 |
+
self.start_node(0)
|
| 157 |
+
self.test_taproot_carrier()
|
| 158 |
+
|
| 159 |
if __name__ == '__main__':
|
| 160 |
DataCarrierTest(__file__).main()
|