Skip to content
Bitcoin Roots

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()