diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 43994ff41..4109dc8dd 100755 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -289,14 +289,18 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= proxy.url = url # store URL on proxy for info return proxy + def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None): """ Start multiple pastelds, return RPC connections to them """ - if extra_args is None: extra_args = [ None for i in range(num_nodes) ] - if binary is None: binary = [ None for i in range(num_nodes) ] + if extra_args is None: + extra_args = [ None for i in range(num_nodes) ] + if binary is None: + binary = [ None for i in range(num_nodes) ] return [ start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]) for i in range(num_nodes) ] + def log_filename(dirname, n_node, logname): return os.path.join(dirname, "node"+str(n_node), "regtest", logname) diff --git a/qa/rpc-tests/wallet_changeindicator.py b/qa/rpc-tests/wallet_changeindicator.py index 52c2d0c25..44cababfe 100755 --- a/qa/rpc-tests/wallet_changeindicator.py +++ b/qa/rpc-tests/wallet_changeindicator.py @@ -1,20 +1,34 @@ #!/usr/bin/env python3 # Copyright (c) 2018 The Zcash developers +# Copyright (c) 2018-2022 The Pastel Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, assert_true, assert_false, wait_and_assert_operationid_status +from test_framework.util import ( + assert_equal, + assert_true, + assert_false, + wait_and_assert_operationid_status, + start_nodes +) from decimal import Decimal class WalletChangeIndicatorTest (BitcoinTestFramework): + def setup_nodes(self): + return start_nodes(self.num_nodes, self.options.tmpdir, + extra_args=[['-debug=net']] * self.num_nodes) + # Tests def run_test(self): taddr = self.nodes[1].getnewaddress() zaddr1 = self.nodes[1].z_getnewaddress() zaddr2 = self.nodes[1].z_getnewaddress() + # generate one block to make sure initial block download (IBD) mode is reset + self.generate_and_sync_inc(1) + self.nodes[0].sendtoaddress(taddr, Decimal('1.0')) self.generate_and_sync_inc(1) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 913292a74..4bfe60cd3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -312,11 +312,13 @@ static CBlock CreateRegtestGenesisBlock() const arith_uint256 maxUint = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); -class CMainParams : public CChainParams { +class CMainParams : public CChainParams +{ public: - CMainParams() { + CMainParams() : + CChainParams(ChainNetwork::MAIN) + { strNetworkID = "main"; - network = CBaseChainParams::Network::MAIN; strCurrencyUnits = "PSL"; bip44CoinType = 133; // As registered in https://github.com/patoshilabs/slips/blob/master/slip-0044.md consensus.nSubsidyHalvingInterval = 840'000; @@ -418,11 +420,13 @@ class CMainParams : public CChainParams { /** * Testnet (v3) */ -class CTestNetParams : public CChainParams { +class CTestNetParams : public CChainParams +{ public: - CTestNetParams() { + CTestNetParams() : + CChainParams(ChainNetwork::TESTNET) + { strNetworkID = "test"; - network = CBaseChainParams::Network::TESTNET; strCurrencyUnits = "LSP"; bip44CoinType = 1; consensus.nSubsidyHalvingInterval = 840'000; @@ -519,12 +523,13 @@ class CTestNetParams : public CChainParams { /** * Regression test */ -class CRegTestParams : public CChainParams { +class CRegTestParams : public CChainParams +{ public: - CRegTestParams() + CRegTestParams() : + CChainParams(ChainNetwork::REGTEST) { strNetworkID = "regtest"; - network = CBaseChainParams::Network::REGTEST; strCurrencyUnits = "REG"; bip44CoinType = 1; consensus.nSubsidyHalvingInterval = 150; @@ -626,20 +631,20 @@ const CChainParams &Params() * \param network - MAIN, TESTNET or REGTEST * \return unique_ptr with chain parameters */ -std::unique_ptr CreateChainParams(const CBaseChainParams::Network network) +std::unique_ptr CreateChainParams(const ChainNetwork network) { std::unique_ptr ChainParams; switch (network) { - case CBaseChainParams::Network::MAIN: + case ChainNetwork::MAIN: ChainParams = std::make_unique(); break; - case CBaseChainParams::Network::TESTNET: + case ChainNetwork::TESTNET: ChainParams = std::make_unique(); break; - case CBaseChainParams::Network::REGTEST: + case ChainNetwork::REGTEST: ChainParams = std::make_unique(); break; @@ -656,7 +661,7 @@ std::unique_ptr CreateChainParams(const CBaseChainParams::Ne * * \param network - blockchain network type (MAIN, TESTNET or REGTEST) */ -void SelectParams(const CBaseChainParams::Network network) +void SelectParams(const ChainNetwork network) { SelectBaseParams(network); globalChainParams = CreateChainParams(network); @@ -664,8 +669,8 @@ void SelectParams(const CBaseChainParams::Network network) bool SelectParamsFromCommandLine() { - CBaseChainParams::Network network = NetworkIdFromCommandLine(); - if (network == CBaseChainParams::Network::MAX_NETWORK_TYPES) + const ChainNetwork network = NetworkIdFromCommandLine(); + if (network == ChainNetwork::MAX_NETWORK_TYPES) return false; SelectParams(network); diff --git a/src/chainparams.h b/src/chainparams.h index f077defc8..abb35e5fb 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -91,9 +91,15 @@ class CChainParams : public CBaseKeyConstants const std::vector& FixedSeeds() const noexcept { return vFixedSeeds; } const CCheckpointData& Checkpoints() const noexcept { return checkpointData; } - bool IsMainNet() const noexcept { return network == CBaseChainParams::Network::MAIN; } - bool IsTestNet() const noexcept { return network == CBaseChainParams::Network::TESTNET; } - bool IsRegTest() const noexcept { return network == CBaseChainParams::Network::REGTEST; } + CChainParams(ChainNetwork network) : + consensus(network) + { + memset(&pchMessageStart, 0, sizeof(pchMessageStart)); + } + + bool IsMainNet() const noexcept { return consensus.network == ChainNetwork::MAIN; } + bool IsTestNet() const noexcept { return consensus.network == ChainNetwork::TESTNET; } + bool IsRegTest() const noexcept { return consensus.network == ChainNetwork::REGTEST; } void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, const uint32_t nActivationHeight) { @@ -102,11 +108,6 @@ class CChainParams : public CBaseKeyConstants } protected: - CChainParams() - { - memset(&pchMessageStart, 0, sizeof(pchMessageStart)); - } - Consensus::Params consensus; CMessageHeader::MessageStartChars pchMessageStart; //! Raw pub key bytes for the broadcast alert signing key. @@ -115,7 +116,6 @@ class CChainParams : public CBaseKeyConstants uint64_t nPruneAfterHeight = 0; std::vector vSeeds; std::string strNetworkID; - CBaseChainParams::Network network = CBaseChainParams::Network::MAIN; std::string strCurrencyUnits; uint32_t bip44CoinType = 0; CBlock genesis; @@ -135,10 +135,10 @@ class CChainParams : public CBaseKeyConstants const CChainParams &Params(); // Create blockchain parameters based on network type. -std::unique_ptr CreateChainParams(const CBaseChainParams::Network network); +std::unique_ptr CreateChainParams(const ChainNetwork network); /** Sets the params returned by Params() to those for the given network. */ -void SelectParams(const CBaseChainParams::Network network); +void SelectParams(const ChainNetwork network); /** * Looks for -regtest or -testnet and then calls SelectParams as appropriate. diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 5fc947c0d..bda118ff0 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -1,14 +1,15 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018-2022 The Pastel Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "chainparamsbase.h" -#include "port_config.h" -#include "util.h" +// file COPYING or https://www.opensource.org/licenses/mit-license.php. #include +#include +#include +#include + /** * Main network */ @@ -73,20 +74,20 @@ const CBaseChainParams& BaseParams() * \param network - blockchain type (MAIN, TESTNET or REGTEST) * \return std::unique_ptr */ -std::unique_ptr CreateBaseChainParams(const CBaseChainParams::Network network) +std::unique_ptr CreateBaseChainParams(const ChainNetwork network) { std::unique_ptr BaseChainParams; switch (network) { - case CBaseChainParams::Network::MAIN: + case ChainNetwork::MAIN: BaseChainParams = std::make_unique(); break; - case CBaseChainParams::Network::TESTNET: + case ChainNetwork::TESTNET: BaseChainParams = std::make_unique(); break; - case CBaseChainParams::Network::REGTEST: + case ChainNetwork::REGTEST: BaseChainParams = std::make_unique(); break; @@ -99,29 +100,29 @@ std::unique_ptr CreateBaseChainParams(const CBaseChainParams:: } /** Sets the params returned by Params() to those for the given network. */ -void SelectBaseParams(const CBaseChainParams::Network network) +void SelectBaseParams(const ChainNetwork network) { globalChainBaseParams = CreateBaseChainParams(network); } -CBaseChainParams::Network NetworkIdFromCommandLine() +ChainNetwork NetworkIdFromCommandLine() { - bool fRegTest = GetBoolArg("-regtest", false); - bool fTestNet = GetBoolArg("-testnet", false); + const bool fRegTest = GetBoolArg("-regtest", false); + const bool fTestNet = GetBoolArg("-testnet", false); if (fTestNet && fRegTest) - return CBaseChainParams::Network::MAX_NETWORK_TYPES; + return ChainNetwork::MAX_NETWORK_TYPES; if (fRegTest) - return CBaseChainParams::Network::REGTEST; + return ChainNetwork::REGTEST; if (fTestNet) - return CBaseChainParams::Network::TESTNET; - return CBaseChainParams::Network::MAIN; + return ChainNetwork::TESTNET; + return ChainNetwork::MAIN; } bool SelectBaseParamsFromCommandLine() { - CBaseChainParams::Network network = NetworkIdFromCommandLine(); - if (network == CBaseChainParams::Network::MAX_NETWORK_TYPES) + const ChainNetwork network = NetworkIdFromCommandLine(); + if (network == ChainNetwork::MAX_NETWORK_TYPES) return false; SelectBaseParams(network); diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 9837fabd1..ed09164ff 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -6,6 +6,8 @@ #include #include +#include + /** * CBaseChainParams defines the base parameters (shared between pastel-cli and pasteld) * of a given instance of the Bitcoin system. @@ -13,15 +15,6 @@ class CBaseChainParams { public: - enum class Network - { - MAIN, - TESTNET, - REGTEST, - - MAX_NETWORK_TYPES - }; - const std::string& DataDir() const noexcept { return strDataDir; } int RPCPort() const noexcept { return nRPCPort; } @@ -36,10 +29,10 @@ class CBaseChainParams * Creates and returns a std::unique_ptr. This won't change after app * startup, except for unit tests. */ -std::unique_ptr CreateBaseChainParams(const CBaseChainParams::Network network); +std::unique_ptr CreateBaseChainParams(const ChainNetwork network); /** Sets the params returned by Params() to those for the given network. */ -void SelectBaseParams(const CBaseChainParams::Network network); +void SelectBaseParams(const ChainNetwork network); /** * Return the currently selected parameters. This won't change after app @@ -51,7 +44,7 @@ const CBaseChainParams& BaseParams(); * Looks for -regtest or -testnet and returns the appropriate Network ID. * Returns MAX_NETWORK_TYPES if an invalid combination is given. */ -CBaseChainParams::Network NetworkIdFromCommandLine(); +ChainNetwork NetworkIdFromCommandLine(); /** * Calls NetworkIdFromCommandLine() and then calls SelectParams as appropriate. diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 6f6791414..d2875c8f0 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -5,6 +5,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. +enum class ChainNetwork +{ + MAIN = 0, + TESTNET, + REGTEST, + + MAX_NETWORK_TYPES +}; + /** The minimum allowed block version (network rule) */ constexpr int32_t MIN_BLOCK_VERSION = 4; /** The minimum allowed transaction version (network rule) */ diff --git a/src/consensus/params.h b/src/consensus/params.h index a07c8277f..f04b492d2 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace Consensus { @@ -94,7 +95,11 @@ struct Params int64_t nMaxGovernanceAmount; // The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks) uint32_t nNetworkUpgradePeerPreferenceBlockPeriod = 0; + ChainNetwork network; + Params(const ChainNetwork aNetwork) : + network(aNetwork) + {} /** * Add network upgrade. @@ -115,5 +120,6 @@ struct Params const auto nUpgradeIndex = to_integral_type(idx); vUpgrades[nUpgradeIndex].nActivationHeight = nActivationHeight; } + }; } // namespace Consensus diff --git a/src/gtest/pastel_gtest_main.cpp b/src/gtest/pastel_gtest_main.cpp index d46bf7746..63b4ae852 100644 --- a/src/gtest/pastel_gtest_main.cpp +++ b/src/gtest/pastel_gtest_main.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2021-2022 The Pastel developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. + #include #include #include @@ -167,7 +168,7 @@ void CPastelTest_Environment::ClearTempDataDir() * \param network - main, regtest or testnet * \return if true - regtest initialized successfully */ -void CPastelTest_Environment::InitializeChainTest(const CBaseChainParams::Network network) +void CPastelTest_Environment::InitializeChainTest(const ChainNetwork network) { if (m_TestNetwork.has_value()) { @@ -211,7 +212,7 @@ void CPastelTest_Environment::InitializeChainTest(const CBaseChainParams::Networ void CPastelTest_Environment::InitializeRegTest() { - InitializeChainTest(CBaseChainParams::Network::REGTEST); + InitializeChainTest(ChainNetwork::REGTEST); } void CPastelTest_Environment::FinalizeChainTest() diff --git a/src/gtest/pastel_gtest_main.h b/src/gtest/pastel_gtest_main.h index 3b47dde28..c5173c6c9 100644 --- a/src/gtest/pastel_gtest_main.h +++ b/src/gtest/pastel_gtest_main.h @@ -15,7 +15,7 @@ class CPastelTest_Environment : public ::testing::Environment CPastelTest_Environment() = default; // initialize given network for unittests - void InitializeChainTest(const CBaseChainParams::Network network); + void InitializeChainTest(const ChainNetwork network); // finalize test network void FinalizeChainTest(); @@ -34,7 +34,7 @@ class CPastelTest_Environment : public ::testing::Environment CCoinsViewDB* pcoinsdbview = nullptr; CServiceThreadGroup threadGroup; fs::path m_TempDataDir; // generated temp datadir - std::optional m_TestNetwork; + std::optional m_TestNetwork; void SetUp() override; void TearDown() override; diff --git a/src/gtest/pastel_gtest_utils.cpp b/src/gtest/pastel_gtest_utils.cpp index ed020d980..6bc44fc3c 100644 --- a/src/gtest/pastel_gtest_utils.cpp +++ b/src/gtest/pastel_gtest_utils.cpp @@ -6,6 +6,7 @@ #include #include +#include using namespace std; int GenZero(int n) @@ -56,3 +57,18 @@ std::string generateTempFileName(const char* szFileExt) auto file = fs::temp_directory_path() / fs::path(s); return file.string(); } + +// Sapling +const Consensus::Params& RegtestActivateSapling() +{ + SelectParams(ChainNetwork::REGTEST); + UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + return Params().GetConsensus(); +} + +void RegtestDeactivateSapling() +{ + UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); +} diff --git a/src/gtest/pastel_gtest_utils.h b/src/gtest/pastel_gtest_utils.h index c53288af8..80a39ffd1 100644 --- a/src/gtest/pastel_gtest_utils.h +++ b/src/gtest/pastel_gtest_utils.h @@ -4,6 +4,7 @@ // file COPYING or httpa://www.opensource.org/licenses/mit-license.php. #include +#include int GenZero(int n); int GenMax(int n); @@ -15,3 +16,6 @@ std::string generateRandomId(const size_t nLength); // this is for test purposes only - no need to use mkstemp function // or ensure that file is unique std::string generateTempFileName(const char* szFileExt = ".tmp"); + +const Consensus::Params& RegtestActivateSapling(); +void RegtestDeactivateSapling(); \ No newline at end of file diff --git a/src/gtest/test_alert.cpp b/src/gtest/test_alert.cpp index 20dee5385..c63021b09 100644 --- a/src/gtest/test_alert.cpp +++ b/src/gtest/test_alert.cpp @@ -270,7 +270,7 @@ struct ReadAlerts : public Test TEST_F(ReadAlerts, AlertApplies) { SetMockTime(11); - auto pChainParams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto pChainParams = CreateChainParams(ChainNetwork::MAIN); const auto& alertKey = pChainParams->AlertKey(); for (const auto& alert : alerts) @@ -312,7 +312,7 @@ TEST_F(ReadAlerts, AlertApplies) TEST_F(ReadAlerts, AlertNotify) { SetMockTime(11); - auto pChainParams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto pChainParams = CreateChainParams(ChainNetwork::MAIN); const auto& alertKey = pChainParams->AlertKey(); fs::path temp = GetTempPath() / @@ -353,7 +353,7 @@ TEST_F(ReadAlerts, AlertNotify) TEST_F(ReadAlerts, AlertDisablesRPC) { SetMockTime(11); - auto pChainParams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto pChainParams = CreateChainParams(ChainNetwork::MAIN); const auto& alertKey = pChainParams->AlertKey(); // Command should work before alerts @@ -381,7 +381,7 @@ TEST_F(ReadAlerts, PartitionAlert) // Test PartitionCheck CCriticalSection csDummy; CBlockIndex indexDummy[400]; - auto pChainParams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto pChainParams = CreateChainParams(ChainNetwork::MAIN); const auto& consensusParams = pChainParams->GetConsensus(); int64_t nPowTargetSpacing = consensusParams.nPowTargetSpacing; diff --git a/src/gtest/test_base58.cpp b/src/gtest/test_base58.cpp index 483f116af..dd77fd7c7 100644 --- a/src/gtest/test_base58.cpp +++ b/src/gtest/test_base58.cpp @@ -75,7 +75,7 @@ TEST(base58, keys_valid_parse) CTxDestination destination; string strTest, sKeyError, exp_base58string; v_uint8 exp_payload; - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); for (const auto& test : tests.getValues()) { @@ -87,7 +87,7 @@ TEST(base58, keys_valid_parse) const UniValue& metadata = test[2].get_obj(); const bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); const bool bIsTestnet = find_value(metadata, "chain").get_str() == "testnet"; - SelectParams(bIsTestnet ? CBaseChainParams::Network::TESTNET : CBaseChainParams::Network::MAIN); + SelectParams(bIsTestnet ? ChainNetwork::TESTNET : ChainNetwork::MAIN); KeyIO keyIO(Params()); if (isPrivkey) { @@ -134,7 +134,7 @@ TEST(base58, keys_valid_gen) const UniValue& metadata = test[2].get_obj(); const bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); const bool bIsTestnet = find_value(metadata, "chain").get_str() == "testnet"; - SelectParams(bIsTestnet ? CBaseChainParams::Network::TESTNET : CBaseChainParams::Network::MAIN); + SelectParams(bIsTestnet ? ChainNetwork::TESTNET : ChainNetwork::MAIN); KeyIO keyIO(Params()); if (isPrivkey) { @@ -154,7 +154,7 @@ TEST(base58, keys_valid_gen) } } - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); } // Goal: check that base58 parsing code is robust against a variety of corrupted data @@ -165,7 +165,7 @@ TEST(base58, keys_invalid) CTxDestination destination; string strTest, sKeyError, exp_base58string; - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); KeyIO keyIO(Params()); for (const auto& test : tests.getValues()) { diff --git a/src/gtest/test_bip32.cpp b/src/gtest/test_bip32.cpp index 6626e8351..1ad9ff44d 100644 --- a/src/gtest/test_bip32.cpp +++ b/src/gtest/test_bip32.cpp @@ -47,14 +47,8 @@ class PTestBip32 : public TestWithParam public: static void SetUpTestSuite() { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); } - - void TearDown() - { - } - - }; TestVector test1 = diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index 111672088..d6d081ae8 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -1,13 +1,18 @@ +// Copyright (c) 2018-2022 The Pastel developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + #include -#include "main.h" -#include "key_io.h" -#include "zcash/Proof.hpp" -#include "clientversion.h" +#include +#include +#include +#include -TEST(CheckBlock, VersionTooLow) { - SelectParams(CBaseChainParams::Network::MAIN); +TEST(CheckBlock, VersionTooLow) +{ + SelectParams(ChainNetwork::MAIN); auto verifier = libzcash::ProofVerifier::Strict(); CBlock block; @@ -21,8 +26,9 @@ TEST(CheckBlock, VersionTooLow) { // Test that a Sprout tx with negative version is still rejected // by CheckBlock under Sprout consensus rules. -TEST(CheckBlock, BlockSproutRejectsBadVersion) { - SelectParams(CBaseChainParams::Network::MAIN); +TEST(CheckBlock, BlockSproutRejectsBadVersion) +{ + SelectParams(ChainNetwork::MAIN); const auto& chainparams = Params(); CMutableTransaction mtx; @@ -59,10 +65,11 @@ class ContextualCheckBlockTest : public ::testing::Test protected: void SetUp() override { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); } - void TearDown() override { + void TearDown() override + { // Revert to test default. No-op on mainnet params. UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -133,7 +140,6 @@ class ContextualCheckBlockTest : public ::testing::Test EXPECT_CALL(state, DoS(level, false, REJECT_INVALID, reason, false)); EXPECT_FALSE(ContextualCheckBlock(block, state, chainparams, &indexPrev)); } - }; @@ -203,7 +209,7 @@ TEST_F(ContextualCheckBlockTest, BlockSproutRulesAcceptSproutTx) { // Test block evaluated under Overwinter rules will accept Overwinter transactions. TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesAcceptOverwinterTx) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, 1); CMutableTransaction mtx = GetFirstBlockCoinbaseTx(); @@ -220,7 +226,7 @@ TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesAcceptOverwinterTx) { // Test that a block evaluated under Sapling rules can contain Sapling transactions. TEST_F(ContextualCheckBlockTest, BlockSaplingRulesAcceptSaplingTx) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, 1); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, 1); @@ -254,7 +260,7 @@ TEST_F(ContextualCheckBlockTest, BlockSproutRulesRejectOtherTx) { SCOPED_TRACE("BlockSproutRulesRejectOverwinterTx"); - ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "tx-overwinter-not-active"); + ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwinter-not-active"); } // Make it a Sapling transaction @@ -264,7 +270,7 @@ TEST_F(ContextualCheckBlockTest, BlockSproutRulesRejectOtherTx) { SCOPED_TRACE("BlockSproutRulesRejectSaplingTx"); - ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "tx-overwinter-not-active"); + ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwinter-not-active"); } }; @@ -273,7 +279,7 @@ TEST_F(ContextualCheckBlockTest, BlockSproutRulesRejectOtherTx) // transactions. TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesRejectOtherTx) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, 1); CMutableTransaction mtx = GetFirstBlockCoinbaseTx(); @@ -283,7 +289,7 @@ TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesRejectOtherTx) { SCOPED_TRACE("BlockOverwinterRulesRejectSproutTx"); - ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwinter-active"); + ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwintered-flag-not-set"); } // Make it a Sapling transaction @@ -293,14 +299,14 @@ TEST_F(ContextualCheckBlockTest, BlockOverwinterRulesRejectOtherTx) { SCOPED_TRACE("BlockOverwinterRulesRejectSaplingTx"); - ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "bad-overwinter-tx-version-group-id"); + ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "bad-tx-overwinter-version-too-high"); } } // Test block evaluated under Sapling rules cannot contain non-Sapling transactions. TEST_F(ContextualCheckBlockTest, BlockSaplingRulesRejectOtherTx) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, 1); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, 1); @@ -311,7 +317,7 @@ TEST_F(ContextualCheckBlockTest, BlockSaplingRulesRejectOtherTx) { { SCOPED_TRACE("BlockSaplingRulesRejectSproutTx"); - ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwinter-active"); + ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "tx-overwintered-flag-not-set"); } // Make it an Overwinter transaction @@ -321,7 +327,7 @@ TEST_F(ContextualCheckBlockTest, BlockSaplingRulesRejectOtherTx) { { SCOPED_TRACE("BlockSaplingRulesRejectOverwinterTx"); - ExpectInvalidBlockFromTx(CTransaction(mtx), 0, "bad-sapling-tx-version-group-id"); + ExpectInvalidBlockFromTx(CTransaction(mtx), 100, "bad-sapling-tx-version-group-id"); } } diff --git a/src/gtest/test_checkpoints.cpp b/src/gtest/test_checkpoints.cpp index 24b56a278..09760eac8 100644 --- a/src/gtest/test_checkpoints.cpp +++ b/src/gtest/test_checkpoints.cpp @@ -17,7 +17,7 @@ using namespace std; // TODO: checkpoints have been removed for now. TEST(checkpoints, totalblocks) { - auto chainparams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto chainparams = CreateChainParams(ChainNetwork::MAIN); ASSERT_NE(chainparams, nullptr); const CCheckpointData& checkpoints = chainparams->Checkpoints(); EXPECT_GE(Checkpoints::GetTotalBlocksEstimate(checkpoints), 237'200u); diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index f477797fb..65083c766 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -1,8 +1,9 @@ #include #include -#include "main.h" -#include "primitives/transaction.h" +#include +#include +#include using namespace testing; @@ -24,24 +25,38 @@ CMutableTransaction GetValidTransaction() return mtx; } -TEST(checktransaction_tests, valid_transaction) { +// Subclass of CTransaction which doesn't call UpdateHash when constructing +// from a CMutableTransaction. This enables us to create a CTransaction +// with bad values which normally trigger an exception during construction. +class UNSAFE_CTransaction : public CTransaction +{ +public: + UNSAFE_CTransaction(const CMutableTransaction &tx) : + CTransaction(tx, true) + {} +}; + +TEST(checktransaction_tests, valid_transaction) +{ CMutableTransaction mtx = GetValidTransaction(); CTransaction tx(mtx); MockCValidationState state; EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); } -TEST(checktransaction_tests, BadVersionTooLow) { +TEST(checktransaction_tests, bad_txns_version_too_low) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.nVersion = 0; - CTransaction tx(mtx); + UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1); CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vin_empty) { +TEST(checktransaction_tests, bad_txns_vin_empty) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vin.resize(0); @@ -51,7 +66,8 @@ TEST(checktransaction_tests, bad_txns_vin_empty) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vout_empty) { +TEST(checktransaction_tests, bad_txns_vout_empty) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vout.resize(0); @@ -62,9 +78,9 @@ TEST(checktransaction_tests, bad_txns_vout_empty) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, BadTxnsOversize) +TEST(checktransaction_tests, bad_txns_oversize) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); CMutableTransaction mtx = GetValidTransaction(); mtx.vin[0].scriptSig = CScript(); @@ -94,7 +110,7 @@ TEST(checktransaction_tests, BadTxnsOversize) // ... but fails contextual ones! EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-oversize", false)).Times(1); - EXPECT_FALSE(ContextualCheckTransaction(tx, state, Params(), 1, 100)); + EXPECT_FALSE(ContextualCheckTransaction(tx, state, Params(), 1, true)); } { @@ -111,7 +127,7 @@ TEST(checktransaction_tests, BadTxnsOversize) MockCValidationState state; EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); - EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 1, 100)); + EXPECT_TRUE(ContextualCheckTransaction(tx, state, Params(), 1, true)); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -119,11 +135,9 @@ TEST(checktransaction_tests, BadTxnsOversize) } } -TEST(checktransaction_tests, OversizeSaplingTxns) +TEST(checktransaction_tests, oversize_sapling_txns) { - SelectParams(CBaseChainParams::Network::REGTEST); - UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); + RegtestActivateSapling(); CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; @@ -171,33 +185,35 @@ TEST(checktransaction_tests, OversizeSaplingTxns) } // Revert to default - UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); - UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + RegtestDeactivateSapling(); } -TEST(checktransaction_tests, bad_txns_vout_negative) { +TEST(checktransaction_tests, bad_txns_vout_negative) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = -1; - CTransaction tx(mtx); + UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative", false)).Times(1); CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vout_toolarge) { +TEST(checktransaction_tests, bad_txns_vout_toolarge) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = MAX_MONEY + 1; - CTransaction tx(mtx); + UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge", false)).Times(1); CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_outputs) { +TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_outputs) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = MAX_MONEY; mtx.vout[1].nValue = 1; @@ -209,7 +225,8 @@ TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_outputs) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, ValueBalanceNonZero) { +TEST(checktransaction_tests, value_balance_non_zero) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.valueBalance = 10; @@ -220,7 +237,8 @@ TEST(checktransaction_tests, ValueBalanceNonZero) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, PositiveValueBalanceTooLarge) { +TEST(checktransaction_tests, positive_value_balance_too_large) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vShieldedSpend.resize(1); mtx.valueBalance = MAX_MONEY + 1; @@ -232,7 +250,8 @@ TEST(checktransaction_tests, PositiveValueBalanceTooLarge) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, NegativeValueBalanceTooLarge) { +TEST(checktransaction_tests, negative_value_balance_too_large) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vShieldedSpend.resize(1); mtx.valueBalance = -(MAX_MONEY + 1); @@ -244,7 +263,8 @@ TEST(checktransaction_tests, NegativeValueBalanceTooLarge) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, ValueBalanceOverflowsTotal) { +TEST(checktransaction_tests, value_balance_overflows_total) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vShieldedSpend.resize(1); mtx.vout[0].nValue = 1; @@ -257,7 +277,8 @@ TEST(checktransaction_tests, ValueBalanceOverflowsTotal) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_inputs_duplicate) { +TEST(checktransaction_tests, bad_txns_inputs_duplicate) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vin[1].prevout.hash = mtx.vin[0].prevout.hash; mtx.vin[1].prevout.n = mtx.vin[0].prevout.n; @@ -269,7 +290,8 @@ TEST(checktransaction_tests, bad_txns_inputs_duplicate) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_cb_empty_scriptsig) { +TEST(checktransaction_tests, bad_cb_empty_scriptsig) +{ CMutableTransaction mtx = GetValidTransaction(); // Make it a coinbase. mtx.vin.resize(1); @@ -283,7 +305,8 @@ TEST(checktransaction_tests, bad_cb_empty_scriptsig) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_prevout_null) { +TEST(checktransaction_tests, bad_txns_prevout_null) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.vin[1].prevout.SetNull(); @@ -295,7 +318,8 @@ TEST(checktransaction_tests, bad_txns_prevout_null) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, OverwinterConstructors) { +TEST(checktransaction_tests, overwinter_constructors) +{ CMutableTransaction mtx; mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; @@ -326,7 +350,8 @@ TEST(checktransaction_tests, OverwinterConstructors) { EXPECT_TRUE(tx2 == tx); } -TEST(checktransaction_tests, OverwinterSerialization) { +TEST(checktransaction_tests, overwinter_serialization) +{ CMutableTransaction mtx; mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; @@ -379,7 +404,8 @@ TEST(checktransaction_tests, OverwinterSerialization) { } } -TEST(checktransaction_tests, OverwinterDefaultValues) { +TEST(checktransaction_tests, overwinter_default_values) +{ // Check default values (this will fail when defaults change; test should then be updated) CTransaction tx; EXPECT_EQ(tx.nVersion, 1); @@ -389,7 +415,8 @@ TEST(checktransaction_tests, OverwinterDefaultValues) { } // A valid v3 transaction with no joinsplits -TEST(checktransaction_tests, OverwinterValidTx) { +TEST(checktransaction_tests, overwinter_valid_tx) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; @@ -400,7 +427,8 @@ TEST(checktransaction_tests, OverwinterValidTx) { EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); } -TEST(checktransaction_tests, OverwinterExpiryHeight) { +TEST(checktransaction_tests, overwinter_expiry_height) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; @@ -440,29 +468,20 @@ TEST(checktransaction_tests, OverwinterExpiryHeight) { // Test that a Sprout tx with a negative version number is detected // given the new Overwinter logic -TEST(checktransaction_tests, SproutTxVersionTooLow) { +TEST(checktransaction_tests, sprout_TxVersion_too_low) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = false; mtx.nVersion = -1; - CTransaction tx(mtx); + UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1); CheckTransactionWithoutProofVerification(tx, state); } - - -// Subclass of CTransaction which doesn't call UpdateHash when constructing -// from a CMutableTransaction. This enables us to create a CTransaction -// with bad values which normally trigger an exception during construction. -class UNSAFE_CTransaction : public CTransaction { - public: - UNSAFE_CTransaction(const CMutableTransaction &tx) : CTransaction(tx, true) {} -}; - // Test bad Overwinter version number in CheckTransactionWithoutProofVerification -TEST(checktransaction_tests, OverwinterVersionNumberLow) +TEST(checktransaction_tests, overwinter_version_low) { CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; @@ -477,9 +496,9 @@ TEST(checktransaction_tests, OverwinterVersionNumberLow) } // Test bad Overwinter version number in ContextualCheckTransaction -TEST(checktransaction_tests, OverwinterVersionNumberHigh) +TEST(checktransaction_tests, overwinter_version_high) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); CMutableTransaction mtx = GetValidTransaction(); @@ -488,10 +507,11 @@ TEST(checktransaction_tests, OverwinterVersionNumberHigh) mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; mtx.nExpiryHeight = 0; + EXPECT_THROW((CTransaction(mtx)), std::ios_base::failure); UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-overwinter-version-too-high", false)).Times(1); - ContextualCheckTransaction(tx, state, Params(), 1, 100); + ContextualCheckTransaction(tx, state, Params(), 1, true); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -499,7 +519,7 @@ TEST(checktransaction_tests, OverwinterVersionNumberHigh) // Test bad Overwinter version group id -TEST(checktransaction_tests, OverwinterBadVersionGroupId) +TEST(checktransaction_tests, overwinter_bad_VersionGroupId) { CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; @@ -507,6 +527,7 @@ TEST(checktransaction_tests, OverwinterBadVersionGroupId) mtx.nExpiryHeight = 0; mtx.nVersionGroupId = 0x12345678; + EXPECT_THROW((CTransaction(mtx)), std::ios_base::failure); UNSAFE_CTransaction tx(mtx); MockCValidationState state; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-tx-version-group-id", false)).Times(1); @@ -514,8 +535,9 @@ TEST(checktransaction_tests, OverwinterBadVersionGroupId) } // This tests an Overwinter transaction checked against Sprout -TEST(checktransaction_tests, OverwinterNotActive) { - SelectParams(CBaseChainParams::Network::TESTNET); +TEST(checktransaction_tests, overwinter_not_active) +{ + SelectParams(ChainNetwork::TESTNET); CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; @@ -525,17 +547,24 @@ TEST(checktransaction_tests, OverwinterNotActive) { CTransaction tx(mtx); MockCValidationState state; - // during initial block download, DoS ban score should be zero, else 100 + // during initial block download, for transactions being accepted into the + // mempool (and thus not mined), DoS ban score should be zero, else 10 const auto& chainparams = Params(); EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 1, 100, [](const Consensus::Params &) { return true; }); + ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params &) { return true; }); + EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); + ContextualCheckTransaction(tx, state, chainparams, 0, false, [](const Consensus::Params&) { return false; }); + // for transactions that have been mined in a block, DoS ban score should always be 100. EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 1, 100, [](const Consensus::Params&) { return false; }); + ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return true; }); + EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-not-active", false)).Times(1); + ContextualCheckTransaction(tx, state, chainparams, 0, true, [](const Consensus::Params&) { return false; }); } // This tests a transaction without the fOverwintered flag set, against the Overwinter consensus rule set. -TEST(checktransaction_tests, OverwinterFlagNotSet) { - SelectParams(CBaseChainParams::Network::REGTEST); +TEST(checktransaction_tests, overwinter_flag_not_set) +{ + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); CMutableTransaction mtx = GetValidTransaction(); @@ -546,8 +575,8 @@ TEST(checktransaction_tests, OverwinterFlagNotSet) { CTransaction tx(mtx); MockCValidationState state; - EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwinter-flag-not-set", false)).Times(1); - ContextualCheckTransaction(tx, state, Params(), 1, 100); + EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "tx-overwintered-flag-not-set", false)).Times(1); + ContextualCheckTransaction(tx, state, Params(), 1, true); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -555,7 +584,8 @@ TEST(checktransaction_tests, OverwinterFlagNotSet) { // Overwinter (NU0) does not allow soft fork to version 4 Overwintered tx. -TEST(checktransaction_tests, OverwinterInvalidSoftForkVersion) { +TEST(checktransaction_tests, overwinter_invalid_soft_fork_version) +{ CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; mtx.nVersion = 4; // This is not allowed @@ -575,97 +605,67 @@ TEST(checktransaction_tests, OverwinterInvalidSoftForkVersion) { } } +static void ContextualCreateTxCheck(const Consensus::Params& params, const int nHeight, + const int expectedVersion, const bool expectedOverwintered, const int expectedVersionGroupId, + const int expectedExpiryHeight) +{ + const CMutableTransaction mtx = CreateNewContextualCMutableTransaction(params, nHeight); + EXPECT_EQ(mtx.nVersion, expectedVersion); + EXPECT_EQ(mtx.fOverwintered, expectedOverwintered); + EXPECT_EQ(mtx.nVersionGroupId, expectedVersionGroupId); + EXPECT_EQ(mtx.nExpiryHeight, expectedExpiryHeight); +} + // Test CreateNewContextualCMutableTransaction sets default values based on height -TEST(checktransaction_tests, OverwinteredContextualCreateTx) { - SelectParams(CBaseChainParams::Network::REGTEST); +TEST(checktransaction_tests, OverwinteredContextualCreateTx) +{ + SelectParams(ChainNetwork::REGTEST); const Consensus::Params& consensusParams = Params().GetConsensus(); - int activationHeight = 5; + int overwinterActivationHeight = 5; int saplingActivationHeight = 30; - UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, activationHeight); + UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, overwinterActivationHeight); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, saplingActivationHeight); - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, activationHeight - 1); - - EXPECT_EQ(mtx.nVersion, 1); - EXPECT_EQ(mtx.fOverwintered, false); - EXPECT_EQ(mtx.nVersionGroupId, 0); - EXPECT_EQ(mtx.nExpiryHeight, 0); - } - + ContextualCreateTxCheck(consensusParams, overwinterActivationHeight - 1, + 1, false, 0, 0); // Overwinter activates - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, activationHeight ); - - EXPECT_EQ(mtx.nVersion, 3); - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nExpiryHeight, activationHeight + expiryDelta); - } - + ContextualCreateTxCheck(consensusParams, overwinterActivationHeight, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, overwinterActivationHeight + expiryDelta); // Close to Sapling activation - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - expiryDelta - 2); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 2); - } - - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - expiryDelta - 1); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 1); - } - - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - expiryDelta); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 1); - } + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - expiryDelta - 2, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 2); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - expiryDelta - 1, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - expiryDelta, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - expiryDelta + 1, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - expiryDelta + 2, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - expiryDelta + 3, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); // Just before Sapling activation - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight - 1); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, OVERWINTER_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, OVERWINTER_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight - 1); - } + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - 4, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - 3, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - 2, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(consensusParams, saplingActivationHeight - 1, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); // Sapling activates - { - CMutableTransaction mtx = CreateNewContextualCMutableTransaction( - consensusParams, saplingActivationHeight); - - EXPECT_EQ(mtx.fOverwintered, true); - EXPECT_EQ(mtx.nVersionGroupId, SAPLING_VERSION_GROUP_ID); - EXPECT_EQ(mtx.nVersion, SAPLING_TX_VERSION); - EXPECT_EQ(mtx.nExpiryHeight, saplingActivationHeight + expiryDelta); - } + ContextualCreateTxCheck(consensusParams, saplingActivationHeight, + SAPLING_TX_VERSION, true, SAPLING_VERSION_GROUP_ID, saplingActivationHeight + expiryDelta); // Revert to default - UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); - UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); + RegtestDeactivateSapling(); } // Test a v1 transaction which has a malformed header, perhaps modified in-flight -TEST(checktransaction_tests, BadTxReceivedOverNetwork) +TEST(checktransaction_tests, bad_tx_received_over_network) { // First four bytes <01 00 00 00> have been modified to be (-4 as an int32) std::string goodPrefix = "01000000"; diff --git a/src/gtest/test_deprecation.cpp b/src/gtest/test_deprecation.cpp index 4e3efa8e2..caf28571e 100644 --- a/src/gtest/test_deprecation.cpp +++ b/src/gtest/test_deprecation.cpp @@ -39,7 +39,7 @@ class DeprecationTest : public ::testing::Test { virtual void SetUp() { uiInterface.ThreadSafeMessageBox.disconnect_all_slots(); uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, &mock_, _1, _2, _3)); - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); } @@ -110,14 +110,14 @@ TEST_F(DeprecationTest, DeprecatedNodeErrorIsRepeatedOnStartup) { } TEST_F(DeprecationTest, DeprecatedNodeIgnoredOnRegtest) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); EXPECT_FALSE(ShutdownRequested()); EnforceNodeDeprecation(DEPRECATION_HEIGHT+1); EXPECT_FALSE(ShutdownRequested()); } TEST_F(DeprecationTest, DeprecatedNodeIgnoredOnTestnet) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); EXPECT_FALSE(ShutdownRequested()); EnforceNodeDeprecation(DEPRECATION_HEIGHT+1); EXPECT_FALSE(ShutdownRequested()); diff --git a/src/gtest/test_keys.cpp b/src/gtest/test_keys.cpp index 0a9f08e18..daa2cfab3 100644 --- a/src/gtest/test_keys.cpp +++ b/src/gtest/test_keys.cpp @@ -17,7 +17,7 @@ using namespace testing; TEST(Keys, EncodeAndDecodeSapling) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); KeyIO keyIO(Params()); const auto msk = GetTestMasterSaplingSpendingKey(); diff --git a/src/gtest/test_main.cpp b/src/gtest/test_main.cpp index 38dfc92ba..6172d8461 100644 --- a/src/gtest/test_main.cpp +++ b/src/gtest/test_main.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin Core developers -// Copyright (c) 2021 The Pastel developers +// Copyright (c) 2021-2022 The Pastel developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -31,14 +31,14 @@ static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams) static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval) { - Consensus::Params consensusParams; + Consensus::Params consensusParams(ChainNetwork::REGTEST); consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval; TestBlockSubsidyHalvings(consensusParams); } TEST(test_main, block_subsidy_test) { - auto pChainParams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto pChainParams = CreateChainParams(ChainNetwork::MAIN); TestBlockSubsidyHalvings(pChainParams->GetConsensus()); // As in main TestBlockSubsidyHalvings(500000); TestBlockSubsidyHalvings(100000); @@ -46,7 +46,7 @@ TEST(test_main, block_subsidy_test) TEST(test_main, subsidy_limit_test) { - auto pChainParams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto pChainParams = CreateChainParams(ChainNetwork::MAIN); const auto& consensusParams = pChainParams->GetConsensus(); CAmount nSum = 0; //1002 is the first block with real subsidy diff --git a/src/gtest/test_mempool.cpp b/src/gtest/test_mempool.cpp index daa85310c..015eab23c 100644 --- a/src/gtest/test_mempool.cpp +++ b/src/gtest/test_mempool.cpp @@ -86,7 +86,7 @@ class FakeCoinsViewDB : public CCoinsView { // Valid overwinter v3 format tx gets rejected because overwinter hasn't activated yet. TEST(Mempool, OverwinterNotActiveYet) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); CTxMemPool pool(::minRelayTxFee); @@ -112,7 +112,7 @@ TEST(Mempool, OverwinterNotActiveYet) // 3. fail IsStandardTx TEST(Mempool, SproutV3TxFailsAsExpected) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); CTxMemPool pool(::minRelayTxFee); bool missingInputs; @@ -132,7 +132,7 @@ TEST(Mempool, SproutV3TxFailsAsExpected) // 2. fails ContextualCheckTransaction TEST(Mempool, SproutV3TxWhenOverwinterActive) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); CTxMemPool pool(::minRelayTxFee); @@ -144,7 +144,7 @@ TEST(Mempool, SproutV3TxWhenOverwinterActive) CTransaction tx1(mtx); EXPECT_FALSE(AcceptToMemoryPool(Params(), pool, state1, tx1, false, &missingInputs)); - EXPECT_EQ(state1.GetRejectReason(), "tx-overwinter-flag-not-set"); + EXPECT_EQ(state1.GetRejectReason(), "tx-overwintered-flag-not-set"); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -155,7 +155,7 @@ TEST(Mempool, SproutV3TxWhenOverwinterActive) // 1. fails CheckTransaction (specifically CheckTransactionWithoutProofVerification) TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); CTxMemPool pool(::minRelayTxFee); @@ -203,7 +203,7 @@ TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) TEST(Mempool, ExpiringSoonTxRejection) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); CTxMemPool pool(::minRelayTxFee); diff --git a/src/gtest/test_miner.cpp b/src/gtest/test_miner.cpp index 1789bba39..4a44a305d 100644 --- a/src/gtest/test_miner.cpp +++ b/src/gtest/test_miner.cpp @@ -31,7 +31,7 @@ class MockReserveKey : public CReserveKey { #endif TEST(Miner, GetMinerScriptPubKey) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); const auto& chainparams = Params(); diff --git a/src/gtest/test_mnode/test_governance.cpp b/src/gtest/test_mnode/test_governance.cpp index ea71d7d01..bb5b58609 100644 --- a/src/gtest/test_mnode/test_governance.cpp +++ b/src/gtest/test_mnode/test_governance.cpp @@ -16,7 +16,7 @@ #ifdef GOVERNANCE_TICKETS TEST(mnode_governance, CalculateLastPaymentBlock) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); CMasternodeGovernance gov; @@ -34,7 +34,7 @@ TEST(mnode_governance, CalculateLastPaymentBlock) TEST(mnode_governance, TicketProcessing) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); std::string address("tPVQMdSyVnSYgrww5TTXSJeF75aPQ3bAfdm"); diff --git a/src/gtest/test_mnode/test_mnode_rpc.cpp b/src/gtest/test_mnode/test_mnode_rpc.cpp index 65827f04b..1dc0f8750 100644 --- a/src/gtest/test_mnode/test_mnode_rpc.cpp +++ b/src/gtest/test_mnode/test_mnode_rpc.cpp @@ -31,7 +31,7 @@ class PTest_ani2psl_secret : public TestWithParamGenerateTempDataDir(); auto guard = sg::make_scope_guard([&]() noexcept diff --git a/src/gtest/test_orphan_tx.cpp b/src/gtest/test_orphan_tx.cpp index 6324e6ab4..cc4d0ebf1 100644 --- a/src/gtest/test_orphan_tx.cpp +++ b/src/gtest/test_orphan_tx.cpp @@ -86,7 +86,7 @@ class TestOrphanTxManager : TEST_F(TestOrphanTxManager, ProcessOrphanTxs) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); uint256 origin = GetRandHash(); const size_t nTxCount = CreateTestOrphanTxTree(origin, 7, 3); diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index 534614d95..0fc2c357d 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -13,7 +13,7 @@ using namespace std; TEST(PoW, DifficultyAveraging) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); const Consensus::Params& params = Params().GetConsensus(); size_t lastBlk = 2*params.nPowAveragingWindow+1002; size_t firstBlk = lastBlk - params.nPowAveragingWindow; @@ -78,7 +78,7 @@ TEST(PoW, DifficultyAveraging) { } TEST(PoW, MinDifficultyRules) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); const Consensus::Params& params = Params().GetConsensus(); size_t lastBlk = 2*params.nPowAveragingWindow; size_t firstBlk = lastBlk - params.nPowAveragingWindow; @@ -121,7 +121,7 @@ TEST(PoW, MinDifficultyRules) { /* Test calculation of next difficulty target with no constraints applying */ TEST(PoW, get_next_work) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); const Consensus::Params& params = Params().GetConsensus(); int64_t nLastRetargetTime = 1'262'149'169; // NOTE: Not an actual block time @@ -135,7 +135,7 @@ TEST(PoW, get_next_work) /* Test the constraint on the upper bound for next work */ TEST(PoW, get_next_work_pow_limit) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); const Consensus::Params& params = Params().GetConsensus(); int64_t nLastRetargetTime = 1'231'006'505; // Block #0 of Bitcoin @@ -149,7 +149,7 @@ TEST(PoW, get_next_work_pow_limit) /* Test the constraint on the lower bound for actual time taken */ TEST(PoW, get_next_work_lower_limit_actual) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); const Consensus::Params& params = Params().GetConsensus(); int64_t nLastRetargetTime = 1'279'296'753; // NOTE: Not an actual block time @@ -163,7 +163,7 @@ TEST(PoW, get_next_work_lower_limit_actual) /* Test the constraint on the upper bound for actual time taken */ TEST(PoW, get_next_work_upper_limit_actual) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); const Consensus::Params& params = Params().GetConsensus(); int64_t nLastRetargetTime = 1'269'205'629; // NOTE: Not an actual block time @@ -176,7 +176,7 @@ TEST(PoW, get_next_work_upper_limit_actual) TEST(PoW, GetBlockProofEquivalentTime_test) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); const Consensus::Params& params = Params().GetConsensus(); vector blocks(10000); diff --git a/src/gtest/test_rpc.cpp b/src/gtest/test_rpc.cpp index 02b13b987..2c7cdba21 100644 --- a/src/gtest/test_rpc.cpp +++ b/src/gtest/test_rpc.cpp @@ -23,7 +23,7 @@ extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, /* TEST(rpc, check_blockToJSON_returns_minified_solution) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); // Testnet block 0030b0d110441f5bdad733adcd68ad308aa96cf43aeb8bdcd57b04fed11cd56e // Height 4 CDataStream ss(ParseHex("040000003e2c55a654c68204bba5b13fbc48ad731174ed0e1ba71097db08734a4c53cf00b758a79b2ec8f6734e4a7be0bc12af7e7686230d05042bec9304786a88608ba4fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e0bb2785cffff07200000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffff000036a98fefa4ee22001f9c8577b706561a602cd71a16ce00315c0cc3ed0000fd40050154da8a6882d3b56624452d8c5821ea293839dacb2554521752d246b1da2d53ba67a910553dff98d1201d1c11c262d723f6c19234f2ba2e64454609cc72082982c4dddaa3cb316671833c7958ec7245b1197d870b4dc71a521edf15ec93c27a4a4609863c75b6c8cc25aeecc49529d2016310d49e6a497731e9167fc7b9292b91dd0310c640f18fd854e15cae924066b66b1b4ae753fb49e18bffda144984a17f84cea8ecb5eea408a67de4b7e8aa71e04821e5e82f7925b7df58dd07110cf955438b953da575786a33c7e422aab11f8c5409b0b969c102bd71cb45f1da10b16f712efa2a846b0c0338f5b0d3d146a132413d425c1465c83dd9d2f715a561a863a873c3e4a9b628df428349a90231bee92ffc4e900b1e24c0f12fc37cdcaaa35121db986ce736cd4e809befa40fa1e2081a68572f7228c5ff1ec749c1fcf9e8d9cf373f63ba4e80586a5ab5053c239902c6bbdb4b0cd873474843685dd1351d4ed4570b651cce9a4e9e15b9bde077c46b924b4fb2a89e1faed40e9f61192ca3bead383622a3b3e7704559f59e74832090a38ff59c92abc856f3c8dfd8e3123a37f84f110f6ba3b904e9466d572026d1b8ea862a145755df4813f8cc94e9a081cbc547447fd7d9f31a548532b6f7149350aa0bc890cf17a0d4a2372ba911911f4e8b5c4126677bd196b365b602ba99976bd4fb6d9afcd35f072091e8b0d79bcbba3203942228b9a9a4a991e43b1d55137d2160e5f3f12b6234f9d9bfe0f695effe4b090f8fc763aa02f3944b95750167e4099bdc56765c3aa4d29f4798448f113e0470dfa66c3952c7cd556a083d6ad673d1a2cdb84501c7e62b7ff084cd7f61e1358fc2e199d85f79625457b5256c72120b6633b8270cc16c8fe50759197e9be26120ee3eea863255a2f60fbc0e4c63c5424c5ab612e714790b6606afbc57ad0182967f62c1b49ef1a64161e3e88928e8a167c1a2123b2fee659e0a8520d9d3e713dae42528db6aa334103396cbb26203af719a430edd3cb8b5477f6fa547305527a7d95969732cb3135b602ed20186f9f1bf43085775eb2a6bd0b5b43d7366896d199615d37d1d3d3430c3f405e2d979397e242b18294147a4d05e552e14f9556b990c145a766084944733f7af9992fe418439559b9f8828bcd7c4fdb595cbe2ce57c78ebe3f18023e43ed3ac31f53788ae5e56bc8e8e5feba716c070888f1cbd489d3ed848d91334ab1e63e25787b75bf0d764a6ecd8cfcce7ec422e75219d9f20745f7446e23f84214103cba91f97046bf91bcdb22e87e9f2d630a9c52eca39cac010bc9b44df024eec9f7f03902910beb47350676e1ebcd375a7ca8f098f2bbf3984b6a0bff15052ed41ca1aeec88eef3e2e0979f841d8ab74014eda17ab4eec9fa7e24194729f1a14040953e7602f1d9f9385417b33eb4b058272729b5d482f6b97158799eebea6b9d8fb7d07682adcc327623721dbc06141447a12fb350a5fffa216ab5ddda106dad924c2a510a8f01295527712ec89693fac2793698339f3dea17956b3571a278636c05b3806dad90fafb9bdd07a01db06523f95bfe13bc2ae5f90d583266ca5538cbb433f915a3f9d1d6db38d5d4c57140b3927f1e1d952839e88f22716b6b9f9a90b56c87cec3b16da00c0c4d0369491c92237fc3442310f57d5d2ca65433f9e57c1e84374b35afadefaabb328ebb271bbd6219952a16057bbfdf8d859d5092ff330b4ac68af0eb5bbe7f6719df73aaf5c76a8586be62c5259bda56148432f3eb1175f35eddd57acd2d60f1969f32ed3f85b49d410630d89d5201ce97abb2e4d59518c625feda66b740b12174dfbb6193bbdf1e3ee2f58ca2faa1a91bb3a44250c216d15ce5d99552d8d5be32b19da3252c1b5d880101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03540109ffffffff0140be4025000000001976a914bd1bfac7ae0fb27ef01003ac7a46de25205e3f5b88ac00000000"), SER_DISK, CLIENT_VERSION); @@ -107,7 +107,7 @@ void CheckRPCThrows(string rpcString, string expectedErrorMessage) { TEST_F(TestRpc, rpc_rawparams) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); // Test raw transaction API argument handling UniValue r; @@ -153,7 +153,7 @@ TEST_F(TestRpc, rpc_rawparams) TEST_F(TestRpc, rpc_rawsign) { - // SelectParams(CBaseChainParams::Network::MAIN); + // SelectParams(ChainNetwork::MAIN); UniValue r; // input is a 1-of-2 multisig (so is output): string prevout = @@ -377,7 +377,7 @@ TEST_F(TestRpc, rpc_ban) TEST_F(TestRpc, rpc_raw_create_overwinter_v3) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); // Sample regtest address: @@ -424,7 +424,7 @@ TEST(test_rpc, rpc_getnetworksolps) // Test parameter processing (not functionality) TEST_F(TestRpc, rpc_insightexplorer) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); CheckRPCThrows("getblockdeltas \"a\"", "Error: getblockdeltas is disabled. " diff --git a/src/gtest/test_rpc_wallet.cpp b/src/gtest/test_rpc_wallet.cpp index 46c462ece..319285d62 100644 --- a/src/gtest/test_rpc_wallet.cpp +++ b/src/gtest/test_rpc_wallet.cpp @@ -121,7 +121,7 @@ class TestRpcWallet1 : public Test TEST_F(TestRpcWallet1, rpc_wallet) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); // Test RPC calls for various wallet statistics UniValue r; @@ -323,7 +323,7 @@ TEST_F(TestRpcWallet1, rpc_wallet) TEST_F(TestRpcWallet, rpc_wallet_getbalance) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -355,7 +355,7 @@ TEST_F(TestRpcWallet, rpc_wallet_getbalance) */ TEST_F(TestRpcWallet, rpc_wallet_z_validateaddress) { - SelectParams(CBaseChainParams::Network::MAIN); + SelectParams(ChainNetwork::MAIN); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -760,7 +760,7 @@ TEST_F(TestRpcWallet, rpc_z_getoperations) TEST_F(TestRpcWallet, rpc_z_sendmany_parameters) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); KeyIO keyIO(Params()); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -820,33 +820,33 @@ TEST_F(TestRpcWallet, rpc_z_sendmany_parameters) vector vZRecipients; // vector of z-address recipients // Test constructor of AsyncRPCOperation_sendmany try { - auto operation = make_shared(nullopt, mtx, "", vTRecipients, vZRecipients, -1); + auto operation = make_shared(nullptr, mtx, "", vTRecipients, vZRecipients, -1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Minconf cannot be negative")); } try { - auto operation = make_shared(nullopt, mtx, "", vTRecipients, vZRecipients, 1); + auto operation = make_shared(nullptr, mtx, "", vTRecipients, vZRecipients, 1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "From address parameter missing")); } try { - auto operation = make_shared(nullopt, mtx, "tPmCf9DhN5jv5CgrxDMHRz6wsEjWwM6qJnZ", vTRecipients, vZRecipients, 1); + auto operation = make_shared(nullptr, mtx, "tPmCf9DhN5jv5CgrxDMHRz6wsEjWwM6qJnZ", vTRecipients, vZRecipients, 1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "No recipients")); } vTRecipients.emplace_back("dummy", 1, ""); try { - auto operation = make_shared(nullopt, mtx, "INVALID", vTRecipients, vZRecipients, 1); + auto operation = make_shared(nullptr, mtx, "INVALID", vTRecipients, vZRecipients, 1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Invalid from address")); } // Testnet payment addresses begin with 'tZ'. This test detects an incorrect prefix. try { - auto operation = make_shared(nullopt, mtx, + auto operation = make_shared(nullptr, mtx, "tTWgZLnrRJ13fF6YDJmnL32QZqJJD8UfMBcjGhECgF8GTT54SrAkHyvUW5AgbqTF2v4WLRq7Nchrymbr3eyWY2RNoGJjmNL", vTRecipients, vZRecipients, 1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Invalid from address")); @@ -855,7 +855,7 @@ TEST_F(TestRpcWallet, rpc_z_sendmany_parameters) TEST_F(TestRpcWallet, rpc_z_sendmany_taddr_to_sapling) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); @@ -867,14 +867,16 @@ TEST_F(TestRpcWallet, rpc_z_sendmany_taddr_to_sapling) UniValue retValue; - KeyIO keyIO(Params()); + const auto& chainparams = Params(); + const auto &consensusParams = chainparams.GetConsensus(); + + KeyIO keyIO(chainparams); // add keys manually auto taddr = pwalletMain->GenerateNewKey().GetID(); string taddr1 = keyIO.EncodeDestination(taddr); auto pa = pwalletMain->GenerateNewSaplingZKey(); string zaddr1 = keyIO.EncodePaymentAddress(pa); - auto consensusParams = Params().GetConsensus(); retValue = CallRPC("getblockcount"); int nextBlockHeight = retValue.get_int() + 1; @@ -894,7 +896,7 @@ TEST_F(TestRpcWallet, rpc_z_sendmany_taddr_to_sapling) auto blockHash = block.GetHash(); CBlockIndex fakeIndex {block}; fakeIndex.nHeight = 1; - mapBlockIndex.insert(make_pair(blockHash, &fakeIndex)); + mapBlockIndex.emplace(blockHash, &fakeIndex); chainActive.SetTip(&fakeIndex); EXPECT_TRUE(chainActive.Contains(&fakeIndex)); EXPECT_EQ(1, chainActive.Height()); @@ -902,12 +904,12 @@ TEST_F(TestRpcWallet, rpc_z_sendmany_taddr_to_sapling) pwalletMain->AddToWallet(wtx, true, nullptr); // Context that z_sendmany requires - auto builder = TransactionBuilder(consensusParams, nextBlockHeight, pwalletMain); + auto builder = make_unique(consensusParams, nextBlockHeight, pwalletMain); mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight); vector vtRecipients; vector vzRecipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") }; - auto operation = make_shared(builder, mtx, taddr1, vtRecipients, vzRecipients, 0); + auto operation = make_shared(move(builder), mtx, taddr1, vtRecipients, vzRecipients, 0); // Enable test mode so tx is not sent operation->testmode = true; @@ -1032,7 +1034,7 @@ TEST_F(TestRpcWallet2, rpc_wallet_encrypted_wallet_sapzkeys) TEST_F(TestRpcWallet2, rpc_z_listunspent_parameters) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1069,7 +1071,7 @@ TEST_F(TestRpcWallet2, rpc_z_listunspent_parameters) TEST_F(TestRpcWallet2, rpc_z_shieldcoinbase_parameters) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1124,13 +1126,13 @@ TEST_F(TestRpcWallet2, rpc_z_shieldcoinbase_parameters) vector vInputs; try { - auto operation = make_shared(TransactionBuilder(), mtx, vInputs, testnetzaddr, -1); + auto operation = make_shared(nullptr, mtx, vInputs, testnetzaddr, -1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Fee is out of range")); } try { - auto operation = make_shared(TransactionBuilder(), mtx, vInputs, testnetzaddr, 1); + auto operation = make_shared(nullptr, mtx, vInputs, testnetzaddr, 1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Empty inputs")); } @@ -1138,7 +1140,7 @@ TEST_F(TestRpcWallet2, rpc_z_shieldcoinbase_parameters) // Testnet payment addresses begin with 'tZ'. This test detects an incorrect prefix. try { vInputs.emplace_back(uint256(), 0, 0); - auto operation = make_shared(TransactionBuilder(), mtx, vInputs, mainnetzaddr, 1); + auto operation = make_shared(nullptr, mtx, vInputs, mainnetzaddr, 1); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Invalid to address")); } @@ -1147,7 +1149,7 @@ TEST_F(TestRpcWallet2, rpc_z_shieldcoinbase_parameters) TEST_F(TestRpcWallet2, rpc_z_mergetoaddress_parameters) { - SelectParams(CBaseChainParams::Network::TESTNET); + SelectParams(ChainNetwork::TESTNET); LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1235,14 +1237,14 @@ TEST_F(TestRpcWallet2, rpc_z_mergetoaddress_parameters) vector utxoInputs; vector saplingNoteInputs; try { - auto operation = make_shared(nullopt, mtx, utxoInputs, saplingNoteInputs, testnetzaddr, -1); + auto operation = make_shared(nullptr, mtx, utxoInputs, saplingNoteInputs, testnetzaddr, -1); // BOOST_FAIL("Should have caused an error"); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Fee is out of range")); } try { - auto operation = make_shared(nullopt, mtx, utxoInputs, saplingNoteInputs, testnetzaddr, 1); + auto operation = make_shared(nullptr, mtx, utxoInputs, saplingNoteInputs, testnetzaddr, 1); // BOOST_FAIL("Should have caused an error"); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "No inputs")); @@ -1251,7 +1253,7 @@ TEST_F(TestRpcWallet2, rpc_z_mergetoaddress_parameters) utxoInputs.emplace_back(COutPoint(uint256(), 0), 0, CScript()); try { MergeToAddressRecipient badaddr("", "memo"); - auto operation = make_shared(nullopt, mtx, utxoInputs, saplingNoteInputs, badaddr, 1); + auto operation = make_shared(nullptr, mtx, utxoInputs, saplingNoteInputs, badaddr, 1); // BOOST_FAIL("Should have caused an error"); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Recipient parameter missing")); @@ -1259,7 +1261,7 @@ TEST_F(TestRpcWallet2, rpc_z_mergetoaddress_parameters) // Testnet payment addresses begin with 'tZ'. This test detects an incorrect prefix. try { - auto operation = make_shared(nullopt, mtx, utxoInputs, saplingNoteInputs, mainnetzaddr, 1); + auto operation = make_shared(nullptr, mtx, utxoInputs, saplingNoteInputs, mainnetzaddr, 1); // BOOST_FAIL("Should have caused an error"); } catch (const UniValue& objError) { EXPECT_TRUE( find_error(objError, "Invalid recipient address")); diff --git a/src/gtest/test_transaction_builder.cpp b/src/gtest/test_transaction_builder.cpp index 71cd61af0..747002930 100644 --- a/src/gtest/test_transaction_builder.cpp +++ b/src/gtest/test_transaction_builder.cpp @@ -1,26 +1,28 @@ -#include "chainparams.h" -#include "consensus/params.h" -#include "consensus/validation.h" -#include "key_io.h" -#include "main.h" -#include "pubkey.h" -#include "rpc/protocol.h" -#include "transaction_builder.h" -#include "zcash/Address.hpp" - #include #include -static const std::string tSecretRegtest = "cND2ZvtabDbJ1gucx9GWH6XT9kgTAqfb6cotPt5Q5CyxVDhid2EN"; +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +static const string tSecretRegtest = "cND2ZvtabDbJ1gucx9GWH6XT9kgTAqfb6cotPt5Q5CyxVDhid2EN"; TEST(TransactionBuilder, Invoke) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); auto consensusParams = Params().GetConsensus(); - std::string sKeyError; + string sKeyError; CBasicKeyStore keystore; KeyIO keyIO(Params()); const CKey tsk = keyIO.DecodeSecret(tSecretRegtest, sKeyError); @@ -53,7 +55,7 @@ TEST(TransactionBuilder, Invoke) EXPECT_EQ(tx1.valueBalance, -40000); CValidationState state; - EXPECT_TRUE(ContextualCheckTransaction(tx1, state, Params(), 2, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx1, state, Params(), 2, true)); EXPECT_EQ(state.GetRejectReason(), ""); // Prepare to spend the note that was just created @@ -85,7 +87,7 @@ TEST(TransactionBuilder, Invoke) EXPECT_EQ(tx2.vShieldedOutput.size(), 2); EXPECT_EQ(tx2.valueBalance, 10000); - EXPECT_TRUE(ContextualCheckTransaction(tx2, state, Params(), 3, 0)); + EXPECT_TRUE(ContextualCheckTransaction(tx2, state, Params(), 3, true)); EXPECT_EQ(state.GetRejectReason(), ""); // Revert to default @@ -95,17 +97,17 @@ TEST(TransactionBuilder, Invoke) TEST(TransactionBuilder, ThrowsOnTransparentInputWithoutKeyStore) { - SelectParams(CBaseChainParams::Network::REGTEST); - auto consensusParams = Params().GetConsensus(); + SelectParams(ChainNetwork::REGTEST); + const auto &consensusParams = Params().GetConsensus(); auto builder = TransactionBuilder(consensusParams, 1); - ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), std::runtime_error); + ASSERT_THROW(builder.AddTransparentInput(COutPoint(), CScript(), 1), runtime_error); } TEST(TransactionBuilder, RejectsInvalidTransparentOutput) { - SelectParams(CBaseChainParams::Network::REGTEST); - auto consensusParams = Params().GetConsensus(); + SelectParams(ChainNetwork::REGTEST); + const auto &consensusParams = Params().GetConsensus(); // Default CTxDestination type is an invalid address CTxDestination taddr; @@ -115,8 +117,8 @@ TEST(TransactionBuilder, RejectsInvalidTransparentOutput) TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress) { - SelectParams(CBaseChainParams::Network::REGTEST); - auto consensusParams = Params().GetConsensus(); + SelectParams(ChainNetwork::REGTEST); + const auto &consensusParams = Params().GetConsensus(); // Default CTxDestination type is an invalid address CTxDestination taddr; @@ -126,7 +128,7 @@ TEST(TransactionBuilder, RejectsInvalidTransparentChangeAddress) TEST(TransactionBuilder, FailsWithNegativeChange) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); auto consensusParams = Params().GetConsensus(); @@ -138,7 +140,7 @@ TEST(TransactionBuilder, FailsWithNegativeChange) auto pk = sk.default_address(); // Set up dummy transparent address - std::string sKeyError; + string sKeyError; CBasicKeyStore keystore; KeyIO keyIO(Params()); const CKey tsk = keyIO.DecodeSecret(tSecretRegtest, sKeyError); @@ -159,24 +161,24 @@ TEST(TransactionBuilder, FailsWithNegativeChange) // Fail if there is only a Sapling output // 0.0005 z-ZEC out, 0.0001 t-ZEC fee - auto builder = TransactionBuilder(consensusParams, 1); - builder.AddSaplingOutput(fvk.ovk, pk, 50000, {}); - EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); + auto builder = make_unique(consensusParams, 1); + builder->AddSaplingOutput(fvk.ovk, pk, 50000, {}); + EXPECT_EQ("Change cannot be negative", builder->Build().GetError()); // Fail if there is only a transparent output // 0.0005 t-ZEC out, 0.0001 t-ZEC fee - builder = TransactionBuilder(consensusParams, 1, &keystore); - builder.AddTransparentOutput(taddr, 50000); - EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); + builder = make_unique(consensusParams, 1, &keystore); + builder->AddTransparentOutput(taddr, 50000); + EXPECT_EQ("Change cannot be negative", builder->Build().GetError()); // Fails if there is insufficient input // 0.0005 t-ZEC out, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in - builder.AddSaplingSpend(expsk, note, anchor, witness); - EXPECT_EQ("Change cannot be negative", builder.Build().GetError()); + builder->AddSaplingSpend(expsk, note, anchor, witness); + EXPECT_EQ("Change cannot be negative", builder->Build().GetError()); // Succeeds if there is sufficient input - builder.AddTransparentInput(COutPoint(), scriptPubKey, 1); - EXPECT_TRUE(builder.Build().IsTx()); + builder->AddTransparentInput(COutPoint(), scriptPubKey, 1); + EXPECT_TRUE(builder->Build().IsTx()); // Revert to default UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); @@ -185,7 +187,7 @@ TEST(TransactionBuilder, FailsWithNegativeChange) TEST(TransactionBuilder, ChangeOutput) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); auto consensusParams = Params().GetConsensus(); @@ -209,7 +211,7 @@ TEST(TransactionBuilder, ChangeOutput) auto zChangeAddr = sk2.default_address(); // Set up dummy transparent address - std::string sKeyError; + string sKeyError; CBasicKeyStore keystore; KeyIO keyIO(Params()); const CKey tsk = keyIO.DecodeSecret(tSecretRegtest, sKeyError); @@ -277,7 +279,7 @@ TEST(TransactionBuilder, ChangeOutput) TEST(TransactionBuilder, SetFee) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); auto consensusParams = Params().GetConsensus(); @@ -332,9 +334,9 @@ TEST(TransactionBuilder, SetFee) TEST(TransactionBuilder, CheckSaplingTxVersion) { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - auto consensusParams = Params().GetConsensus(); + const auto &consensusParams = Params().GetConsensus(); auto sk = libzcash::SaplingSpendingKey::random(); auto expsk = sk.expanded_spending_key(); @@ -344,10 +346,10 @@ TEST(TransactionBuilder, CheckSaplingTxVersion) auto builder = TransactionBuilder(consensusParams, 1); try { builder.AddSaplingOutput(uint256(), pk, 12345, {}); - } catch (std::runtime_error const & err) { - EXPECT_EQ(err.what(), std::string("TransactionBuilder cannot add Sapling output to pre-Sapling transaction")); + } catch (runtime_error const & err) { + EXPECT_EQ(err.what(), string("TransactionBuilder cannot add Sapling output to pre-Sapling transaction")); } catch(...) { - FAIL() << "Expected std::runtime_error"; + FAIL() << "Expected runtime_error"; } // Cannot add Sapling spends to a non-Sapling transaction @@ -355,10 +357,10 @@ TEST(TransactionBuilder, CheckSaplingTxVersion) SaplingMerkleTree tree; try { builder.AddSaplingSpend(expsk, note, uint256(), tree.witness()); - } catch (std::runtime_error const & err) { - EXPECT_EQ(err.what(), std::string("TransactionBuilder cannot add Sapling spend to pre-Sapling transaction")); + } catch (runtime_error const & err) { + EXPECT_EQ(err.what(), string("TransactionBuilder cannot add Sapling spend to pre-Sapling transaction")); } catch(...) { - FAIL() << "Expected std::runtime_error"; + FAIL() << "Expected runtime_error"; } // Revert to default diff --git a/src/gtest/test_upgrades.cpp b/src/gtest/test_upgrades.cpp index 4adc33d39..48b4c9578 100644 --- a/src/gtest/test_upgrades.cpp +++ b/src/gtest/test_upgrades.cpp @@ -13,7 +13,7 @@ class UpgradesTest : public Test protected: static void SetUpTestSuite() { - SelectParams(CBaseChainParams::Network::REGTEST); + SelectParams(ChainNetwork::REGTEST); } void TearDown() override diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp index 96d73260e..3168add73 100644 --- a/src/gtest/test_validation.cpp +++ b/src/gtest/test_validation.cpp @@ -77,7 +77,7 @@ TEST(Validation, ContextualCheckInputsPassesWithCoinbase) FakeCoinsViewDB fakeDB; CCoinsViewCache view(&fakeDB); - auto pMainNetParams = CreateChainParams(CBaseChainParams::Network::MAIN); + auto pMainNetParams = CreateChainParams(ChainNetwork::MAIN); for (auto idx = to_integral_type(Consensus::UpgradeIndex::BASE_SPROUT); idx < to_integral_type(Consensus::UpgradeIndex::MAX_NETWORK_UPGRADES); ++idx) { auto consensusBranchId = NetworkUpgradeInfo[idx].nBranchId; diff --git a/src/main.cpp b/src/main.cpp index 0a12016db..6eee8b07b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -290,15 +290,47 @@ struct CNodeState nBlocksInFlightValidHeaders = 0; fPreferredDownload = false; } + + void BlocksInFlightCleanup(const NodeId nodeid) + { + string s; + const size_t nBlockCount = vBlocksInFlight.size(); + const bool bLogNetCategory = LogAcceptCategory("net"); + if (bLogNetCategory && nBlockCount) + s.reserve(nBlockCount * 42); + for (const auto& entry : vBlocksInFlight) + { + if (bLogNetCategory) + { + if (!s.empty()) + s += ", "; + s += entry.hash.ToString(); + if (entry.pindex) + { + int nHeight = entry.pindex->nHeight; + if (nHeight >= 0) + s += strprintf("(%d)", nHeight); + } + } + + mapBlocksInFlight.erase(entry.hash); + } + if (bLogNetCategory && nBlockCount) + LogPrint("net", "Peer %d had %zu blocks in-flight [%s]\n", nodeid, nBlockCount, s.c_str()); + nBlocksInFlight = 0; + nBlocksInFlightValidHeaders = 0; + pindexBestKnownBlock = nullptr; + hashLastUnknownBlock.SetNull(); + } }; /** Map maintaining per-node state. Requires cs_main. */ unordered_map mapNodeState; // Requires cs_main. -CNodeState *State(NodeId pnode) +CNodeState *State(const NodeId nodeid) { - auto it = mapNodeState.find(pnode); + auto it = mapNodeState.find(nodeid); if (it == mapNodeState.end()) return nullptr; return &it->second; @@ -339,8 +371,7 @@ void FinalizeNode(NodeId nodeid) if (state->nMisbehavior == 0 && state->fCurrentlyConnected) AddressCurrentlyConnected(state->address); - for (const auto& entry : state->vBlocksInFlight) - mapBlocksInFlight.erase(entry.hash); + state->BlocksInFlightCleanup(nodeid); if (gl_pOrphanTxManager) gl_pOrphanTxManager->EraseOrphansFor(nodeid); nPreferredDownload -= state->fPreferredDownload; @@ -379,7 +410,7 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa int64_t nNow = GetTimeMicros(); QueuedBlock newentry = {hash, pindex, nNow, pindex != nullptr, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)}; nQueuedValidatedHeaders += newentry.fValidatedHeaders; - list::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry); + auto it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry); state->nBlocksInFlight++; state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders; mapBlocksInFlight[hash] = make_pair(nodeid, it); @@ -831,122 +862,155 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in * 1. AcceptToMemoryPool calls CheckTransaction and this function. * 2. ProcessNewBlock calls AcceptBlock, which calls CheckBlock (which calls CheckTransaction) * and ContextualCheckBlock (which calls this function). - * 3. The isInitBlockDownload argument is only to assist with testing. + * 3. For consensus rules that relax restrictions (where a transaction that is invalid at height M + * can become valid at a later height N), we make the bans conditional on not being in Initial + * Block Download (IBD) mode. + * + * \param tx + * \param state + * \param chainparams + * \param nHeight + * \param isMined + * \param isInitBlockDownload - functor to check IBD mode + * \return */ bool ContextualCheckTransaction( const CTransaction& tx, CValidationState &state, const CChainParams& chainparams, const int nHeight, - const int dosLevel, + const bool isMined, funcIsInitialBlockDownload_t isInitBlockDownload) { const auto& consensusParams = chainparams.GetConsensus(); const bool overwinterActive = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UpgradeIndex::UPGRADE_OVERWINTER); + const bool beforeOverwinter = !overwinterActive; const bool saplingActive = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UpgradeIndex::UPGRADE_SAPLING); - const bool isSprout = !overwinterActive; - - // If Sprout rules apply, reject transactions which are intended for Overwinter and beyond - if (isSprout && tx.fOverwintered) { - return state.DoS(isInitBlockDownload(consensusParams) ? 0 : dosLevel, error("ContextualCheckTransaction(): overwinter is not active yet"), - REJECT_INVALID, "tx-overwinter-not-active"); - } - if (saplingActive) - { - // Reject transactions with valid version but missing overwintered flag - if (tx.nVersion >= SAPLING_MIN_TX_VERSION && !tx.fOverwintered) { - return state.DoS(dosLevel, error("ContextualCheckTransaction(): overwintered flag must be set"), - REJECT_INVALID, "tx-overwintered-flag-not-set"); - } - - // Reject transactions with non-Sapling version group ID - if (tx.fOverwintered && tx.nVersionGroupId != SAPLING_VERSION_GROUP_ID) { - return state.DoS(isInitBlockDownload(consensusParams) ? 0 : dosLevel, error("CheckTransaction(): invalid Sapling tx version"), - REJECT_INVALID, "bad-sapling-tx-version-group-id"); - } - - // Reject transactions with invalid version - if (tx.fOverwintered && tx.nVersion < SAPLING_MIN_TX_VERSION ) { - return state.DoS(100, error("CheckTransaction(): Sapling version too low"), - REJECT_INVALID, "bad-tx-sapling-version-too-low"); - } - - // Reject transactions with invalid version - if (tx.fOverwintered && tx.nVersion > SAPLING_MAX_TX_VERSION ) { - return state.DoS(100, error("CheckTransaction(): Sapling version too high"), - REJECT_INVALID, "bad-tx-sapling-version-too-high"); - } - } else if (overwinterActive) { - // Reject transactions with valid version but missing overwinter flag - if (tx.nVersion >= OVERWINTER_MIN_TX_VERSION && !tx.fOverwintered) { - return state.DoS(dosLevel, error("ContextualCheckTransaction(): overwinter flag must be set"), - REJECT_INVALID, "tx-overwinter-flag-not-set"); - } + // DoS level to ban peers. + const int DOS_LEVEL_BLOCK = 100; + // DoS level set to 10 to be more forgiving. + const int DOS_LEVEL_MEMPOOL = 10; - // Reject transactions with non-Overwinter version group ID - if (tx.fOverwintered && tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID) { - return state.DoS(isInitBlockDownload(consensusParams) ? 0 : dosLevel, error("CheckTransaction(): invalid Overwinter tx version"), - REJECT_INVALID, "bad-overwinter-tx-version-group-id"); - } + // For constricting rules, we don't need to account for IBD mode. + auto dosLevelConstricting = isMined ? DOS_LEVEL_BLOCK : DOS_LEVEL_MEMPOOL; + // For rules that are relaxing (or might become relaxing when a future + // network upgrade is implemented), we need to account for IBD mode. + auto dosLevelPotentiallyRelaxing = isMined ? DOS_LEVEL_BLOCK : + (isInitBlockDownload(consensusParams) ? 0 : DOS_LEVEL_MEMPOOL); - // Reject transactions with invalid version - if (tx.fOverwintered && tx.nVersion > OVERWINTER_MAX_TX_VERSION ) { - return state.DoS(100, error("CheckTransaction(): overwinter version too high"), - REJECT_INVALID, "bad-tx-overwinter-version-too-high"); - } + // Rules that apply only to Sprout + if (beforeOverwinter) + { + // Reject transactions which are intended for Overwinter and beyond + if (tx.fOverwintered) + return state.DoS( + dosLevelPotentiallyRelaxing, + error("ContextualCheckTransaction(): overwinter is not active yet"), + REJECT_INVALID, "tx-overwinter-not-active"); } - // Rules that apply to Overwinter or later: + // Rules that apply to Overwinter and later if (overwinterActive) { // Reject transactions intended for Sprout - if (!tx.fOverwintered) { - return state.DoS(dosLevel, error("ContextualCheckTransaction: overwinter is active"), - REJECT_INVALID, "tx-overwinter-active"); - } - + if (!tx.fOverwintered) + return state.DoS( + dosLevelConstricting, + error("ContextualCheckTransaction: fOverwintered flag must be set when Overwinter is active"), + REJECT_INVALID, "tx-overwintered-flag-not-set"); + // Check that all transactions are unexpired - if (IsExpiredTx(tx, nHeight)) { + if (IsExpiredTx(tx, nHeight)) + { // Don't increase banscore if the transaction only just expired - int expiredDosLevel = IsExpiredTx(tx, nHeight - 1) ? dosLevel : 0; - return state.DoS(expiredDosLevel, error("ContextualCheckTransaction(): transaction is expired"), - REJECT_INVALID, "tx-overwinter-expired"); + const int expiredDosLevel = IsExpiredTx(tx, nHeight - 1) ? dosLevelConstricting : 0; + return state.DoS( + expiredDosLevel, + error("ContextualCheckTransaction(): transaction is expired"), + REJECT_INVALID, "tx-overwinter-expired"); + } + + // Rules that became inactive after Sapling activation. + if (!saplingActive) + { + // Reject transactions with invalid version + // OVERWINTER_MIN_TX_VERSION is checked against as a non-contextual check. + if (tx.nVersion > OVERWINTER_MAX_TX_VERSION) + return state.DoS( + dosLevelPotentiallyRelaxing, + error("ContextualCheckTransaction(): overwinter version too high"), + REJECT_INVALID, "bad-tx-overwinter-version-too-high"); + + // Reject transactions with non-Overwinter version group ID + if (tx.nVersionGroupId != OVERWINTER_VERSION_GROUP_ID) + return state.DoS( + dosLevelPotentiallyRelaxing, + error("ContextualCheckTransaction(): invalid Overwinter tx version"), + REJECT_INVALID, "bad-overwinter-tx-version-group-id"); } } - // Rules that apply before Sapling: - if (!saplingActive) + // Rules that apply to Sapling and later + if (saplingActive) { + if (tx.nVersionGroupId == SAPLING_VERSION_GROUP_ID) + { + // Reject transactions with invalid version + if (tx.fOverwintered && tx.nVersion < SAPLING_MIN_TX_VERSION) + return state.DoS( + dosLevelConstricting, + error("CheckTransaction(): Sapling version too low"), + REJECT_INVALID, "bad-tx-sapling-version-too-low"); + + // Reject transactions with invalid version + if (tx.fOverwintered && tx.nVersion > SAPLING_MAX_TX_VERSION) + return state.DoS( + dosLevelPotentiallyRelaxing, + error("CheckTransaction(): Sapling version too high"), + REJECT_INVALID, "bad-tx-sapling-version-too-high"); + } + else + { + // Reject transactions with non-Sapling version group ID + if (tx.fOverwintered) + return state.DoS( + dosLevelPotentiallyRelaxing, + error("CheckTransaction(): invalid Sapling tx version"), + REJECT_INVALID, "bad-sapling-tx-version-group-id"); + } + } else { + // Rules that apply generally before Sapling. These were previously + // noncontextual checks that became contextual after Sapling activation. + // Size limits static_assert(MAX_BLOCK_SIZE > MAX_TX_SIZE_BEFORE_SAPLING); // sanity if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_TX_SIZE_BEFORE_SAPLING) - return state.DoS(100, error("ContextualCheckTransaction(): size limits failed"), - REJECT_INVALID, "bad-txns-oversize"); + return state.DoS( + dosLevelPotentiallyRelaxing, + error("ContextualCheckTransaction(): size limits failed"), + REJECT_INVALID, "bad-txns-oversize"); } uint256 dataToBeSigned; - if (!tx.vShieldedSpend.empty() || - !tx.vShieldedOutput.empty()) + if (!tx.vShieldedSpend.empty() || !tx.vShieldedOutput.empty()) { auto consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams); // Empty output script. CScript scriptCode; - try { + try + { dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, to_integral_type(SIGHASH::ALL), 0, consensusBranchId); - } catch (logic_error ex) { - return state.DoS(100, error("CheckTransaction(): error computing signature hash"), - REJECT_INVALID, "error-computing-signature-hash"); + } catch (logic_error ex) + { + return state.DoS( + DOS_LEVEL_BLOCK, + error("CheckTransaction(): error computing signature hash"), + REJECT_INVALID, "error-computing-signature-hash"); } - } - - if (!tx.vShieldedSpend.empty() || - !tx.vShieldedOutput.empty()) - { auto ctx = librustzcash_sapling_verification_ctx_init(); - for (const auto &spend : tx.vShieldedSpend) { if (!librustzcash_sapling_check_spend( @@ -961,8 +1025,10 @@ bool ContextualCheckTransaction( )) { librustzcash_sapling_verification_ctx_free(ctx); - return state.DoS(100, error("ContextualCheckTransaction(): Sapling spend description invalid"), - REJECT_INVALID, "bad-txns-sapling-spend-description-invalid"); + return state.DoS( + dosLevelPotentiallyRelaxing, + error("ContextualCheckTransaction(): Sapling spend description invalid"), + REJECT_INVALID, "bad-txns-sapling-spend-description-invalid"); } } @@ -977,8 +1043,13 @@ bool ContextualCheckTransaction( )) { librustzcash_sapling_verification_ctx_free(ctx); - return state.DoS(100, error("ContextualCheckTransaction(): Sapling output description invalid"), - REJECT_INVALID, "bad-txns-sapling-output-description-invalid"); + // This should be a non-contextual check, but we check it here + // as we need to pass over the outputs anyway in order to then + // call librustzcash_sapling_final_check(). + return state.DoS( + DOS_LEVEL_BLOCK, + error("ContextualCheckTransaction(): Sapling output description invalid"), + REJECT_INVALID, "bad-txns-sapling-output-description-invalid"); } } @@ -990,8 +1061,10 @@ bool ContextualCheckTransaction( )) { librustzcash_sapling_verification_ctx_free(ctx); - return state.DoS(100, error("ContextualCheckTransaction(): Sapling binding signature invalid"), - REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid"); + return state.DoS( + dosLevelPotentiallyRelaxing, + error("ContextualCheckTransaction(): Sapling binding signature invalid"), + REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid"); } librustzcash_sapling_verification_ctx_free(ctx); @@ -1219,9 +1292,9 @@ bool AcceptToMemoryPool( if (!CheckTransaction(tx, state, verifier)) return error("AcceptToMemoryPool [%s]: CheckTransaction failed", hash.ToString()); - // DoS level set to 10 to be more forgiving. // Check transaction contextually against the set of consensus rules which apply in the next block to be mined. - if (!ContextualCheckTransaction(tx, state, chainparams, nextBlockHeight, 10)) + // isMined flag is false + if (!ContextualCheckTransaction(tx, state, chainparams, nextBlockHeight, false)) { if (state.IsRejectCode(REJECT_MISSING_INPUTS)) { @@ -1315,7 +1388,7 @@ bool AcceptToMemoryPool( // are the sapling spends requirements met in tx(valid anchors/nullifiers)? if (!view.HaveShieldedRequirements(tx)) return state.Invalid(error("AcceptToMemoryPool [%s]: sapling spends requirements not met", hash.ToString()), - REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); + REJECT_DUPLICATE, "bad-txns-shielded-requirements-not-met"); // Bring the best block into scope view.GetBestBlock(); @@ -1444,16 +1517,17 @@ bool AcceptToMemoryPool( /** * Search for transaction by txid (transaction hash) and return in txOut. - * If transaction was found inside a block, its hash is placed in hashBlock. + * If transaction was found inside a block, its hash (txid) is placed in hashBlock. * If blockIndex is provided, the transaction is fetched from the corresponding block. * - * \param hash - transaction hash + * \param hash - transaction hash (txid) * \param txOut - returns transaction object if found (in case GetTransaction returns true) * \param consensusParams - chain consensus parameters * \param hashBlock - returns hash of the found block if the transaction found inside a block * \param fAllowSlow - if true: use coin database to locate block that contains transaction * \param pnBlockHeight - if not nullptr - returns block height if found, or -1 if not * \param blockIndex - optional hint to get transaction from the specified block + * * \return true if transaction was found by hash */ bool GetTransaction(const uint256 &txid, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, @@ -1551,7 +1625,7 @@ bool GetTransaction(const uint256 &txid, CTransaction &txOut, const Consensus::P } } while (false); if (pnBlockHeight) - *pnBlockHeight = nBlockHeight; // if block height is still not defined: -1 will assigned + *pnBlockHeight = nBlockHeight; // if block height is still not defined: -1 will be assigned return bRet; } @@ -1680,8 +1754,11 @@ bool IsInitialBlockDownload(const Consensus::Params& consensusParams) return true; if (chainActive.Tip()->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) return true; - if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) - return true; + if (consensusParams.network != ChainNetwork::REGTEST) + { + if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) + return true; + } LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); latchToFalse.store(true, memory_order_relaxed); return false; @@ -2428,8 +2505,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, const CChainPara // are the shielded requirements met? if (!view.HaveShieldedRequirements(tx)) - return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), - REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); + return state.DoS(100, error("ConnectBlock(): Shielded requirements not met"), + REJECT_INVALID, "bad-txns-shielded-requirements-not-met"); // Add in sigops done by pay-to-script-hash inputs; // this is to prevent a "rogue miner" from creating @@ -3000,7 +3077,7 @@ static bool ActivateBestChainStep(CValidationState &state, const CChainParams& c while (fContinue && nHeight != pindexMostWork->nHeight) { // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need // a few blocks along the way. - int nTargetHeight = min(nHeight + 32, pindexMostWork->nHeight); + const int nTargetHeight = min(nHeight + 32, pindexMostWork->nHeight); vpindexToConnect.clear(); vpindexToConnect.reserve(nTargetHeight - nHeight); CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight); @@ -3624,7 +3701,8 @@ bool ContextualCheckBlock( { // Check transaction contextually against consensus rules at block height - if (!ContextualCheckTransaction(tx, state, chainparams, nHeight, 100)) + // isMined flag is true + if (!ContextualCheckTransaction(tx, state, chainparams, nHeight, true)) return false; // Failure reason has been set in validation state object int nLockTimeFlags = 0; @@ -5120,6 +5198,8 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string } const auto& consensusParams = chainparams.GetConsensus(); + // check if we're in IBD mode + const bool bIsInitialBlockDownload = fnIsInitialBlockDownload(consensusParams); if (strCommand == "version") { // Each connection can only send one version message @@ -5203,7 +5283,7 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string if (!pfrom->fInbound) { // Advertise our address - if (fListen && !fnIsInitialBlockDownload(consensusParams)) + if (fListen && !bIsInitialBlockDownload) { CAddress addr = GetLocalAddress(&pfrom->addr); if (addr.IsRoutable()) @@ -5378,15 +5458,14 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string func_thread_interrupt_point(); pfrom->AddInventoryKnown(inv); - bool fAlreadyHave = AlreadyHave(inv); + const bool fAlreadyHave = AlreadyHave(inv); LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); - if (!fAlreadyHave && !fImporting && !fReindex && inv.type != MSG_BLOCK) - pfrom->AskFor(inv); - - if (inv.type == MSG_BLOCK) { + if (inv.type == MSG_BLOCK) + { UpdateBlockAvailability(pfrom->GetId(), inv.hash); - if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) { + if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) + { // First request the headers preceding the announced block. In the normal fully-synced // case where a new block is announced that succeeds the current tip (no reorganization), // there are no such headers. @@ -5398,7 +5477,8 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), inv.hash); CNodeState *nodestate = State(pfrom->GetId()); if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20 && - nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { + nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) + { vToFetch.push_back(inv); // Mark block as in flight already, even though the actual "getdata" message only goes out // later (within the same cs_main lock, though). @@ -5407,6 +5487,11 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id); } } + else + { + if (!fAlreadyHave && !bIsInitialBlockDownload) + pfrom->AskFor(inv); + } // Track requests for our stuff GetMainSignals().Inventory(inv.hash); @@ -5493,7 +5578,7 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string LOCK(cs_main); - if (fnIsInitialBlockDownload(consensusParams)) + if (bIsInitialBlockDownload) return true; CBlockIndex* pindex = nullptr; @@ -5530,78 +5615,88 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string { CTransaction tx; vRecv >> tx; + const auto& txid = tx.GetHash(); - CInv inv(MSG_TX, tx.GetHash()); - pfrom->AddInventoryKnown(inv); - - LOCK(cs_main); - - bool fMissingInputs = false; - CValidationState state; - - pfrom->setAskFor.erase(inv.hash); - mapAlreadyAskedFor.erase(inv); - - if (!AlreadyHave(inv) && AcceptToMemoryPool(chainparams, mempool, state, tx, true, &fMissingInputs)) - { - mempool.check(pcoinsTip); - RelayTransaction(tx); - LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s: accepted %s (poolsz %u)\n", - pfrom->id, pfrom->cleanSubVer, - tx.GetHash().ToString(), - mempool.mapTx.size()); - - // Recursively process any orphan transactions that depended on this o ne - gl_pOrphanTxManager->ProcessOrphanTxs(chainparams, inv.hash, *recentRejects); - } - // TODO: currently, prohibit shielded spends/outputs from entering mapOrphans - else if (fMissingInputs && - tx.vShieldedSpend.empty() && - tx.vShieldedOutput.empty()) + // skip tx in IBD mode + if (bIsInitialBlockDownload) { - gl_pOrphanTxManager->AddOrphanTx(tx, pfrom->GetId()); - - // DoS prevention: do not allow mapOrphanTransactions to grow unbounded - const size_t nMaxOrphanTx = static_cast(max(0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS))); - const size_t nEvicted = gl_pOrphanTxManager->LimitOrphanTxSize(nMaxOrphanTx); - if (nEvicted > 0) - LogPrint("mempool", "mapOrphan overflow, removed %zu tx\n", nEvicted); + LogPrintf("'tx' message skipped in IBD mode [%s]\n", txid.ToString()); } else { - assert(recentRejects); - recentRejects->insert(tx.GetHash()); + CInv inv(MSG_TX, txid); + pfrom->AddInventoryKnown(inv); - if (pfrom->fWhitelisted) + LOCK(cs_main); + + bool fMissingInputs = false; + CValidationState state; + + pfrom->setAskFor.erase(inv.hash); + mapAlreadyAskedFor.erase(inv); + + if (!AlreadyHave(inv) && AcceptToMemoryPool(chainparams, mempool, state, tx, true, &fMissingInputs)) { - // Always relay transactions received from whitelisted peers, even - // if they were already in the mempool or rejected from it due - // to policy, allowing the node to function as a gateway for - // nodes hidden behind it. - // - // Never relay transactions that we would assign a non-zero DoS - // score for, as we expect peers to do the same with us in that - // case. - int nDoS = 0; - if (!state.IsInvalid(nDoS) || nDoS == 0) { - LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id); - RelayTransaction(tx); - } else { - LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s (code %d))\n", - tx.GetHash().ToString(), pfrom->id, state.GetRejectReason(), state.GetRejectCode()); + mempool.check(pcoinsTip); + RelayTransaction(tx); + LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s: accepted %s (poolsz %u)\n", + pfrom->id, pfrom->cleanSubVer, + txid.ToString(), + mempool.mapTx.size()); + + // Recursively process any orphan transactions that depended on this one + gl_pOrphanTxManager->ProcessOrphanTxs(chainparams, inv.hash, *recentRejects); + } + // TODO: currently, prohibit shielded spends/outputs from entering mapOrphans + else if (fMissingInputs && + tx.vShieldedSpend.empty() && + tx.vShieldedOutput.empty()) + { + gl_pOrphanTxManager->AddOrphanTx(tx, pfrom->GetId()); + + // DoS prevention: do not allow mapOrphanTransactions to grow unbounded + const size_t nMaxOrphanTx = static_cast(max(0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS))); + const size_t nEvicted = gl_pOrphanTxManager->LimitOrphanTxSize(nMaxOrphanTx); + if (nEvicted > 0) + LogPrint("mempool", "mapOrphan overflow, removed %zu tx\n", nEvicted); + } + else + { + assert(recentRejects); + recentRejects->insert(txid); + + if (pfrom->fWhitelisted) + { + // Always relay transactions received from whitelisted peers, even + // if they were already in the mempool or rejected from it due + // to policy, allowing the node to function as a gateway for + // nodes hidden behind it. + // + // Never relay transactions that we would assign a non-zero DoS + // score for, as we expect peers to do the same with us in that + // case. + int nDoS = 0; + if (!state.IsInvalid(nDoS) || nDoS == 0) { + LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", txid.ToString(), pfrom->id); + RelayTransaction(tx); + } + else { + LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s (code %d))\n", + txid.ToString(), pfrom->id, state.GetRejectReason(), state.GetRejectCode()); + } } } - } - int nDoS = 0; - if (state.IsInvalid(nDoS)) - { - LogPrint("mempool", "%s from peer=%d %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(), - pfrom->id, pfrom->cleanSubVer, - state.GetRejectReason()); - pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), - state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); - if (nDoS > 0) - Misbehaving(pfrom->GetId(), nDoS); + int nDoS = 0; + if (state.IsInvalid(nDoS)) + { + LogPrint("mempool", "%s from peer=%d %s was not accepted into the memory pool: %s\n", txid.ToString(), + pfrom->id, pfrom->cleanSubVer, + state.GetRejectReason()); + pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), + state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); + if (nDoS > 0) + Misbehaving(pfrom->GetId(), nDoS); + } } } @@ -5686,7 +5781,7 @@ static bool ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string // unless we're still syncing with the network. // Such an unrequested block may still be processed, subject to the // conditions in AcceptBlock(). - const bool bForceProcessing = pfrom->fWhitelisted && !fnIsInitialBlockDownload(consensusParams); + const bool bForceProcessing = pfrom->fWhitelisted && !bIsInitialBlockDownload; ProcessNewBlock(state, chainparams, pfrom, &block, bForceProcessing); // some input transactions may be missing for this block, in this case ProcessNewBlock // will set rejection code REJECT_MISSING_INPUTS. @@ -6193,7 +6288,8 @@ bool SendMessages(const CChainParams& chainparams, CNode* pto, bool fSendTrickle pto->PushMessage("addr", vAddr); } - CNodeState* pNodeState = State(pto->GetId()); + const NodeId nodeId = pto->GetId(); + CNodeState* pNodeState = State(nodeId); if (!pNodeState) { LogPrintf("Banning unregistered peer %s!\n", pto->addr.ToString()); @@ -6232,7 +6328,7 @@ bool SendMessages(const CChainParams& chainparams, CNode* pto, bool fSendTrickle state.fSyncStarted = true; nSyncStarted++; const auto pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader; - LogPrint("net", "initial getheaders (height=%d) to peer=%d (startheight=%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight); + LogPrint("net", "initial getheaders (height=%d) to peer=%d (startheight=%d)\n", pindexStart->nHeight, nodeId, pto->nStartingHeight); pto->PushMessage("getheaders", chainActive.GetLocator(pindexStart), uint256()); } } @@ -6300,8 +6396,9 @@ bool SendMessages(const CChainParams& chainparams, CNode* pto, bool fSendTrickle // Stalling only triggers when the block download window cannot move. During normal steady state, // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection // should only happen during initial block download. - LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id); + LogPrintf("Peer=%d is stalling block download (%d blocks in-flight), disconnecting\n", nodeId, state.nBlocksInFlight); pto->fDisconnect = true; + state.BlocksInFlightCleanup(nodeId); } // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to @@ -6322,7 +6419,7 @@ bool SendMessages(const CChainParams& chainparams, CNode* pto, bool fSendTrickle // log this only if block download timeout becomes less than some predefined time if (nTimeoutIfRequestedNow - nNow < BLOCK_STALLING_LOG_TIMEOUT_MICROSECS) LogPrint("net", "Reducing block download timeout for peer=%d block=%s: %" PRIi64 " -> %" PRIi64 "\n", - pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow); + nodeId, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow); queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow; } if (queuedBlock.nTimeDisconnect < nNow) @@ -6343,13 +6440,13 @@ bool SendMessages(const CChainParams& chainparams, CNode* pto, bool fSendTrickle { vector vToDownload; NodeId staller = -1; - FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); + FindNextBlocksToDownload(nodeId, MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); for (auto pindex : vToDownload) { vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); - MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); + MarkBlockAsInFlight(nodeId, pindex->GetBlockHash(), consensusParams, pindex); LogPrint("net", "Requesting block %s (height=%d) from peer=%d\n", pindex->GetBlockHash().ToString(), - pindex->nHeight, pto->id); + pindex->nHeight, nodeId); } if (state.nBlocksInFlight == 0 && staller != -1) { @@ -6370,7 +6467,7 @@ bool SendMessages(const CChainParams& chainparams, CNode* pto, bool fSendTrickle if (!AlreadyHave(inv)) { if (fDebug) - LogPrint("net", "Requesting %s from peer=%d\n", inv.ToString(), pto->id); + LogPrint("net", "Requesting %s from peer=%d\n", inv.ToString(), nodeId); vGetData.push_back(inv); if (vGetData.size() >= 1000) { diff --git a/src/main.h b/src/main.h index de5e470ff..720bae74e 100644 --- a/src/main.h +++ b/src/main.h @@ -382,8 +382,8 @@ bool ContextualCheckTransaction( const CTransaction& tx, CValidationState &state, const CChainParams& chainparams, - int nHeight, - int dosLevel, + const int nHeight, + const bool isMined, funcIsInitialBlockDownload_t isInitBlockDownload = fnIsInitialBlockDownload); /** Apply the effects of this transaction on the UTXO set represented by view */ diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index a1c934821..8c8b8e7a7 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2018 The Zcash developers +// Copyright (c) 2018-2022 The Pastel Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -46,8 +47,11 @@ string TransactionBuilderResult::GetError() { TransactionBuilder::TransactionBuilder( const Consensus::Params& consensusParams, - int nHeight, - CKeyStore* keystore) : consensusParams(consensusParams), nHeight(nHeight), keystore(keystore) + const int nHeight, + CKeyStore* keystore) : + consensusParams(consensusParams), + nHeight(nHeight), + keystore(keystore) { mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight); } @@ -262,7 +266,7 @@ TransactionBuilderResult TransactionBuilder::Build() // Signatures // - auto consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams); + const auto consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams); // Empty output script. uint256 dataToBeSigned; diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 70354aef8..306ec0239 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -1,21 +1,20 @@ +#pragma once // Copyright (c) 2018 The Zcash developers +// Copyright (c) 2018-2022 The Pastel Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef TRANSACTION_BUILDER_H -#define TRANSACTION_BUILDER_H +// file COPYING or https://www.opensource.org/licenses/mit-license.php. +#include +#include #include #include #include #include