diff options
author | MarcoFalke <falke.marco@gmail.com> | 2020-11-02 10:12:00 +0100 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2020-11-02 10:12:06 +0100 |
commit | c5ec0367d718544caa3a1578d6c730fc92ee4e94 (patch) | |
tree | 04509a4643f08cca98bdc10c35ccd209d2e19109 /src | |
parent | 867dbeba5f91be15ca0d4a7303a71957ff9a37ad (diff) | |
parent | 3d0556d41087f945ed0a47a5d770076ad42ce432 (diff) | |
download | bitcoin-c5ec0367d718544caa3a1578d6c730fc92ee4e94.tar.xz |
Merge #20165: Only relay Taproot spends if next block has it active
3d0556d41087f945ed0a47a5d770076ad42ce432 Increase feature_taproot inactive test coverage (Pieter Wuille)
525cbd425e2f6a1dbd0febc53d7ada22cec4661f Only relay Taproot spends if next block has it active (Pieter Wuille)
Pull request description:
There should be no change to mempool transaction behavior for witness v1 transactions as long as no activation is defined. Until that point, we should treat the consensus rules as under debate, and for soft-fork safety, that means spends should be treated as non-standard.
It's possible to go further: don't relay them unless the consensus rules are actually active for the next block. This extends non-relay to the period where a deployment is defined, started, locked in, or failed. I see no downsides to this, and the code change is very simple.
ACKs for top commit:
Sjors:
utACK 3d0556d41087f945ed0a47a5d770076ad42ce432
MarcoFalke:
review ACK 3d0556d41087f945ed0a47a5d770076ad42ce432 🏓
jnewbery:
utACK 3d0556d41087f945ed0a47a5d770076ad42ce432
Tree-SHA512: ca625a2981716b4b44e8f3722718fd25fd04e25bf3ca1684924b8974fca49f7c1d438fdd9dcdfbc091a442002e20d441d42c41a0e2096e74a61068da6c60267a
Diffstat (limited to 'src')
-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/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 |
8 files changed, 19 insertions, 11 deletions
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/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"); } |