aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/blockencodings_tests.cpp19
-rw-r--r--src/test/blockfilter_index_tests.cpp8
-rw-r--r--src/test/dbwrapper_tests.cpp36
-rw-r--r--src/test/denialofservice_tests.cpp10
-rw-r--r--src/test/fuzz/coins_view.cpp294
-rw-r--r--src/test/fuzz/fuzz.cpp2
-rw-r--r--src/test/fuzz/process_message.cpp4
-rw-r--r--src/test/fuzz/string.cpp4
-rw-r--r--src/test/fuzz/util.h12
-rw-r--r--src/test/miner_tests.cpp2
-rw-r--r--src/test/ref_tests.cpp33
-rw-r--r--src/test/rpc_tests.cpp14
-rw-r--r--src/test/serialize_tests.cpp23
-rw-r--r--src/test/util/mining.cpp2
-rw-r--r--src/test/util/setup_common.cpp14
-rw-r--r--src/test/validation_block_tests.cpp14
16 files changed, 409 insertions, 82 deletions
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 8694891a51..14cf1a4a76 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -132,24 +132,7 @@ public:
return base.GetShortID(txhash);
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(header);
- READWRITE(nonce);
- size_t shorttxids_size = shorttxids.size();
- READWRITE(VARINT(shorttxids_size));
- shorttxids.resize(shorttxids_size);
- for (size_t i = 0; i < shorttxids.size(); i++) {
- uint32_t lsb = shorttxids[i] & 0xffffffff;
- uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
- READWRITE(lsb);
- READWRITE(msb);
- shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
- }
- READWRITE(prefilledtxn);
- }
+ SERIALIZE_METHODS(TestHeaderAndShortIDs, obj) { READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<CBlockHeaderAndShortTxIDs::SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); }
};
BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
index e5043f6816..7dff2e6e86 100644
--- a/src/test/blockfilter_index_tests.cpp
+++ b/src/test/blockfilter_index_tests.cpp
@@ -94,7 +94,7 @@ bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex,
CBlockHeader header = block->GetBlockHeader();
BlockValidationState state;
- if (!ProcessNewBlockHeaders({header}, state, Params(), &pindex)) {
+ if (!EnsureChainman(m_node).ProcessNewBlockHeaders({header}, state, Params(), &pindex)) {
return false;
}
}
@@ -171,7 +171,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
uint256 chainA_last_header = last_header;
for (size_t i = 0; i < 2; i++) {
const auto& block = chainA[i];
- BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+ BOOST_REQUIRE(EnsureChainman(m_node).ProcessNewBlock(Params(), block, true, nullptr));
}
for (size_t i = 0; i < 2; i++) {
const auto& block = chainA[i];
@@ -189,7 +189,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
uint256 chainB_last_header = last_header;
for (size_t i = 0; i < 3; i++) {
const auto& block = chainB[i];
- BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+ BOOST_REQUIRE(EnsureChainman(m_node).ProcessNewBlock(Params(), block, true, nullptr));
}
for (size_t i = 0; i < 3; i++) {
const auto& block = chainB[i];
@@ -220,7 +220,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
// Reorg back to chain A.
for (size_t i = 2; i < 4; i++) {
const auto& block = chainA[i];
- BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr));
+ BOOST_REQUIRE(EnsureChainman(m_node).ProcessNewBlock(Params(), block, true, nullptr));
}
// Check that chain A and B blocks can be retrieved.
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index c378546e8b..3d802cbeb3 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -331,24 +331,26 @@ struct StringContentsSerializer {
}
StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- if (ser_action.ForRead()) {
- str.clear();
- char c = 0;
- while (true) {
- try {
- READWRITE(c);
- str.push_back(c);
- } catch (const std::ios_base::failure&) {
- break;
- }
+ template<typename Stream>
+ void Serialize(Stream& s) const
+ {
+ for (size_t i = 0; i < str.size(); i++) {
+ s << str[i];
+ }
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream& s)
+ {
+ str.clear();
+ char c = 0;
+ while (true) {
+ try {
+ s >> c;
+ str.push_back(c);
+ } catch (const std::ios_base::failure&) {
+ break;
}
- } else {
- for (size_t i = 0; i < str.size(); i++)
- READWRITE(str[i]);
}
}
};
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index 75b38670c9..348b170536 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -78,7 +78,7 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, *m_node.scheduler, *m_node.mempool);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -148,7 +148,7 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, *m_node.scheduler, *m_node.mempool);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
const Consensus::Params& consensusParams = Params().GetConsensus();
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
@@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
{
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.mempool);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
{
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.mempool);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
banman->ClearBanned();
gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
@@ -323,7 +323,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
{
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.mempool);
+ auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
banman->ClearBanned();
int64_t nStartTime = GetTime();
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
new file mode 100644
index 0000000000..52dd62a145
--- /dev/null
+++ b/src/test/fuzz/coins_view.cpp
@@ -0,0 +1,294 @@
+// Copyright (c) 2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <amount.h>
+#include <chainparams.h>
+#include <chainparamsbase.h>
+#include <coins.h>
+#include <consensus/tx_verify.h>
+#include <consensus/validation.h>
+#include <key.h>
+#include <node/coinstats.h>
+#include <policy/policy.h>
+#include <primitives/transaction.h>
+#include <pubkey.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <validation.h>
+
+#include <cstdint>
+#include <limits>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace {
+const Coin EMPTY_COIN{};
+
+bool operator==(const Coin& a, const Coin& b)
+{
+ if (a.IsSpent() && b.IsSpent()) return true;
+ return a.fCoinBase == b.fCoinBase && a.nHeight == b.nHeight && a.out == b.out;
+}
+} // namespace
+
+void initialize()
+{
+ static const ECCVerifyHandle ecc_verify_handle;
+ ECC_Start();
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+void test_one_input(const std::vector<uint8_t>& buffer)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ CCoinsView backend_coins_view;
+ CCoinsViewCache coins_view_cache{&backend_coins_view};
+ COutPoint random_out_point;
+ Coin random_coin;
+ CMutableTransaction random_mutable_transaction;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 9)) {
+ case 0: {
+ if (random_coin.IsSpent()) {
+ break;
+ }
+ Coin coin = random_coin;
+ bool expected_code_path = false;
+ const bool possible_overwrite = fuzzed_data_provider.ConsumeBool();
+ try {
+ coins_view_cache.AddCoin(random_out_point, std::move(coin), possible_overwrite);
+ expected_code_path = true;
+ } catch (const std::logic_error& e) {
+ if (e.what() == std::string{"Attempted to overwrite an unspent coin (when possible_overwrite is false)"}) {
+ assert(!possible_overwrite);
+ expected_code_path = true;
+ }
+ }
+ assert(expected_code_path);
+ break;
+ }
+ case 1: {
+ (void)coins_view_cache.Flush();
+ break;
+ }
+ case 2: {
+ coins_view_cache.SetBestBlock(ConsumeUInt256(fuzzed_data_provider));
+ break;
+ }
+ case 3: {
+ Coin move_to;
+ (void)coins_view_cache.SpendCoin(random_out_point, fuzzed_data_provider.ConsumeBool() ? &move_to : nullptr);
+ break;
+ }
+ case 4: {
+ coins_view_cache.Uncache(random_out_point);
+ break;
+ }
+ case 5: {
+ if (fuzzed_data_provider.ConsumeBool()) {
+ backend_coins_view = CCoinsView{};
+ }
+ coins_view_cache.SetBackend(backend_coins_view);
+ break;
+ }
+ case 6: {
+ const std::optional<COutPoint> opt_out_point = ConsumeDeserializable<COutPoint>(fuzzed_data_provider);
+ if (!opt_out_point) {
+ break;
+ }
+ random_out_point = *opt_out_point;
+ break;
+ }
+ case 7: {
+ const std::optional<Coin> opt_coin = ConsumeDeserializable<Coin>(fuzzed_data_provider);
+ if (!opt_coin) {
+ break;
+ }
+ random_coin = *opt_coin;
+ break;
+ }
+ case 8: {
+ const std::optional<CMutableTransaction> opt_mutable_transaction = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
+ if (!opt_mutable_transaction) {
+ break;
+ }
+ random_mutable_transaction = *opt_mutable_transaction;
+ break;
+ }
+ case 9: {
+ CCoinsMap coins_map;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ CCoinsCacheEntry coins_cache_entry;
+ coins_cache_entry.flags = fuzzed_data_provider.ConsumeIntegral<unsigned char>();
+ if (fuzzed_data_provider.ConsumeBool()) {
+ coins_cache_entry.coin = random_coin;
+ } else {
+ const std::optional<Coin> opt_coin = ConsumeDeserializable<Coin>(fuzzed_data_provider);
+ if (!opt_coin) {
+ break;
+ }
+ coins_cache_entry.coin = *opt_coin;
+ }
+ coins_map.emplace(random_out_point, std::move(coins_cache_entry));
+ }
+ bool expected_code_path = false;
+ try {
+ coins_view_cache.BatchWrite(coins_map, fuzzed_data_provider.ConsumeBool() ? ConsumeUInt256(fuzzed_data_provider) : coins_view_cache.GetBestBlock());
+ expected_code_path = true;
+ } catch (const std::logic_error& e) {
+ if (e.what() == std::string{"FRESH flag misapplied to coin that exists in parent cache"}) {
+ expected_code_path = true;
+ }
+ }
+ assert(expected_code_path);
+ break;
+ }
+ }
+ }
+
+ {
+ const Coin& coin_using_access_coin = coins_view_cache.AccessCoin(random_out_point);
+ const bool exists_using_access_coin = !(coin_using_access_coin == EMPTY_COIN);
+ const bool exists_using_have_coin = coins_view_cache.HaveCoin(random_out_point);
+ const bool exists_using_have_coin_in_cache = coins_view_cache.HaveCoinInCache(random_out_point);
+ Coin coin_using_get_coin;
+ const bool exists_using_get_coin = coins_view_cache.GetCoin(random_out_point, coin_using_get_coin);
+ if (exists_using_get_coin) {
+ assert(coin_using_get_coin == coin_using_access_coin);
+ }
+ assert((exists_using_access_coin && exists_using_have_coin_in_cache && exists_using_have_coin && exists_using_get_coin) ||
+ (!exists_using_access_coin && !exists_using_have_coin_in_cache && !exists_using_have_coin && !exists_using_get_coin));
+ const bool exists_using_have_coin_in_backend = backend_coins_view.HaveCoin(random_out_point);
+ if (exists_using_have_coin_in_backend) {
+ assert(exists_using_have_coin);
+ }
+ Coin coin_using_backend_get_coin;
+ if (backend_coins_view.GetCoin(random_out_point, coin_using_backend_get_coin)) {
+ assert(exists_using_have_coin_in_backend);
+ assert(coin_using_get_coin == coin_using_backend_get_coin);
+ } else {
+ assert(!exists_using_have_coin_in_backend);
+ }
+ }
+
+ {
+ bool expected_code_path = false;
+ try {
+ (void)coins_view_cache.Cursor();
+ } catch (const std::logic_error&) {
+ expected_code_path = true;
+ }
+ assert(expected_code_path);
+ (void)coins_view_cache.DynamicMemoryUsage();
+ (void)coins_view_cache.EstimateSize();
+ (void)coins_view_cache.GetBestBlock();
+ (void)coins_view_cache.GetCacheSize();
+ (void)coins_view_cache.GetHeadBlocks();
+ (void)coins_view_cache.HaveInputs(CTransaction{random_mutable_transaction});
+ }
+
+ {
+ const CCoinsViewCursor* coins_view_cursor = backend_coins_view.Cursor();
+ assert(coins_view_cursor == nullptr);
+ (void)backend_coins_view.EstimateSize();
+ (void)backend_coins_view.GetBestBlock();
+ (void)backend_coins_view.GetHeadBlocks();
+ }
+
+ if (fuzzed_data_provider.ConsumeBool()) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 6)) {
+ case 0: {
+ const CTransaction transaction{random_mutable_transaction};
+ bool is_spent = false;
+ for (const CTxOut& tx_out : transaction.vout) {
+ if (Coin{tx_out, 0, transaction.IsCoinBase()}.IsSpent()) {
+ is_spent = true;
+ }
+ }
+ if (is_spent) {
+ // Avoid:
+ // coins.cpp:69: void CCoinsViewCache::AddCoin(const COutPoint &, Coin &&, bool): Assertion `!coin.IsSpent()' failed.
+ break;
+ }
+ bool expected_code_path = false;
+ const int height = fuzzed_data_provider.ConsumeIntegral<int>();
+ const bool possible_overwrite = fuzzed_data_provider.ConsumeBool();
+ try {
+ AddCoins(coins_view_cache, transaction, height, possible_overwrite);
+ expected_code_path = true;
+ } catch (const std::logic_error& e) {
+ if (e.what() == std::string{"Attempted to overwrite an unspent coin (when possible_overwrite is false)"}) {
+ assert(!possible_overwrite);
+ expected_code_path = true;
+ }
+ }
+ assert(expected_code_path);
+ break;
+ }
+ case 1: {
+ (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache);
+ break;
+ }
+ case 2: {
+ TxValidationState state;
+ CAmount tx_fee_out;
+ const CTransaction transaction{random_mutable_transaction};
+ if (ContainsSpentInput(transaction, coins_view_cache)) {
+ // Avoid:
+ // consensus/tx_verify.cpp:171: bool Consensus::CheckTxInputs(const CTransaction &, TxValidationState &, const CCoinsViewCache &, int, CAmount &): Assertion `!coin.IsSpent()' failed.
+ break;
+ }
+ try {
+ (void)Consensus::CheckTxInputs(transaction, state, coins_view_cache, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, std::numeric_limits<int>::max()), tx_fee_out);
+ assert(MoneyRange(tx_fee_out));
+ } catch (const std::runtime_error&) {
+ }
+ break;
+ }
+ case 3: {
+ const CTransaction transaction{random_mutable_transaction};
+ if (ContainsSpentInput(transaction, coins_view_cache)) {
+ // Avoid:
+ // consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed.
+ break;
+ }
+ (void)GetP2SHSigOpCount(transaction, coins_view_cache);
+ break;
+ }
+ case 4: {
+ const CTransaction transaction{random_mutable_transaction};
+ if (ContainsSpentInput(transaction, coins_view_cache)) {
+ // Avoid:
+ // consensus/tx_verify.cpp:130: unsigned int GetP2SHSigOpCount(const CTransaction &, const CCoinsViewCache &): Assertion `!coin.IsSpent()' failed.
+ break;
+ }
+ const int flags = fuzzed_data_provider.ConsumeIntegral<int>();
+ if (!transaction.vin.empty() && (flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) {
+ // Avoid:
+ // script/interpreter.cpp:1705: size_t CountWitnessSigOps(const CScript &, const CScript &, const CScriptWitness *, unsigned int): Assertion `(flags & SCRIPT_VERIFY_P2SH) != 0' failed.
+ break;
+ }
+ (void)GetTransactionSigOpCost(transaction, coins_view_cache, flags);
+ break;
+ }
+ case 5: {
+ CCoinsStats stats;
+ bool expected_code_path = false;
+ try {
+ (void)GetUTXOStats(&coins_view_cache, stats);
+ } catch (const std::logic_error&) {
+ expected_code_path = true;
+ }
+ assert(expected_code_path);
+ break;
+ }
+ case 6: {
+ (void)IsWitnessStandard(CTransaction{random_mutable_transaction}, coins_view_cache);
+ break;
+ }
+ }
+ }
+}
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index 6e2188fe86..82e1d55c0b 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -19,8 +19,6 @@ static bool read_stdin(std::vector<uint8_t>& data)
ssize_t length = 0;
while ((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
data.insert(data.end(), buffer, buffer + length);
-
- if (data.size() > (1 << 20)) return false;
}
return length == 0;
}
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index c03365199a..665a6224b4 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -29,7 +29,7 @@
#include <string>
#include <vector>
-bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc);
+bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, ChainstateManager& chainman, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc);
namespace {
@@ -74,7 +74,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
p2p_node.SetSendVersion(PROTOCOL_VERSION);
g_setup->m_node.peer_logic->InitializeNode(&p2p_node);
try {
- (void)ProcessMessage(&p2p_node, random_message_type, random_bytes_data_stream, GetTimeMillis(), Params(), *g_setup->m_node.mempool, g_setup->m_node.connman.get(), g_setup->m_node.banman.get(), std::atomic<bool>{false});
+ (void)ProcessMessage(&p2p_node, random_message_type, random_bytes_data_stream, GetTimeMillis(), Params(), *g_setup->m_node.chainman, *g_setup->m_node.mempool, g_setup->m_node.connman.get(), g_setup->m_node.banman.get(), std::atomic<bool>{false});
} catch (const std::ios_base::failure&) {
}
SyncWithValidationInterfaceQueue();
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index 3c1f911f7e..50984b1aef 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -93,7 +93,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
{
CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
std::string s;
- LimitedString<10> limited_string = LIMITED_STRING(s, 10);
+ auto limited_string = LIMITED_STRING(s, 10);
data_stream << random_string_1;
try {
data_stream >> limited_string;
@@ -108,7 +108,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
{
CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
- const LimitedString<10> limited_string = LIMITED_STRING(random_string_1, 10);
+ const auto limited_string = LIMITED_STRING(random_string_1, 10);
data_stream << limited_string;
std::string deserialized_string;
data_stream >> deserialized_string;
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index f72d9380eb..9d0fb02128 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -8,6 +8,7 @@
#include <amount.h>
#include <arith_uint256.h>
#include <attributes.h>
+#include <coins.h>
#include <consensus/consensus.h>
#include <primitives/transaction.h>
#include <script/script.h>
@@ -149,4 +150,15 @@ NODISCARD bool AdditionOverflow(const T i, const T j) noexcept
return std::numeric_limits<T>::max() - i < j;
}
+NODISCARD inline bool ContainsSpentInput(const CTransaction& tx, const CCoinsViewCache& inputs) noexcept
+{
+ for (const CTxIn& tx_in : tx.vin) {
+ const Coin& coin = inputs.AccessCoin(tx_in.prevout);
+ if (coin.IsSpent()) {
+ return true;
+ }
+ }
+ return false;
+}
+
#endif // BITCOIN_TEST_FUZZ_UTIL_H
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 9f3ca87206..57eee94330 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -253,7 +253,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->nNonce = blockinfo[i].nonce;
}
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
- BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, nullptr));
+ BOOST_CHECK(EnsureChainman(m_node).ProcessNewBlock(chainparams, shared_pblock, true, nullptr));
pblock->hashPrevBlock = pblock->GetHash();
}
diff --git a/src/test/ref_tests.cpp b/src/test/ref_tests.cpp
new file mode 100644
index 0000000000..0ec0799fbc
--- /dev/null
+++ b/src/test/ref_tests.cpp
@@ -0,0 +1,33 @@
+// Copyright (c) 2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/ref.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(ref_tests)
+
+BOOST_AUTO_TEST_CASE(ref_test)
+{
+ util::Ref ref;
+ BOOST_CHECK(!ref.Has<int>());
+ BOOST_CHECK_THROW(ref.Get<int>(), NonFatalCheckError);
+ int value = 5;
+ ref.Set(value);
+ BOOST_CHECK(ref.Has<int>());
+ BOOST_CHECK_EQUAL(ref.Get<int>(), 5);
+ ++ref.Get<int>();
+ BOOST_CHECK_EQUAL(ref.Get<int>(), 6);
+ BOOST_CHECK_EQUAL(value, 6);
+ ++value;
+ BOOST_CHECK_EQUAL(value, 7);
+ BOOST_CHECK_EQUAL(ref.Get<int>(), 7);
+ BOOST_CHECK(!ref.Has<bool>());
+ BOOST_CHECK_THROW(ref.Get<bool>(), NonFatalCheckError);
+ ref.Clear();
+ BOOST_CHECK(!ref.Has<int>());
+ BOOST_CHECK_THROW(ref.Get<int>(), NonFatalCheckError);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index d9c66f1c19..b54cbb3f00 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -10,6 +10,7 @@
#include <interfaces/chain.h>
#include <node/context.h>
#include <test/util/setup_common.h>
+#include <util/ref.h>
#include <util/time.h>
#include <boost/algorithm/string.hpp>
@@ -19,13 +20,20 @@
#include <rpc/blockchain.h>
-UniValue CallRPC(std::string args)
+class RPCTestingSetup : public TestingSetup
+{
+public:
+ UniValue CallRPC(std::string args);
+};
+
+UniValue RPCTestingSetup::CallRPC(std::string args)
{
std::vector<std::string> vArgs;
boost::split(vArgs, args, boost::is_any_of(" \t"));
std::string strMethod = vArgs[0];
vArgs.erase(vArgs.begin());
- JSONRPCRequest request;
+ util::Ref context{m_node};
+ JSONRPCRequest request(context);
request.strMethod = strMethod;
request.params = RPCConvertValues(strMethod, vArgs);
request.fHelp = false;
@@ -40,7 +48,7 @@ UniValue CallRPC(std::string args)
}
-BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(rpc_tests, RPCTestingSetup)
BOOST_AUTO_TEST_CASE(rpc_rawparams)
{
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 9a6c721ab8..c2328f931c 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -29,15 +29,13 @@ public:
memcpy(charstrval, charstrvalin, sizeof(charstrval));
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(intval);
- READWRITE(boolval);
- READWRITE(stringval);
- READWRITE(charstrval);
- READWRITE(txval);
+ SERIALIZE_METHODS(CSerializeMethodsTestSingle, obj)
+ {
+ READWRITE(obj.intval);
+ READWRITE(obj.boolval);
+ READWRITE(obj.stringval);
+ READWRITE(obj.charstrval);
+ READWRITE(obj.txval);
}
bool operator==(const CSerializeMethodsTestSingle& rhs)
@@ -54,11 +52,10 @@ class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
{
public:
using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle;
- ADD_SERIALIZE_METHODS;
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(intval, boolval, stringval, charstrval, txval);
+ SERIALIZE_METHODS(CSerializeMethodsTestMany, obj)
+ {
+ READWRITE(obj.intval, obj.boolval, obj.stringval, obj.charstrval, obj.txval);
}
};
diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp
index 1df6844062..dac7f1a07b 100644
--- a/src/test/util/mining.cpp
+++ b/src/test/util/mining.cpp
@@ -31,7 +31,7 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
assert(block->nNonce);
}
- bool processed{ProcessNewBlock(Params(), block, true, nullptr)};
+ bool processed{EnsureChainman(node).ProcessNewBlock(Params(), block, true, nullptr)};
assert(processed);
return CTxIn{block->vtx[0]->GetHash(), 0};
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index bf0afc4171..3b7a7c8d12 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -123,7 +123,6 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
const CChainParams& chainparams = Params();
// Ideally we'd move all the RPC tests to the functional testing framework
// instead of unit tests, but for now we need these here.
- g_rpc_node = &m_node;
RegisterAllCoreRPCCommands(tableRPC);
m_node.scheduler = MakeUnique<CScheduler>();
@@ -131,11 +130,12 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
// We have to run a scheduler thread to prevent ActivateBestChain
// from blocking due to queue overrun.
threadGroup.create_thread([&]{ m_node.scheduler->serviceQueue(); });
- GetMainSignals().RegisterBackgroundSignalScheduler(*g_rpc_node->scheduler);
+ GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler);
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- g_chainman.InitializeChainstate();
+ m_node.chainman = &::g_chainman;
+ m_node.chainman->InitializeChainstate();
::ChainstateActive().InitCoinsDB(
/* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
assert(!::ChainstateActive().CanFlushToDisk());
@@ -161,7 +161,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
m_node.mempool->setSanityCheck(1.0);
m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
- m_node.peer_logic = MakeUnique<PeerLogicValidation>(m_node.connman.get(), m_node.banman.get(), *m_node.scheduler, *m_node.mempool);
+ m_node.peer_logic = MakeUnique<PeerLogicValidation>(m_node.connman.get(), m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
{
CConnman::Options options;
options.m_msgproc = m_node.peer_logic.get();
@@ -176,14 +176,14 @@ TestingSetup::~TestingSetup()
threadGroup.join_all();
GetMainSignals().FlushBackgroundCallbacks();
GetMainSignals().UnregisterBackgroundSignalScheduler();
- g_rpc_node = nullptr;
m_node.connman.reset();
m_node.banman.reset();
m_node.args = nullptr;
m_node.mempool = nullptr;
m_node.scheduler.reset();
UnloadBlockIndex();
- g_chainman.Reset();
+ m_node.chainman->Reset();
+ m_node.chainman = nullptr;
pblocktree.reset();
}
@@ -228,7 +228,7 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransa
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
- ProcessNewBlock(chainparams, shared_pblock, true, nullptr);
+ EnsureChainman(m_node).ProcessNewBlock(chainparams, shared_pblock, true, nullptr);
CBlock result = block;
return result;
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index 899f054b83..45e0c5484e 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -163,10 +163,10 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
std::transform(blocks.begin(), blocks.end(), std::back_inserter(headers), [](std::shared_ptr<const CBlock> b) { return b->GetBlockHeader(); });
// Process all the headers so we understand the toplogy of the chain
- BOOST_CHECK(ProcessNewBlockHeaders(headers, state, Params()));
+ BOOST_CHECK(EnsureChainman(m_node).ProcessNewBlockHeaders(headers, state, Params()));
// Connect the genesis block and drain any outstanding events
- BOOST_CHECK(ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored));
+ BOOST_CHECK(EnsureChainman(m_node).ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored));
SyncWithValidationInterfaceQueue();
// subscribe to events (this subscriber will validate event ordering)
@@ -183,18 +183,18 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
// will subscribe to events generated during block validation and assert on ordering invariance
std::vector<std::thread> threads;
for (int i = 0; i < 10; i++) {
- threads.emplace_back([&blocks]() {
+ threads.emplace_back([&]() {
bool ignored;
FastRandomContext insecure;
for (int i = 0; i < 1000; i++) {
auto block = blocks[insecure.randrange(blocks.size() - 1)];
- ProcessNewBlock(Params(), block, true, &ignored);
+ EnsureChainman(m_node).ProcessNewBlock(Params(), block, true, &ignored);
}
// to make sure that eventually we process the full chain - do it here
for (auto block : blocks) {
if (block->vtx.size() == 1) {
- bool processed = ProcessNewBlock(Params(), block, true, &ignored);
+ bool processed = EnsureChainman(m_node).ProcessNewBlock(Params(), block, true, &ignored);
assert(processed);
}
}
@@ -232,8 +232,8 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
{
bool ignored;
- auto ProcessBlock = [&ignored](std::shared_ptr<const CBlock> block) -> bool {
- return ProcessNewBlock(Params(), block, /* fForceProcessing */ true, /* fNewBlock */ &ignored);
+ auto ProcessBlock = [&](std::shared_ptr<const CBlock> block) -> bool {
+ return EnsureChainman(m_node).ProcessNewBlock(Params(), block, /* fForceProcessing */ true, /* fNewBlock */ &ignored);
};
// Process all mined blocks