mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-14 15:25:51 +02:00
rpc: add vsize_adjusted and vsize_bip141 field to mempool-related RPCs
This commit adds a new `vsize_adjusted` and `vsize_bip141` field to mempool acceptance and submission RPCs, including `testmempoolaccept` and `submitpackage`, to report the sigop-adjusted virtual transaction size and virtual transaction size as defined in BIP 141 respectively. While `vsize` is now marked as deprecated. RPC help texts are updated to reflect this addition. Tests in `mempool_accept.py, mempool_accept, p2p_segwit, rpc_packages, mempool_sigoplimit` are extended to verify the presence and correctness of the new fields. Co-authored-by: Gloria Zhao <gloriajzhao@gmail.com>
This commit is contained in:
@@ -136,7 +136,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
raw_tx_0 = tx.serialize().hex()
|
||||
txid_0 = tx.txid_hex
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee}}],
|
||||
result_expected=[{'txid': txid_0, 'allowed': True, 'vsize_adjusted': tx.get_vsize(), 'vsize': tx.get_vsize(), 'vsize_bip141': tx.get_vsize(),'fees': {'base': fee}}],
|
||||
rawtxs=[raw_tx_0],
|
||||
)
|
||||
|
||||
@@ -151,7 +151,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
tx = tx_from_hex(raw_tx_final)
|
||||
fee_expected = Decimal('50.0') - output_amount
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee_expected}}],
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize_adjusted': tx.get_vsize(), 'vsize': tx.get_vsize(), 'vsize_bip141': tx.get_vsize(), 'fees': {'base': fee_expected}}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
maxfeerate=0,
|
||||
)
|
||||
@@ -172,7 +172,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
raw_tx_0 = tx.serialize().hex()
|
||||
txid_0 = tx.txid_hex
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': (2 * fee)}}],
|
||||
result_expected=[{'txid': txid_0, 'allowed': True, 'vsize_adjusted': tx.get_vsize(), 'vsize': tx.get_vsize(), 'vsize_bip141': tx.get_vsize(), 'fees': {'base': (2 * fee)}}],
|
||||
rawtxs=[raw_tx_0],
|
||||
)
|
||||
node.sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0)
|
||||
@@ -218,7 +218,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
raw_tx_reference = tx.serialize().hex()
|
||||
# Reference tx should be valid on itself
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.1') - Decimal('0.05')}}],
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize_adjusted': tx.get_vsize(), 'vsize': tx.get_vsize(), 'vsize_bip141': tx.get_vsize(), 'fees': { 'base': Decimal('0.1') - Decimal('0.05')}}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
maxfeerate=0,
|
||||
)
|
||||
@@ -354,7 +354,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
tx.vout.append(CTxOut(0, CScript([OP_RETURN, b'\xff' * 50000])))
|
||||
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': Decimal('0.05')}}],
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize_adjusted': tx.get_vsize(), 'vsize': tx.get_vsize(), 'vsize_bip141': tx.get_vsize(), 'fees': {'base': Decimal('0.05')}}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
maxfeerate=0
|
||||
)
|
||||
@@ -366,7 +366,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
tx.vout[0].scriptPubKey = CScript([OP_RETURN, b'\xff'])
|
||||
tx.vout = [tx.vout[0]] * op_return_count
|
||||
self.check_mempool_result(
|
||||
result_expected=[{"txid": tx.txid_hex, "allowed": True, "vsize": tx.get_vsize(), "fees": {"base": Decimal("0.05000026")}}],
|
||||
result_expected=[{"txid": tx.txid_hex, "allowed": True, "vsize_adjusted": tx.get_vsize(), "vsize": tx.get_vsize(), 'vsize_bip141': tx.get_vsize(), "fees": {"base": Decimal("0.05000026")}}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
)
|
||||
|
||||
@@ -377,7 +377,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
tx.vout[0].scriptPubKey = CScript([OP_RETURN, b"\xff" * (data_len)])
|
||||
assert_equal(tx.get_vsize(), int(MAX_STANDARD_TX_WEIGHT / 4))
|
||||
self.check_mempool_result(
|
||||
result_expected=[{"txid": tx.txid_hex, "allowed": True, "vsize": tx.get_vsize(), "fees": {"base": Decimal("0.1") - Decimal("0.05")}}],
|
||||
result_expected=[{"txid": tx.txid_hex, "allowed": True, "vsize_adjusted": tx.get_vsize(), "vsize": tx.get_vsize(), 'vsize_bip141': tx.get_vsize(), "fees": {"base": Decimal("0.1") - Decimal("0.05")}}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
)
|
||||
tx.vout[0].scriptPubKey = CScript([OP_RETURN, b"\xff" * (data_len + 1)])
|
||||
@@ -430,7 +430,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
tx.vout[0] = CTxOut(COIN - 1000, DUMMY_MIN_OP_RETURN_SCRIPT)
|
||||
assert_equal(len(tx.serialize_without_witness()), MIN_STANDARD_TX_NONWITNESS_SIZE)
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.00001000')}}],
|
||||
result_expected=[{'txid': tx.txid_hex, 'allowed': True, 'vsize_adjusted': tx.get_vsize(), 'vsize': tx.get_vsize(), 'vsize_bip141': tx.get_vsize(), 'fees': { 'base': Decimal('0.00001000')}}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
maxfeerate=0,
|
||||
)
|
||||
@@ -468,7 +468,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
assert_equal(anchor_spend.txid_hex, anchor_spend.wtxid_hex)
|
||||
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': anchor_spend.txid_hex, 'allowed': True, 'vsize': anchor_spend.get_vsize(), 'fees': { 'base': Decimal('0.00000700')}}],
|
||||
result_expected=[{'txid': anchor_spend.txid_hex, 'allowed': True, 'vsize_adjusted': anchor_spend.get_vsize(), 'vsize': anchor_spend.get_vsize(), 'vsize_bip141': anchor_spend.get_vsize(), 'fees': { 'base': Decimal('0.00000700')}}],
|
||||
rawtxs=[anchor_spend.serialize().hex()],
|
||||
maxfeerate=0,
|
||||
)
|
||||
@@ -503,7 +503,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
||||
sign_input_legacy(tx_spend, 0, tx.vout[0].scriptPubKey, privkey, sighash_type=SIGHASH_ALL)
|
||||
tx_spend.vin[0].scriptSig = bytes(CScript([OP_0])) + tx_spend.vin[0].scriptSig
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': tx_spend.txid_hex, 'allowed': True, 'vsize': tx_spend.get_vsize(), 'fees': { 'base': Decimal('0.00000700')}}],
|
||||
result_expected=[{'txid': tx_spend.txid_hex, 'allowed': True, 'vsize_adjusted': tx_spend.get_vsize(), 'vsize': tx_spend.get_vsize(), 'vsize_bip141': tx_spend.get_vsize(), 'fees': { 'base': Decimal('0.00000700')}}],
|
||||
rawtxs=[tx_spend.serialize().hex()],
|
||||
maxfeerate=0,
|
||||
)
|
||||
|
||||
@@ -41,6 +41,7 @@ from test_framework.util import (
|
||||
assert_equal,
|
||||
assert_greater_than,
|
||||
assert_greater_than_or_equal,
|
||||
assert_not_equal,
|
||||
assert_raises_rpc_error,
|
||||
)
|
||||
from test_framework.wallet import MiniWallet
|
||||
@@ -98,14 +99,20 @@ class BytesPerSigOpTest(BitcoinTestFramework):
|
||||
|
||||
res = self.nodes[0].testmempoolaccept([tx.serialize().hex()])[0]
|
||||
assert_equal(res['allowed'], True)
|
||||
assert_equal(sigop_equivalent_vsize, tx.get_vsize())
|
||||
assert_equal(res['vsize'], sigop_equivalent_vsize)
|
||||
assert_equal(res['vsize_adjusted'], sigop_equivalent_vsize)
|
||||
assert_equal(res['vsize_bip141'], tx.get_vsize())
|
||||
|
||||
# increase the tx's vsize to be right above the sigop-limit equivalent size
|
||||
# => tx's vsize in mempool should also grow accordingly
|
||||
tx.vout[0].scriptPubKey = CScript([OP_RETURN, b'X'*(256+vsize_to_pad+1)])
|
||||
res = self.nodes[0].testmempoolaccept([tx.serialize().hex()])[0]
|
||||
assert_equal(res['allowed'], True)
|
||||
assert_equal(sigop_equivalent_vsize + 1, tx.get_vsize())
|
||||
assert_equal(res['vsize'], sigop_equivalent_vsize+1)
|
||||
assert_equal(res['vsize_adjusted'], sigop_equivalent_vsize + 1)
|
||||
assert_equal(res['vsize_bip141'], tx.get_vsize())
|
||||
|
||||
# decrease the tx's vsize to be right below the sigop-limit equivalent size
|
||||
# => tx's vsize in mempool should stick at the sigop-limit equivalent
|
||||
@@ -114,7 +121,10 @@ class BytesPerSigOpTest(BitcoinTestFramework):
|
||||
tx.vout[0].scriptPubKey = CScript([OP_RETURN, b'X'*(256+vsize_to_pad-1)])
|
||||
res = self.nodes[0].testmempoolaccept([tx.serialize().hex()])[0]
|
||||
assert_equal(res['allowed'], True)
|
||||
assert_not_equal(sigop_equivalent_vsize, tx.get_vsize())
|
||||
assert_equal(res['vsize'], sigop_equivalent_vsize)
|
||||
assert_equal(res['vsize_adjusted'], sigop_equivalent_vsize)
|
||||
assert_equal(res['vsize_bip141'], tx.get_vsize())
|
||||
|
||||
# check that the ancestor and descendant size calculations in the mempool
|
||||
# also use the same max(sigop_equivalent_vsize, serialized_vsize) logic
|
||||
@@ -166,7 +176,7 @@ class BytesPerSigOpTest(BitcoinTestFramework):
|
||||
parent_individual_testres = self.nodes[0].testmempoolaccept([tx_parent.serialize().hex()])[0]
|
||||
assert parent_individual_testres["allowed"]
|
||||
max_multisig_vsize = MAX_PUBKEYS_PER_MULTISIG * 5000
|
||||
assert_equal(parent_individual_testres["vsize"], max_multisig_vsize)
|
||||
assert_equal(parent_individual_testres["vsize_adjusted"], max_multisig_vsize)
|
||||
|
||||
# But together, it's exceeding limits in the *package* context. If sigops adjusted vsize wasn't being checked
|
||||
# here, it would get further in validation and give too-large-cluster error instead.
|
||||
|
||||
@@ -615,7 +615,9 @@ class SegWitTest(BitcoinTestFramework):
|
||||
'txid': tx3.txid_hex,
|
||||
'wtxid': tx3.wtxid_hex,
|
||||
'allowed': True,
|
||||
'vsize_adjusted': tx3.get_vsize(),
|
||||
'vsize': tx3.get_vsize(),
|
||||
'vsize_bip141': tx3.get_vsize(),
|
||||
'fees': {
|
||||
'base': Decimal('0.00001000'),
|
||||
},
|
||||
@@ -633,7 +635,9 @@ class SegWitTest(BitcoinTestFramework):
|
||||
'txid': tx3.txid_hex,
|
||||
'wtxid': tx3.wtxid_hex,
|
||||
'allowed': True,
|
||||
'vsize_adjusted': tx3.get_vsize(),
|
||||
'vsize': tx3.get_vsize(),
|
||||
'vsize_bip141': tx3.get_vsize(),
|
||||
'fees': {
|
||||
'base': Decimal('0.00011000'),
|
||||
},
|
||||
|
||||
@@ -302,6 +302,7 @@ class RPCPackagesTest(BitcoinTestFramework):
|
||||
assert_equal(testres_replaceable["wtxid"], replaceable_tx["wtxid"])
|
||||
assert testres_replaceable["allowed"]
|
||||
assert_equal(testres_replaceable["vsize"], replaceable_tx["tx"].get_vsize())
|
||||
assert_equal(testres_replaceable["vsize_bip141"], replaceable_tx["tx"].get_vsize())
|
||||
assert_equal(testres_replaceable["fees"]["base"], fee)
|
||||
assert_fee_amount(fee, replaceable_tx["tx"].get_vsize(), testres_replaceable["fees"]["effective-feerate"])
|
||||
assert_equal(testres_replaceable["fees"]["effective-includes"], [replaceable_tx["wtxid"]])
|
||||
@@ -339,9 +340,11 @@ class RPCPackagesTest(BitcoinTestFramework):
|
||||
# No "allowed" if the tx was already in the mempool
|
||||
if "allowed" in testres_tx and testres_tx["allowed"]:
|
||||
assert_equal(submitres_tx["vsize"], testres_tx["vsize"])
|
||||
assert_equal(submitres_tx["vsize_bip141"], testres_tx["vsize"])
|
||||
assert_equal(submitres_tx["fees"]["base"], testres_tx["fees"]["base"])
|
||||
entry_info = node.getmempoolentry(submitres_tx["txid"])
|
||||
assert_equal(submitres_tx["vsize"], entry_info["vsize"])
|
||||
assert_equal(submitres_tx["vsize_bip141"], entry_info["vsize"])
|
||||
assert_equal(submitres_tx["fees"]["base"], entry_info["fees"]["base"])
|
||||
|
||||
def test_submit_child_with_parents(self, num_parents, partial_submit):
|
||||
@@ -371,7 +374,9 @@ class RPCPackagesTest(BitcoinTestFramework):
|
||||
assert wtxid in submitpackage_result["tx-results"]
|
||||
tx_result = submitpackage_result["tx-results"][wtxid]
|
||||
assert_equal(tx_result["txid"], tx.txid_hex)
|
||||
assert_equal(tx_result["vsize_adjusted"], tx.get_vsize())
|
||||
assert_equal(tx_result["vsize"], tx.get_vsize())
|
||||
assert_equal(tx_result["vsize_bip141"], tx.get_vsize())
|
||||
assert_equal(tx_result["fees"]["base"], DEFAULT_FEE)
|
||||
if wtxid not in presubmitted_wtxids:
|
||||
assert_fee_amount(DEFAULT_FEE, tx.get_vsize(), tx_result["fees"]["effective-feerate"])
|
||||
|
||||
Reference in New Issue
Block a user