diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 3f340724a..36c4d17ff 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -1,221 +1,221 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // Unit tests for denial-of-service detection/prevention code #include "chainparams.h" #include "config.h" #include "keystore.h" #include "net.h" #include "net_processing.h" #include "pow.h" #include "script/sign.h" #include "serialize.h" #include "util.h" #include "validation.h" #include "test/test_bitcoin.h" #include #include #include // Tests these internal-to-net_processing.cpp methods: extern bool AddOrphanTx(const CTransactionRef &tx, NodeId peer); extern void EraseOrphansFor(NodeId peer); extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); struct COrphanTx { CTransactionRef tx; NodeId fromPeer; int64_t nTimeExpire; }; extern std::map mapOrphanTransactions; CService ip(uint32_t i) { struct in_addr s; s.s_addr = i; return CService(CNetAddr(s), Params().GetDefaultPort()); } static NodeId id = 0; BOOST_FIXTURE_TEST_SUITE(DoS_tests, TestingSetup) BOOST_AUTO_TEST_CASE(DoS_banning) { const Config &config = GetConfig(); std::atomic interruptDummy(false); connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(config, &dummyNode1, *connman); dummyNode1.nVersion = 1; dummyNode1.fSuccessfullyConnected = true; // Should get banned. Misbehaving(dummyNode1.GetId(), 100, ""); SendMessages(config, &dummyNode1, *connman, interruptDummy); BOOST_CHECK(connman->IsBanned(addr1)); // Different IP, not banned. BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001 | 0x0000ff00))); CAddress addr2(ip(0xa0b0c002), NODE_NONE); CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, "", true); dummyNode2.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(config, &dummyNode2, *connman); dummyNode2.nVersion = 1; dummyNode2.fSuccessfullyConnected = true; Misbehaving(dummyNode2.GetId(), 50, ""); SendMessages(config, &dummyNode2, *connman, interruptDummy); // 2 not banned yet... BOOST_CHECK(!connman->IsBanned(addr2)); // ... but 1 still should be. BOOST_CHECK(connman->IsBanned(addr1)); Misbehaving(dummyNode2.GetId(), 50, ""); SendMessages(config, &dummyNode2, *connman, interruptDummy); BOOST_CHECK(connman->IsBanned(addr2)); } BOOST_AUTO_TEST_CASE(DoS_banscore) { const Config &config = GetConfig(); std::atomic interruptDummy(false); connman->ClearBanned(); // because 11 is my favorite number. ForceSetArg("-banscore", "111"); CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(config, &dummyNode1, *connman); dummyNode1.nVersion = 1; dummyNode1.fSuccessfullyConnected = true; Misbehaving(dummyNode1.GetId(), 100, ""); SendMessages(config, &dummyNode1, *connman, interruptDummy); BOOST_CHECK(!connman->IsBanned(addr1)); Misbehaving(dummyNode1.GetId(), 10, ""); SendMessages(config, &dummyNode1, *connman, interruptDummy); BOOST_CHECK(!connman->IsBanned(addr1)); Misbehaving(dummyNode1.GetId(), 1, ""); SendMessages(config, &dummyNode1, *connman, interruptDummy); BOOST_CHECK(connman->IsBanned(addr1)); ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); } BOOST_AUTO_TEST_CASE(DoS_bantime) { const Config &config = GetConfig(); std::atomic interruptDummy(false); connman->ClearBanned(); int64_t nStartTime = GetTime(); // Overrides future calls to GetTime() SetMockTime(nStartTime); CAddress addr(ip(0xa0b0c001), NODE_NONE); CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, "", true); dummyNode.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(config, &dummyNode, *connman); dummyNode.nVersion = 1; dummyNode.fSuccessfullyConnected = true; Misbehaving(dummyNode.GetId(), 100, ""); SendMessages(config, &dummyNode, *connman, interruptDummy); BOOST_CHECK(connman->IsBanned(addr)); SetMockTime(nStartTime + 60 * 60); BOOST_CHECK(connman->IsBanned(addr)); SetMockTime(nStartTime + 60 * 60 * 24 + 1); BOOST_CHECK(!connman->IsBanned(addr)); } CTransactionRef RandomOrphan() { std::map::iterator it; it = mapOrphanTransactions.lower_bound(GetRandHash()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); return it->second.tx; } BOOST_AUTO_TEST_CASE(DoS_mapOrphans) { CKey key; key.MakeNewKey(true); CBasicKeyStore keystore; keystore.AddKey(key); // 50 orphan transactions: for (int i = 0; i < 50; i++) { CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; tx.vin[0].prevout.hash = GetRandHash(); tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); - tx.vout[0].nValue = 1 * CENT.GetSatoshis(); + tx.vout[0].nValue = 1 * CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); AddOrphanTx(MakeTransactionRef(tx), i); } // ... and 50 that depend on other orphans: for (int i = 0; i < 50; i++) { CTransactionRef txPrev = RandomOrphan(); CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; tx.vin[0].prevout.hash = txPrev->GetId(); tx.vout.resize(1); - tx.vout[0].nValue = 1 * CENT.GetSatoshis(); + tx.vout[0].nValue = 1 * CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL); AddOrphanTx(MakeTransactionRef(tx), i); } // This really-big orphan should be ignored: for (int i = 0; i < 10; i++) { CTransactionRef txPrev = RandomOrphan(); CMutableTransaction tx; tx.vout.resize(1); - tx.vout[0].nValue = 1 * CENT.GetSatoshis(); + tx.vout[0].nValue = 1 * CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); tx.vin.resize(2777); for (unsigned int j = 0; j < tx.vin.size(); j++) { tx.vin[j].prevout.n = j; tx.vin[j].prevout.hash = txPrev->GetId(); } SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL); // Re-use same signature for other inputs // (they don't have to be valid for this test) for (unsigned int j = 1; j < tx.vin.size(); j++) tx.vin[j].scriptSig = tx.vin[0].scriptSig; BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i)); } // Test EraseOrphansFor: for (NodeId i = 0; i < 3; i++) { size_t sizeBefore = mapOrphanTransactions.size(); EraseOrphansFor(i); BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore); } // Test LimitOrphanTxSize() function: LimitOrphanTxSize(40); BOOST_CHECK(mapOrphanTransactions.size() <= 40); LimitOrphanTxSize(10); BOOST_CHECK(mapOrphanTransactions.size() <= 10); LimitOrphanTxSize(0); BOOST_CHECK(mapOrphanTransactions.empty()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 5cd84e0bb..3e7ac560f 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -1,128 +1,124 @@ // Copyright (c) 2016 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 "test/test_bitcoin.h" #include BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(AmountTests) { BOOST_CHECK(Amount(2) <= Amount(2)); BOOST_CHECK(Amount(2) <= Amount(3)); BOOST_CHECK(Amount(2) >= Amount(2)); BOOST_CHECK(Amount(3) >= Amount(2)); BOOST_CHECK(Amount(1) < Amount(2)); BOOST_CHECK(Amount(-1) < Amount(0)); BOOST_CHECK(Amount(2) > Amount(1)); BOOST_CHECK(Amount(0) > Amount(-1)); BOOST_CHECK(Amount(1) < Amount(2)); BOOST_CHECK(Amount(-1) < Amount(0)); BOOST_CHECK(Amount(2) > Amount(1)); BOOST_CHECK(Amount(0) > Amount(-1)); BOOST_CHECK(Amount(0) == Amount(0)); BOOST_CHECK(Amount(0) != Amount(1)); Amount amount(0); BOOST_CHECK_EQUAL(amount += Amount(1), Amount(1)); BOOST_CHECK_EQUAL(amount += Amount(-1), Amount(0)); BOOST_CHECK_EQUAL(amount -= Amount(1), Amount(-1)); BOOST_CHECK_EQUAL(amount -= Amount(-1), Amount(0)); BOOST_CHECK_EQUAL(COIN + COIN, Amount(2 * COIN)); BOOST_CHECK_EQUAL(2 * COIN + COIN, Amount(3 * COIN)); BOOST_CHECK_EQUAL(-1 * COIN + COIN, Amount(0)); BOOST_CHECK_EQUAL(COIN - COIN, Amount(0)); BOOST_CHECK_EQUAL(COIN - 2 * COIN, -1 * COIN); BOOST_CHECK_EQUAL(10 * Amount(10), Amount(100)); BOOST_CHECK_EQUAL(-1 * Amount(1), Amount(-1)); BOOST_CHECK_EQUAL(Amount(10) / 3, Amount(3)); BOOST_CHECK_EQUAL(10 * COIN / COIN, 10.0); BOOST_CHECK_EQUAL(Amount(10) / -3, Amount(-3)); BOOST_CHECK_EQUAL(-10 * COIN / (-1 * COIN), 10.0); - BOOST_CHECK_EQUAL(Amount(100).GetSatoshis() / 10, 10); - // This should probably be Banker's rounding, - // but that's a large change - BOOST_CHECK_EQUAL(Amount(100).GetSatoshis() / 3, 33); - BOOST_CHECK_EQUAL(Amount(101).GetSatoshis() / 3, 33); - - // Modulus - BOOST_CHECK_EQUAL(COIN.GetSatoshis() % 1, Amount(0)); - BOOST_CHECK_EQUAL((3 * COIN.GetSatoshis()) % (2 * COIN.GetSatoshis()), - COIN); + BOOST_CHECK_EQUAL(Amount(100) / 10, Amount(10)); + BOOST_CHECK_EQUAL(Amount(100) / 3, Amount(33)); + BOOST_CHECK_EQUAL(Amount(101) / 3, Amount(33)); + + BOOST_CHECK_EQUAL(Amount(100) % 10, Amount(0)); + BOOST_CHECK_EQUAL(Amount(100) % 3, Amount(1)); + BOOST_CHECK_EQUAL(Amount(101) % 3, Amount(2)); } BOOST_AUTO_TEST_CASE(GetFeeTest) { CFeeRate feeRate; - feeRate = CFeeRate(0); + feeRate = CFeeRate(Amount(0)); // Must always return 0 - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), Amount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), Amount(0)); - feeRate = CFeeRate(1000); + feeRate = CFeeRate(Amount(1000)); // Must always just return the arg - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(1), 1); - BOOST_CHECK_EQUAL(feeRate.GetFee(121), 121); - BOOST_CHECK_EQUAL(feeRate.GetFee(999), 999); - BOOST_CHECK_EQUAL(feeRate.GetFee(1000), 1000); - BOOST_CHECK_EQUAL(feeRate.GetFee(9000), 9000); - - feeRate = CFeeRate(-1000); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), Amount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1), Amount(1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), Amount(121)); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), Amount(999)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1000), Amount(1000)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9000), Amount(9000)); + + feeRate = CFeeRate(Amount(-1000)); // Must always just return -1 * arg - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(1), -1); - BOOST_CHECK_EQUAL(feeRate.GetFee(121), -121); - BOOST_CHECK_EQUAL(feeRate.GetFee(999), -999); - BOOST_CHECK_EQUAL(feeRate.GetFee(1000), -1000); - BOOST_CHECK_EQUAL(feeRate.GetFee(9000), -9000); - - feeRate = CFeeRate(123); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), Amount(0)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1), Amount(-1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), Amount(-121)); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), Amount(-999)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1000), Amount(-1000)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9000), Amount(-9000)); + + feeRate = CFeeRate(Amount(123)); // Truncates the result, if not integer - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(8), - 1); // Special case: returns 1 instead of 0 - BOOST_CHECK_EQUAL(feeRate.GetFee(9), 1); - BOOST_CHECK_EQUAL(feeRate.GetFee(121), 14); - BOOST_CHECK_EQUAL(feeRate.GetFee(122), 15); - BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122); - BOOST_CHECK_EQUAL(feeRate.GetFee(1000), 123); - BOOST_CHECK_EQUAL(feeRate.GetFee(9000), 1107); - - feeRate = CFeeRate(-123); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), Amount(0)); + // Special case: returns 1 instead of 0 + BOOST_CHECK_EQUAL(feeRate.GetFee(8), Amount(1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9), Amount(1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(121), Amount(14)); + BOOST_CHECK_EQUAL(feeRate.GetFee(122), Amount(15)); + BOOST_CHECK_EQUAL(feeRate.GetFee(999), Amount(122)); + BOOST_CHECK_EQUAL(feeRate.GetFee(1000), Amount(123)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9000), Amount(1107)); + + feeRate = CFeeRate(Amount(-123)); // Truncates the result, if not integer - BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0); - BOOST_CHECK_EQUAL(feeRate.GetFee(8), - -1); // Special case: returns -1 instead of 0 - BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1); + BOOST_CHECK_EQUAL(feeRate.GetFee(0), Amount(0)); + // Special case: returns -1 instead of 0 + BOOST_CHECK_EQUAL(feeRate.GetFee(8), Amount(-1)); + BOOST_CHECK_EQUAL(feeRate.GetFee(9), Amount(-1)); // Check full constructor // default value - BOOST_CHECK(CFeeRate(Amount(-1), 1000) == CFeeRate(-1)); - BOOST_CHECK(CFeeRate(Amount(0), 1000) == CFeeRate(0)); - BOOST_CHECK(CFeeRate(Amount(1), 1000) == CFeeRate(1)); + BOOST_CHECK(CFeeRate(Amount(-1), 1000) == CFeeRate(Amount(-1))); + BOOST_CHECK(CFeeRate(Amount(0), 1000) == CFeeRate(Amount(0))); + BOOST_CHECK(CFeeRate(Amount(1), 1000) == CFeeRate(Amount(1))); // lost precision (can only resolve satoshis per kB) - BOOST_CHECK(CFeeRate(Amount(1), 1001) == CFeeRate(0)); - BOOST_CHECK(CFeeRate(Amount(2), 1001) == CFeeRate(1)); + BOOST_CHECK(CFeeRate(Amount(1), 1001) == CFeeRate(Amount(0))); + BOOST_CHECK(CFeeRate(Amount(2), 1001) == CFeeRate(Amount(1))); // some more integer checks - BOOST_CHECK(CFeeRate(Amount(26), 789) == CFeeRate(32)); - BOOST_CHECK(CFeeRate(Amount(27), 789) == CFeeRate(34)); + BOOST_CHECK(CFeeRate(Amount(26), 789) == CFeeRate(Amount(32))); + BOOST_CHECK(CFeeRate(Amount(27), 789) == CFeeRate(Amount(34))); // Maximum size in bytes, should not crash - CFeeRate(MAX_MONEY.GetSatoshis(), std::numeric_limits::max() >> 1) - .GetFeePerK(); + CFeeRate(MAX_MONEY, std::numeric_limits::max() >> 1).GetFeePerK(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockcheck_tests.cpp b/src/test/blockcheck_tests.cpp index e51e7defa..98e978b99 100644 --- a/src/test/blockcheck_tests.cpp +++ b/src/test/blockcheck_tests.cpp @@ -1,99 +1,99 @@ // Copyright (c) 2013-2015 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 "chainparams.h" #include "config.h" #include "consensus/consensus.h" #include "consensus/validation.h" #include "validation.h" #include "test/test_bitcoin.h" #include BOOST_FIXTURE_TEST_SUITE(blockcheck_tests, BasicTestingSetup) static void RunCheckOnBlockImpl(const GlobalConfig &config, const CBlock &block, CValidationState &state, bool expected) { block.fChecked = false; bool fValid = CheckBlock(config, block, state, false, false); BOOST_CHECK_EQUAL(fValid, expected); BOOST_CHECK_EQUAL(fValid, state.IsValid()); } static void RunCheckOnBlock(const GlobalConfig &config, const CBlock &block) { CValidationState state; RunCheckOnBlockImpl(config, block, state, true); } static void RunCheckOnBlock(const GlobalConfig &config, const CBlock &block, const std::string &reason) { CValidationState state; RunCheckOnBlockImpl(config, block, state, false); BOOST_CHECK_EQUAL(state.GetRejectCode(), REJECT_INVALID); BOOST_CHECK_EQUAL(state.GetRejectReason(), reason); } BOOST_AUTO_TEST_CASE(blockfail) { SelectParams(CBaseChainParams::MAIN); // Set max blocksize to default in case other tests left it dirty GlobalConfig config; config.SetMaxBlockSize(DEFAULT_MAX_BLOCK_SIZE); CBlock block; RunCheckOnBlock(config, block, "bad-cb-missing"); CMutableTransaction tx; // Coinbase only. tx.vin.resize(1); tx.vin[0].scriptSig.resize(10); tx.vout.resize(1); - tx.vout[0].nValue = 42; + tx.vout[0].nValue = Amount(42); auto coinbaseTx = CTransaction(tx); block.vtx.resize(1); block.vtx[0] = MakeTransactionRef(tx); RunCheckOnBlock(config, block); // No coinbase tx.vin[0].prevout.hash = GetRandHash(); tx.vin[0].prevout.n = 0; block.vtx[0] = MakeTransactionRef(tx); RunCheckOnBlock(config, block, "bad-cb-missing"); // Invalid coinbase tx = CMutableTransaction(coinbaseTx); tx.vin[0].scriptSig.resize(0); block.vtx[0] = MakeTransactionRef(tx); RunCheckOnBlock(config, block, "bad-cb-length"); // Oversize block. tx = CMutableTransaction(coinbaseTx); block.vtx[0] = MakeTransactionRef(tx); tx.vin[0].prevout.n = 0; auto txSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); auto maxTxCount = ((DEFAULT_MAX_BLOCK_SIZE - 1) / txSize) - 1; for (size_t i = 1; i < maxTxCount; i++) { tx.vin[0].prevout.hash = GetRandHash(); block.vtx.push_back(MakeTransactionRef(tx)); } // Check that at this point, we still accept the block. RunCheckOnBlock(config, block); // But reject it with one more transaction as it goes over the maximum // allowed block size. tx.vin[0].prevout.hash = GetRandHash(); block.vtx.push_back(MakeTransactionRef(tx)); RunCheckOnBlock(config, block, "bad-blk-length"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index ebd5d7783..712738405 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -1,390 +1,390 @@ // Copyright (c) 2011-2016 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 "blockencodings.h" #include "chainparams.h" #include "config.h" #include "consensus/merkle.h" #include "random.h" #include "test/test_bitcoin.h" #include std::vector> extra_txn; struct RegtestingSetup : public TestingSetup { RegtestingSetup() : TestingSetup(CBaseChainParams::REGTEST) {} }; BOOST_FIXTURE_TEST_SUITE(blockencodings_tests, RegtestingSetup) static CBlock BuildBlockTestCase() { CBlock block; CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].scriptSig.resize(10); tx.vout.resize(1); - tx.vout[0].nValue = 42; + tx.vout[0].nValue = Amount(42); block.vtx.resize(3); block.vtx[0] = MakeTransactionRef(tx); block.nVersion = 42; block.hashPrevBlock = GetRandHash(); block.nBits = 0x207fffff; tx.vin[0].prevout.hash = GetRandHash(); tx.vin[0].prevout.n = 0; block.vtx[1] = MakeTransactionRef(tx); tx.vin.resize(10); for (size_t i = 0; i < tx.vin.size(); i++) { tx.vin[i].prevout.hash = GetRandHash(); tx.vin[i].prevout.n = 0; } block.vtx[2] = MakeTransactionRef(tx); bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); GlobalConfig config; while (!CheckProofOfWork(block.GetHash(), block.nBits, config)) { ++block.nNonce; } return block; } // Number of shared use_counts we expect for a tx we havent touched // == 2 (mempool + our copy from the GetSharedTx call) #define SHARED_TX_OFFSET 2 BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) { - CTxMemPool pool(CFeeRate(0)); + CTxMemPool pool(CFeeRate(Amount(0))); TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); pool.addUnchecked(block.vtx[2]->GetId(), entry.FromTx(*block.vtx[2])); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); // Do a simple ShortTxIDs RT { CBlockHeaderAndShortTxIDs shortIDs(block); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(partialBlock.IsTxAvailable(0)); BOOST_CHECK(!partialBlock.IsTxAvailable(1)); BOOST_CHECK(partialBlock.IsTxAvailable(2)); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); size_t poolSize = pool.size(); pool.removeRecursive(*block.vtx[2]); BOOST_CHECK_EQUAL(pool.size(), poolSize - 1); CBlock block2; { // No transactions. PartiallyDownloadedBlock tmp = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); partialBlock = tmp; } // Wrong transaction { // Current implementation doesn't check txn here, but don't require // that. PartiallyDownloadedBlock tmp = partialBlock; partialBlock.FillBlock(block2, {block.vtx[2]}); partialBlock = tmp; } bool mutated; BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated)); CBlock block3; BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString()); BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString()); BOOST_CHECK(!mutated); } } class TestHeaderAndShortIDs { // Utility to encode custom CBlockHeaderAndShortTxIDs public: CBlockHeader header; uint64_t nonce; std::vector shorttxids; std::vector prefilledtxn; TestHeaderAndShortIDs(const CBlockHeaderAndShortTxIDs &orig) { CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << orig; stream >> *this; } TestHeaderAndShortIDs(const CBlock &block) : TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block)) {} uint64_t GetShortID(const uint256 &txhash) const { CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << *this; CBlockHeaderAndShortTxIDs base; stream >> base; return base.GetShortID(txhash); } ADD_SERIALIZE_METHODS; template 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); } }; BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest) { - CTxMemPool pool(CFeeRate(0)); + CTxMemPool pool(CFeeRate(Amount(0))); TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); pool.addUnchecked(block.vtx[2]->GetId(), entry.FromTx(*block.vtx[2])); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); uint256 txhash; // Test with pre-forwarding tx 1, but not coinbase { TestHeaderAndShortIDs shortIDs(block); shortIDs.prefilledtxn.resize(1); shortIDs.prefilledtxn[0] = {1, block.vtx[1]}; shortIDs.shorttxids.resize(2); shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0]->GetId()); shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2]->GetId()); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(!partialBlock.IsTxAvailable(0)); BOOST_CHECK(partialBlock.IsTxAvailable(1)); BOOST_CHECK(partialBlock.IsTxAvailable(2)); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[2]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); CBlock block2; { // No transactions. PartiallyDownloadedBlock tmp = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); partialBlock = tmp; } // Wrong transaction { // Current implementation doesn't check txn here, but don't require // that. PartiallyDownloadedBlock tmp = partialBlock; partialBlock.FillBlock(block2, {block.vtx[1]}); partialBlock = tmp; } bool mutated; BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated)); CBlock block3; PartiallyDownloadedBlock partialBlockCopy = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString()); BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString()); BOOST_CHECK(!mutated); txhash = block.vtx[2]->GetId(); block.vtx.clear(); block2.vtx.clear(); block3.vtx.clear(); // + 1 because of partialBlockCopy. BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); } BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); } BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest) { - CTxMemPool pool(CFeeRate(0)); + CTxMemPool pool(CFeeRate(Amount(0))); TestMemPoolEntryHelper entry; CBlock block(BuildBlockTestCase()); pool.addUnchecked(block.vtx[1]->GetId(), entry.FromTx(*block.vtx[1])); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[1]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); uint256 txhash; // Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool { TestHeaderAndShortIDs shortIDs(block); shortIDs.prefilledtxn.resize(2); shortIDs.prefilledtxn[0] = {0, block.vtx[0]}; // id == 1 as it is 1 after index 1 shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; shortIDs.shorttxids.resize(1); shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1]->GetId()); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(partialBlock.IsTxAvailable(0)); BOOST_CHECK(partialBlock.IsTxAvailable(1)); BOOST_CHECK(partialBlock.IsTxAvailable(2)); BOOST_CHECK_EQUAL( pool.mapTx.find(block.vtx[1]->GetId())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); CBlock block2; PartiallyDownloadedBlock partialBlockCopy = partialBlock; BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); bool mutated; BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); BOOST_CHECK(!mutated); txhash = block.vtx[1]->GetId(); block.vtx.clear(); block2.vtx.clear(); // + 1 because of partialBlockCopy. BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); } BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0); } BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) { - CTxMemPool pool(CFeeRate(0)); + CTxMemPool pool(CFeeRate(Amount(0))); CMutableTransaction coinbase; coinbase.vin.resize(1); coinbase.vin[0].scriptSig.resize(10); coinbase.vout.resize(1); - coinbase.vout[0].nValue = 42; + coinbase.vout[0].nValue = Amount(42); CBlock block; block.vtx.resize(1); block.vtx[0] = MakeTransactionRef(std::move(coinbase)); block.nVersion = 42; block.hashPrevBlock = GetRandHash(); block.nBits = 0x207fffff; bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); GlobalConfig config; while (!CheckProofOfWork(block.GetHash(), block.nBits, config)) { ++block.nNonce; } // Test simple header round-trip with only coinbase { CBlockHeaderAndShortTxIDs shortIDs(block); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << shortIDs; CBlockHeaderAndShortTxIDs shortIDs2; stream >> shortIDs2; PartiallyDownloadedBlock partialBlock(GetConfig(), &pool); BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK); BOOST_CHECK(partialBlock.IsTxAvailable(0)); CBlock block2; std::vector vtx_missing; BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); BOOST_CHECK(!mutated); } } BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BlockTransactionsRequest req1; req1.blockhash = GetRandHash(); req1.indexes.resize(4); req1.indexes[0] = 0; req1.indexes[1] = 1; req1.indexes[2] = 3; req1.indexes[3] = 4; CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << req1; BlockTransactionsRequest req2; stream >> req2; BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString()); BOOST_CHECK_EQUAL(req1.indexes.size(), req2.indexes.size()); BOOST_CHECK_EQUAL(req1.indexes[0], req2.indexes[0]); BOOST_CHECK_EQUAL(req1.indexes[1], req2.indexes[1]); BOOST_CHECK_EQUAL(req1.indexes[2], req2.indexes[2]); BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]); } BOOST_AUTO_TEST_SUITE_END()