mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-03 22:47:32 +01:00
Merge bitcoin/bitcoin#29496: policy: bump TX_MAX_STANDARD_VERSION to 3
30a01134cd
[doc] update bips.md for 431 (glozow)9dbe6a03f0
[test] wallet uses CURRENT_VERSION which is 2 (glozow)539404fe0f
[policy] make v3 transactions standard (glozow)052ede75af
[refactor] use TRUC_VERSION in place of 3 (glozow) Pull request description: Make `nVersion=3` (which is currently nonstandard on mainnet) standard. Note that we will treat these transactions as Topologically Restricted Until Confirmation (TRUC). Spec is in BIP 431 and implementation is in #28948, #29306, and #29873 See #27463 for overall project tracking, and #29319 for information about relevance to cluster mempool. ACKs for top commit: sdaftuar: utACK30a01134c
achow101: ACK30a01134cd
instagibbs: utACK30a01134cd
murchandamus: ACK30a01134cd
ismaelsadeeq: ACK30a01134cd
🛰️ Tree-SHA512: 2a4aec0442c860e792a061d83e36483c1f1b426f946efbdf664c8db97a596e498b535707e1d3a900218429486ea69fd4552e3d476526a6883cbd5556c6534b48
This commit is contained in:
commit
6e4d18f37f
12 changed files with 58 additions and 35 deletions
|
@ -69,3 +69,4 @@ BIPs that are implemented by Bitcoin Core:
|
|||
[`385`](https://github.com/bitcoin/bips/blob/master/bip-0385.mediawiki):
|
||||
Output Script Descriptors, and most of Script Expressions are implemented as of **v0.17.0** ([PR 13697](https://github.com/bitcoin/bitcoin/pull/13697)).
|
||||
* [`BIP 386`](https://github.com/bitcoin/bips/blob/master/bip-0386.mediawiki): tr() Output Script Descriptors are implemented as of **v22.0** ([PR 22051](https://github.com/bitcoin/bitcoin/pull/22051)).
|
||||
* [`BIP 431`](https://github.com/bitcoin/bips/blob/master/bip-0431.mediawiki): transactions with nVersion=3 are standard and treated as Topologically Restricted Until Confirmation as of **v28.0** ([PR 29496](https://github.com/bitcoin/bitcoin/pull/29496)).
|
||||
|
|
|
@ -131,7 +131,7 @@ bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_
|
|||
// Changing the default transaction version requires a two step process: first
|
||||
// adapting relay policy by bumping TX_MAX_STANDARD_VERSION, and then later
|
||||
// allowing the new transaction version in the wallet/RPC.
|
||||
static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
|
||||
static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{3};
|
||||
|
||||
/**
|
||||
* Check for standard transaction types
|
||||
|
|
|
@ -66,7 +66,7 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
|
|||
const auto in_package_parents{FindInPackageParents(package, ptx)};
|
||||
|
||||
// Now we have all ancestors, so we can start checking v3 rules.
|
||||
if (ptx->nVersion == 3) {
|
||||
if (ptx->nVersion == TRUC_VERSION) {
|
||||
// SingleV3Checks should have checked this already.
|
||||
if (!Assume(vsize <= V3_MAX_VSIZE)) {
|
||||
return strprintf("v3 tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
||||
|
@ -107,7 +107,7 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
|
|||
}();
|
||||
|
||||
// If there is a parent, it must have the right version.
|
||||
if (parent_info.m_version != 3) {
|
||||
if (parent_info.m_version != TRUC_VERSION) {
|
||||
return strprintf("v3 tx %s (wtxid=%s) cannot spend from non-v3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
parent_info.m_txid.ToString(), parent_info.m_wtxid.ToString());
|
||||
|
@ -146,14 +146,14 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
|
|||
} else {
|
||||
// Non-v3 transactions cannot have v3 parents.
|
||||
for (auto it : mempool_ancestors) {
|
||||
if (it->GetTx().nVersion == 3) {
|
||||
if (it->GetTx().nVersion == TRUC_VERSION) {
|
||||
return strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
it->GetSharedTx()->GetHash().ToString(), it->GetSharedTx()->GetWitnessHash().ToString());
|
||||
}
|
||||
}
|
||||
for (const auto& index: in_package_parents) {
|
||||
if (package.at(index)->nVersion == 3) {
|
||||
if (package.at(index)->nVersion == TRUC_VERSION) {
|
||||
return strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(),
|
||||
ptx->GetWitnessHash().ToString(),
|
||||
|
@ -172,12 +172,12 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleV3Checks(const CTra
|
|||
{
|
||||
// Check v3 and non-v3 inheritance.
|
||||
for (const auto& entry : mempool_ancestors) {
|
||||
if (ptx->nVersion != 3 && entry->GetTx().nVersion == 3) {
|
||||
if (ptx->nVersion != TRUC_VERSION && entry->GetTx().nVersion == TRUC_VERSION) {
|
||||
return std::make_pair(strprintf("non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()),
|
||||
nullptr);
|
||||
} else if (ptx->nVersion == 3 && entry->GetTx().nVersion != 3) {
|
||||
} else if (ptx->nVersion == TRUC_VERSION && entry->GetTx().nVersion != TRUC_VERSION) {
|
||||
return std::make_pair(strprintf("v3 tx %s (wtxid=%s) cannot spend from non-v3 tx %s (wtxid=%s)",
|
||||
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
||||
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()),
|
||||
|
@ -190,7 +190,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleV3Checks(const CTra
|
|||
static_assert(V3_DESCENDANT_LIMIT == 2);
|
||||
|
||||
// The rest of the rules only apply to transactions with nVersion=3.
|
||||
if (ptx->nVersion != 3) return std::nullopt;
|
||||
if (ptx->nVersion != TRUC_VERSION) return std::nullopt;
|
||||
|
||||
if (vsize > V3_MAX_VSIZE) {
|
||||
return std::make_pair(strprintf("v3 tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
|
||||
// This module enforces rules for transactions with nVersion=3 ("v3 transactions") which help make
|
||||
// This module enforces rules for BIP 431 TRUC transactions (with nVersion=3) which help make
|
||||
// RBF abilities more robust.
|
||||
static constexpr decltype(CTransaction::nVersion) TRUC_VERSION{3};
|
||||
|
||||
// v3 only allows 1 parent and 1 child when unconfirmed.
|
||||
/** Maximum number of transactions including an unconfirmed tx and its descendants. */
|
||||
|
|
|
@ -173,7 +173,7 @@ FUZZ_TARGET(tx_package_eval, .init = initialize_tx_pool)
|
|||
// Create transaction to add to the mempool
|
||||
const CTransactionRef tx = [&] {
|
||||
CMutableTransaction tx_mut;
|
||||
tx_mut.nVersion = fuzzed_data_provider.ConsumeBool() ? 3 : CTransaction::CURRENT_VERSION;
|
||||
tx_mut.nVersion = fuzzed_data_provider.ConsumeBool() ? TRUC_VERSION : CTransaction::CURRENT_VERSION;
|
||||
tx_mut.nLockTime = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<uint32_t>();
|
||||
// Last tx will sweep all outpoints in package
|
||||
const auto num_in = last_tx ? package_outpoints.size() : fuzzed_data_provider.ConsumeIntegralInRange<int>(1, mempool_outpoints.size());
|
||||
|
|
|
@ -226,7 +226,7 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
|
|||
// Create transaction to add to the mempool
|
||||
const CTransactionRef tx = [&] {
|
||||
CMutableTransaction tx_mut;
|
||||
tx_mut.nVersion = fuzzed_data_provider.ConsumeBool() ? 3 : CTransaction::CURRENT_VERSION;
|
||||
tx_mut.nVersion = fuzzed_data_provider.ConsumeBool() ? TRUC_VERSION : CTransaction::CURRENT_VERSION;
|
||||
tx_mut.nLockTime = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<uint32_t>();
|
||||
const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<int>(1, outpoints_rbf.size());
|
||||
const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<int>(1, outpoints_rbf.size() * 2);
|
||||
|
|
|
@ -286,7 +286,7 @@ BOOST_FIXTURE_TEST_CASE(version3_tests, RegTestingSetup)
|
|||
script_multisig << OP_2 << OP_CHECKMULTISIG;
|
||||
{
|
||||
CMutableTransaction mtx_many_sigops = CMutableTransaction{};
|
||||
mtx_many_sigops.nVersion = 3;
|
||||
mtx_many_sigops.nVersion = TRUC_VERSION;
|
||||
for (const auto& outpoint : multisig_outpoints) {
|
||||
mtx_many_sigops.vin.emplace_back(outpoint);
|
||||
mtx_many_sigops.vin.back().scriptWitness.stack.emplace_back(script_multisig.begin(), script_multisig.end());
|
||||
|
|
|
@ -118,7 +118,7 @@ void CheckMempoolV3Invariants(const CTxMemPool& tx_pool)
|
|||
LOCK(tx_pool.cs);
|
||||
for (const auto& tx_info : tx_pool.infoAll()) {
|
||||
const auto& entry = *Assert(tx_pool.GetEntry(tx_info.tx->GetHash()));
|
||||
if (tx_info.tx->nVersion == 3) {
|
||||
if (tx_info.tx->nVersion == TRUC_VERSION) {
|
||||
// Check that special maximum virtual size is respected
|
||||
Assert(entry.GetTxSize() <= V3_MAX_VSIZE);
|
||||
|
||||
|
@ -133,12 +133,12 @@ void CheckMempoolV3Invariants(const CTxMemPool& tx_pool)
|
|||
Assert(entry.GetTxSize() <= V3_CHILD_MAX_VSIZE);
|
||||
// All v3 transactions must only have v3 unconfirmed parents.
|
||||
const auto& parents = entry.GetMemPoolParentsConst();
|
||||
Assert(parents.begin()->get().GetSharedTx()->nVersion == 3);
|
||||
Assert(parents.begin()->get().GetSharedTx()->nVersion == TRUC_VERSION);
|
||||
}
|
||||
} else if (entry.GetCountWithAncestors() > 1) {
|
||||
// All non-v3 transactions must only have non-v3 unconfirmed parents.
|
||||
for (const auto& parent : entry.GetMemPoolParentsConst()) {
|
||||
Assert(parent.get().GetSharedTx()->nVersion != 3);
|
||||
Assert(parent.get().GetSharedTx()->nVersion != TRUC_VERSION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -831,7 +831,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|||
//
|
||||
// Replaceability signaling of the original transactions may be
|
||||
// ignored due to node setting.
|
||||
const bool allow_rbf{m_pool.m_opts.full_rbf || SignalsOptInRBF(*ptxConflicting) || ptxConflicting->nVersion == 3};
|
||||
const bool allow_rbf{m_pool.m_opts.full_rbf || SignalsOptInRBF(*ptxConflicting) || ptxConflicting->nVersion == TRUC_VERSION};
|
||||
if (!allow_rbf) {
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "txn-mempool-conflict");
|
||||
}
|
||||
|
@ -935,7 +935,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|||
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
|
||||
// due to a replacement.
|
||||
// The only exception is v3 transactions.
|
||||
if (!bypass_limits && ws.m_ptx->nVersion != 3 && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)) {
|
||||
if (!bypass_limits && ws.m_ptx->nVersion != TRUC_VERSION && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)) {
|
||||
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
||||
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
||||
|
@ -1017,7 +1017,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|||
.descendant_count = maybe_rbf_limits.descendant_count + 1,
|
||||
.descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
|
||||
};
|
||||
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || ws.m_ptx->nVersion == 3) {
|
||||
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || ws.m_ptx->nVersion == TRUC_VERSION) {
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
|
||||
}
|
||||
if (auto ancestors_retry{m_pool.CalculateMemPoolAncestors(*entry, cpfp_carve_out_limits)}) {
|
||||
|
|
|
@ -287,7 +287,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
|
|||
|
||||
self.log.info('Some nonstandard transactions')
|
||||
tx = tx_from_hex(raw_tx_reference)
|
||||
tx.nVersion = 3 # A version currently non-standard
|
||||
tx.nVersion = 4 # A version currently non-standard
|
||||
self.check_mempool_result(
|
||||
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'version'}],
|
||||
rawtxs=[tx.serialize().hex()],
|
||||
|
|
|
@ -42,7 +42,7 @@ def cleanup(extra_args=None):
|
|||
class MempoolAcceptV3(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
self.extra_args = [["-acceptnonstdtxn=1"]]
|
||||
self.extra_args = [[]]
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def check_mempool(self, txids):
|
||||
|
@ -51,7 +51,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
assert_equal(len(txids), len(mempool_contents))
|
||||
assert all([txid in txids for txid in mempool_contents])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=20000", "-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=["-datacarriersize=20000"])
|
||||
def test_v3_max_vsize(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test v3-specific maximum transaction vsize")
|
||||
|
@ -65,7 +65,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
tx_v2_heavy = self.wallet.send_self_transfer(from_node=node, target_weight=(V3_MAX_VSIZE + 1) * WITNESS_SCALE_FACTOR, version=2)
|
||||
self.check_mempool([tx_v2_heavy["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=1000", "-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=["-datacarriersize=1000"])
|
||||
def test_v3_acceptance(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test a child of a v3 transaction cannot be more than 1000vB")
|
||||
|
@ -105,7 +105,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
self.check_mempool([tx_v3_parent_normal["txid"], tx_v3_child_almost_heavy_rbf["txid"]])
|
||||
assert_equal(node.getmempoolentry(tx_v3_parent_normal["txid"])["descendantcount"], 2)
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_replacement(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test v3 transactions may be replaced by v3 transactions")
|
||||
|
@ -162,7 +162,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
self.check_mempool([tx_v3_bip125_rbf_v2["txid"], tx_v3_parent["txid"], tx_v3_child["txid"]])
|
||||
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_bip125(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test v3 transactions that don't signal BIP125 are replaceable")
|
||||
|
@ -186,7 +186,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
)
|
||||
self.check_mempool([tx_v3_no_bip125_rbf["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=40000", "-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=["-datacarriersize=40000"])
|
||||
def test_v3_reorg(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that, during a reorg, v3 rules are not enforced")
|
||||
|
@ -208,7 +208,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
node.reconsiderblock(block[0])
|
||||
|
||||
|
||||
@cleanup(extra_args=["-limitdescendantsize=10", "-datacarriersize=40000", "-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=["-limitdescendantsize=10", "-datacarriersize=40000"])
|
||||
def test_nondefault_package_limits(self):
|
||||
"""
|
||||
Max standard tx size + v3 rules imply the ancestor/descendant rules (at their default
|
||||
|
@ -241,7 +241,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
self.generate(node, 1)
|
||||
|
||||
self.log.info("Test that a decreased limitancestorsize also applies to v3 parent")
|
||||
self.restart_node(0, extra_args=["-limitancestorsize=10", "-datacarriersize=40000", "-acceptnonstdtxn=1"])
|
||||
self.restart_node(0, extra_args=["-limitancestorsize=10", "-datacarriersize=40000"])
|
||||
tx_v3_parent_large2 = self.wallet.send_self_transfer(
|
||||
from_node=node,
|
||||
target_weight=parent_target_weight,
|
||||
|
@ -261,7 +261,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
assert_raises_rpc_error(-26, f"too-long-mempool-chain, exceeds ancestor size limit", node.sendrawtransaction, tx_v3_child_large2["hex"])
|
||||
self.check_mempool([tx_v3_parent_large2["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=1000", "-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=["-datacarriersize=1000"])
|
||||
def test_v3_ancestors_package(self):
|
||||
self.log.info("Test that v3 ancestor limits are checked within the package")
|
||||
node = self.nodes[0]
|
||||
|
@ -304,7 +304,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
result = node.testmempoolaccept([tx_v3_parent["hex"], tx_v3_child["hex"], tx_v3_grandchild["hex"]])
|
||||
assert all([txresult["package-error"] == f"v3-violation, tx {tx_v3_grandchild['txid']} (wtxid={tx_v3_grandchild['wtxid']}) would have too many ancestors" for txresult in result])
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_ancestors_package_and_mempool(self):
|
||||
"""
|
||||
A v3 transaction in a package cannot have 2 v3 parents.
|
||||
|
@ -334,7 +334,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
assert_equal(result['package_msg'], f"v3-violation, tx {tx_child_violator['txid']} (wtxid={tx_child_violator['wtxid']}) would have too many ancestors")
|
||||
self.check_mempool([tx_in_mempool["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_sibling_eviction_package(self):
|
||||
"""
|
||||
When a transaction has a mempool sibling, it may be eligible for sibling eviction.
|
||||
|
@ -410,7 +410,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
assert_equal(result_package_cpfp["tx-results"][tx_sibling_3['wtxid']]['error'], expected_error_cpfp)
|
||||
|
||||
|
||||
@cleanup(extra_args=["-datacarriersize=1000", "-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=["-datacarriersize=1000"])
|
||||
def test_v3_package_inheritance(self):
|
||||
self.log.info("Test that v3 inheritance is checked within package")
|
||||
node = self.nodes[0]
|
||||
|
@ -429,7 +429,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
assert_equal(result['package_msg'], f"v3-violation, non-v3 tx {tx_v2_child['txid']} (wtxid={tx_v2_child['wtxid']}) cannot spend from v3 tx {tx_v3_parent['txid']} (wtxid={tx_v3_parent['wtxid']})")
|
||||
self.check_mempool([])
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_in_testmempoolaccept(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
|
@ -479,7 +479,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
test_accept_2children_with_in_mempool_parent = node.testmempoolaccept([tx_v3_child_1["hex"], tx_v3_child_2["hex"]])
|
||||
assert all([result["package-error"] == expected_error_extra for result in test_accept_2children_with_in_mempool_parent])
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_reorg_2child_rbf(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that children of a v3 transaction can be replaced individually, even if there are multiple due to reorg")
|
||||
|
@ -510,7 +510,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
self.check_mempool([ancestor_tx["txid"], child_1_conflict["txid"], child_2["txid"]])
|
||||
assert_equal(node.getmempoolentry(ancestor_tx["txid"])["descendantcount"], 3)
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_v3_sibling_eviction(self):
|
||||
self.log.info("Test sibling eviction for v3")
|
||||
node = self.nodes[0]
|
||||
|
@ -583,7 +583,7 @@ class MempoolAcceptV3(BitcoinTestFramework):
|
|||
node.sendrawtransaction(tx_v3_child_3["hex"])
|
||||
self.check_mempool(txids_v2_100 + [tx_v3_parent["txid"], tx_v3_child_3["txid"]])
|
||||
|
||||
@cleanup(extra_args=["-acceptnonstdtxn=1"])
|
||||
@cleanup(extra_args=None)
|
||||
def test_reorg_sibling_eviction_1p2c(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that sibling eviction is not allowed when multiple siblings exist")
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from test_framework.messages import (
|
||||
tx_from_hex,
|
||||
)
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
|
@ -33,6 +36,7 @@ class CreateTxWalletTest(BitcoinTestFramework):
|
|||
self.test_anti_fee_sniping()
|
||||
self.test_tx_size_too_large()
|
||||
self.test_create_too_long_mempool_chain()
|
||||
self.test_version3()
|
||||
|
||||
def test_anti_fee_sniping(self):
|
||||
self.log.info('Check that we have some (old) blocks and that anti-fee-sniping is disabled')
|
||||
|
@ -106,6 +110,23 @@ class CreateTxWalletTest(BitcoinTestFramework):
|
|||
|
||||
test_wallet.unloadwallet()
|
||||
|
||||
def test_version3(self):
|
||||
self.log.info('Check wallet does not create transactions with nVersion=3 yet')
|
||||
wallet_rpc = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
|
||||
|
||||
self.nodes[0].createwallet("v3")
|
||||
wallet_v3 = self.nodes[0].get_wallet_rpc("v3")
|
||||
|
||||
tx_data = wallet_rpc.send(outputs=[{wallet_v3.getnewaddress(): 25}], options={"change_position": 0})
|
||||
wallet_tx_data = wallet_rpc.gettransaction(tx_data["txid"])
|
||||
tx_current_version = tx_from_hex(wallet_tx_data["hex"])
|
||||
|
||||
# While v3 transactions are standard, the CURRENT_VERSION is 2.
|
||||
# This test can be removed if CURRENT_VERSION is changed, and replaced with tests that the
|
||||
# wallet handles v3 rules properly.
|
||||
assert_equal(tx_current_version.nVersion, 2)
|
||||
wallet_v3.unloadwallet()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
CreateTxWalletTest().main()
|
||||
|
|
Loading…
Add table
Reference in a new issue