diff options
-rw-r--r-- | doc/release-process.md | 11 | ||||
-rw-r--r-- | src/bench/ccoins_caching.cpp | 2 | ||||
-rw-r--r-- | src/policy/policy.cpp | 5 | ||||
-rw-r--r-- | src/policy/policy.h | 5 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 4 | ||||
-rw-r--r-- | src/test/fuzz/coins_view.cpp | 3 | ||||
-rw-r--r-- | src/test/fuzz/transaction.cpp | 3 | ||||
-rw-r--r-- | src/test/script_p2sh_tests.cpp | 6 | ||||
-rw-r--r-- | src/test/transaction_tests.cpp | 2 | ||||
-rw-r--r-- | src/validation.cpp | 4 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 1 | ||||
-rwxr-xr-x | test/functional/feature_taproot.py | 14 |
12 files changed, 36 insertions, 24 deletions
diff --git a/doc/release-process.md b/doc/release-process.md index a61b67c35f..8191c3034d 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -27,11 +27,10 @@ Release Process #### Before branch-off * Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example. -* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-m_assumed_blockchain_size-and-m_assumed_chain_state_size) for information on how to calculate them). -* Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. Use the output of the RPC `getchaintxstats`, see - [this pull request](https://github.com/bitcoin/bitcoin/pull/17002) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_last_block_hash>` with the `window_block_count` and `window_last_block_hash` from your output. -* Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc. -* Update `src/chainparams.cpp` defaultAssumeValid with information from the getblockhash rpc. +* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-assumed-blockchain-and-chain-state-size) for information on how to calculate them). +* Update [`src/chainparams.cpp`](/src/chainparams.cpp) chainTxData with statistics about the transaction count and rate. Use the output of the `getchaintxstats` RPC, see + [this pull request](https://github.com/bitcoin/bitcoin/pull/20263) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_final_block_hash>` with the `window_block_count` and `window_final_block_hash` from your output. +* Update `src/chainparams.cpp` nMinimumChainWork and defaultAssumeValid (and the block height comment) with information from the `getblockheader` (and `getblockhash`) RPCs. - The selected value must not be orphaned so it may be useful to set the value two blocks back from the tip. - Testnet should be set some tens of thousands back from the tip due to reorgs there. - This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect @@ -371,7 +370,7 @@ bitcoin.org (see below for bitcoin.org update instructions). ### Additional information -#### How to calculate `m_assumed_blockchain_size` and `m_assumed_chain_state_size` +#### <a name="how-to-calculate-assumed-blockchain-and-chain-state-size"></a>How to calculate `m_assumed_blockchain_size` and `m_assumed_chain_state_size` Both variables are used as a guideline for how much space the user needs on their drive in total, not just strictly for the blockchain. Note that all values should be taken from a **fully synced** node and have an overhead of 5-10% added on top of its base value. diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp index 116de98b14..d5275b0b76 100644 --- a/src/bench/ccoins_caching.cpp +++ b/src/bench/ccoins_caching.cpp @@ -45,7 +45,7 @@ static void CCoinsCaching(benchmark::Bench& bench) // Benchmark. const CTransaction tx_1(t1); bench.run([&] { - bool success = AreInputsStandard(tx_1, coins); + bool success = AreInputsStandard(tx_1, coins, false); assert(success); }); ECC_Stop(); diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 69f2b456f1..91997aa883 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -155,7 +155,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR * * Note that only the non-witness portion of the transaction is checked here. */ -bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) +bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, bool taproot_active) { if (tx.IsCoinBase()) return true; // Coinbases don't use vin normally @@ -183,6 +183,9 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) { return false; } + } else if (whichType == TxoutType::WITNESS_V1_TAPROOT) { + // Don't allow Taproot spends unless Taproot is active. + if (!taproot_active) return false; } } diff --git a/src/policy/policy.h b/src/policy/policy.h index 51d67b9390..8090dff4c6 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -95,10 +95,11 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType); bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason); /** * Check for standard transaction types - * @param[in] mapInputs Map of previous transactions that have outputs we're spending + * @param[in] mapInputs Map of previous transactions that have outputs we're spending + * @param[in] taproot_active Whether or taproot consensus rules are active (used to decide whether spends of them are permitted) * @return True if all inputs (scriptSigs) use only standard transaction forms */ -bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); +bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, bool taproot_active); /** * Check if the transaction is over standard P2WSH resources limit: * 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a162c1ee70..392073d047 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1816,12 +1816,12 @@ static RPCHelpMan getblockstats() {RPCResult::Type::NUM, "outs", "The number of outputs"}, {RPCResult::Type::NUM, "subsidy", "The block subsidy"}, {RPCResult::Type::NUM, "swtotal_size", "Total size of all segwit transactions"}, - {RPCResult::Type::NUM, "swtotal_weight", "Total weight of all segwit transactions divided by segwit scale factor (4)"}, + {RPCResult::Type::NUM, "swtotal_weight", "Total weight of all segwit transactions"}, {RPCResult::Type::NUM, "swtxs", "The number of segwit transactions"}, {RPCResult::Type::NUM, "time", "The block time"}, {RPCResult::Type::NUM, "total_out", "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"}, {RPCResult::Type::NUM, "total_size", "Total size of all non-coinbase transactions"}, - {RPCResult::Type::NUM, "total_weight", "Total weight of all non-coinbase transactions divided by segwit scale factor (4)"}, + {RPCResult::Type::NUM, "total_weight", "Total weight of all non-coinbase transactions"}, {RPCResult::Type::NUM, "totalfee", "The fee total"}, {RPCResult::Type::NUM, "txs", "The number of transactions (including coinbase)"}, {RPCResult::Type::NUM, "utxo_increase", "The increase/decrease in the number of unspent outputs"}, diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index c186bef7ae..ac034809b0 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -229,7 +229,8 @@ void test_one_input(const std::vector<uint8_t>& buffer) break; } case 1: { - (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache); + (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache, false); + (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache, true); break; } case 2: { diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index d6deb7fc3d..4f972dea1c 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -95,7 +95,8 @@ void test_one_input(const std::vector<uint8_t>& buffer) CCoinsView coins_view; const CCoinsViewCache coins_view_cache(&coins_view); - (void)AreInputsStandard(tx, coins_view_cache); + (void)AreInputsStandard(tx, coins_view_cache, false); + (void)AreInputsStandard(tx, coins_view_cache, true); (void)IsWitnessStandard(tx, coins_view_cache); UniValue u(UniValue::VOBJ); diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index f6824a4e5e..856ec6346d 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txTo.vin[3].scriptSig << OP_11 << OP_11 << std::vector<unsigned char>(oneAndTwo.begin(), oneAndTwo.end()); txTo.vin[4].scriptSig << std::vector<unsigned char>(fifteenSigops.begin(), fifteenSigops.end()); - BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins)); + BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins, false)); // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4] BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U); @@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txToNonStd1.vin[0].prevout.hash = txFrom.GetHash(); txToNonStd1.vin[0].scriptSig << std::vector<unsigned char>(sixteenSigops.begin(), sixteenSigops.end()); - BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins)); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins, false)); BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U); CMutableTransaction txToNonStd2; @@ -368,7 +368,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txToNonStd2.vin[0].prevout.hash = txFrom.GetHash(); txToNonStd2.vin[0].scriptSig << std::vector<unsigned char>(twentySigops.begin(), twentySigops.end()); - BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins)); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins, false)); BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U); } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index b7ee280336..1f520074b1 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -305,7 +305,7 @@ BOOST_AUTO_TEST_CASE(test_Get) t1.vout[0].nValue = 90*CENT; t1.vout[0].scriptPubKey << OP_1; - BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins)); + BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins, false)); } static void CreateCreditAndSpend(const FillableSigningProvider& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true) diff --git a/src/validation.cpp b/src/validation.cpp index 423b93479a..8241cb159f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -690,7 +690,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) } // Check for non-standard pay-to-script-hash in inputs - if (fRequireStandard && !AreInputsStandard(tx, m_view)) { + const auto& params = args.m_chainparams.GetConsensus(); + auto taproot_state = VersionBitsState(::ChainActive().Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache); + if (fRequireStandard && !AreInputsStandard(tx, m_view, taproot_state == ThresholdState::ACTIVE)) { return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs"); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6b7d05fdf3..d1cde6aa89 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -100,6 +100,7 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet) if (i != vpwallets.end()) return false; vpwallets.push_back(wallet); wallet->ConnectScriptPubKeyManNotifiers(); + wallet->NotifyCanGetAddressesChanged(); return true; } diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py index 7b534c1c2f..3e47e24a3b 100755 --- a/test/functional/feature_taproot.py +++ b/test/functional/feature_taproot.py @@ -1129,13 +1129,13 @@ def spenders_taproot_inactive(): ] tap = taproot_construct(pub, scripts) - # Test that keypath spending is valid & standard if compliant, but valid and nonstandard otherwise. - add_spender(spenders, "inactive/keypath_valid", key=sec, tap=tap) + # Test that keypath spending is valid & non-standard, regardless of validity. + add_spender(spenders, "inactive/keypath_valid", key=sec, tap=tap, standard=False) add_spender(spenders, "inactive/keypath_invalidsig", key=sec, tap=tap, standard=False, sighash=bitflipper(default_sighash)) add_spender(spenders, "inactive/keypath_empty", key=sec, tap=tap, standard=False, witness=[]) - # Same for scriptpath spending (but using future features like annex, leaf versions, or OP_SUCCESS is nonstandard). - add_spender(spenders, "inactive/scriptpath_valid", key=sec, tap=tap, leaf="pk", inputs=[getter("sign")]) + # Same for scriptpath spending (and features like annex, leaf versions, or OP_SUCCESS don't change this) + add_spender(spenders, "inactive/scriptpath_valid", key=sec, tap=tap, leaf="pk", standard=False, inputs=[getter("sign")]) add_spender(spenders, "inactive/scriptpath_invalidsig", key=sec, tap=tap, leaf="pk", standard=False, inputs=[getter("sign")], sighash=bitflipper(default_sighash)) add_spender(spenders, "inactive/scriptpath_invalidcb", key=sec, tap=tap, leaf="pk", standard=False, inputs=[getter("sign")], controlblock=bitflipper(default_controlblock)) add_spender(spenders, "inactive/scriptpath_valid_unkleaf", key=sec, tap=tap, leaf="future_leaf", standard=False, inputs=[getter("sign")]) @@ -1451,7 +1451,11 @@ class TaprootTest(BitcoinTestFramework): # Pre-taproot activation tests. self.log.info("Pre-activation tests...") - self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[1, 2, 2, 2, 2, 3]) + # Run each test twice; once in isolation, and once combined with others. Testing in isolation + # means that the standardness is verified in every test (as combined transactions are only standard + # when all their inputs are standard). + self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[1]) + self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[2, 3]) if __name__ == '__main__': |