diff --git a/doc/bips.md b/doc/bips.md index 6f9b322e33da..d9bf9d2fa9c8 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -18,6 +18,7 @@ BIPs that are implemented by Bitcoin Core: * [`BIP 43`](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki): The experimental descriptor wallets introduced in **v0.21.0** by default use the Hierarchical Deterministic Wallet derivation proposed by BIP 43. ([PR #16528](https://github.com/bitcoin/bitcoin/pull/16528)) * [`BIP 44`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki): The experimental descriptor wallets introduced in **v0.21.0** by default use the Hierarchical Deterministic Wallet derivation proposed by BIP 44. ([PR #16528](https://github.com/bitcoin/bitcoin/pull/16528)) * [`BIP 49`](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki): The experimental descriptor wallets introduced in **v0.21.0** by default use the Hierarchical Deterministic Wallet derivation proposed by BIP 49. ([PR #16528](https://github.com/bitcoin/bitcoin/pull/16528)) +* [`BIP 54`](https://github.com/bitcoin/bips/blob/master/bip-0054.md): Validation rules for the Consensus Cleanup soft fork are implemented as of version **v32.0**. No deployment is defined for the soft fork, outside of regtest where the rules are now always active. * [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)). Starting **v0.17.0**, whether to send reject messages can be configured with the `-enablebip61` option, and support is deprecated (disabled by default) as of **v0.18.0**. Support was removed in **v0.20.0** ([PR #15437](https://github.com/bitcoin/bitcoin/pull/15437)). * [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124). * [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)). diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2b6840bbc390..7040a48f664d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -115,6 +115,7 @@ add_library(bitcoin_common STATIC EXCLUDE_FROM_ALL common/system.cpp common/url.cpp compressor.cpp + consensus/tx_verify.cpp core_io.cpp deploymentinfo.cpp external_signer.cpp @@ -188,7 +189,6 @@ add_library(bitcoin_node STATIC EXCLUDE_FROM_ALL bip324.cpp blockencodings.cpp blockfilter.cpp - consensus/tx_verify.cpp dbwrapper.cpp deploymentstatus.cpp flatfile.cpp diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 71b5fe2468d9..d8925548ccf3 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -27,11 +27,26 @@ static const size_t MIN_SERIALIZABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * /** Interpret sequence numbers as relative lock-time constraints. */ static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE = (1 << 0); +/** + * Under BIP54, the first block in a difficulty adjustment period must not be more than 2 + * hours (7200 seconds) earlier than the last block of the previous period. + */ +static constexpr int64_t MAX_TIMEWARP_BIP54{2 * 60 * 60}; + /** * Maximum number of seconds that the timestamp of the first * block of a difficulty adjustment period is allowed to * be earlier than the last block of the previous period (BIP94). */ -static constexpr int64_t MAX_TIMEWARP = 600; +static constexpr int64_t MAX_TIMEWARP_TESTNET4 = 600; + +/** The maximum number of potentially executed legacy signature operations in a single tx */ +static constexpr unsigned int MAX_TX_BIP54_SIGOPS{2'500}; + +/** + * 64-byte transactions are invalid (BIP 54) due to serious flaws in the Merkle tree algorithm + * that make it so that such transactions may be re-interpreted as inner tree nodes. + */ +static constexpr unsigned int INVALID_TX_NONWITNESS_SIZE{64}; #endif // BITCOIN_CONSENSUS_CONSENSUS_H diff --git a/src/consensus/params.h b/src/consensus/params.h index 7f56729455a8..e33bce3e95e9 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -36,6 +36,7 @@ constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_ enum DeploymentPos : uint16_t { DEPLOYMENT_TESTDUMMY, + DEPLOYMENT_CONSENSUSCLEANUP, // Deployment of BIP 54 // NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp // Removing an entry may require bumping MinBIP9WarningHeight. MAX_VERSION_BITS_DEPLOYMENTS diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 4efed70fd411..0c0ab2393c29 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -161,7 +161,33 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i return nSigOps; } -bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee) +bool Consensus::CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs) +{ + Assert(!tx.IsCoinBase()); + + unsigned int sigops{0}; + for (const auto& txin: tx.vin) { + const auto& prev_txo{inputs.AccessCoin(txin.prevout).out}; + + // Unlike the existing block wide sigop limit which counts sigops present in the block + // itself (including the scriptPubKey which is not executed until spending later), BIP54 + // counts sigops in the block where they are potentially executed (only). + // This means sigops in the spent scriptPubKey count toward the limit. + // `fAccurate` means correctly accounting sigops for CHECKMULTISIGs(VERIFY) with 16 pubkeys + // or fewer. This method of accounting was introduced by BIP16, and BIP54 reuses it. + // The GetSigOpCount call on the previous scriptPubKey counts both bare and P2SH sigops. + sigops += txin.scriptSig.GetSigOpCount(/*fAccurate=*/true); + sigops += prev_txo.scriptPubKey.GetSigOpCount(txin.scriptSig); + + if (sigops > MAX_TX_BIP54_SIGOPS) { + return false; + } + } + + return true; +} + +bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee, bool enforce_bip54) { // are the actual inputs available? if (!inputs.HaveInputs(tx)) { @@ -169,6 +195,10 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, strprintf("%s: inputs missing/spent", __func__)); } + if (enforce_bip54 && !Consensus::CheckSigopsBIP54(tx, inputs)) { + return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-legacy-sigops", "too many legacy sigops (BIP54)"); + } + CAmount nValueIn = 0; for (unsigned int i = 0; i < tx.vin.size(); ++i) { const COutPoint &prevout = tx.vin[i].prevout; diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h index ed44d435c1b9..6657373fc5a2 100644 --- a/src/consensus/tx_verify.h +++ b/src/consensus/tx_verify.h @@ -19,13 +19,19 @@ class TxValidationState; /** Transaction validation functions */ namespace Consensus { +/** + * Check the total number of non-witness sigops across the whole transaction, as per BIP54. + */ +bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs); + /** * Check whether all inputs of this transaction are valid (no double spends and amounts) * This does not modify the UTXO set. This does not check scripts and sigs. * @param[out] txfee Set to the transaction fee if successful. + * @param[in] enforce_bip54 Whether to perform the BIP54 sigops check. * Preconditions: tx.IsCoinBase() is false. */ -[[nodiscard]] bool CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee); +[[nodiscard]] bool CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee, bool enforce_bip54); } // namespace Consensus /** Auxiliary functions for transaction validation (ideally should not be exposed) */ diff --git a/src/deploymentinfo.cpp b/src/deploymentinfo.cpp index 551982b23ae7..69076a3040b2 100644 --- a/src/deploymentinfo.cpp +++ b/src/deploymentinfo.cpp @@ -13,6 +13,10 @@ const std::array Versi .name = "testdummy", .gbt_optional_rule = true, }, + VBDeploymentInfo{ + .name = "consensuscleanup", + .gbt_optional_rule = false, + }, }; std::string DeploymentName(Consensus::BuriedDeployment dep) diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp index 352434dae51c..5fe6f94743e2 100644 --- a/src/kernel/chainparams.cpp +++ b/src/kernel/chainparams.cpp @@ -136,6 +136,11 @@ class CMainParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90% consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; + // Deployment of the Consensus Cleanup (BIP 54) + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].bit = 3; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; + ApplyDeploymentOptions(opts.dep_opts); consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000001128750f82f4c366153a3a030"}; @@ -260,6 +265,11 @@ class CTestNetParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75% consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; + // Deployment of the Consensus Cleanup (BIP 54) + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].bit = 3; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; + ApplyDeploymentOptions(opts.dep_opts); consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000017dde1c649f3708d14b6"}; @@ -362,6 +372,11 @@ class CTestNet4Params : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1512; // 75% consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; + // Deployment of the Consensus Cleanup (BIP 54) + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].bit = 3; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; + ApplyDeploymentOptions(opts.dep_opts); consensus.nMinimumChainWork = uint256{"0000000000000000000000000000000000000000000009a0fe15d0177d086304"}; @@ -507,6 +522,11 @@ class SigNetParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 1815; // 90% consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 2016; + // Deployment of the Consensus Cleanup (BIP 54) + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].bit = 3; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; + ApplyDeploymentOptions(options.dep_opts); // message start is defined as the first 4 bytes of the sha256d of the block script @@ -591,6 +611,14 @@ class CRegTestParams : public CChainParams consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].threshold = 108; // 75% consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].period = 144; // Faster than normal for regtest (144 instead of 2016) + // Deployment of the Consensus Cleanup (BIP 54) + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].bit = 3; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].min_activation_height = 0; // No activation delay + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].threshold = 108; // 75% + consensus.vDeployments[Consensus::DEPLOYMENT_CONSENSUSCLEANUP].period = 144; + consensus.nMinimumChainWork = uint256{}; consensus.defaultAssumeValid = uint256{}; diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 06611a4a2f42..723e38be6791 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -59,10 +59,10 @@ int64_t GetMinimumTime(const CBlockIndex* pindexPrev, const int64_t difficulty_a int64_t min_time{pindexPrev->GetMedianTimePast() + 1}; // Height of block to be mined. const int height{pindexPrev->nHeight + 1}; - // Account for BIP94 timewarp rule on all networks. This makes future - // activation safer. + // Account for BIP94 timewarp rule on all networks. This makes BIP54 + // activation safer since BIP94 sets a tighter bound. if (height % difficulty_adjustment_interval == 0) { - min_time = std::max(min_time, pindexPrev->GetBlockTime() - MAX_TIMEWARP); + min_time = std::max(min_time, pindexPrev->GetBlockTime() - MAX_TIMEWARP_TESTNET4); } return min_time; } diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 83ceb63cbcd7..d3739f43db27 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -164,35 +165,6 @@ bool IsStandardTx(const CTransaction& tx, const std::optional& max_dat return true; } -/** - * Check the total number of non-witness sigops across the whole transaction, as per BIP54. - */ -static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inputs) -{ - Assert(!tx.IsCoinBase()); - - unsigned int sigops{0}; - for (const auto& txin: tx.vin) { - const auto& prev_txo{inputs.AccessCoin(txin.prevout).out}; - - // Unlike the existing block wide sigop limit which counts sigops present in the block - // itself (including the scriptPubKey which is not executed until spending later), BIP54 - // counts sigops in the block where they are potentially executed (only). - // This means sigops in the spent scriptPubKey count toward the limit. - // `fAccurate` means correctly accounting sigops for CHECKMULTISIGs(VERIFY) with 16 pubkeys - // or fewer. This method of accounting was introduced by BIP16, and BIP54 reuses it. - // The GetSigOpCount call on the previous scriptPubKey counts both bare and P2SH sigops. - sigops += txin.scriptSig.GetSigOpCount(/*fAccurate=*/true); - sigops += prev_txo.scriptPubKey.GetSigOpCount(txin.scriptSig); - - if (sigops > MAX_TX_LEGACY_SIGOPS) { - return false; - } - } - - return true; -} - /** * Check transaction inputs. * @@ -208,8 +180,6 @@ static bool CheckSigopsBIP54(const CTransaction& tx, const CCoinsViewCache& inpu * as potential new upgrade hooks. * * Note that only the non-witness portion of the transaction is checked here. - * - * We also check the total number of non-witness sigops across the whole transaction, as per BIP54. */ TxValidationState ValidateInputsStandardness(const CTransaction& tx, const CCoinsViewCache& mapInputs) { @@ -218,11 +188,6 @@ TxValidationState ValidateInputsStandardness(const CTransaction& tx, const CCoin return state; // Coinbases don't use vin normally } - if (!CheckSigopsBIP54(tx, mapInputs)) { - state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs", "non-witness sigops exceed bip54 limit"); - return state; - } - for (unsigned int i = 0; i < tx.vin.size(); i++) { const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out; diff --git a/src/policy/policy.h b/src/policy/policy.h index 13bcf4cef750..48b12c7ffde2 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -36,14 +36,13 @@ static constexpr unsigned int MINIMUM_BLOCK_RESERVED_WEIGHT{2000}; static constexpr unsigned int DEFAULT_BLOCK_MIN_TX_FEE{1}; /** The maximum weight for transactions we're willing to relay/mine */ static constexpr int32_t MAX_STANDARD_TX_WEIGHT{400000}; -/** The minimum non-witness size for transactions we're willing to relay/mine: one larger than 64 */ +/** The minimum non-witness size for transactions we're willing to relay/mine: one larger than 64. + * BIP54 makes 64-byte transactions invalid, but smaller than that are still non-standard. */ static constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE{65}; /** Maximum number of signature check operations in an IsStandard() P2SH script */ static constexpr unsigned int MAX_P2SH_SIGOPS{15}; /** The maximum number of sigops we're willing to relay/mine in a single tx */ static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5}; -/** The maximum number of potentially executed legacy signature operations in a single standard tx */ -static constexpr unsigned int MAX_TX_LEGACY_SIGOPS{2'500}; /** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/ static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{100}; /** Default for -bytespersigop */ diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f3e1330b4494..cc9214a4da88 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1508,6 +1508,7 @@ UniValue DeploymentInfo(const CBlockIndex* blockindex, const ChainstateManager& SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CSV); SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_SEGWIT); SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_TESTDUMMY); + SoftForkDescPushBack(blockindex, softforks, chainman, Consensus::DEPLOYMENT_CONSENSUSCLEANUP); return softforks; } } // anon namespace diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index c9b6de0baca8..793fa4a87cf7 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(test_bitcoin bech32_tests.cpp bip32_tests.cpp bip324_tests.cpp + bip54_tests.cpp blockchain_tests.cpp blockencodings_tests.cpp blockfilter_index_tests.cpp @@ -144,6 +145,8 @@ include(TargetDataSources) target_json_data_sources(test_bitcoin data/base58_encode_decode.json data/bip341_wallet_vectors.json + data/bip54_coinbases.json + data/bip54_timestamps.json data/blockfilters.json data/key_io_invalid.json data/key_io_valid.json diff --git a/src/test/bip54_tests.cpp b/src/test/bip54_tests.cpp new file mode 100644 index 000000000000..f7311fe0235a --- /dev/null +++ b/src/test/bip54_tests.cpp @@ -0,0 +1,1609 @@ +// Copyright (c) The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include