diff options
Diffstat (limited to 'src/test')
74 files changed, 2680 insertions, 849 deletions
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 37ff8a9afe..d438537606 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -100,7 +100,7 @@ static CNetAddr ResolveIP(const std::string& ip) return addr; } -static CService ResolveService(const std::string& ip, const int port = 0) +static CService ResolveService(const std::string& ip, uint16_t port = 0) { CService serv; BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port)); diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index d33d668a04..b523173a45 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <util/memory.h> #include <util/system.h> #include <test/util/setup_common.h> @@ -163,7 +162,7 @@ private: BOOST_AUTO_TEST_CASE(lockedpool_tests_mock) { // Test over three virtual arenas, of which one will succeed being locked - std::unique_ptr<LockedPageAllocator> x = MakeUnique<TestLockedPageAllocator>(3, 1); + std::unique_ptr<LockedPageAllocator> x = std::make_unique<TestLockedPageAllocator>(3, 1); LockedPool pool(std::move(x)); BOOST_CHECK(pool.stats().total == 0); BOOST_CHECK(pool.stats().locked == 0); diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp index a2098f4f56..2651e46430 100644 --- a/src/test/bech32_tests.cpp +++ b/src/test/bech32_tests.cpp @@ -10,7 +10,7 @@ BOOST_FIXTURE_TEST_SUITE(bech32_tests, BasicTestingSetup) -BOOST_AUTO_TEST_CASE(bip173_testvectors_valid) +BOOST_AUTO_TEST_CASE(bech32_testvectors_valid) { static const std::string CASES[] = { "A12UEL5L", @@ -22,15 +22,35 @@ BOOST_AUTO_TEST_CASE(bip173_testvectors_valid) "?1ezyfcl", }; for (const std::string& str : CASES) { - auto ret = bech32::Decode(str); - BOOST_CHECK(!ret.first.empty()); - std::string recode = bech32::Encode(ret.first, ret.second); + const auto dec = bech32::Decode(str); + BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32); + std::string recode = bech32::Encode(bech32::Encoding::BECH32, dec.hrp, dec.data); BOOST_CHECK(!recode.empty()); BOOST_CHECK(CaseInsensitiveEqual(str, recode)); } } -BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid) +BOOST_AUTO_TEST_CASE(bech32m_testvectors_valid) +{ + static const std::string CASES[] = { + "A1LQFN3A", + "a1lqfn3a", + "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6", + "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx", + "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8", + "split1checkupstagehandshakeupstreamerranterredcaperredlc445v", + "?1v759aa" + }; + for (const std::string& str : CASES) { + const auto dec = bech32::Decode(str); + BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32M); + std::string recode = bech32::Encode(bech32::Encoding::BECH32M, dec.hrp, dec.data); + BOOST_CHECK(!recode.empty()); + BOOST_CHECK(CaseInsensitiveEqual(str, recode)); + } +} + +BOOST_AUTO_TEST_CASE(bech32_testvectors_invalid) { static const std::string CASES[] = { " 1nwldj5", @@ -49,8 +69,32 @@ BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid) "A12uEL5L", }; for (const std::string& str : CASES) { - auto ret = bech32::Decode(str); - BOOST_CHECK(ret.first.empty()); + const auto dec = bech32::Decode(str); + BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID); + } +} + +BOOST_AUTO_TEST_CASE(bech32m_testvectors_invalid) +{ + static const std::string CASES[] = { + " 1xj0phk", + "\x7f""1g6xzxy", + "\x80""1vctc34", + "an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4", + "qyrz8wqd2c9m", + "1qyrz8wqd2c9m", + "y1b0jsk6g", + "lt1igcx5c0", + "in1muywd", + "mm1crxm3i", + "au1s5cgom", + "M1VUXWEZ", + "16plkw9", + "1p2gdwpf" + }; + for (const std::string& str : CASES) { + const auto dec = bech32::Decode(str); + BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID); } } diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index 633a95ce96..9903ba75cb 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -62,7 +62,7 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev, const CScript& scriptPubKey) { const CChainParams& chainparams = Params(); - std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(*m_node.mempool, chainparams).CreateNewBlock(scriptPubKey); + std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(::ChainstateActive(), *m_node.mempool, chainparams).CreateNewBlock(scriptPubKey); CBlock& block = pblocktemplate->block; block.hashPrevBlock = prev->GetBlockHash(); block.nTime = prev->nTime + 1; diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp index c89cb5488d..2dbca4e8b6 100644 --- a/src/test/bswap_tests.cpp +++ b/src/test/bswap_tests.cpp @@ -11,7 +11,6 @@ BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(bswap_tests) { - // Sibling in bitcoin/src/qt/test/compattests.cpp uint16_t u1 = 0x1234; uint32_t u2 = 0x56789abc; uint64_t u3 = 0xdef0123456789abc; diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 21921375b3..64c6d7f634 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -5,7 +5,6 @@ #include <checkqueue.h> #include <sync.h> #include <test/util/setup_common.h> -#include <util/memory.h> #include <util/system.h> #include <util/time.h> @@ -146,7 +145,7 @@ typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue; */ static void Correct_Queue_range(std::vector<size_t> range) { - auto small_queue = MakeUnique<Correct_Queue>(QUEUE_BATCH_SIZE); + auto small_queue = std::make_unique<Correct_Queue>(QUEUE_BATCH_SIZE); small_queue->StartWorkerThreads(SCRIPT_CHECK_THREADS); // Make vChecks here to save on malloc (this test can be slow...) std::vector<FakeCheckCheckCompletion> vChecks; @@ -206,7 +205,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random) /** Test that failing checks are caught */ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) { - auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE); + auto fail_queue = std::make_unique<Failing_Queue>(QUEUE_BATCH_SIZE); fail_queue->StartWorkerThreads(SCRIPT_CHECK_THREADS); for (size_t i = 0; i < 1001; ++i) { @@ -234,7 +233,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) // future blocks, ie, the bad state is cleared. BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) { - auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE); + auto fail_queue = std::make_unique<Failing_Queue>(QUEUE_BATCH_SIZE); fail_queue->StartWorkerThreads(SCRIPT_CHECK_THREADS); for (auto times = 0; times < 10; ++times) { @@ -258,7 +257,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) // more than once as well BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { - auto queue = MakeUnique<Unique_Queue>(QUEUE_BATCH_SIZE); + auto queue = std::make_unique<Unique_Queue>(QUEUE_BATCH_SIZE); queue->StartWorkerThreads(SCRIPT_CHECK_THREADS); size_t COUNT = 100000; @@ -293,7 +292,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) // time could leave the data hanging across a sequence of blocks. BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { - auto queue = MakeUnique<Memory_Queue>(QUEUE_BATCH_SIZE); + auto queue = std::make_unique<Memory_Queue>(QUEUE_BATCH_SIZE); queue->StartWorkerThreads(SCRIPT_CHECK_THREADS); for (size_t i = 0; i < 1000; ++i) { size_t total = i; @@ -320,7 +319,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) // have been destructed BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) { - auto queue = MakeUnique<FrozenCleanup_Queue>(QUEUE_BATCH_SIZE); + auto queue = std::make_unique<FrozenCleanup_Queue>(QUEUE_BATCH_SIZE); bool fails = false; queue->StartWorkerThreads(SCRIPT_CHECK_THREADS); std::thread t0([&]() { @@ -360,7 +359,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) /** Test that CCheckQueueControl is threadsafe */ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { - auto queue = MakeUnique<Standard_Queue>(QUEUE_BATCH_SIZE); + auto queue = std::make_unique<Standard_Queue>(QUEUE_BATCH_SIZE); { std::vector<std::thread> tg; std::atomic<int> nThreads {0}; diff --git a/src/test/data/key_io_invalid.json b/src/test/data/key_io_invalid.json index 9b52943ac6..abe07dad24 100644 --- a/src/test/data/key_io_invalid.json +++ b/src/test/data/key_io_invalid.json @@ -6,177 +6,207 @@ "x" ], [ - "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y" + "2v7k5Bb8Lr1MMgTgW6HAf5YHXi6BzpPjHpQ4srD4RSwHYpzXKiXmLAgiLhkXvp3JF5v7nq45EWr" ], [ - "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv" + "RAZzCGtMbiUgMiiyrZySrSpdfnQReFXA3r" ], [ - "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S" + "NYamy7tcPQTzoU5iyQojD3sqhiz7zxkvn8" ], [ - "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf" + "geaFG555Ex5nyRf7JjW6Pj2GwZA8KYxtJJLbr1eZhVW75STbYBZeRszy3wg4pkKdF4ez9J4wQiz" ], [ - "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq" + "2Cxmid3c2XQ2zvQ8SA1ha2TKqvqbJS9XFmXRsCneBS3Po7Qqb65z5zNdsoF9AfieXFcpoVPmkmfa" ], [ - "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb" + "gaJ7UVge2njVg9tFTetJrtHgruMm7aQDiSAxfHrVEgzK8N2ooagDVmDkdph434xzc4K96Gjyxcs" ], [ - "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs" + "5JN5BEVQPZ3tAiatz1RGXkrJuE3EC6bervMaPb38wTNgEuZCeqp" ], [ - "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3" + "3TnFbyUtBRS5rE1KTW81qLVspjJNaB3uu6uuvLjxhZo2DB6PCGh" ], [ - "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th" + "7UgSZGaMaTc4d2mdEgcGBFiMeS6eMsithGUqvBsKTQdGzD7XQDbMEYo3gojdbXEPbUdFF3CQoK72f" ], [ - "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va" + "9261wfqQqruNDnBDhbbb4tN9oKA1KpRFHeoYeufyJApVGixyAG4V" ], [ - "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk" + "cS824CTUh18scFmYuqt6BgxuRhdR4dEEnCHs3fzBbcyQgbfasHbw" ], [ - "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs" + "tc1q0ywf7wkz6t580n3yemd3ucfw8jxn93tpc6wskt" ], [ - "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo" + "bt1pxeeuh96wpm5c6u3kavts2qgwlv6y8um7u7ga6ltlwrhrv7w9vers8lgt3k" ], [ - "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso" + "tb130lvl2lyugsk2tf3zhwcjjv39dmwt2tt7ytqaexy8edwcuwks6p5scll5kz" ], [ - "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq" + "bcrt1rhsveeudk" ], [ - "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN" + "bc10rmfwl8nxdweeyc4sf89t0tn9fv9w6qpyzsnl2r4k48vjqh03qas9asdje0rlr0phru0wqw0p" ], [ - "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i" + "tb1qjqnfsuatr54e957xzg9sqk7yqcry9lns" ], [ - "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos" + "bcrt1q8p08mv8echkf3es027u4cdswxlylm3th76ls8v6y4zy4vwsavngpr4e4td" ], [ - "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu" + "BC1QNC2H66VLWTWTW52DP0FYUSNU3QQG5VT4V" ], [ - "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb" + "tb1qgk665m2auw09rc7pqyf7aulcuhmatz9xqtr5mxew7zuysacaascqs9v0vn" ], [ - "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ" + "bcrt17CAPP7" ], [ - "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ" + "bc1qxmf2d6aerjzam3rur0zufqxqnyqfts5u302s7x" ], [ - "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu" + "tb1qn8x5dnzpexq7nnvrvnhwr9c3wkakpcyu9wwsjzq9pstkwg0t6qhs4l3rv6" ], [ - "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU" + "BCRT1Q397G2RNVYRL5LK07CE8NCKHVKP8Z4SC9U0MVH9" ], [ - "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs" + "bc1pgxwyajq0gdn389f69uwn2fw9q0z5c9s063j5dgkdd23ajaud4hpsercr9h" ], [ - "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn" + "tb1z6mnmp5k542l6yk4ul0mp4rq3yvz44lfm" ], [ - "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj" + "bcrt17capp7" ], [ - "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny" + "2D2bqvKseKHdoKjCNvjVULUgmxHu9hjKGwDbPRjTRH59tsHNLeyKwq3vyVBbo9LByY9wiapqjwFY" ], [ - "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc" + "2SSjAim4wZpeQRe5zTj1qqS6Li9ttJDaZ3ze" ], [ - "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ" + "mi9H6MjLwXxy9kxe1x4ToxyLRBsmcZxgVi" ], [ - "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP" + "VciXoxEitcn88jy197J9n9cpJ1pZahzU3SyWUiHqLgcfjttLEEJz" ], [ - "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw" + "KppmwADGoExPT9Eq5hjRWpWFDbzJyfzHFgsfxBiDHNpVBgWPRNuy" ], [ - "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX" + "TN7EQXMxKffzvHo54yHHu9R4ks9f5gWBW3MMVf5k72zAqrgVK9ys" ], [ - "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB" + "92dbrMEYzP5dD5UhQ6maNkCQ4GLG42BM4Gc6XKZzSSMSfosfkkcB" ], [ - "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ" + "J7VQxPxyzuWEkRstQWpCz2AgysEz1APgnWCEQrFvkN3umAnCrhQF" ], [ - "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs" + "tc1qymllj6c96v5qj2504y27ldtner6eh8ldx38t83" ], [ - "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ" + "bt1flep4g" ], [ - "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4" + "tb13c553hwygcgj48qwmr9f8q0hgdcfklyaye5sxzcpcjnmxv4z506xs90tchn" ], [ - "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK" + "bcrt1tyddyu" ], [ - "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig" + "bc10qssq2mknjqf0glwe2f3587wc4jysvs3f8s6chysae6hcl6fxzdm4wxyyscrl5k9f5qmnf05a" ], [ - "EsYbG4tWWWY45G31nox838qNdzksbPySWc" + "tb1q425lmgvxdgtyl2m6xuu2pc354y4fvgg8" ], [ - "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT" + "bcrt1q9wp8e5d2u3u4g0pll0cy7smeeuqezdun9xl439n3p2gg4fvgfvk3hu52hj" ], [ - "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx" + "bc1qrz5acazpue8vl4zsaxn8fxtmeuqmyjkq3" ], [ - "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde" + "tb1qkeuglpgmnex9tv3fr7htzfrh3rwrk23r52rx9halxzmv9fr85lwq0fwhmp" ], [ - "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU" + "bcrt1qd0t2wrhl7s57z99rsyaekpq0dyjcQRSSmz80r4" ], [ - "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf" + "BC1QXLFDUCGX90T3E53PQCNKJ2PK25MSF3VLPMVY6T" ], [ - "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd" + "tb1qmycg4zszgnk34vaurx3cu8wpvteg9h40yq6cp52gt26gjel03t3su3x3xu" ], [ - "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED" + "bcrt1q9hy58r4fnuxqzdqndpmq9pptc9nt2dw3rczf5e" ], [ - "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty" + "BC1PA7682NAY6JQSLUWAJYTC0ERWTMW7A4RPWLNTUS32LCXWLHVKKKTQ2UL8CG" ], [ - "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5" + "tb1z850dpxnwz2fzae5h2myatj4yvu6rq5xq" ], [ - "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2" + "bcrt1sp525pzjsmpqvcrawjreww36e9keg876skjvpwt" ], [ - "bc1rw5uspcuh" + "xcAvW5jurCpzSpLxBKEhCewCgwwuGhqJnC" ], [ - "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90" + "2Cvv8yp9kXbQt8EKh6Yma95yJ1uwYF9YKXuVhGJyu3dHGVsb2AVpTC62TFACZZ3KDNrALxR2CVNs" ], [ - "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P" + "niUuL46hCuEVvkAzZKHvD746qbmLmzip9Pv3F6UZV14JxzEXBnTkVxCT4URapChJG6qAEgsZs6G" ], [ - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7" + "2UHHgGfiipzvB8Eumnmvq6SowvrMJimjT3NwwG1839XEiUfwtpSdkUrseNsQuagXv21ce7aZu6yo" ], [ - "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du" + "8u9djKu4u6o3bsgeR4BKNnLK3akpo64FYzDAmA9239wKeshgF97" ], [ - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv" + "TC1QPAARXSLVMXHVRR0474LZXQYZWLGFZYPSFVL9E4" ], [ - "bc1gmk9yu" + "bt1pakek0n2267t9yaksxaczgr2syhv9y3xkx0wnsdwchfa6xkmjtvuqg3kgyr" + ], + [ + "tb13h83rtwq62udrhwpn87uely7cyxcjrj0azz6a4r3n9s87x5uj98ys6ufp83" + ], + [ + "bcrt1rk5vw5qf2" + ], + [ + "bc10d3rmtg62h747en5j6fju5g5qyvsransrkty6ghh96pu647wumctejlsngh9pf26cysrys2x2" + ], + [ + "tb1qajuy2cdwqgmrzc7la85al5cwcq374tsp" + ], + [ + "bcrt1q3udxvj6x20chqh723mn064mzz65yr56ef00xk8czvu3jnx04ydapzk02s5" + ], + [ + "bc1qule2szwzyaq4qy0s3aa4mauucyqt6fewe" + ], + [ + "tb1ql0qny5vg9gh5tyzke6dw36px5ulkrp24x53x0pl2t5lpwrtejw3s2seej2" + ], + [ + "bcrt17CAPP7" + ], + [ + "bc1qtvm6davyf725wfedc2d5mrgfewqgcrce8gjrpl" + ], + [ + "tb1q5acjgtqrrw3an0dzavxxxzlex8k7aukjzjk9v2u4rmfdqxjphcyq7ge97e" ] ] diff --git a/src/test/data/key_io_valid.json b/src/test/data/key_io_valid.json index 8418a6002d..5dee44c04b 100644 --- a/src/test/data/key_io_valid.json +++ b/src/test/data/key_io_valid.json @@ -1,533 +1,610 @@ [ [ - "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", - "76a91465a16059864a2fdbc7c99a4723a8395bc6f188eb88ac", + "1BShJZ8A5q53oJJfMJoEF1gfZCWdZqZwwD", + "76a914728d4cc27d19707b0197cfcd7c412d43287864b588ac", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isPrivkey": false } ], [ - "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", - "a91474f209f6ea907e2ea48f74fae05782ae8a66525787", + "3L1YkZjdeNSqaZcNKZFXQfyokx3zVYm7r6", + "a914c8f37c3cc21561296ad81f4bec6b5de10ebc185187", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isPrivkey": false } ], [ - "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", - "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac", + "mhJuoGLgnJC8gdBgBzEigsoyG4omQXejPT", + "76a91413a92d1998e081354d36c13ce0c9dc04b865d40a88ac", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isPrivkey": false } ], [ - "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", - "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac", + "2N5VpzKEuYvZJbmg6eUNGnfrrD1ir92FWGu", + "a91486648cc2faaf05660e72c04c7a837bcc3e986f1787", { - "isPrivkey": false, - "chain": "regtest" + "chain": "test", + "isPrivkey": false } ], [ - "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", - "a9146349a418fc4578d10a372b54b45c280cc8c4382f87", + "mtQueCtmAnP3E4aBHXCiFNEQAuPaLMuQNy", + "76a9148d74ecd86c845baf9c6d4484d2d00e731b79e34788ac", { - "isPrivkey": false, - "chain": "test" + "chain": "signet", + "isPrivkey": false + } + ], + [ + "2NEvWRTHjh89gV52fkperFtwzoFWQiQmiCh", + "a914edc895152c67ccff0ba620bcc373b789ec68266f87", + { + "chain": "signet", + "isPrivkey": false } ], [ - "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr", - "eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19", + "mngdx94qJFhSf7A7SAEgQSC9fQJuapujJp", + "76a9144e9dba545455a80ce94c343d1cac9dec62cbf22288ac", { + "chain": "regtest", + "isPrivkey": false + } + ], + [ + "2NBzRN3pV56k3JUvSHifaHyzjGHv7ZS9FZZ", + "a914cd9da5642451273e5b6d088854cc1fad4a8d442187", + { + "chain": "regtest", + "isPrivkey": false + } + ], + [ + "5KcrFZvJ2p4dM6QVUPu53cKXcCfozA1PJLHm1mNAxkDYhgThLu4", + "ed6c796e2f62377410766214f55aa81ac9a6590ad7ed57c509c983bf648409ac", + { + "chain": "main", "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD", - "55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4", + "L195WBrf2G3nCnun4CLxrb8XKk9LbCqH43THh4n4QrL5SzRzpq9j", + "74f76c106e38d20514a99a86e4fe3bb28319e7dd2ad21dbc170cbb516a5358fa", { + "chain": "main", "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", - "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", + "92z6HnMQR4tWqjfVA3UaUN5EuUMgoVMdCa5rZFYZfmgyD7wxYCw", + "b8511e1d74549e305517d48a1d394d1be2cfa5d0f3c0d83f9f450316ffa01276", { + "chain": "test", "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", - "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", + "cTPnaF52x4w4Tq6afPxRHux3wbYb86thS7S45A7r3oZc1AHTQ6Qm", + "ad68c48d337181da125de9061933ececcdf7d917631af7d34f7e38082bff9a11", { + "chain": "test", + "isCompressed": true, + "isPrivkey": true + } + ], + [ + "924U35yFcYkxe2JXGmuhSRVaShGyhRDZx1ysPmw1sAHuszGMoxq", + "3e8dfaf78d4f02b11d0b645648a4f3080d71d0d068979c47f7255c9a29eee01d", + { + "chain": "signet", "isCompressed": false, - "isPrivkey": true, - "chain": "regtest" + "isPrivkey": true } ], [ - "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", - "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3", + "cRy1qCf2LUesGPQagTkYwk2V3PyN2KCPKgxeg6k6KoJPzH7nrVjw", + "82d4187690d6b59bcffda27dae52f2ecb87313cfc0904e0b674a27d906a65fde", { + "chain": "signet", "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", - "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3", + "932NTcHK35Apf2C3K9Zv1ZdeZEmB1x7ZT2Ju3SjoEY6pUgUpT7H", + "bd7dba24df9e003e145ae9b4862776413a0bb6fa5b4e42753397f2d9536e58a9", { - "isCompressed": true, - "isPrivkey": true, - "chain": "regtest" + "chain": "regtest", + "isCompressed": false, + "isPrivkey": true } ], [ - "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", - "76a9146d23156cbbdcc82a5a47eee4c2c7c583c18b6bf488ac", + "cNa75orYQ2oos52zCnMaS5PG6XbNZKc5LpGxTHacrxwWeX4WAK3E", + "1d87e3c58b08766fea03598380ec8d59f8c88d5392bf683ab1088bd4caf073ee", { - "isPrivkey": false, - "chain": "main" + "chain": "regtest", + "isCompressed": true, + "isPrivkey": true } ], [ - "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", - "a914fcc5460dd6e2487c7d75b1963625da0e8f4c597587", + "bc1q5cuatynjmk4szh40mmunszfzh7zrc5xm9w8ccy", + "0014a639d59272ddab015eafdef9380922bf843c50db", { + "chain": "main", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ", - "76a914f1d470f9b02370fdec2e6b708b08ac431bf7a5f788ac", + "bc1qkw7lz3ahms6e0ajv27mzh7g62tchjpmve4afc29u7w49tddydy2syv0087", + "0020b3bdf147b7dc3597f64c57b62bf91a52f179076ccd7a9c28bcf3aa55b5a46915", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", - "a914c579342c2c4c9220205e2cdc285617040c924a0a87", + "bc1p5rgvqejqh9dh37t9g94dd9cm8vtqns7dndgj423egwggsggcdzmsspvr7j", + "5120a0d0c06640b95b78f965416ad6971b3b1609c3cd9b512aaa39439088211868b7", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc", - "a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e", + "bc1zr4pq63udck", + "52021d42", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "main", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi", - "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4", + "tb1q74fxwnvhsue0l8wremgq66xzvn48jlc5zthsvz", + "0014f552674d978732ff9dc3ced00d68c264ea797f14", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj", - "d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203", + "tb1qpt7cqgq8ukv92dcraun9c3n0s3aswrt62vtv8nqmkfpa2tjfghesv9ln74", + "00200afd802007e598553703ef265c466f847b070d7a5316c3cc1bb243d52e4945f3", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN", - "a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9", + "tb1ph9v3e8nxct57hknlkhkz75p5pnxnkn05cw8ewpxu6tek56g29xgqydzfu7", + "5120b9591c9e66c2e9ebda7fb5ec2f50340ccd3b4df4c38f9704dcd2f36a690a2990", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", - "76a9147987ccaa53d02c8873487ef919677cd3db7a691288ac", + "tb1ray6e8gxfx49ers6c4c70l3c8lsxtcmlx", + "5310e93593a0c9354b91c358ae3cffc707fc", { + "chain": "test", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", - "a91463bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb87", + "tb1q0sqzfp3zj42u0perxr6jahhu4y03uw4dypk6sc", + "00147c002486229555c7872330f52edefca91f1e3aad", { + "chain": "signet", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk", - "76a914ef66444b5b17f14e8fae6e7e19b045a78c54fd7988ac", + "tb1q9jv4qnawnuevqaeadn47gkq05ev78m4qg3zqejykdr9u0cm7yutq6gu5dj", + "00202c99504fae9f32c0773d6cebe4580fa659e3eea044440cc89668cbc7e37e2716", { + "chain": "signet", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o", - "a914c3e55fceceaa4391ed2a9677f4a4d34eacd021a087", + "tb1pxqf7d825wjtcftj7uep8w24jq3tz8vudfaqj20rns8ahqya56gcs92eqtu", + "51203013e69d54749784ae5ee642772ab2045623b38d4f41253c7381fb7013b4d231", { + "chain": "signet", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9", - "e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252", + "tb1rsrzkyvu2rt0dcgexajtazlw5nft4j7494ay396q6auw9375wxsrsgag884", + "532080c562338a1adedc2326ec97d17dd49a57597aa5af4912e81aef1c58fa8e3407", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "signet", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT", - "8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c", + "bcrt1qwf52dt9y2sv0f7fwkcpmtfjf74d4np2saeljt6", + "00147268a6aca45418f4f92eb603b5a649f55b598550", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "regtest", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo", - "44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52", + "bcrt1q0lma84unycxl4n96etffthqlf7y5axyp4fxf64kmhymvw8l6pwfs39futd", + "00207ff7d3d793260dfaccbacad295dc1f4f894e9881aa4c9d56dbb936c71ffa0b93", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "regtest", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7", - "d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69", + "bcrt1p3xat2ryucc2v0adrktqnavfzttvezrr27ngltsa2726p2ehvxz4se722v2", + "512089bab50c9cc614c7f5a3b2c13eb1225ad9910c6af4d1f5c3aaf2b41566ec30ab", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "regtest", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", - "76a914adc1cc2081a27206fae25792f28bbc55b831549d88ac", + "bcrt1saflydw6e26xhp29euhy5jke5jjqyywk3wvtc9ulgw9dvxyuqy9hdnxthyw755c7ldavy7u", + "6028ea7e46bb59568d70a8b9e5c9495b349480423ad1731782f3e8715ac31380216ed9997723bd4a63df", { + "chain": "regtest", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", - "a914188f91a931947eddd7432d6e614387e32b24470987", + "16y3Q1XVRZqMR9T1XL1FkvNtD2E1bXBuYa", + "76a9144171ec673aeb9fcf42af6094a3c82207e3b9a78188ac", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isPrivkey": false } ], [ - "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H", - "76a9141694f5bc1a7295b600f40018a618a6ea48eeb49888ac", + "3CmZZnAiHVQgiAKSakf864oJMxN2BP1eLC", + "a914798575fc1041b9440c4e63c28e57e597d00b7e4387", { - "isPrivkey": false, - "chain": "test" + "chain": "main", + "isPrivkey": false } ], [ - "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN", - "a9143b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f387", + "mtCB3SoBo7EYUv8j54kUubGY4x3aJPY8nk", + "76a9148b0c5f9ee714e0d1d24642ad63d9d5f398d9b56588ac", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isPrivkey": false } ], [ - "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR", - "091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0", + "2N5ymzzKpx6EdUR4UdMZ7t9hcuwqtpHwgw5", + "a9148badb3c3b5c0d39f906f7618e0018b7eae4baf7387", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false } ], [ - "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8", - "ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af", + "myXnpYbub28zgiJupDdZSWZtDbjcyfJVby", + "76a914c59ac57661b57daadd7c0caf7318c14f54c6c0fa88ac", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "signet", + "isPrivkey": false } ], [ - "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", - "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", + "2MtLg8jS5jSXm9evMzTtvpLjy26dBmjFEoT", + "a9140c0007e89cea625d3bf9543baa5a470bb7e5b67287", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "signet", + "isPrivkey": false } ], [ - "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", - "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", + "mzCyqdf2UNGdpgkD9NBgLcxdwXRg1i9buY", + "76a914cd04311bdd1ef9c5c24e41930e032aade82a863a88ac", { - "isCompressed": false, - "isPrivkey": true, - "chain": "regtest" + "chain": "regtest", + "isPrivkey": false } ], [ - "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA", - "e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef", + "2N3zGiwFku2vQjYnAqXv5Qu2ztfYRhh7tbF", + "a91475d56d75c88e704d6c72fbe84ac1505abf736b4087", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "regtest", + "isPrivkey": false } ], [ - "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", - "76a914c4c1b72491ede1eedaca00618407ee0b772cad0d88ac", + "5JUHCgyxNSHg64wwju72eNsG6ajqo4Z2fHHw9iLDLfh69rSiL7w", + "5644d06d88855dacf3192a31df8f4acd8e4c155c52a86d2c1fa48303f5cff053", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isCompressed": false, + "isPrivkey": true } ], [ - "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", - "a914f6fe69bcb548a829cce4c57bf6fff8af3a5981f987", + "L2kZaexG69VSriMe9T2m1jkS86iPe3xNbjcdfakRC1PHe7ay78Ji", + "a50ee94aefcabf5a5d7c85be5b3844dee03c5604861dbfc77fe388c91e5a30f8", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isCompressed": true, + "isPrivkey": true } ], [ - "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6", - "76a914261f83568a098a8638844bd7aeca039d5f2352c088ac", + "927JwT1ViCr5TD2ZX8CsMNhg17dXmou5xu4y2KiH54zD7i34UJq", + "4502a54c0026b0150281d41f40860d1e23870c63cdc32645bbed688f2ee41f64", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isCompressed": false, + "isPrivkey": true } ], [ - "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda", - "a914e930e1834a4d234702773951d627cce82fbb5d2e87", + "cTpGGNPVy2Eagawohbr4aGtRJzpLnjxGsGYh9DUcBM45f3KdKGF6", + "ba005a0cb39587aab00bd54c848b59e8adaed47403228567ddc739c2a344ff59", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isCompressed": true, + "isPrivkey": true } ], [ - "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg", - "d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0", + "932PLCLA19yPNqV67qwHBSGjxi82LVzWBF7josL9ab4Q1kxgPGF", + "bd8677e076eb39770bf7e9f9e8d3f2cf257effab9b4c220fd3439ccfc208c984", { + "chain": "signet", "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi", - "b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3", + "cViUpEy8URSsLjUvxwL7cEuNgCVqM7oKBzd1ZPbA4khcQsQJuj1j", + "f2b36ade8393e29dc71e52cb75ba1109ba210203cd7d0a5ae881ad6846516203", { + "chain": "signet", "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys", - "037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb", + "92jddDjJCVDmJtgvBHQ9i58PMash8kwsYhRdNo22ea2MYPXdCBE", + "977bf8686f1bcad28f86c4c14afbd33215746bd19203647bf7ff9c6fddc9cc87", { + "chain": "regtest", "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw", - "6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de", + "cVwAuMoUqRo399X7vXzuzQyPEvZJMXM8c82zHzRkFCxPCSGx8A6y", + "f93acbbce02b8cb9ddca3fad495441e324cc01eb640b0a7b4c9f0e31644c822a", { + "chain": "regtest", "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", - "76a9145eadaf9bb7121f0f192561a5a62f5e5f5421029288ac", + "bc1qz377zwe5awr68dnggengqx9vrjt05k98q3sw2n", + "0014147de13b34eb87a3b66846668018ac1c96fa58a7", { + "chain": "main", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", - "a9143f210e7277c899c3a155cc1c90f4106cbddeec6e87", + "bc1qkmhskpdzg8kdkfywhu09kswwn9qan9vnkrf6mk40jvnr06s6sz5ssf82ya", + "0020b6ef0b05a241ecdb248ebf1e5b41ce9941d99593b0d3addaaf932637ea1a80a9", { + "chain": "main", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "myoqcgYiehufrsnnkqdqbp69dddVDMopJu", - "76a914c8a3c2a09a298592c3e180f02487cd91ba3400b588ac", + "bc1ps8cndas60cntk8x79sg9f5e5jz7x050z8agyugln2ukkks23rryqpejzkc", + "512081f136f61a7e26bb1cde2c1054d33490bc67d1e23f504e23f3572d6b415118c8", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C", - "a91499b31df7c9068d1481b596578ddbb4d3bd90baeb87", + "bc1zn4tsczge9l", + "52029d57", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4", - "c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae", + "tb1q6xw0wwd9n9d7ge87dryz4vm5vtahzhvz6yett3", + "0014d19cf739a5995be464fe68c82ab37462fb715d82", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2", - "07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd", + "tb1qwn9zq9fu5uk35ykpgsc7rz4uawy4yh0r5m5er26768h5ur50su3qj6evun", + "002074ca20153ca72d1a12c14431e18abceb89525de3a6e991ab5ed1ef4e0e8f8722", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV", - "ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801", + "tb1pmcdc5d8gr92rtemfsnhpeqanvs0nr82upn5dktxluz9n0qcv34lqxke0wq", + "5120de1b8a34e8195435e76984ee1c83b3641f319d5c0ce8db2cdfe08b37830c8d7e", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h", - "0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c", + "tb1rgxjvtfzp0xczz6dlzqv8d5cmuykk4qkk", + "531041a4c5a44179b02169bf101876d31be1", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", - "76a9141ed467017f043e91ed4c44b4e8dd674db211c4e688ac", + "tb1qa9dlyt6fydestul4y4wh72yshh044w32np8etk", + "0014e95bf22f49237305f3f5255d7f2890bddf5aba2a", { + "chain": "signet", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", - "a9145ece0cadddc415b1980f001785947120acdb36fc87", + "tb1qu4p26n0033720xm0rjgkds5ehdwf039k2fgv75um5krrvfhrrj7qckl9r2", + "0020e542ad4def8c7ca79b6f1c9166c299bb5c97c4b65250cf539ba5863626e31cbc", { + "chain": "signet", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", - "0014751e76e8199196d454941c45d1b3a323f1433bd6", + "tb1pjyukm4n4flwd0ey3lrl06c9kalr60ggmlkcxq2rhhxmy4lvkmkpqexdzqy", + "512091396dd6754fdcd7e491f8fefd60b6efc7a7a11bfdb0602877b9b64afd96dd82", { + "chain": "signet", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080", - "0014751e76e8199196d454941c45d1b3a323f1433bd6", + "tb1r4k75s5syvewsvxufdc3xfhf4tw4u30alw39xny3dnxrl6hau7systymfdv", + "5320adbd485204665d061b896e2264dd355babc8bfbf744a69922d9987fd5fbcf409", { + "chain": "signet", "isPrivkey": false, - "chain": "regtest", "tryCaseFlip": true } ], [ - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", - "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262", + "bcrt1qnk3tdwwj47ppc4pqmxkjdusegedn9ru5gvccwa", + "00149da2b6b9d2af821c5420d9ad26f219465b328f94", { + "chain": "regtest", "isPrivkey": false, - "chain": "test", "tryCaseFlip": true } ], [ - "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", - "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6", + "bcrt1qz7prfshfkwsxuk72pt6mzr6uumq4qllxe4vmwqt89tat48d362yqlykk6a", + "0020178234c2e9b3a06e5bca0af5b10f5ce6c1507fe6cd59b701672afaba9db1d288", { + "chain": "regtest", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "bc1sw50qa3jx3s", - "6002751e", + "bcrt1pumee3wj80xvyr7wjmj7zsk26x5pn095aegy862yhx6f2j9sgc9hq6cj4cm", + "5120e6f398ba47799841f9d2dcbc28595a350337969dca087d28973692a91608c16e", { + "chain": "regtest", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", - "5210751e76e8199196d454941c45d1b3a323", + "bcrt1szqz8hj64d2hhc6nt65v09jxal66pgff2xpcp9kj648qkk8kjzxelsts4dktd799g47uase", + "602810047bcb556aaf7c6a6bd518f2c8ddfeb414252a307012da5aa9c16b1ed211b3f82e156d96df14a8", { + "chain": "regtest", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", - "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", + "12agZTajtRE3STSchwWNWnrm467zzTQ916", + "76a9141156e00f70061e5faba8b71593a8c7554b47090c88ac", + { + "chain": "main", + "isPrivkey": false + } + ], + [ + "3NXqB6iZiPYbKruNT3d9xNBTmtb73xMvvf", + "a914e49decc9e5d97e0547d3642f3a4795b13ae62bca87", + { + "chain": "main", + "isPrivkey": false + } + ], + [ + "mjgt4BoCYxjzWvJFoh68x7cj5GeaKDYhyx", + "76a9142dc11fc7b8072f733f690ffb0591c00f4062295c88ac", { - "isPrivkey": false, "chain": "test", - "tryCaseFlip": true + "isPrivkey": false } ], [ - "bcrt1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvseswlauz7", - "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", + "2NCT6FdQ5MxorHgnFxLeHyGwTGRdkHcrJDH", + "a914d2a8ec992b0894a0d9391ca5d9c45c388c41be7e87", { - "isPrivkey": false, - "chain": "regtest", - "tryCaseFlip": true + "chain": "test", + "isPrivkey": false + } + ], + [ + "mpomiA7wqDnMcxaNLC23eBuXAb4U6H4ZqW", + "76a91465e75e340415ed297c58d6a14d3c17ceeaa17bbd88ac", + { + "chain": "signet", + "isPrivkey": false + } + ], + [ + "2N1pGAA5uatbU2PKvMA9BnJmHcK6yHfMiZa", + "a9145e008b6cc232164570befc23d216060bf4ea793b87", + { + "chain": "signet", + "isPrivkey": false } ] ] diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 3d802cbeb3..a6080ad3dd 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -5,7 +5,6 @@ #include <dbwrapper.h> #include <test/util/setup_common.h> #include <uint256.h> -#include <util/memory.h> #include <memory> @@ -207,7 +206,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. - std::unique_ptr<CDBWrapper> dbw = MakeUnique<CDBWrapper>(ph, (1 << 10), false, false, false); + std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false); char key = 'k'; uint256 in = InsecureRand256(); uint256 res; @@ -248,7 +247,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. - std::unique_ptr<CDBWrapper> dbw = MakeUnique<CDBWrapper>(ph, (1 << 10), false, false, false); + std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false); char key = 'k'; uint256 in = InsecureRand256(); uint256 res; diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 0d480e35ea..7557d4618a 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -14,7 +14,7 @@ #include <script/signingprovider.h> #include <script/standard.h> #include <serialize.h> -#include <util/memory.h> +#include <txorphanage.h> #include <util/string.h> #include <util/system.h> #include <util/time.h> @@ -43,18 +43,6 @@ struct CConnmanTest : public CConnman { } }; -// 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<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); - static CService ip(uint32_t i) { struct in_addr s; @@ -79,9 +67,9 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup) BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) { const CChainParams& chainparams = Params(); - auto connman = MakeUnique<CConnman>(0x1337, 0x1337); - auto peerLogic = PeerManager::make(chainparams, *connman, nullptr, *m_node.scheduler, - *m_node.chainman, *m_node.mempool, false); + auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, + *m_node.scheduler, *m_node.chainman, *m_node.mempool, false); // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -129,8 +117,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) BOOST_CHECK(dummyNode1.fDisconnect == true); SetMockTime(0); - bool dummy; - peerLogic->FinalizeNode(dummyNode1, dummy); + peerLogic->FinalizeNode(dummyNode1); } static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &peerLogic, CConnmanTest* connman) @@ -149,9 +136,9 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &pee BOOST_AUTO_TEST_CASE(stale_tip_peer_management) { const CChainParams& chainparams = Params(); - auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337); - auto peerLogic = PeerManager::make(chainparams, *connman, nullptr, *m_node.scheduler, - *m_node.chainman, *m_node.mempool, false); + auto connman = std::make_unique<CConnmanTest>(0x1337, 0x1337, *m_node.addrman); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, + *m_node.scheduler, *m_node.chainman, *m_node.mempool, false); constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS; CConnman::Options options; @@ -211,9 +198,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) BOOST_CHECK(vNodes[max_outbound_full_relay-1]->fDisconnect == true); BOOST_CHECK(vNodes.back()->fDisconnect == false); - bool dummy; for (const CNode *node : vNodes) { - peerLogic->FinalizeNode(*node, dummy); + peerLogic->FinalizeNode(*node); } connman->ClearNodes(); @@ -222,10 +208,10 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) BOOST_AUTO_TEST_CASE(peer_discouragement) { const CChainParams& chainparams = Params(); - auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); - auto connman = MakeUnique<CConnman>(0x1337, 0x1337); - auto peerLogic = PeerManager::make(chainparams, *connman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, false); + auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), + *m_node.scheduler, *m_node.chainman, *m_node.mempool, false); banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -261,18 +247,17 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) BOOST_CHECK(banman->IsDiscouraged(addr1)); // Expect both 1 and 2 BOOST_CHECK(banman->IsDiscouraged(addr2)); // to be discouraged now - bool dummy; - peerLogic->FinalizeNode(dummyNode1, dummy); - peerLogic->FinalizeNode(dummyNode2, dummy); + peerLogic->FinalizeNode(dummyNode1); + peerLogic->FinalizeNode(dummyNode2); } BOOST_AUTO_TEST_CASE(DoS_bantime) { const CChainParams& chainparams = Params(); - auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); - auto connman = MakeUnique<CConnman>(0x1337, 0x1337); - auto peerLogic = PeerManager::make(chainparams, *connman, banman.get(), *m_node.scheduler, - *m_node.chainman, *m_node.mempool, false); + auto banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), + *m_node.scheduler, *m_node.chainman, *m_node.mempool, false); banman->ClearBanned(); int64_t nStartTime = GetTime(); @@ -291,19 +276,26 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) } BOOST_CHECK(banman->IsDiscouraged(addr)); - bool dummy; - peerLogic->FinalizeNode(dummyNode, dummy); + peerLogic->FinalizeNode(dummyNode); } -static CTransactionRef RandomOrphan() +class TxOrphanageTest : public TxOrphanage { - std::map<uint256, COrphanTx>::iterator it; - LOCK2(cs_main, g_cs_orphans); - it = mapOrphanTransactions.lower_bound(InsecureRand256()); - if (it == mapOrphanTransactions.end()) - it = mapOrphanTransactions.begin(); - return it->second.tx; -} +public: + inline size_t CountOrphans() const EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) + { + return m_orphans.size(); + } + + CTransactionRef RandomOrphan() EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) + { + std::map<uint256, OrphanTx>::iterator it; + it = m_orphans.lower_bound(InsecureRand256()); + if (it == m_orphans.end()) + it = m_orphans.begin(); + return it->second.tx; + } +}; static void MakeNewKeyWithFastRandomContext(CKey& key) { @@ -323,11 +315,14 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) // signature's R and S values have leading zeros. g_insecure_rand_ctx = FastRandomContext(ArithToUint256(arith_uint256(33))); + TxOrphanageTest orphanage; CKey key; MakeNewKeyWithFastRandomContext(key); FillableSigningProvider keystore; BOOST_CHECK(keystore.AddKey(key)); + LOCK(g_cs_orphans); + // 50 orphan transactions: for (int i = 0; i < 50; i++) { @@ -340,13 +335,13 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vout[0].nValue = 1*CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); - AddOrphanTx(MakeTransactionRef(tx), i); + orphanage.AddTx(MakeTransactionRef(tx), i); } // ... and 50 that depend on other orphans: for (int i = 0; i < 50; i++) { - CTransactionRef txPrev = RandomOrphan(); + CTransactionRef txPrev = orphanage.RandomOrphan(); CMutableTransaction tx; tx.vin.resize(1); @@ -357,13 +352,13 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey())); BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL)); - AddOrphanTx(MakeTransactionRef(tx), i); + orphanage.AddTx(MakeTransactionRef(tx), i); } // This really-big orphan should be ignored: for (int i = 0; i < 10; i++) { - CTransactionRef txPrev = RandomOrphan(); + CTransactionRef txPrev = orphanage.RandomOrphan(); CMutableTransaction tx; tx.vout.resize(1); @@ -381,25 +376,24 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) for (unsigned int j = 1; j < tx.vin.size(); j++) tx.vin[j].scriptSig = tx.vin[0].scriptSig; - BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i)); + BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i)); } - LOCK2(cs_main, g_cs_orphans); // Test EraseOrphansFor: for (NodeId i = 0; i < 3; i++) { - size_t sizeBefore = mapOrphanTransactions.size(); - EraseOrphansFor(i); - BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore); + size_t sizeBefore = orphanage.CountOrphans(); + orphanage.EraseForPeer(i); + BOOST_CHECK(orphanage.CountOrphans() < sizeBefore); } // Test LimitOrphanTxSize() function: - LimitOrphanTxSize(40); - BOOST_CHECK(mapOrphanTransactions.size() <= 40); - LimitOrphanTxSize(10); - BOOST_CHECK(mapOrphanTransactions.size() <= 10); - LimitOrphanTxSize(0); - BOOST_CHECK(mapOrphanTransactions.empty()); + orphanage.LimitOrphans(40); + BOOST_CHECK(orphanage.CountOrphans() <= 40); + orphanage.LimitOrphans(10); + BOOST_CHECK(orphanage.CountOrphans() <= 10); + orphanage.LimitOrphans(0); + BOOST_CHECK(orphanage.CountOrphans() == 0); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index acbd6a01ee..aecf955fee 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -10,6 +10,7 @@ #include <boost/test/unit_test.hpp> +#include <optional> #include <string> #include <vector> @@ -65,7 +66,7 @@ std::string UseHInsteadOfApostrophe(const std::string& desc) const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}}; -void DoCheck(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY, +void DoCheck(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY, bool replace_apostrophe_with_h_in_prv=false, bool replace_apostrophe_with_h_in_pub=false) { FlatSigningProvider keys_priv, keys_pub; @@ -262,7 +263,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string& BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv); } -void Check(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY) +void Check(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY) { bool found_apostrophes_in_prv = false; bool found_apostrophes_in_pub = false; @@ -295,8 +296,8 @@ BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(descriptor_test) { // Basic single-key compressed - Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, nullopt); - Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, nullopt); + Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, std::nullopt); + Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, std::nullopt); Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}}); Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}, OutputType::BECH32); Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, OutputType::P2SH_SEGWIT); @@ -305,8 +306,8 @@ BOOST_AUTO_TEST_CASE(descriptor_test) CheckUnparsable("pkh([deadbeef]/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef]/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "Multiple ']' characters found for a single pubkey"); // Multiple end brackets in key origin // Basic single-key uncompressed - Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)",SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, nullopt); - Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, nullopt); + Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)",SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, std::nullopt); + Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, std::nullopt); Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, OutputType::LEGACY); CheckUnparsable("wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Uncompressed keys are not allowed"); // No uncompressed keys in witness CheckUnparsable("wsh(pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "Uncompressed keys are not allowed"); // No uncompressed keys in witness @@ -321,23 +322,23 @@ BOOST_AUTO_TEST_CASE(descriptor_test) Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}}, OutputType::P2SH_SEGWIT); // Versions with BIP32 derivations - Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, nullopt); - Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", "pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, nullopt, {{0}}); + Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, std::nullopt); + Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", "pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, std::nullopt, {{0}}); Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([bd16bee5/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0)", "pkh([bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}}); Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", "wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}}); Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}}); - Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", "combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, nullopt, {{0}, {1}}); + Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", "combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, std::nullopt, {{0}, {1}}); CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long key fingerprint CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)", "Key path value 2147483648 is out of range"); // BIP 32 path element overflow CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1aa)", "Key path value '1aa' is not a valid uint32"); // Path is not valid uint Check("pkh([01234567/10/20]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh([01234567/10/20]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([01234567/10/20/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0)", "pkh([01234567/10/20/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{10, 20, 0xFFFFFFFFUL, 0}}); // Multisig constructions - Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt); - Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt); - Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt); + Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt); + Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt); + Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt); Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}}); - Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", "sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}}); + Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", "sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, std::nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}}); Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}}); Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", "sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}, OutputType::P2SH_SEGWIT); CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript diff --git a/src/test/fuzz/FuzzedDataProvider.h b/src/test/fuzz/FuzzedDataProvider.h index 744a9d78ce..6cbfc39bc2 100644 --- a/src/test/fuzz/FuzzedDataProvider.h +++ b/src/test/fuzz/FuzzedDataProvider.h @@ -20,6 +20,7 @@ #include <cstdint> #include <cstring> #include <initializer_list> +#include <limits> #include <string> #include <type_traits> #include <utility> diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp index b55f1c72b1..0baf30aef6 100644 --- a/src/test/fuzz/addrman.cpp +++ b/src/test/fuzz/addrman.cpp @@ -104,7 +104,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman) [&] { const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); if (opt_service) { - addr_man.SetServices(*opt_service, ServiceFlags{fuzzed_data_provider.ConsumeIntegral<uint64_t>()}); + addr_man.SetServices(*opt_service, ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS)); } }, [&] { diff --git a/src/test/fuzz/asmap_direct.cpp b/src/test/fuzz/asmap_direct.cpp index 8b7822dc16..8ca4de3919 100644 --- a/src/test/fuzz/asmap_direct.cpp +++ b/src/test/fuzz/asmap_direct.cpp @@ -2,8 +2,9 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <test/fuzz/fuzz.h> +#include <netaddress.h> #include <util/asmap.h> +#include <test/fuzz/fuzz.h> #include <cstdint> #include <optional> diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp index dbc0b5ab81..479342e4be 100644 --- a/src/test/fuzz/autofile.cpp +++ b/src/test/fuzz/autofile.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <optional.h> #include <streams.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp index 124439559e..8bf484722c 100644 --- a/src/test/fuzz/banman.cpp +++ b/src/test/fuzz/banman.cpp @@ -8,6 +8,7 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> +#include <test/util/setup_common.h> #include <util/system.h> #include <cstdint> diff --git a/src/test/fuzz/bech32.cpp b/src/test/fuzz/bech32.cpp index 95cd4b413f..ad3bf73af4 100644 --- a/src/test/fuzz/bech32.cpp +++ b/src/test/fuzz/bech32.cpp @@ -16,28 +16,28 @@ FUZZ_TARGET(bech32) { const std::string random_string(buffer.begin(), buffer.end()); - const std::pair<std::string, std::vector<uint8_t>> r1 = bech32::Decode(random_string); - if (r1.first.empty()) { - assert(r1.second.empty()); + const auto r1 = bech32::Decode(random_string); + if (r1.hrp.empty()) { + assert(r1.encoding == bech32::Encoding::INVALID); + assert(r1.data.empty()); } else { - const std::string& hrp = r1.first; - const std::vector<uint8_t>& data = r1.second; - const std::string reencoded = bech32::Encode(hrp, data); + assert(r1.encoding != bech32::Encoding::INVALID); + const std::string reencoded = bech32::Encode(r1.encoding, r1.hrp, r1.data); assert(CaseInsensitiveEqual(random_string, reencoded)); } std::vector<unsigned char> input; ConvertBits<8, 5, true>([&](unsigned char c) { input.push_back(c); }, buffer.begin(), buffer.end()); - const std::string encoded = bech32::Encode("bc", input); - assert(!encoded.empty()); - const std::pair<std::string, std::vector<uint8_t>> r2 = bech32::Decode(encoded); - if (r2.first.empty()) { - assert(r2.second.empty()); - } else { - const std::string& hrp = r2.first; - const std::vector<uint8_t>& data = r2.second; - assert(hrp == "bc"); - assert(data == input); + if (input.size() + 3 + 6 <= 90) { + // If it's possible to encode input in Bech32(m) without exceeding the 90-character limit: + for (auto encoding : {bech32::Encoding::BECH32, bech32::Encoding::BECH32M}) { + const std::string encoded = bech32::Encode(encoding, "bc", input); + assert(!encoded.empty()); + const auto r2 = bech32::Decode(encoded); + assert(r2.encoding == encoding); + assert(r2.hrp == "bc"); + assert(r2.data == input); + } } } diff --git a/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp index ffe38f10fc..ed72260d10 100644 --- a/src/test/fuzz/buffered_file.cpp +++ b/src/test/fuzz/buffered_file.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <optional.h> #include <streams.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index 19486365f6..b21d2eae79 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -16,6 +16,7 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> +#include <test/util/setup_common.h> #include <validation.h> #include <cstdint> @@ -229,11 +230,8 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view) // consensus/tx_verify.cpp:171: bool Consensus::CheckTxInputs(const CTransaction &, TxValidationState &, const CCoinsViewCache &, int, CAmount &): Assertion `!coin.IsSpent()' failed. return; } - 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&) { - } + (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)); }, [&] { const CTransaction transaction{random_mutable_transaction}; @@ -263,7 +261,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view) CCoinsStats stats; bool expected_code_path = false; try { - (void)GetUTXOStats(&coins_view_cache, stats, CoinStatsHashType::HASH_SERIALIZED); + (void)GetUTXOStats(&coins_view_cache, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman)), stats, CoinStatsHashType::HASH_SERIALIZED); } catch (const std::logic_error&) { expected_code_path = true; } diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index 3fb8d8ca06..e07f25dedf 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -10,6 +10,7 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> +#include <test/util/setup_common.h> #include <util/translation.h> #include <cstdint> @@ -24,40 +25,25 @@ FUZZ_TARGET_INIT(connman, initialize_connman) { FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; SetMockTime(ConsumeTime(fuzzed_data_provider)); - CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeBool()}; - CAddress random_address; + CAddrMan addrman; + CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), addrman, fuzzed_data_provider.ConsumeBool()}; CNetAddr random_netaddr; CNode random_node = ConsumeNode(fuzzed_data_provider); - CService random_service; CSubNet random_subnet; std::string random_string; while (fuzzed_data_provider.ConsumeBool()) { CallOneOf( fuzzed_data_provider, [&] { - random_address = ConsumeAddress(fuzzed_data_provider); - }, - [&] { random_netaddr = ConsumeNetAddr(fuzzed_data_provider); }, [&] { - random_service = ConsumeService(fuzzed_data_provider); - }, - [&] { random_subnet = ConsumeSubNet(fuzzed_data_provider); }, [&] { random_string = fuzzed_data_provider.ConsumeRandomLengthString(64); }, [&] { - std::vector<CAddress> addresses; - while (fuzzed_data_provider.ConsumeBool()) { - addresses.push_back(ConsumeAddress(fuzzed_data_provider)); - } - // Limit nTimePenalty to int32_t to avoid signed integer overflow - (void)connman.AddNewAddresses(addresses, ConsumeAddress(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<int32_t>()); - }, - [&] { connman.AddNode(random_string); }, [&] { @@ -94,17 +80,16 @@ FUZZ_TARGET_INIT(connman, initialize_connman) (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); }, [&] { - (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({CConnman::CONNECTIONS_NONE, CConnman::CONNECTIONS_IN, CConnman::CONNECTIONS_OUT, CConnman::CONNECTIONS_ALL})); - }, - [&] { - connman.MarkAddressGood(random_address); + (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({ConnectionDirection::None, ConnectionDirection::In, ConnectionDirection::Out, ConnectionDirection::Both})); }, [&] { (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool()); }, [&] { // Limit now to int32_t to avoid signed integer overflow - (void)connman.PoissonNextSendInbound(fuzzed_data_provider.ConsumeIntegral<int32_t>(), fuzzed_data_provider.ConsumeIntegral<int>()); + (void)connman.PoissonNextSendInbound( + std::chrono::microseconds{fuzzed_data_provider.ConsumeIntegral<int32_t>()}, + std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<int>()}); }, [&] { CSerializedNetMsg serialized_net_msg; @@ -125,9 +110,6 @@ FUZZ_TARGET_INIT(connman, initialize_connman) connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool()); }, [&] { - connman.SetServices(random_service, ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS)); - }, - [&] { connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool()); }); } diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp index dc20dc3f62..a522c837ef 100644 --- a/src/test/fuzz/cuckoocache.cpp +++ b/src/test/fuzz/cuckoocache.cpp @@ -30,7 +30,7 @@ FUZZ_TARGET(cuckoocache) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); fuzzed_data_provider_ptr = &fuzzed_data_provider; - CuckooCache::cache<bool, RandomHasher> cuckoo_cache{}; + CuckooCache::cache<int, RandomHasher> cuckoo_cache{}; if (fuzzed_data_provider.ConsumeBool()) { const size_t megabytes = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 16); cuckoo_cache.setup_bytes(megabytes << 20); diff --git a/src/test/fuzz/data_stream.cpp b/src/test/fuzz/data_stream.cpp index d6ef0c6691..473caec6ff 100644 --- a/src/test/fuzz/data_stream.cpp +++ b/src/test/fuzz/data_stream.cpp @@ -7,6 +7,7 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> +#include <test/util/setup_common.h> #include <cstdint> #include <vector> diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp index 0d1921f285..ffe4855662 100644 --- a/src/test/fuzz/descriptor_parse.cpp +++ b/src/test/fuzz/descriptor_parse.cpp @@ -6,7 +6,6 @@ #include <pubkey.h> #include <script/descriptor.h> #include <test/fuzz/fuzz.h> -#include <util/memory.h> void initialize_descriptor_parse() { diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index 64c6e49615..1290c78712 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -15,7 +15,6 @@ #include <net.h> #include <netbase.h> #include <node/utxo_snapshot.h> -#include <optional.h> #include <primitives/block.h> #include <protocol.h> #include <psbt.h> @@ -26,6 +25,7 @@ #include <version.h> #include <exception> +#include <optional> #include <stdexcept> #include <stdint.h> #include <unistd.h> @@ -69,7 +69,7 @@ T Deserialize(CDataStream ds) } template <typename T> -void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const Optional<int> protocol_version = nullopt) +void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const std::optional<int> protocol_version = std::nullopt) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); if (protocol_version) { diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp index 635288fc36..77ed798923 100644 --- a/src/test/fuzz/eval_script.cpp +++ b/src/test/fuzz/eval_script.cpp @@ -6,7 +6,6 @@ #include <script/interpreter.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> -#include <util/memory.h> #include <limits> diff --git a/src/test/fuzz/i2p.cpp b/src/test/fuzz/i2p.cpp new file mode 100644 index 0000000000..345d68502a --- /dev/null +++ b/src/test/fuzz/i2p.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2020-2021 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 <i2p.h> +#include <netaddress.h> +#include <netbase.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/setup_common.h> +#include <threadinterrupt.h> +#include <util/system.h> + +void initialize_i2p() +{ + static const auto testing_setup = MakeNoLogFileContext<>(); +} + +FUZZ_TARGET_INIT(i2p, initialize_i2p) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + + // Mock CreateSock() to create FuzzedSock. + auto CreateSockOrig = CreateSock; + CreateSock = [&fuzzed_data_provider](const CService&) { + return std::make_unique<FuzzedSock>(fuzzed_data_provider); + }; + + const CService sam_proxy; + CThreadInterrupt interrupt; + + i2p::sam::Session sess{GetDataDir() / "fuzzed_i2p_private_key", sam_proxy, &interrupt}; + + i2p::Connection conn; + + if (sess.Listen(conn)) { + if (sess.Accept(conn)) { + try { + conn.sock->RecvUntilTerminator('\n', 10ms, interrupt, i2p::sam::MAX_MSG_SIZE); + } catch (const std::runtime_error&) { + } + } + } + + const CService to; + bool proxy_error; + + if (sess.Connect(to, conn, proxy_error)) { + try { + conn.sock->SendComplete("verack\n", 10ms, interrupt); + } catch (const std::runtime_error&) { + } + } + + CreateSock = CreateSockOrig; +} diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp index ac83d91ea0..5bc99ddcb9 100644 --- a/src/test/fuzz/integer.cpp +++ b/src/test/fuzz/integer.cpp @@ -84,8 +84,7 @@ FUZZ_TARGET_INIT(integer, initialize_integer) (void)DecompressAmount(u64); (void)FormatISO8601Date(i64); (void)FormatISO8601DateTime(i64); - // FormatMoney(i) not defined when i == std::numeric_limits<int64_t>::min() - if (i64 != std::numeric_limits<int64_t>::min()) { + { int64_t parsed_money; if (ParseMoney(FormatMoney(i64), parsed_money)) { assert(parsed_money == i64); @@ -132,8 +131,7 @@ FUZZ_TARGET_INIT(integer, initialize_integer) (void)SipHashUint256Extra(u64, u64, u256, u32); (void)ToLower(ch); (void)ToUpper(ch); - // ValueFromAmount(i) not defined when i == std::numeric_limits<int64_t>::min() - if (i64 != std::numeric_limits<int64_t>::min()) { + { int64_t parsed_money; if (ParseMoney(ValueFromAmount(i64).getValStr(), parsed_money)) { assert(parsed_money == i64); diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp index aa8f826e4a..32077b1fe2 100644 --- a/src/test/fuzz/key.cpp +++ b/src/test/fuzz/key.cpp @@ -17,7 +17,6 @@ #include <script/standard.h> #include <streams.h> #include <test/fuzz/fuzz.h> -#include <util/memory.h> #include <util/strencodings.h> #include <cassert> diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index b056f46f2e..272f6415a9 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -7,7 +7,6 @@ #include <net.h> #include <net_permissions.h> #include <netaddress.h> -#include <optional.h> #include <protocol.h> #include <random.h> #include <test/fuzz/FuzzedDataProvider.h> @@ -17,6 +16,7 @@ #include <test/util/setup_common.h> #include <cstdint> +#include <optional> #include <string> #include <vector> diff --git a/src/test/fuzz/netbase_dns_lookup.cpp b/src/test/fuzz/netbase_dns_lookup.cpp new file mode 100644 index 0000000000..cf2fa33744 --- /dev/null +++ b/src/test/fuzz/netbase_dns_lookup.cpp @@ -0,0 +1,71 @@ +// Copyright (c) 2021 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 <netaddress.h> +#include <netbase.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> + +#include <cstdint> +#include <string> +#include <vector> + +FUZZ_TARGET(netbase_dns_lookup) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + const std::string name = fuzzed_data_provider.ConsumeRandomLengthString(512); + const unsigned int max_results = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); + const bool allow_lookup = fuzzed_data_provider.ConsumeBool(); + const uint16_t default_port = fuzzed_data_provider.ConsumeIntegral<uint16_t>(); + + auto fuzzed_dns_lookup_function = [&](const std::string&, bool) { + std::vector<CNetAddr> resolved_addresses; + while (fuzzed_data_provider.ConsumeBool()) { + resolved_addresses.push_back(ConsumeNetAddr(fuzzed_data_provider)); + } + return resolved_addresses; + }; + + { + std::vector<CNetAddr> resolved_addresses; + if (LookupHost(name, resolved_addresses, max_results, allow_lookup, fuzzed_dns_lookup_function)) { + for (const CNetAddr& resolved_address : resolved_addresses) { + assert(!resolved_address.IsInternal()); + } + } + assert(resolved_addresses.size() <= max_results || max_results == 0); + } + { + CNetAddr resolved_address; + if (LookupHost(name, resolved_address, allow_lookup, fuzzed_dns_lookup_function)) { + assert(!resolved_address.IsInternal()); + } + } + { + std::vector<CService> resolved_services; + if (Lookup(name, resolved_services, default_port, allow_lookup, max_results, fuzzed_dns_lookup_function)) { + for (const CNetAddr& resolved_service : resolved_services) { + assert(!resolved_service.IsInternal()); + } + } + assert(resolved_services.size() <= max_results || max_results == 0); + } + { + CService resolved_service; + if (Lookup(name, resolved_service, default_port, allow_lookup, fuzzed_dns_lookup_function)) { + assert(!resolved_service.IsInternal()); + } + } + { + CService resolved_service = LookupNumeric(name, default_port, fuzzed_dns_lookup_function); + assert(!resolved_service.IsInternal()); + } + { + CSubNet resolved_subnet; + if (LookupSubNet(name, resolved_subnet, fuzzed_dns_lookup_function)) { + assert(resolved_subnet.IsValid()); + } + } +} diff --git a/src/test/fuzz/node_eviction.cpp b/src/test/fuzz/node_eviction.cpp index aaebe83c0a..70ffc6bf37 100644 --- a/src/test/fuzz/node_eviction.cpp +++ b/src/test/fuzz/node_eviction.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <net.h> -#include <optional.h> #include <protocol.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> @@ -21,23 +20,24 @@ FUZZ_TARGET(node_eviction) std::vector<NodeEvictionCandidate> eviction_candidates; while (fuzzed_data_provider.ConsumeBool()) { eviction_candidates.push_back({ - fuzzed_data_provider.ConsumeIntegral<NodeId>(), - fuzzed_data_provider.ConsumeIntegral<int64_t>(), - fuzzed_data_provider.ConsumeIntegral<int64_t>(), - fuzzed_data_provider.ConsumeIntegral<int64_t>(), - fuzzed_data_provider.ConsumeIntegral<int64_t>(), - fuzzed_data_provider.ConsumeBool(), - fuzzed_data_provider.ConsumeBool(), - fuzzed_data_provider.ConsumeBool(), - fuzzed_data_provider.ConsumeIntegral<uint64_t>(), - fuzzed_data_provider.ConsumeBool(), - fuzzed_data_provider.ConsumeBool(), + /* id */ fuzzed_data_provider.ConsumeIntegral<NodeId>(), + /* nTimeConnected */ fuzzed_data_provider.ConsumeIntegral<int64_t>(), + /* m_min_ping_time */ std::chrono::microseconds{fuzzed_data_provider.ConsumeIntegral<int64_t>()}, + /* nLastBlockTime */ fuzzed_data_provider.ConsumeIntegral<int64_t>(), + /* nLastTXTime */ fuzzed_data_provider.ConsumeIntegral<int64_t>(), + /* fRelevantServices */ fuzzed_data_provider.ConsumeBool(), + /* fRelayTxes */ fuzzed_data_provider.ConsumeBool(), + /* fBloomFilter */ fuzzed_data_provider.ConsumeBool(), + /* nKeyedNetGroup */ fuzzed_data_provider.ConsumeIntegral<uint64_t>(), + /* prefer_evict */ fuzzed_data_provider.ConsumeBool(), + /* m_is_local */ fuzzed_data_provider.ConsumeBool(), + /* m_is_onion */ fuzzed_data_provider.ConsumeBool(), }); } // Make a copy since eviction_candidates may be in some valid but otherwise // indeterminate state after the SelectNodeToEvict(&&) call. const std::vector<NodeEvictionCandidate> eviction_candidates_copy = eviction_candidates; - const Optional<NodeId> node_to_evict = SelectNodeToEvict(std::move(eviction_candidates)); + const std::optional<NodeId> node_to_evict = SelectNodeToEvict(std::move(eviction_candidates)); if (node_to_evict) { assert(std::any_of(eviction_candidates_copy.begin(), eviction_candidates_copy.end(), [&node_to_evict](const NodeEvictionCandidate& eviction_candidate) { return *node_to_evict == eviction_candidate.id; })); } diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp index 163f1b839e..3a1fdaad8f 100644 --- a/src/test/fuzz/p2p_transport_deserializer.cpp +++ b/src/test/fuzz/p2p_transport_deserializer.cpp @@ -10,6 +10,7 @@ #include <cassert> #include <cstdint> #include <limits> +#include <optional> #include <vector> void initialize_p2p_transport_deserializer() @@ -30,7 +31,7 @@ FUZZ_TARGET_INIT(p2p_transport_deserializer, initialize_p2p_transport_deserializ if (deserializer.Complete()) { const std::chrono::microseconds m_time{std::numeric_limits<int64_t>::max()}; uint32_t out_err_raw_size{0}; - Optional<CNetMessage> result{deserializer.GetMessage(m_time, out_err_raw_size)}; + std::optional<CNetMessage> result{deserializer.GetMessage(m_time, out_err_raw_size)}; if (result) { assert(result->m_command.size() <= CMessageHeader::COMMAND_SIZE); assert(result->m_raw_message_size <= buffer.size()); diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp index ddd2bcfba3..2c546e9b4a 100644 --- a/src/test/fuzz/parse_numbers.cpp +++ b/src/test/fuzz/parse_numbers.cpp @@ -18,6 +18,12 @@ FUZZ_TARGET(parse_numbers) double d; (void)ParseDouble(random_string, &d); + uint8_t u8; + (void)ParseUInt8(random_string, &u8); + + uint16_t u16; + (void)ParseUInt16(random_string, &u16); + int32_t i32; (void)ParseInt32(random_string, &i32); (void)atoi(random_string); diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp index afe382ba21..3fffaac8d0 100644 --- a/src/test/fuzz/parse_univalue.cpp +++ b/src/test/fuzz/parse_univalue.cpp @@ -7,7 +7,6 @@ #include <rpc/client.h> #include <rpc/util.h> #include <test/fuzz/fuzz.h> -#include <util/memory.h> #include <limits> #include <string> diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp index 311550f041..116b7a71d9 100644 --- a/src/test/fuzz/policy_estimator.cpp +++ b/src/test/fuzz/policy_estimator.cpp @@ -7,6 +7,7 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> +#include <test/util/setup_common.h> #include <txmempool.h> #include <cstdint> diff --git a/src/test/fuzz/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp index c24ad3d49a..9021d95954 100644 --- a/src/test/fuzz/policy_estimator_io.cpp +++ b/src/test/fuzz/policy_estimator_io.cpp @@ -6,6 +6,7 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> +#include <test/util/setup_common.h> #include <cstdint> #include <vector> diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp index 53726ca893..47b4323e81 100644 --- a/src/test/fuzz/pow.cpp +++ b/src/test/fuzz/pow.cpp @@ -34,7 +34,7 @@ FUZZ_TARGET_INIT(pow, initialize_pow) } CBlockIndex current_block{*block_header}; { - CBlockIndex* previous_block = !blocks.empty() ? &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)] : nullptr; + CBlockIndex* previous_block = blocks.empty() ? nullptr : &PickValue(fuzzed_data_provider, blocks); const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits<int>::max()) ? previous_block->nHeight + 1 : 0; if (fuzzed_data_provider.ConsumeBool()) { current_block.pprev = previous_block; @@ -66,9 +66,9 @@ FUZZ_TARGET_INIT(pow, initialize_pow) } } { - const CBlockIndex* to = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)]; - const CBlockIndex* from = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)]; - const CBlockIndex* tip = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)]; + const CBlockIndex* to = &PickValue(fuzzed_data_provider, blocks); + const CBlockIndex* from = &PickValue(fuzzed_data_provider, blocks); + const CBlockIndex* tip = &PickValue(fuzzed_data_provider, blocks); try { (void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params); } catch (const uint_error&) { diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index e3571e15b7..96e1cfa08f 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -18,7 +18,7 @@ #include <test/util/net.h> #include <test/util/setup_common.h> #include <test/util/validation.h> -#include <util/memory.h> +#include <txorphanage.h> #include <validationinterface.h> #include <version.h> @@ -68,8 +68,8 @@ void fuzz_target(FuzzBufferType buffer, const std::string& LIMIT_TO_MESSAGE_TYPE { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get(); - TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate(); + ConnmanTestMsg& connman = *static_cast<ConnmanTestMsg*>(g_setup->m_node.connman.get()); + TestChainState& chainstate = *static_cast<TestChainState*>(&g_setup->m_node.chainman->ActiveChainstate()); SetMockTime(1610000000); // any time to successfully reset ibd chainstate.ResetIbd(); diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index f62a0c64ed..203c0ef8e1 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -13,7 +13,7 @@ #include <test/util/net.h> #include <test/util/setup_common.h> #include <test/util/validation.h> -#include <util/memory.h> +#include <txorphanage.h> #include <validation.h> #include <validationinterface.h> @@ -35,8 +35,8 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get(); - TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate(); + ConnmanTestMsg& connman = *static_cast<ConnmanTestMsg*>(g_setup->m_node.connman.get()); + TestChainState& chainstate = *static_cast<TestChainState*>(&g_setup->m_node.chainman->ActiveChainstate()); SetMockTime(1610000000); // any time to successfully reset ibd chainstate.ResetIbd(); @@ -65,7 +65,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages) net_msg.m_type = random_message_type; net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider); - CNode& random_node = *peers.at(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, peers.size() - 1)); + CNode& random_node = *PickValue(fuzzed_data_provider, peers); (void)connman.ReceiveMsgFrom(random_node, net_msg); random_node.fPauseSend = false; diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp index 0b4588c4ce..d1cc6f9c7e 100644 --- a/src/test/fuzz/psbt.cpp +++ b/src/test/fuzz/psbt.cpp @@ -5,15 +5,14 @@ #include <test/fuzz/fuzz.h> #include <node/psbt.h> -#include <optional.h> #include <psbt.h> #include <pubkey.h> #include <script/script.h> #include <streams.h> -#include <util/memory.h> #include <version.h> #include <cstdint> +#include <optional> #include <string> #include <vector> @@ -40,7 +39,7 @@ FUZZ_TARGET_INIT(psbt, initialize_psbt) (void)psbt.IsNull(); - Optional<CMutableTransaction> tx = psbt.tx; + std::optional<CMutableTransaction> tx = psbt.tx; if (tx) { const CMutableTransaction& mtx = *tx; const PartiallySignedTransaction psbt_from_tx{mtx}; diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp index 193862e847..e87ae5b04b 100644 --- a/src/test/fuzz/script.cpp +++ b/src/test/fuzz/script.cpp @@ -20,7 +20,6 @@ #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> #include <univalue.h> -#include <util/memory.h> #include <algorithm> #include <cassert> @@ -104,9 +103,11 @@ FUZZ_TARGET_INIT(script, initialize_script) (void)ScriptToAsmStr(script, true); UniValue o1(UniValue::VOBJ); - ScriptPubKeyToUniv(script, o1, true); + ScriptPubKeyToUniv(script, o1, true, true); + ScriptPubKeyToUniv(script, o1, true, false); UniValue o2(UniValue::VOBJ); - ScriptPubKeyToUniv(script, o2, false); + ScriptPubKeyToUniv(script, o2, false, true); + ScriptPubKeyToUniv(script, o2, false, false); UniValue o3(UniValue::VOBJ); ScriptToUniv(script, o3, true); UniValue o4(UniValue::VOBJ); diff --git a/src/test/fuzz/script_descriptor_cache.cpp b/src/test/fuzz/script_descriptor_cache.cpp index 1c62c018e7..6ce13d5679 100644 --- a/src/test/fuzz/script_descriptor_cache.cpp +++ b/src/test/fuzz/script_descriptor_cache.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <optional.h> #include <pubkey.h> #include <script/descriptor.h> #include <test/fuzz/FuzzedDataProvider.h> @@ -10,6 +9,7 @@ #include <test/fuzz/util.h> #include <cstdint> +#include <optional> #include <string> #include <vector> diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp index ce8915ca2c..387f9c069c 100644 --- a/src/test/fuzz/script_flags.cpp +++ b/src/test/fuzz/script_flags.cpp @@ -5,14 +5,11 @@ #include <pubkey.h> #include <script/interpreter.h> #include <streams.h> -#include <util/memory.h> +#include <test/util/script.h> #include <version.h> #include <test/fuzz/fuzz.h> -/** Flags that are not forbidden by an assert */ -static bool IsValidFlagCombination(unsigned flags); - void initialize_script_flags() { static const ECCVerifyHandle verify_handle; @@ -75,10 +72,3 @@ FUZZ_TARGET_INIT(script_flags, initialize_script_flags) return; } } - -static bool IsValidFlagCombination(unsigned flags) -{ - if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false; - if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false; - return true; -} diff --git a/src/test/fuzz/signature_checker.cpp b/src/test/fuzz/signature_checker.cpp index 3e7b72805e..6b86c8889d 100644 --- a/src/test/fuzz/signature_checker.cpp +++ b/src/test/fuzz/signature_checker.cpp @@ -6,7 +6,8 @@ #include <script/interpreter.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> -#include <util/memory.h> +#include <test/fuzz/util.h> +#include <test/util/script.h> #include <cstdint> #include <limits> @@ -15,7 +16,7 @@ void initialize_signature_checker() { - static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); + static const auto verify_handle = std::make_unique<ECCVerifyHandle>(); } namespace { @@ -57,17 +58,12 @@ FUZZ_TARGET_INIT(signature_checker, initialize_signature_checker) FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}); - const std::string script_string_1 = fuzzed_data_provider.ConsumeRandomLengthString(65536); - const std::vector<uint8_t> script_bytes_1{script_string_1.begin(), script_string_1.end()}; - const std::string script_string_2 = fuzzed_data_provider.ConsumeRandomLengthString(65536); - const std::vector<uint8_t> script_bytes_2{script_string_2.begin(), script_string_2.end()}; + const auto script_1 = ConsumeScript(fuzzed_data_provider, 65536); + const auto script_2 = ConsumeScript(fuzzed_data_provider, 65536); std::vector<std::vector<unsigned char>> stack; - (void)EvalScript(stack, {script_bytes_1.begin(), script_bytes_1.end()}, flags, FuzzedSignatureChecker(fuzzed_data_provider), sig_version, nullptr); - if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0 && ((flags & SCRIPT_VERIFY_P2SH) == 0 || (flags & SCRIPT_VERIFY_WITNESS) == 0)) { + (void)EvalScript(stack, script_1, flags, FuzzedSignatureChecker(fuzzed_data_provider), sig_version, nullptr); + if (!IsValidFlagCombination(flags)) { return; } - if ((flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) { - return; - } - (void)VerifyScript({script_bytes_1.begin(), script_bytes_1.end()}, {script_bytes_2.begin(), script_bytes_2.end()}, nullptr, flags, FuzzedSignatureChecker(fuzzed_data_provider), nullptr); + (void)VerifyScript(script_1, script_2, nullptr, flags, FuzzedSignatureChecker(fuzzed_data_provider), nullptr); } diff --git a/src/test/fuzz/signet.cpp b/src/test/fuzz/signet.cpp index 0d1999731f..303dcf13e3 100644 --- a/src/test/fuzz/signet.cpp +++ b/src/test/fuzz/signet.cpp @@ -10,6 +10,7 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/fuzz/util.h> +#include <test/util/setup_common.h> #include <cstdint> #include <optional> diff --git a/src/test/fuzz/socks5.cpp b/src/test/fuzz/socks5.cpp new file mode 100644 index 0000000000..c3a6eed089 --- /dev/null +++ b/src/test/fuzz/socks5.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2020-2021 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 <netaddress.h> +#include <netbase.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/setup_common.h> + +#include <cstdint> +#include <string> +#include <vector> + +namespace { +int default_socks5_recv_timeout; +}; + +extern int g_socks5_recv_timeout; + +void initialize_socks5() +{ + static const auto testing_setup = MakeNoLogFileContext<const BasicTestingSetup>(); + default_socks5_recv_timeout = g_socks5_recv_timeout; +} + +FUZZ_TARGET_INIT(socks5, initialize_socks5) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + ProxyCredentials proxy_credentials; + proxy_credentials.username = fuzzed_data_provider.ConsumeRandomLengthString(512); + proxy_credentials.password = fuzzed_data_provider.ConsumeRandomLengthString(512); + InterruptSocks5(fuzzed_data_provider.ConsumeBool()); + // Set FUZZED_SOCKET_FAKE_LATENCY=1 to exercise recv timeout code paths. This + // will slow down fuzzing. + g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1 : default_socks5_recv_timeout; + FuzzedSock fuzzed_sock = ConsumeSock(fuzzed_data_provider); + // This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within + // a few seconds of fuzzing. + (void)Socks5(fuzzed_data_provider.ConsumeRandomLengthString(512), + fuzzed_data_provider.ConsumeIntegral<uint16_t>(), + fuzzed_data_provider.ConsumeBool() ? &proxy_credentials : nullptr, + fuzzed_sock); +} diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp index 93b4948a2f..286375f7ae 100644 --- a/src/test/fuzz/string.cpp +++ b/src/test/fuzz/string.cpp @@ -5,6 +5,7 @@ #include <blockfilter.h> #include <clientversion.h> #include <logging.h> +#include <netaddress.h> #include <netbase.h> #include <outputtype.h> #include <rpc/client.h> @@ -82,7 +83,7 @@ FUZZ_TARGET(string) #ifndef WIN32 (void)ShellEscape(random_string_1); #endif // WIN32 - int port_out; + uint16_t port_out; std::string host_out; SplitHostPort(random_string_1, port_out, host_out); (void)TimingResistantEqual(random_string_1, random_string_2); diff --git a/src/test/fuzz/system.cpp b/src/test/fuzz/system.cpp index d9571209fa..b25dcfcd3b 100644 --- a/src/test/fuzz/system.cpp +++ b/src/test/fuzz/system.cpp @@ -51,7 +51,7 @@ FUZZ_TARGET(system) // Avoid hitting: // util/system.cpp:425: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed. const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16)); - if (args_manager.GetArgFlags(argument_name) != nullopt) { + if (args_manager.GetArgFlags(argument_name) != std::nullopt) { return; } args_manager.AddArg(argument_name, fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeIntegral<unsigned int>() & ~ArgsManager::COMMAND, options_category); @@ -63,7 +63,7 @@ FUZZ_TARGET(system) std::vector<std::string> hidden_arguments; for (const std::string& name : names) { const std::string hidden_argument = GetArgumentName(name); - if (args_manager.GetArgFlags(hidden_argument) != nullopt) { + if (args_manager.GetArgFlags(hidden_argument) != std::nullopt) { continue; } if (std::find(hidden_arguments.begin(), hidden_arguments.end(), hidden_argument) != hidden_arguments.end()) { diff --git a/src/test/fuzz/torcontrol.cpp b/src/test/fuzz/torcontrol.cpp new file mode 100644 index 0000000000..a97d3962bf --- /dev/null +++ b/src/test/fuzz/torcontrol.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2020-2021 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 <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/setup_common.h> +#include <torcontrol.h> + +#include <cstdint> +#include <string> +#include <vector> + +class DummyTorControlConnection : public TorControlConnection +{ +public: + DummyTorControlConnection() : TorControlConnection{nullptr} + { + } + + bool Connect(const std::string&, const ConnectionCB&, const ConnectionCB&) + { + return true; + } + + void Disconnect() + { + } + + bool Command(const std::string&, const ReplyHandlerCB&) + { + return true; + } +}; + +void initialize_torcontrol() +{ + static const auto testing_setup = MakeNoLogFileContext<>(); +} + +FUZZ_TARGET_INIT(torcontrol, initialize_torcontrol) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + + TorController tor_controller; + while (fuzzed_data_provider.ConsumeBool()) { + TorControlReply tor_control_reply; + CallOneOf( + fuzzed_data_provider, + [&] { + tor_control_reply.code = 250; + }, + [&] { + tor_control_reply.code = 510; + }, + [&] { + tor_control_reply.code = fuzzed_data_provider.ConsumeIntegral<int>(); + }); + tor_control_reply.lines = ConsumeRandomLengthStringVector(fuzzed_data_provider); + if (tor_control_reply.lines.empty()) { + break; + } + DummyTorControlConnection dummy_tor_control_connection; + CallOneOf( + fuzzed_data_provider, + [&] { + tor_controller.add_onion_cb(dummy_tor_control_connection, tor_control_reply); + }, + [&] { + tor_controller.auth_cb(dummy_tor_control_connection, tor_control_reply); + }, + [&] { + tor_controller.authchallenge_cb(dummy_tor_control_connection, tor_control_reply); + }, + [&] { + tor_controller.protocolinfo_cb(dummy_tor_control_connection, tor_control_reply); + }); + } +} diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index 13ae450756..17e4405a13 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -100,16 +100,9 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction) (void)IsWitnessStandard(tx, coins_view_cache); UniValue u(UniValue::VOBJ); - // ValueFromAmount(i) not defined when i == std::numeric_limits<int64_t>::min() - bool skip_tx_to_univ = false; - for (const CTxOut& txout : tx.vout) { - if (txout.nValue == std::numeric_limits<int64_t>::min()) { - skip_tx_to_univ = true; - } - } - if (!skip_tx_to_univ) { - TxToUniv(tx, /* hashBlock */ {}, u); - static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); - TxToUniv(tx, u256_max, u); - } + TxToUniv(tx, /* hashBlock */ {}, /* include_addresses */ true, u); + TxToUniv(tx, /* hashBlock */ {}, /* include_addresses */ false, u); + static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + TxToUniv(tx, u256_max, /* include_addresses */ true, u); + TxToUniv(tx, u256_max, /* include_addresses */ false, u); } diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp new file mode 100644 index 0000000000..f84d6702a7 --- /dev/null +++ b/src/test/fuzz/tx_pool.cpp @@ -0,0 +1,285 @@ +// Copyright (c) 2021 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 <consensus/validation.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/mining.h> +#include <test/util/script.h> +#include <test/util/setup_common.h> +#include <util/rbf.h> +#include <validation.h> +#include <validationinterface.h> + +namespace { + +const TestingSetup* g_setup; +std::vector<COutPoint> g_outpoints_coinbase_init_mature; +std::vector<COutPoint> g_outpoints_coinbase_init_immature; + +struct MockedTxPool : public CTxMemPool { + void RollingFeeUpdate() + { + lastRollingFeeUpdate = GetTime(); + blockSinceLastRollingFeeBump = true; + } +}; + +void initialize_tx_pool() +{ + static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); + g_setup = testing_setup.get(); + + for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) { + CTxIn in = MineBlock(g_setup->m_node, P2WSH_OP_TRUE); + // Remember the txids to avoid expensive disk acess later on + auto& outpoints = i < COINBASE_MATURITY ? + g_outpoints_coinbase_init_mature : + g_outpoints_coinbase_init_immature; + outpoints.push_back(in.prevout); + } + SyncWithValidationInterfaceQueue(); +} + +struct TransactionsDelta final : public CValidationInterface { + std::set<CTransactionRef>& m_removed; + std::set<CTransactionRef>& m_added; + + explicit TransactionsDelta(std::set<CTransactionRef>& r, std::set<CTransactionRef>& a) + : m_removed{r}, m_added{a} {} + + void TransactionAddedToMempool(const CTransactionRef& tx, uint64_t /* mempool_sequence */) override + { + Assert(m_added.insert(tx).second); + } + + void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t /* mempool_sequence */) override + { + Assert(m_removed.insert(tx).second); + } +}; + +void SetMempoolConstraints(ArgsManager& args, FuzzedDataProvider& fuzzed_data_provider) +{ + args.ForceSetArg("-limitancestorcount", + ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 50))); + args.ForceSetArg("-limitancestorsize", + ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 202))); + args.ForceSetArg("-limitdescendantcount", + ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 50))); + args.ForceSetArg("-limitdescendantsize", + ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 202))); + args.ForceSetArg("-maxmempool", + ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 200))); + args.ForceSetArg("-mempoolexpiry", + ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 999))); +} + +FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const auto& node = g_setup->m_node; + auto& chainstate = node.chainman->ActiveChainstate(); + + SetMockTime(ConsumeTime(fuzzed_data_provider)); + SetMempoolConstraints(*node.args, fuzzed_data_provider); + + // All RBF-spendable outpoints + std::set<COutPoint> outpoints_rbf; + // All outpoints counting toward the total supply (subset of outpoints_rbf) + std::set<COutPoint> outpoints_supply; + for (const auto& outpoint : g_outpoints_coinbase_init_mature) { + Assert(outpoints_supply.insert(outpoint).second); + } + outpoints_rbf = outpoints_supply; + + // The sum of the values of all spendable outpoints + constexpr CAmount SUPPLY_TOTAL{COINBASE_MATURITY * 50 * COIN}; + + CTxMemPool tx_pool_{/* estimator */ nullptr, /* check_ratio */ 1}; + MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_); + + // Helper to query an amount + const CCoinsViewMemPool amount_view{WITH_LOCK(::cs_main, return &chainstate.CoinsTip()), tx_pool}; + const auto GetAmount = [&](const COutPoint& outpoint) { + Coin c; + Assert(amount_view.GetCoin(outpoint, c)); + return c.out.nValue; + }; + + while (fuzzed_data_provider.ConsumeBool()) { + { + // Total supply is the mempool fee + all outpoints + CAmount supply_now{WITH_LOCK(tx_pool.cs, return tx_pool.GetTotalFee())}; + for (const auto& op : outpoints_supply) { + supply_now += GetAmount(op); + } + Assert(supply_now == SUPPLY_TOTAL); + } + Assert(!outpoints_supply.empty()); + + // Create transaction to add to the mempool + const CTransactionRef tx = [&] { + CMutableTransaction tx_mut; + tx_mut.nVersion = CTransaction::CURRENT_VERSION; + tx_mut.nLockTime = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<uint32_t>(); + const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<int>(1, outpoints_rbf.size()); + const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<int>(1, outpoints_rbf.size() * 2); + + CAmount amount_in{0}; + for (int i = 0; i < num_in; ++i) { + // Pop random outpoint + auto pop = outpoints_rbf.begin(); + std::advance(pop, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, outpoints_rbf.size() - 1)); + const auto outpoint = *pop; + outpoints_rbf.erase(pop); + amount_in += GetAmount(outpoint); + + // Create input + const auto sequence = ConsumeSequence(fuzzed_data_provider); + const auto script_sig = CScript{}; + const auto script_wit_stack = std::vector<std::vector<uint8_t>>{WITNESS_STACK_ELEM_OP_TRUE}; + CTxIn in; + in.prevout = outpoint; + in.nSequence = sequence; + in.scriptSig = script_sig; + in.scriptWitness.stack = script_wit_stack; + + tx_mut.vin.push_back(in); + } + const auto amount_fee = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-1000, amount_in); + const auto amount_out = (amount_in - amount_fee) / num_out; + for (int i = 0; i < num_out; ++i) { + tx_mut.vout.emplace_back(amount_out, P2WSH_OP_TRUE); + } + const auto tx = MakeTransactionRef(tx_mut); + // Restore previously removed outpoints + for (const auto& in : tx->vin) { + Assert(outpoints_rbf.insert(in.prevout).second); + } + return tx; + }(); + + if (fuzzed_data_provider.ConsumeBool()) { + SetMockTime(ConsumeTime(fuzzed_data_provider)); + } + if (fuzzed_data_provider.ConsumeBool()) { + SetMempoolConstraints(*node.args, fuzzed_data_provider); + } + if (fuzzed_data_provider.ConsumeBool()) { + tx_pool.RollingFeeUpdate(); + } + if (fuzzed_data_provider.ConsumeBool()) { + const auto& txid = fuzzed_data_provider.ConsumeBool() ? + tx->GetHash() : + PickValue(fuzzed_data_provider, outpoints_rbf).hash; + const auto delta = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-50 * COIN, +50 * COIN); + tx_pool.PrioritiseTransaction(txid, delta); + } + + // Remember all removed and added transactions + std::set<CTransactionRef> removed; + std::set<CTransactionRef> added; + auto txr = std::make_shared<TransactionsDelta>(removed, added); + RegisterSharedValidationInterface(txr); + const bool bypass_limits = fuzzed_data_provider.ConsumeBool(); + ::fRequireStandard = fuzzed_data_provider.ConsumeBool(); + const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx_pool, tx, bypass_limits)); + const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID; + SyncWithValidationInterfaceQueue(); + UnregisterSharedValidationInterface(txr); + + Assert(accepted != added.empty()); + Assert(accepted == res.m_state.IsValid()); + Assert(accepted != res.m_state.IsInvalid()); + if (accepted) { + Assert(added.size() == 1); // For now, no package acceptance + Assert(tx == *added.begin()); + } else { + // Do not consider rejected transaction removed + removed.erase(tx); + } + + // Helper to insert spent and created outpoints of a tx into collections + using Sets = std::vector<std::reference_wrapper<std::set<COutPoint>>>; + const auto insert_tx = [](Sets created_by_tx, Sets consumed_by_tx, const auto& tx) { + for (size_t i{0}; i < tx.vout.size(); ++i) { + for (auto& set : created_by_tx) { + Assert(set.get().emplace(tx.GetHash(), i).second); + } + } + for (const auto& in : tx.vin) { + for (auto& set : consumed_by_tx) { + Assert(set.get().insert(in.prevout).second); + } + } + }; + // Add created outpoints, remove spent outpoints + { + // Outpoints that no longer exist at all + std::set<COutPoint> consumed_erased; + // Outpoints that no longer count toward the total supply + std::set<COutPoint> consumed_supply; + for (const auto& removed_tx : removed) { + insert_tx(/* created_by_tx */ {consumed_erased}, /* consumed_by_tx */ {outpoints_supply}, /* tx */ *removed_tx); + } + for (const auto& added_tx : added) { + insert_tx(/* created_by_tx */ {outpoints_supply, outpoints_rbf}, /* consumed_by_tx */ {consumed_supply}, /* tx */ *added_tx); + } + for (const auto& p : consumed_erased) { + Assert(outpoints_supply.erase(p) == 1); + Assert(outpoints_rbf.erase(p) == 1); + } + for (const auto& p : consumed_supply) { + Assert(outpoints_supply.erase(p) == 1); + } + } + } + WITH_LOCK(::cs_main, tx_pool.check(chainstate)); + const auto info_all = tx_pool.infoAll(); + if (!info_all.empty()) { + const auto& tx_to_remove = *PickValue(fuzzed_data_provider, info_all).tx; + WITH_LOCK(tx_pool.cs, tx_pool.removeRecursive(tx_to_remove, /* dummy */ MemPoolRemovalReason::BLOCK)); + std::vector<uint256> all_txids; + tx_pool.queryHashes(all_txids); + assert(all_txids.size() < info_all.size()); + WITH_LOCK(::cs_main, tx_pool.check(chainstate)); + } + SyncWithValidationInterfaceQueue(); +} + +FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const auto& node = g_setup->m_node; + + std::vector<uint256> txids; + for (const auto& outpoint : g_outpoints_coinbase_init_mature) { + txids.push_back(outpoint.hash); + } + for (int i{0}; i <= 3; ++i) { + // Add some immature and non-existent outpoints + txids.push_back(g_outpoints_coinbase_init_immature.at(i).hash); + txids.push_back(ConsumeUInt256(fuzzed_data_provider)); + } + + CTxMemPool tx_pool{/* estimator */ nullptr, /* check_ratio */ 1}; + + while (fuzzed_data_provider.ConsumeBool()) { + const auto mut_tx = ConsumeTransaction(fuzzed_data_provider, txids); + + const auto tx = MakeTransactionRef(mut_tx); + const bool bypass_limits = fuzzed_data_provider.ConsumeBool(); + ::fRequireStandard = fuzzed_data_provider.ConsumeBool(); + const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(node.chainman->ActiveChainstate(), tx_pool, tx, bypass_limits)); + const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID; + if (accepted) { + txids.push_back(tx->GetHash()); + } + + SyncWithValidationInterfaceQueue(); + } +} +} // namespace diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp index 0a541e4186..d786ac1db1 100644 --- a/src/test/fuzz/util.cpp +++ b/src/test/fuzz/util.cpp @@ -3,8 +3,11 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <test/fuzz/util.h> +#include <test/util/script.h> +#include <util/rbf.h> #include <version.h> + void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, bool init_version) noexcept { const ServiceFlags remote_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS); @@ -23,3 +26,78 @@ void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, bool init_v node.m_tx_relay->fRelayTxes = filter_txs; } } + +CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<uint256>>& prevout_txids, const int max_num_in, const int max_num_out) noexcept +{ + CMutableTransaction tx_mut; + const auto p2wsh_op_true = fuzzed_data_provider.ConsumeBool(); + tx_mut.nVersion = fuzzed_data_provider.ConsumeBool() ? + CTransaction::CURRENT_VERSION : + fuzzed_data_provider.ConsumeIntegral<int32_t>(); + tx_mut.nLockTime = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); + const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_in); + const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_out); + for (int i = 0; i < num_in; ++i) { + const auto& txid_prev = prevout_txids ? + PickValue(fuzzed_data_provider, *prevout_txids) : + ConsumeUInt256(fuzzed_data_provider); + const auto index_out = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, max_num_out); + const auto sequence = ConsumeSequence(fuzzed_data_provider); + const auto script_sig = p2wsh_op_true ? CScript{} : ConsumeScript(fuzzed_data_provider); + CScriptWitness script_wit; + if (p2wsh_op_true) { + script_wit.stack = std::vector<std::vector<uint8_t>>{WITNESS_STACK_ELEM_OP_TRUE}; + } else { + script_wit = ConsumeScriptWitness(fuzzed_data_provider); + } + CTxIn in; + in.prevout = COutPoint{txid_prev, index_out}; + in.nSequence = sequence; + in.scriptSig = script_sig; + in.scriptWitness = script_wit; + + tx_mut.vin.push_back(in); + } + for (int i = 0; i < num_out; ++i) { + const auto amount = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-10, 50 * COIN + 10); + const auto script_pk = p2wsh_op_true ? + P2WSH_OP_TRUE : + ConsumeScript(fuzzed_data_provider, /* max_length */ 128, /* maybe_p2wsh */ true); + tx_mut.vout.emplace_back(amount, script_pk); + } + return tx_mut; +} + +CScriptWitness ConsumeScriptWitness(FuzzedDataProvider& fuzzed_data_provider, const size_t max_stack_elem_size) noexcept +{ + CScriptWitness ret; + const auto n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_stack_elem_size); + for (size_t i = 0; i < n_elements; ++i) { + ret.stack.push_back(ConsumeRandomLengthByteVector(fuzzed_data_provider)); + } + return ret; +} + +CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length, const bool maybe_p2wsh) noexcept +{ + const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length); + CScript r_script{b.begin(), b.end()}; + if (maybe_p2wsh && fuzzed_data_provider.ConsumeBool()) { + uint256 script_hash; + CSHA256().Write(&r_script[0], r_script.size()).Finalize(script_hash.begin()); + r_script.clear(); + r_script << OP_0 << ToByteVector(script_hash); + } + return r_script; +} + +uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return fuzzed_data_provider.ConsumeBool() ? + fuzzed_data_provider.PickValueInArray({ + CTxIn::SEQUENCE_FINAL, + CTxIn::SEQUENCE_FINAL - 1, + MAX_BIP125_RBF_SEQUENCE, + }) : + fuzzed_data_provider.ConsumeIntegral<uint32_t>(); +} diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index f3bc3c78ab..50d3ac66e5 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -10,6 +10,7 @@ #include <attributes.h> #include <chainparamsbase.h> #include <coins.h> +#include <compat.h> #include <consensus/consensus.h> #include <merkleblock.h> #include <net.h> @@ -23,14 +24,13 @@ #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> #include <test/util/net.h> -#include <test/util/setup_common.h> #include <txmempool.h> #include <uint256.h> #include <util/time.h> -#include <util/vector.h> #include <version.h> #include <algorithm> +#include <array> #include <cstdint> #include <cstdio> #include <optional> @@ -48,6 +48,16 @@ void CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callables) return ((i++ == call_index ? callables() : void()), ...); } +template <typename Collection> +auto& PickValue(FuzzedDataProvider& fuzzed_data_provider, Collection& col) +{ + const auto sz = col.size(); + assert(sz >= 1); + auto it = col.begin(); + std::advance(it, fuzzed_data_provider.ConsumeIntegralInRange<decltype(sz)>(0, sz - 1)); + return *it; +} + [[nodiscard]] inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(max_length); @@ -125,11 +135,13 @@ template <typename WeakEnumType, size_t size> return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(time_min, time_max); } -[[nodiscard]] inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept -{ - const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider); - return {b.begin(), b.end()}; -} +[[nodiscard]] CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<uint256>>& prevout_txids, const int max_num_in = 10, const int max_num_out = 10) noexcept; + +[[nodiscard]] CScriptWitness ConsumeScriptWitness(FuzzedDataProvider& fuzzed_data_provider, const size_t max_stack_elem_size = 32) noexcept; + +[[nodiscard]] CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096, const bool maybe_p2wsh = false) noexcept; + +[[nodiscard]] uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept; [[nodiscard]] inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept { @@ -251,6 +263,25 @@ template <class T> } /** + * Sets errno to a value selected from the given std::array `errnos`. + */ +template <typename T, size_t size> +void SetFuzzedErrNo(FuzzedDataProvider& fuzzed_data_provider, const std::array<T, size>& errnos) +{ + errno = fuzzed_data_provider.PickValueInArray(errnos); +} + +/* + * Sets a fuzzed errno in the range [0, 133 (EHWPOISON)]. Can be used from functions emulating + * standard library functions that set errno, or in other contexts where the value of errno + * might be relevant for the execution path that will be taken. + */ +inline void SetFuzzedErrNo(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + errno = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 133); +} + +/** * Returns a byte vector of specified size regardless of the number of remaining bytes available * from the fuzzer. Pads with zero value bytes if needed to achieve the specified size. */ @@ -324,19 +355,6 @@ inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, co void FillNode(FuzzedDataProvider& fuzzed_data_provider, CNode& node, bool init_version) noexcept; -template <class T = const BasicTestingSetup> -std::unique_ptr<T> MakeNoLogFileContext(const std::string& chain_name = CBaseChainParams::REGTEST, const std::vector<const char*>& extra_args = {}) -{ - // Prepend default arguments for fuzzing - const std::vector<const char*> arguments = Cat( - { - "-nodebuglogfile", - }, - extra_args); - - return MakeUnique<T>(chain_name, arguments); -} - class FuzzedFileProvider { FuzzedDataProvider& m_fuzzed_data_provider; @@ -349,6 +367,7 @@ public: FILE* open() { + SetFuzzedErrNo(m_fuzzed_data_provider); if (m_fuzzed_data_provider.ConsumeBool()) { return nullptr; } @@ -390,6 +409,7 @@ public: static ssize_t read(void* cookie, char* buf, size_t size) { FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie; + SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider); if (buf == nullptr || size == 0 || fuzzed_file->m_fuzzed_data_provider.ConsumeBool()) { return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1; } @@ -408,6 +428,7 @@ public: static ssize_t write(void* cookie, const char* buf, size_t size) { FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie; + SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider); const ssize_t n = fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<ssize_t>(0, size); if (AdditionOverflow(fuzzed_file->m_offset, (int64_t)n)) { return fuzzed_file->m_fuzzed_data_provider.ConsumeBool() ? 0 : -1; @@ -418,8 +439,9 @@ public: static int seek(void* cookie, int64_t* offset, int whence) { - assert(whence == SEEK_SET || whence == SEEK_CUR); // SEEK_END not implemented yet. + assert(whence == SEEK_SET || whence == SEEK_CUR || whence == SEEK_END); FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie; + SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider); int64_t new_offset = 0; if (whence == SEEK_SET) { new_offset = *offset; @@ -428,6 +450,12 @@ public: return -1; } new_offset = fuzzed_file->m_offset + *offset; + } else if (whence == SEEK_END) { + const int64_t n = fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 4096); + if (AdditionOverflow(n, *offset)) { + return -1; + } + new_offset = n + *offset; } if (new_offset < 0) { return -1; @@ -440,6 +468,7 @@ public: static int close(void* cookie) { FuzzedFileProvider* fuzzed_file = (FuzzedFileProvider*)cookie; + SetFuzzedErrNo(fuzzed_file->m_fuzzed_data_provider); return fuzzed_file->m_fuzzed_data_provider.ConsumeIntegralInRange<int>(-1, 0); } }; @@ -534,4 +563,198 @@ void ReadFromStream(FuzzedDataProvider& fuzzed_data_provider, Stream& stream) no } } +class FuzzedSock : public Sock +{ + FuzzedDataProvider& m_fuzzed_data_provider; + + /** + * Data to return when `MSG_PEEK` is used as a `Recv()` flag. + * If `MSG_PEEK` is used, then our `Recv()` returns some random data as usual, but on the next + * `Recv()` call we must return the same data, thus we remember it here. + */ + mutable std::optional<uint8_t> m_peek_data; + +public: + explicit FuzzedSock(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider{fuzzed_data_provider} + { + m_socket = fuzzed_data_provider.ConsumeIntegral<SOCKET>(); + } + + ~FuzzedSock() override + { + // Sock::~Sock() will be called after FuzzedSock::~FuzzedSock() and it will call + // Sock::Reset() (not FuzzedSock::Reset()!) which will call CloseSocket(m_socket). + // Avoid closing an arbitrary file descriptor (m_socket is just a random number which + // may concide with a real opened file descriptor). + Reset(); + } + + FuzzedSock& operator=(Sock&& other) override + { + assert(false && "Move of Sock into FuzzedSock not allowed."); + return *this; + } + + void Reset() override + { + m_socket = INVALID_SOCKET; + } + + ssize_t Send(const void* data, size_t len, int flags) const override + { + constexpr std::array send_errnos{ + EACCES, + EAGAIN, + EALREADY, + EBADF, + ECONNRESET, + EDESTADDRREQ, + EFAULT, + EINTR, + EINVAL, + EISCONN, + EMSGSIZE, + ENOBUFS, + ENOMEM, + ENOTCONN, + ENOTSOCK, + EOPNOTSUPP, + EPIPE, + EWOULDBLOCK, + }; + if (m_fuzzed_data_provider.ConsumeBool()) { + return len; + } + const ssize_t r = m_fuzzed_data_provider.ConsumeIntegralInRange<ssize_t>(-1, len); + if (r == -1) { + SetFuzzedErrNo(m_fuzzed_data_provider, send_errnos); + } + return r; + } + + ssize_t Recv(void* buf, size_t len, int flags) const override + { + // Have a permanent error at recv_errnos[0] because when the fuzzed data is exhausted + // SetFuzzedErrNo() will always return the first element and we want to avoid Recv() + // returning -1 and setting errno to EAGAIN repeatedly. + constexpr std::array recv_errnos{ + ECONNREFUSED, + EAGAIN, + EBADF, + EFAULT, + EINTR, + EINVAL, + ENOMEM, + ENOTCONN, + ENOTSOCK, + EWOULDBLOCK, + }; + assert(buf != nullptr || len == 0); + if (len == 0 || m_fuzzed_data_provider.ConsumeBool()) { + const ssize_t r = m_fuzzed_data_provider.ConsumeBool() ? 0 : -1; + if (r == -1) { + SetFuzzedErrNo(m_fuzzed_data_provider, recv_errnos); + } + return r; + } + std::vector<uint8_t> random_bytes; + bool pad_to_len_bytes{m_fuzzed_data_provider.ConsumeBool()}; + if (m_peek_data.has_value()) { + // `MSG_PEEK` was used in the preceding `Recv()` call, return `m_peek_data`. + random_bytes.assign({m_peek_data.value()}); + if ((flags & MSG_PEEK) == 0) { + m_peek_data.reset(); + } + pad_to_len_bytes = false; + } else if ((flags & MSG_PEEK) != 0) { + // New call with `MSG_PEEK`. + random_bytes = m_fuzzed_data_provider.ConsumeBytes<uint8_t>(1); + if (!random_bytes.empty()) { + m_peek_data = random_bytes[0]; + pad_to_len_bytes = false; + } + } else { + random_bytes = m_fuzzed_data_provider.ConsumeBytes<uint8_t>( + m_fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, len)); + } + if (random_bytes.empty()) { + const ssize_t r = m_fuzzed_data_provider.ConsumeBool() ? 0 : -1; + if (r == -1) { + SetFuzzedErrNo(m_fuzzed_data_provider, recv_errnos); + } + return r; + } + std::memcpy(buf, random_bytes.data(), random_bytes.size()); + if (pad_to_len_bytes) { + if (len > random_bytes.size()) { + std::memset((char*)buf + random_bytes.size(), 0, len - random_bytes.size()); + } + return len; + } + if (m_fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) { + std::this_thread::sleep_for(std::chrono::milliseconds{2}); + } + return random_bytes.size(); + } + + int Connect(const sockaddr*, socklen_t) const override + { + // Have a permanent error at connect_errnos[0] because when the fuzzed data is exhausted + // SetFuzzedErrNo() will always return the first element and we want to avoid Connect() + // returning -1 and setting errno to EAGAIN repeatedly. + constexpr std::array connect_errnos{ + ECONNREFUSED, + EAGAIN, + ECONNRESET, + EHOSTUNREACH, + EINPROGRESS, + EINTR, + ENETUNREACH, + ETIMEDOUT, + }; + if (m_fuzzed_data_provider.ConsumeBool()) { + SetFuzzedErrNo(m_fuzzed_data_provider, connect_errnos); + return -1; + } + return 0; + } + + int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override + { + constexpr std::array getsockopt_errnos{ + ENOMEM, + ENOBUFS, + }; + if (m_fuzzed_data_provider.ConsumeBool()) { + SetFuzzedErrNo(m_fuzzed_data_provider, getsockopt_errnos); + return -1; + } + if (opt_val == nullptr) { + return 0; + } + std::memcpy(opt_val, + ConsumeFixedLengthByteVector(m_fuzzed_data_provider, *opt_len).data(), + *opt_len); + return 0; + } + + bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override + { + return m_fuzzed_data_provider.ConsumeBool(); + } + + bool IsConnected(std::string& errmsg) const override { + if (m_fuzzed_data_provider.ConsumeBool()) { + return true; + } + errmsg = "disconnected at random by the fuzzer"; + return false; + } +}; + +[[nodiscard]] inline FuzzedSock ConsumeSock(FuzzedDataProvider& fuzzed_data_provider) +{ + return FuzzedSock{fuzzed_data_provider}; +} + #endif // BITCOIN_TEST_FUZZ_UTIL_H diff --git a/src/test/fuzz/validation_load_mempool.cpp b/src/test/fuzz/validation_load_mempool.cpp new file mode 100644 index 0000000000..e1a21b6c53 --- /dev/null +++ b/src/test/fuzz/validation_load_mempool.cpp @@ -0,0 +1,34 @@ +// 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 <chainparamsbase.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/setup_common.h> +#include <txmempool.h> +#include <util/time.h> +#include <validation.h> + +#include <cstdint> +#include <vector> + +void initialize_validation_load_mempool() +{ + static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); +} + +FUZZ_TARGET_INIT(validation_load_mempool, initialize_validation_load_mempool) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + SetMockTime(ConsumeTime(fuzzed_data_provider)); + FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider); + + CTxMemPool pool{}; + auto fuzzed_fopen = [&](const fs::path&, const char*) { + return fuzzed_file_provider.open(); + }; + (void)LoadMempool(pool, ::ChainstateActive(), fuzzed_fopen); + (void)DumpMempool(pool, fuzzed_fopen, true); +} diff --git a/src/test/fuzz/versionbits.cpp b/src/test/fuzz/versionbits.cpp new file mode 100644 index 0000000000..88c1a1a9cb --- /dev/null +++ b/src/test/fuzz/versionbits.cpp @@ -0,0 +1,351 @@ +// Copyright (c) 2020-2021 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 <chain.h> +#include <chainparams.h> +#include <consensus/params.h> +#include <primitives/block.h> +#include <versionbits.h> + +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> + +#include <cstdint> +#include <limits> +#include <memory> +#include <vector> + +namespace { +class TestConditionChecker : public AbstractThresholdConditionChecker +{ +private: + mutable ThresholdConditionCache m_cache; + const Consensus::Params dummy_params{}; + +public: + const int64_t m_begin; + const int64_t m_end; + const int m_period; + const int m_threshold; + const int m_bit; + + TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int bit) + : m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_bit{bit} + { + assert(m_period > 0); + assert(0 <= m_threshold && m_threshold <= m_period); + assert(0 <= m_bit && m_bit < 32 && m_bit < VERSIONBITS_NUM_BITS); + } + + bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return Condition(pindex->nVersion); } + int64_t BeginTime(const Consensus::Params& params) const override { return m_begin; } + int64_t EndTime(const Consensus::Params& params) const override { return m_end; } + int Period(const Consensus::Params& params) const override { return m_period; } + int Threshold(const Consensus::Params& params) const override { return m_threshold; } + + ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, dummy_params, m_cache); } + int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); } + BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateStatisticsFor(pindexPrev, dummy_params); } + + bool Condition(int32_t version) const + { + uint32_t mask = ((uint32_t)1) << m_bit; + return (((version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (version & mask) != 0); + } + + bool Condition(const CBlockIndex* pindex) const { return Condition(pindex->nVersion); } +}; + +/** Track blocks mined for test */ +class Blocks +{ +private: + std::vector<std::unique_ptr<CBlockIndex>> m_blocks; + const uint32_t m_start_time; + const uint32_t m_interval; + const int32_t m_signal; + const int32_t m_no_signal; + +public: + Blocks(uint32_t start_time, uint32_t interval, int32_t signal, int32_t no_signal) + : m_start_time{start_time}, m_interval{interval}, m_signal{signal}, m_no_signal{no_signal} {} + + size_t size() const { return m_blocks.size(); } + + CBlockIndex* tip() const + { + return m_blocks.empty() ? nullptr : m_blocks.back().get(); + } + + CBlockIndex* mine_block(bool signal) + { + CBlockHeader header; + header.nVersion = signal ? m_signal : m_no_signal; + header.nTime = m_start_time + m_blocks.size() * m_interval; + header.nBits = 0x1d00ffff; + + auto current_block = std::make_unique<CBlockIndex>(header); + current_block->pprev = tip(); + current_block->nHeight = m_blocks.size(); + current_block->BuildSkip(); + + return m_blocks.emplace_back(std::move(current_block)).get(); + } +}; + +std::unique_ptr<const CChainParams> g_params; + +void initialize() +{ + // this is actually comparatively slow, so only do it once + g_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN); + assert(g_params != nullptr); +} + +constexpr uint32_t MAX_START_TIME = 4102444800; // 2100-01-01 + +FUZZ_TARGET_INIT(versionbits, initialize) +{ + const CChainParams& params = *g_params; + const int64_t interval = params.GetConsensus().nPowTargetSpacing; + assert(interval > 1); // need to be able to halve it + assert(interval < std::numeric_limits<int32_t>::max()); + + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + // making period/max_periods larger slows these tests down significantly + const int period = 32; + const size_t max_periods = 16; + const size_t max_blocks = 2 * period * max_periods; + + const int threshold = fuzzed_data_provider.ConsumeIntegralInRange(1, period); + assert(0 < threshold && threshold <= period); // must be able to both pass and fail threshold! + + // too many blocks at 10min each might cause uint32_t time to overflow if + // block_start_time is at the end of the range above + assert(std::numeric_limits<uint32_t>::max() - MAX_START_TIME > interval * max_blocks); + + const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.GenesisBlock().nTime, MAX_START_TIME); + + // what values for version will we use to signal / not signal? + const int32_t ver_signal = fuzzed_data_provider.ConsumeIntegral<int32_t>(); + const int32_t ver_nosignal = fuzzed_data_provider.ConsumeIntegral<int32_t>(); + + // select deployment parameters: bit, start time, timeout + const int bit = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, VERSIONBITS_NUM_BITS - 1); + + bool always_active_test = false; + bool never_active_test = false; + int64_t start_time; + int64_t timeout; + if (fuzzed_data_provider.ConsumeBool()) { + // pick the timestamp to switch based on a block + // note states will change *after* these blocks because mediantime lags + int start_block = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, period * (max_periods - 3)); + int end_block = fuzzed_data_provider.ConsumeIntegralInRange<int>(start_block, period * (max_periods - 3)); + + start_time = block_start_time + start_block * interval; + timeout = block_start_time + end_block * interval; + + assert(start_time <= timeout); + + // allow for times to not exactly match a block + if (fuzzed_data_provider.ConsumeBool()) start_time += interval / 2; + if (fuzzed_data_provider.ConsumeBool()) timeout += interval / 2; + + // this may make timeout too early; if so, don't run the test + if (start_time > timeout) return; + } else { + if (fuzzed_data_provider.ConsumeBool()) { + start_time = Consensus::BIP9Deployment::ALWAYS_ACTIVE; + timeout = Consensus::BIP9Deployment::NO_TIMEOUT; + always_active_test = true; + } else { + start_time = 1199145601; // January 1, 2008 + timeout = 1230767999; // December 31, 2008 + never_active_test = true; + } + } + + TestConditionChecker checker(start_time, timeout, period, threshold, bit); + + // Early exit if the versions don't signal sensibly for the deployment + if (!checker.Condition(ver_signal)) return; + if (checker.Condition(ver_nosignal)) return; + if (ver_nosignal < 0) return; + + // TOP_BITS should ensure version will be positive and meet min + // version requirement + assert(ver_signal > 0); + assert(ver_signal >= VERSIONBITS_LAST_OLD_BLOCK_VERSION); + + // Now that we have chosen time and versions, setup to mine blocks + Blocks blocks(block_start_time, interval, ver_signal, ver_nosignal); + + /* Strategy: + * * we will mine a final period worth of blocks, with + * randomised signalling according to a mask + * * but before we mine those blocks, we will mine some + * randomised number of prior periods; with either all + * or no blocks in the period signalling + * + * We establish the mask first, then consume "bools" until + * we run out of fuzz data to work out how many prior periods + * there are and which ones will signal. + */ + + // establish the mask + const uint32_t signalling_mask = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); + + // mine prior periods + while (fuzzed_data_provider.remaining_bytes() > 0) { + // all blocks in these periods either do or don't signal + bool signal = fuzzed_data_provider.ConsumeBool(); + for (int b = 0; b < period; ++b) { + blocks.mine_block(signal); + } + + // don't risk exceeding max_blocks or times may wrap around + if (blocks.size() + 2 * period > max_blocks) break; + } + // NOTE: fuzzed_data_provider may be fully consumed at this point and should not be used further + + // now we mine the final period and check that everything looks sane + + // count the number of signalling blocks + int blocks_sig = 0; + + // get the info for the first block of the period + CBlockIndex* prev = blocks.tip(); + const int exp_since = checker.GetStateSinceHeightFor(prev); + const ThresholdState exp_state = checker.GetStateFor(prev); + BIP9Stats last_stats = checker.GetStateStatisticsFor(prev); + + int prev_next_height = (prev == nullptr ? 0 : prev->nHeight + 1); + assert(exp_since <= prev_next_height); + + // mine (period-1) blocks and check state + for (int b = 1; b < period; ++b) { + const bool signal = (signalling_mask >> (b % 32)) & 1; + if (signal) ++blocks_sig; + + CBlockIndex* current_block = blocks.mine_block(signal); + + // verify that signalling attempt was interpreted correctly + assert(checker.Condition(current_block) == signal); + + // state and since don't change within the period + const ThresholdState state = checker.GetStateFor(current_block); + const int since = checker.GetStateSinceHeightFor(current_block); + assert(state == exp_state); + assert(since == exp_since); + + // GetStateStatistics may crash when state is not STARTED + if (state != ThresholdState::STARTED) continue; + + // check that after mining this block stats change as expected + const BIP9Stats stats = checker.GetStateStatisticsFor(current_block); + assert(stats.period == period); + assert(stats.threshold == threshold); + assert(stats.elapsed == b); + assert(stats.count == last_stats.count + (signal ? 1 : 0)); + assert(stats.possible == (stats.count + period >= stats.elapsed + threshold)); + last_stats = stats; + } + + if (exp_state == ThresholdState::STARTED) { + // double check that stats.possible is sane + if (blocks_sig >= threshold - 1) assert(last_stats.possible); + } + + // mine the final block + bool signal = (signalling_mask >> (period % 32)) & 1; + if (signal) ++blocks_sig; + CBlockIndex* current_block = blocks.mine_block(signal); + assert(checker.Condition(current_block) == signal); + + // GetStateStatistics is safe on a period boundary + // and has progressed to a new period + const BIP9Stats stats = checker.GetStateStatisticsFor(current_block); + assert(stats.period == period); + assert(stats.threshold == threshold); + assert(stats.elapsed == 0); + assert(stats.count == 0); + assert(stats.possible == true); + + // More interesting is whether the state changed. + const ThresholdState state = checker.GetStateFor(current_block); + const int since = checker.GetStateSinceHeightFor(current_block); + + // since is straightforward: + assert(since % period == 0); + assert(0 <= since && since <= current_block->nHeight + 1); + if (state == exp_state) { + assert(since == exp_since); + } else { + assert(since == current_block->nHeight + 1); + } + + // state is where everything interesting is + switch (state) { + case ThresholdState::DEFINED: + assert(since == 0); + assert(exp_state == ThresholdState::DEFINED); + assert(current_block->GetMedianTimePast() < checker.m_begin); + assert(current_block->GetMedianTimePast() < checker.m_end); + break; + case ThresholdState::STARTED: + assert(current_block->GetMedianTimePast() >= checker.m_begin); + assert(current_block->GetMedianTimePast() < checker.m_end); + if (exp_state == ThresholdState::STARTED) { + assert(blocks_sig < threshold); + } else { + assert(exp_state == ThresholdState::DEFINED); + } + break; + case ThresholdState::LOCKED_IN: + assert(exp_state == ThresholdState::STARTED); + assert(current_block->GetMedianTimePast() < checker.m_end); + assert(blocks_sig >= threshold); + break; + case ThresholdState::ACTIVE: + assert(exp_state == ThresholdState::ACTIVE || exp_state == ThresholdState::LOCKED_IN); + break; + case ThresholdState::FAILED: + assert(current_block->GetMedianTimePast() >= checker.m_end); + assert(exp_state != ThresholdState::LOCKED_IN && exp_state != ThresholdState::ACTIVE); + break; + default: + assert(false); + } + + if (blocks.size() >= period * max_periods) { + // we chose the timeout (and block times) so that by the time we have this many blocks it's all over + assert(state == ThresholdState::ACTIVE || state == ThresholdState::FAILED); + } + + // "always active" has additional restrictions + if (always_active_test) { + assert(state == ThresholdState::ACTIVE); + assert(exp_state == ThresholdState::ACTIVE); + assert(since == 0); + } else { + // except for always active, the initial state is always DEFINED + assert(since > 0 || state == ThresholdState::DEFINED); + assert(exp_since > 0 || exp_state == ThresholdState::DEFINED); + } + + // "never active" does too + if (never_active_test) { + assert(state == ThresholdState::FAILED); + assert(since == period); + if (exp_since == 0) { + assert(exp_state == ThresholdState::DEFINED); + } else { + assert(exp_state == ThresholdState::FAILED); + } + } +} +} // namespace diff --git a/src/test/i2p_tests.cpp b/src/test/i2p_tests.cpp new file mode 100644 index 0000000000..334f71106c --- /dev/null +++ b/src/test/i2p_tests.cpp @@ -0,0 +1,44 @@ +// Copyright (c) 2021-2021 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 <i2p.h> +#include <netaddress.h> +#include <test/util/logging.h> +#include <test/util/net.h> +#include <test/util/setup_common.h> +#include <threadinterrupt.h> +#include <util/system.h> + +#include <boost/test/unit_test.hpp> + +#include <memory> +#include <string> + +BOOST_FIXTURE_TEST_SUITE(i2p_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(unlimited_recv) +{ + auto CreateSockOrig = CreateSock; + + // Mock CreateSock() to create MockSock. + CreateSock = [](const CService&) { + return std::make_unique<StaticContentsSock>(std::string(i2p::sam::MAX_MSG_SIZE + 1, 'a')); + }; + + CThreadInterrupt interrupt; + i2p::sam::Session session(GetDataDir() / "test_i2p_private_key", CService{}, &interrupt); + + { + ASSERT_DEBUG_LOG("Creating SAM session"); + ASSERT_DEBUG_LOG("too many bytes without a terminator"); + + i2p::Connection conn; + bool proxy_error; + BOOST_REQUIRE(!session.Connect(CService{}, conn, proxy_error)); + } + + CreateSock = CreateSockOrig; +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index aa628371e6..9ba004cc38 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -44,7 +44,7 @@ BlockAssembler MinerTestingSetup::AssemblerForTest(const CChainParams& params) options.nBlockMaxWeight = MAX_BLOCK_WEIGHT; options.blockMinFeeRate = blockMinFeeRate; - return BlockAssembler(*m_node.mempool, params, options); + return BlockAssembler(::ChainstateActive(), *m_node.mempool, params, options); } constexpr static struct { diff --git a/src/test/net_peer_eviction_tests.cpp b/src/test/net_peer_eviction_tests.cpp new file mode 100644 index 0000000000..31d391bf7d --- /dev/null +++ b/src/test/net_peer_eviction_tests.cpp @@ -0,0 +1,348 @@ +// Copyright (c) 2021 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 <net.h> +#include <test/util/setup_common.h> + +#include <boost/test/unit_test.hpp> + +#include <algorithm> +#include <functional> +#include <optional> +#include <unordered_set> +#include <vector> + +BOOST_FIXTURE_TEST_SUITE(net_peer_eviction_tests, BasicTestingSetup) + +namespace { +constexpr int NODE_EVICTION_TEST_ROUNDS{10}; +constexpr int NODE_EVICTION_TEST_UP_TO_N_NODES{200}; +} // namespace + +std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(const int n_candidates, FastRandomContext& random_context) +{ + std::vector<NodeEvictionCandidate> candidates; + for (int id = 0; id < n_candidates; ++id) { + candidates.push_back({ + /* id */ id, + /* nTimeConnected */ static_cast<int64_t>(random_context.randrange(100)), + /* m_min_ping_time */ std::chrono::microseconds{random_context.randrange(100)}, + /* nLastBlockTime */ static_cast<int64_t>(random_context.randrange(100)), + /* nLastTXTime */ static_cast<int64_t>(random_context.randrange(100)), + /* fRelevantServices */ random_context.randbool(), + /* fRelayTxes */ random_context.randbool(), + /* fBloomFilter */ random_context.randbool(), + /* nKeyedNetGroup */ random_context.randrange(100), + /* prefer_evict */ random_context.randbool(), + /* m_is_local */ random_context.randbool(), + /* m_is_onion */ random_context.randbool(), + }); + } + return candidates; +} + +// Create `num_peers` random nodes, apply setup function `candidate_setup_fn`, +// call ProtectEvictionCandidatesByRatio() to apply protection logic, and then +// return true if all of `protected_peer_ids` and none of `unprotected_peer_ids` +// are protected from eviction, i.e. removed from the eviction candidates. +bool IsProtected(int num_peers, + std::function<void(NodeEvictionCandidate&)> candidate_setup_fn, + const std::unordered_set<NodeId>& protected_peer_ids, + const std::unordered_set<NodeId>& unprotected_peer_ids, + FastRandomContext& random_context) +{ + std::vector<NodeEvictionCandidate> candidates{GetRandomNodeEvictionCandidates(num_peers, random_context)}; + for (NodeEvictionCandidate& candidate : candidates) { + candidate_setup_fn(candidate); + } + Shuffle(candidates.begin(), candidates.end(), random_context); + + const size_t size{candidates.size()}; + const size_t expected{size - size / 2}; // Expect half the candidates will be protected. + ProtectEvictionCandidatesByRatio(candidates); + BOOST_CHECK_EQUAL(candidates.size(), expected); + + size_t unprotected_count{0}; + for (const NodeEvictionCandidate& candidate : candidates) { + if (protected_peer_ids.count(candidate.id)) { + // this peer should have been removed from the eviction candidates + BOOST_TEST_MESSAGE(strprintf("expected candidate to be protected: %d", candidate.id)); + return false; + } + if (unprotected_peer_ids.count(candidate.id)) { + // this peer remains in the eviction candidates, as expected + ++unprotected_count; + } + } + + const bool is_protected{unprotected_count == unprotected_peer_ids.size()}; + if (!is_protected) { + BOOST_TEST_MESSAGE(strprintf("unprotected: expected %d, actual %d", + unprotected_peer_ids.size(), unprotected_count)); + } + return is_protected; +} + +BOOST_AUTO_TEST_CASE(peer_protection_test) +{ + FastRandomContext random_context{true}; + int num_peers{12}; + + // Expect half of the peers with greatest uptime (the lowest nTimeConnected) + // to be protected from eviction. + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = c.m_is_local = false; + }, + /* protected_peer_ids */ {0, 1, 2, 3, 4, 5}, + /* unprotected_peer_ids */ {6, 7, 8, 9, 10, 11}, + random_context)); + + // Verify in the opposite direction. + BOOST_CHECK(IsProtected( + num_peers, [num_peers](NodeEvictionCandidate& c) { + c.nTimeConnected = num_peers - c.id; + c.m_is_onion = c.m_is_local = false; + }, + /* protected_peer_ids */ {6, 7, 8, 9, 10, 11}, + /* unprotected_peer_ids */ {0, 1, 2, 3, 4, 5}, + random_context)); + + // Test protection of onion and localhost peers... + + // Expect 1/4 onion peers to be protected from eviction, + // independently of other characteristics. + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.m_is_onion = (c.id == 3 || c.id == 8 || c.id == 9); + }, + /* protected_peer_ids */ {3, 8, 9}, + /* unprotected_peer_ids */ {}, + random_context)); + + // Expect 1/4 onion peers and 1/4 of the others to be protected + // from eviction, sorted by longest uptime (lowest nTimeConnected). + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_local = false; + c.m_is_onion = (c.id == 3 || c.id > 7); + }, + /* protected_peer_ids */ {0, 1, 2, 3, 8, 9}, + /* unprotected_peer_ids */ {4, 5, 6, 7, 10, 11}, + random_context)); + + // Expect 1/4 localhost peers to be protected from eviction, + // if no onion peers. + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.m_is_onion = false; + c.m_is_local = (c.id == 1 || c.id == 9 || c.id == 11); + }, + /* protected_peer_ids */ {1, 9, 11}, + /* unprotected_peer_ids */ {}, + random_context)); + + // Expect 1/4 localhost peers and 1/4 of the other peers to be protected, + // sorted by longest uptime (lowest nTimeConnected), if no onion peers. + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = false; + c.m_is_local = (c.id > 6); + }, + /* protected_peer_ids */ {0, 1, 2, 7, 8, 9}, + /* unprotected_peer_ids */ {3, 4, 5, 6, 10, 11}, + random_context)); + + // Combined test: expect 1/4 onion and 2 localhost peers to be protected + // from eviction, sorted by longest uptime. + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = (c.id == 0 || c.id == 5 || c.id == 10); + c.m_is_local = (c.id == 1 || c.id == 9 || c.id == 11); + }, + /* protected_peer_ids */ {0, 1, 2, 5, 9, 10}, + /* unprotected_peer_ids */ {3, 4, 6, 7, 8, 11}, + random_context)); + + // Combined test: expect having only 1 onion to allow allocating the + // remaining 2 of the 1/4 to localhost peers, sorted by longest uptime. + BOOST_CHECK(IsProtected( + num_peers + 4, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = (c.id == 15); + c.m_is_local = (c.id > 6 && c.id < 11); + }, + /* protected_peer_ids */ {0, 1, 2, 3, 7, 8, 9, 15}, + /* unprotected_peer_ids */ {4, 5, 6, 10, 11, 12, 13, 14}, + random_context)); + + // Combined test: expect 2 onions (< 1/4) to allow allocating the minimum 2 + // localhost peers, sorted by longest uptime. + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = (c.id == 7 || c.id == 9); + c.m_is_local = (c.id == 6 || c.id == 11); + }, + /* protected_peer_ids */ {0, 1, 6, 7, 9, 11}, + /* unprotected_peer_ids */ {2, 3, 4, 5, 8, 10}, + random_context)); + + // Combined test: when > 1/4, expect max 1/4 onion and 2 localhost peers + // to be protected from eviction, sorted by longest uptime. + BOOST_CHECK(IsProtected( + num_peers, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = (c.id > 3 && c.id < 8); + c.m_is_local = (c.id > 7); + }, + /* protected_peer_ids */ {0, 4, 5, 6, 8, 9}, + /* unprotected_peer_ids */ {1, 2, 3, 7, 10, 11}, + random_context)); + + // Combined test: idem > 1/4 with only 8 peers: expect 2 onion and 2 + // localhost peers (1/4 + 2) to be protected, sorted by longest uptime. + BOOST_CHECK(IsProtected( + 8, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = (c.id > 1 && c.id < 5); + c.m_is_local = (c.id > 4); + }, + /* protected_peer_ids */ {2, 3, 5, 6}, + /* unprotected_peer_ids */ {0, 1, 4, 7}, + random_context)); + + // Combined test: idem > 1/4 with only 6 peers: expect 1 onion peer and no + // localhost peers (1/4 + 0) to be protected, sorted by longest uptime. + BOOST_CHECK(IsProtected( + 6, [](NodeEvictionCandidate& c) { + c.nTimeConnected = c.id; + c.m_is_onion = (c.id == 4 || c.id == 5); + c.m_is_local = (c.id == 3); + }, + /* protected_peer_ids */ {0, 1, 4}, + /* unprotected_peer_ids */ {2, 3, 5}, + random_context)); +} + +// Returns true if any of the node ids in node_ids are selected for eviction. +bool IsEvicted(std::vector<NodeEvictionCandidate> candidates, const std::unordered_set<NodeId>& node_ids, FastRandomContext& random_context) +{ + Shuffle(candidates.begin(), candidates.end(), random_context); + const std::optional<NodeId> evicted_node_id = SelectNodeToEvict(std::move(candidates)); + if (!evicted_node_id) { + return false; + } + return node_ids.count(*evicted_node_id); +} + +// Create number_of_nodes random nodes, apply setup function candidate_setup_fn, +// apply eviction logic and then return true if any of the node ids in node_ids +// are selected for eviction. +bool IsEvicted(const int number_of_nodes, std::function<void(NodeEvictionCandidate&)> candidate_setup_fn, const std::unordered_set<NodeId>& node_ids, FastRandomContext& random_context) +{ + std::vector<NodeEvictionCandidate> candidates = GetRandomNodeEvictionCandidates(number_of_nodes, random_context); + for (NodeEvictionCandidate& candidate : candidates) { + candidate_setup_fn(candidate); + } + return IsEvicted(candidates, node_ids, random_context); +} + +BOOST_AUTO_TEST_CASE(peer_eviction_test) +{ + FastRandomContext random_context{true}; + + for (int i = 0; i < NODE_EVICTION_TEST_ROUNDS; ++i) { + for (int number_of_nodes = 0; number_of_nodes < NODE_EVICTION_TEST_UP_TO_N_NODES; ++number_of_nodes) { + // Four nodes with the highest keyed netgroup values should be + // protected from eviction. + BOOST_CHECK(!IsEvicted( + number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { + candidate.nKeyedNetGroup = number_of_nodes - candidate.id; + }, + {0, 1, 2, 3}, random_context)); + + // Eight nodes with the lowest minimum ping time should be protected + // from eviction. + BOOST_CHECK(!IsEvicted( + number_of_nodes, [](NodeEvictionCandidate& candidate) { + candidate.m_min_ping_time = std::chrono::microseconds{candidate.id}; + }, + {0, 1, 2, 3, 4, 5, 6, 7}, random_context)); + + // Four nodes that most recently sent us novel transactions accepted + // into our mempool should be protected from eviction. + BOOST_CHECK(!IsEvicted( + number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { + candidate.nLastTXTime = number_of_nodes - candidate.id; + }, + {0, 1, 2, 3}, random_context)); + + // Up to eight non-tx-relay peers that most recently sent us novel + // blocks should be protected from eviction. + BOOST_CHECK(!IsEvicted( + number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { + candidate.nLastBlockTime = number_of_nodes - candidate.id; + if (candidate.id <= 7) { + candidate.fRelayTxes = false; + candidate.fRelevantServices = true; + } + }, + {0, 1, 2, 3, 4, 5, 6, 7}, random_context)); + + // Four peers that most recently sent us novel blocks should be + // protected from eviction. + BOOST_CHECK(!IsEvicted( + number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { + candidate.nLastBlockTime = number_of_nodes - candidate.id; + }, + {0, 1, 2, 3}, random_context)); + + // Combination of the previous two tests. + BOOST_CHECK(!IsEvicted( + number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { + candidate.nLastBlockTime = number_of_nodes - candidate.id; + if (candidate.id <= 7) { + candidate.fRelayTxes = false; + candidate.fRelevantServices = true; + } + }, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, random_context)); + + // Combination of all tests above. + BOOST_CHECK(!IsEvicted( + number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { + candidate.nKeyedNetGroup = number_of_nodes - candidate.id; // 4 protected + candidate.m_min_ping_time = std::chrono::microseconds{candidate.id}; // 8 protected + candidate.nLastTXTime = number_of_nodes - candidate.id; // 4 protected + candidate.nLastBlockTime = number_of_nodes - candidate.id; // 4 protected + }, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, random_context)); + + // An eviction is expected given >= 29 random eviction candidates. The eviction logic protects at most + // four peers by net group, eight by lowest ping time, four by last time of novel tx, up to eight non-tx-relay + // peers by last novel block time, and four more peers by last novel block time. + if (number_of_nodes >= 29) { + BOOST_CHECK(SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context))); + } + + // No eviction is expected given <= 20 random eviction candidates. The eviction logic protects at least + // four peers by net group, eight by lowest ping time, four by last time of novel tx and four peers by last + // novel block time. + if (number_of_nodes <= 20) { + BOOST_CHECK(!SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context))); + } + + // Cases left to test: + // * "If any remaining peers are preferred for eviction consider only them. [...]" + // * "Identify the network group with the most connections and youngest member. [...]" + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 1c7c35528e..8eab26f3d5 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -8,13 +8,12 @@ #include <clientversion.h> #include <cstdint> #include <net.h> +#include <netaddress.h> #include <netbase.h> -#include <optional.h> #include <serialize.h> #include <span.h> #include <streams.h> #include <test/util/setup_common.h> -#include <util/memory.h> #include <util/strencodings.h> #include <util/string.h> #include <util/system.h> @@ -25,6 +24,7 @@ #include <algorithm> #include <ios> #include <memory> +#include <optional> #include <string> using namespace std::literals; @@ -92,7 +92,7 @@ BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(cnode_listen_port) { // test default - uint16_t port = GetListenPort(); + uint16_t port{GetListenPort()}; BOOST_CHECK(port == Params().GetDefaultPort()); // test set port uint16_t altPort = 12345; @@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK); std::string pszDest; - std::unique_ptr<CNode> pnode1 = MakeUnique<CNode>( + std::unique_ptr<CNode> pnode1 = std::make_unique<CNode>( id++, NODE_NETWORK, hSocket, addr, /* nKeyedNetGroupIn = */ 0, /* nLocalHostNonceIn = */ 0, @@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) BOOST_CHECK(pnode1->m_inbound_onion == false); BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4); - std::unique_ptr<CNode> pnode2 = MakeUnique<CNode>( + std::unique_ptr<CNode> pnode2 = std::make_unique<CNode>( id++, NODE_NETWORK, hSocket, addr, /* nKeyedNetGroupIn = */ 1, /* nLocalHostNonceIn = */ 1, @@ -218,7 +218,7 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) BOOST_CHECK(pnode2->m_inbound_onion == false); BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4); - std::unique_ptr<CNode> pnode3 = MakeUnique<CNode>( + std::unique_ptr<CNode> pnode3 = std::make_unique<CNode>( id++, NODE_NETWORK, hSocket, addr, /* nKeyedNetGroupIn = */ 0, /* nLocalHostNonceIn = */ 0, @@ -233,7 +233,7 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) BOOST_CHECK(pnode3->m_inbound_onion == false); BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4); - std::unique_ptr<CNode> pnode4 = MakeUnique<CNode>( + std::unique_ptr<CNode> pnode4 = std::make_unique<CNode>( id++, NODE_NETWORK, hSocket, addr, /* nKeyedNetGroupIn = */ 1, /* nLocalHostNonceIn = */ 1, @@ -322,6 +322,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic) BOOST_REQUIRE(addr.IsValid()); BOOST_REQUIRE(addr.IsTor()); + BOOST_CHECK(!addr.IsI2P()); BOOST_CHECK(!addr.IsBindAny()); BOOST_CHECK(addr.IsAddrV1Compatible()); BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion"); @@ -332,6 +333,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic) BOOST_REQUIRE(addr.IsValid()); BOOST_REQUIRE(addr.IsTor()); + BOOST_CHECK(!addr.IsI2P()); BOOST_CHECK(!addr.IsBindAny()); BOOST_CHECK(!addr.IsAddrV1Compatible()); BOOST_CHECK_EQUAL(addr.ToString(), torv3_addr); @@ -352,6 +354,35 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic) // TOR, invalid base32 BOOST_CHECK(!addr.SetSpecial(std::string{"mf*g zak.onion"})); + // I2P + const char* i2p_addr = "UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P"; + BOOST_REQUIRE(addr.SetSpecial(i2p_addr)); + BOOST_REQUIRE(addr.IsValid()); + BOOST_REQUIRE(addr.IsI2P()); + + BOOST_CHECK(!addr.IsTor()); + BOOST_CHECK(!addr.IsBindAny()); + BOOST_CHECK(!addr.IsAddrV1Compatible()); + BOOST_CHECK_EQUAL(addr.ToString(), ToLower(i2p_addr)); + + // I2P, correct length, but decodes to less than the expected number of bytes. + BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jn=.b32.i2p")); + + // I2P, extra unnecessary padding + BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna=.b32.i2p")); + + // I2P, malicious + BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v\0wtf.b32.i2p"s)); + + // I2P, valid but unsupported (56 Base32 characters) + // See "Encrypted LS with Base 32 Addresses" in + // https://geti2p.net/spec/encryptedleaseset.txt + BOOST_CHECK( + !addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.b32.i2p")); + + // I2P, invalid base32 + BOOST_CHECK(!addr.SetSpecial(std::string{"tp*szydbh4dp.b32.i2p"})); + // Internal addr.SetInternal("esffpp"); BOOST_REQUIRE(!addr.IsValid()); // "internal" is considered invalid @@ -365,6 +396,60 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic) BOOST_CHECK(!addr.SetSpecial("totally bogus")); } +BOOST_AUTO_TEST_CASE(cnetaddr_tostring_canonical_ipv6) +{ + // Test that CNetAddr::ToString formats IPv6 addresses with zero compression as described in + // RFC 5952 ("A Recommendation for IPv6 Address Text Representation"). + const std::map<std::string, std::string> canonical_representations_ipv6{ + {"0000:0000:0000:0000:0000:0000:0000:0000", "::"}, + {"000:0000:000:00:0:00:000:0000", "::"}, + {"000:000:000:000:000:000:000:000", "::"}, + {"00:00:00:00:00:00:00:00", "::"}, + {"0:0:0:0:0:0:0:0", "::"}, + {"0:0:0:0:0:0:0:1", "::1"}, + {"2001:0:0:1:0:0:0:1", "2001:0:0:1::1"}, + {"2001:0db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"}, + {"2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:db8:85a3::8a2e:370:7334"}, + {"2001:0db8::0001", "2001:db8::1"}, + {"2001:0db8::0001:0000", "2001:db8::1:0"}, + {"2001:0db8::1:0:0:1", "2001:db8::1:0:0:1"}, + {"2001:db8:0000:0:1::1", "2001:db8::1:0:0:1"}, + {"2001:db8:0000:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"}, + {"2001:db8:0:0:0:0:2:1", "2001:db8::2:1"}, + {"2001:db8:0:0:0::1", "2001:db8::1"}, + {"2001:db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"}, + {"2001:db8:0:0:1::1", "2001:db8::1:0:0:1"}, + {"2001:DB8:0:0:1::1", "2001:db8::1:0:0:1"}, + {"2001:db8:0:0::1", "2001:db8::1"}, + {"2001:db8:0:0:aaaa::1", "2001:db8::aaaa:0:0:1"}, + {"2001:db8:0:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"}, + {"2001:db8:0::1", "2001:db8::1"}, + {"2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334"}, + {"2001:db8::0:1", "2001:db8::1"}, + {"2001:db8::0:1:0:0:1", "2001:db8::1:0:0:1"}, + {"2001:DB8::1", "2001:db8::1"}, + {"2001:db8::1", "2001:db8::1"}, + {"2001:db8::1:0:0:1", "2001:db8::1:0:0:1"}, + {"2001:db8::1:1:1:1:1", "2001:db8:0:1:1:1:1:1"}, + {"2001:db8::aaaa:0:0:1", "2001:db8::aaaa:0:0:1"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:0:1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"}, + {"2001:db8:aaaa:bbbb:cccc:dddd::1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:0001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:01", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AAAA", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"}, + {"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AaAa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"}, + }; + for (const auto& [input_address, expected_canonical_representation_output] : canonical_representations_ipv6) { + CNetAddr net_addr; + BOOST_REQUIRE(LookupHost(input_address, net_addr, false)); + BOOST_REQUIRE(net_addr.IsIPv6()); + BOOST_CHECK_EQUAL(net_addr.ToString(), expected_canonical_representation_output); + } +} + BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1) { CNetAddr addr; @@ -680,7 +765,7 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test) in_addr ipv4AddrPeer; ipv4AddrPeer.s_addr = 0xa0b0c001; CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK); - std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0, NODE_NETWORK, INVALID_SOCKET, addr, /* nKeyedNetGroupIn */ 0, /* nLocalHostNonceIn */ 0, CAddress{}, /* pszDest */ std::string{}, ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false); + std::unique_ptr<CNode> pnode = std::make_unique<CNode>(0, NODE_NETWORK, INVALID_SOCKET, addr, /* nKeyedNetGroupIn */ 0, /* nLocalHostNonceIn */ 0, CAddress{}, /* pszDest */ std::string{}, ConnectionType::OUTBOUND_FULL_RELAY, /* inbound_onion */ false); pnode->fSuccessfullyConnected.store(true); // the peer claims to be reaching us via IPv6 @@ -772,162 +857,4 @@ BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle) BOOST_CHECK_EQUAL(IsLocal(addr), false); } -BOOST_AUTO_TEST_CASE(PoissonNextSend) -{ - g_mock_deterministic_tests = true; - - int64_t now = 5000; - int average_interval_seconds = 600; - - auto poisson = ::PoissonNextSend(now, average_interval_seconds); - std::chrono::microseconds poisson_chrono = ::PoissonNextSend(std::chrono::microseconds{now}, std::chrono::seconds{average_interval_seconds}); - - BOOST_CHECK_EQUAL(poisson, poisson_chrono.count()); - - g_mock_deterministic_tests = false; -} - -std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(const int n_candidates, FastRandomContext& random_context) -{ - std::vector<NodeEvictionCandidate> candidates; - for (int id = 0; id < n_candidates; ++id) { - candidates.push_back({ - /* id */ id, - /* nTimeConnected */ static_cast<int64_t>(random_context.randrange(100)), - /* m_min_ping_time */ static_cast<int64_t>(random_context.randrange(100)), - /* nLastBlockTime */ static_cast<int64_t>(random_context.randrange(100)), - /* nLastTXTime */ static_cast<int64_t>(random_context.randrange(100)), - /* fRelevantServices */ random_context.randbool(), - /* fRelayTxes */ random_context.randbool(), - /* fBloomFilter */ random_context.randbool(), - /* nKeyedNetGroup */ random_context.randrange(100), - /* prefer_evict */ random_context.randbool(), - /* m_is_local */ random_context.randbool(), - }); - } - return candidates; -} - -// Returns true if any of the node ids in node_ids are selected for eviction. -bool IsEvicted(std::vector<NodeEvictionCandidate> candidates, const std::vector<NodeId>& node_ids, FastRandomContext& random_context) -{ - Shuffle(candidates.begin(), candidates.end(), random_context); - const Optional<NodeId> evicted_node_id = SelectNodeToEvict(std::move(candidates)); - if (!evicted_node_id) { - return false; - } - return std::find(node_ids.begin(), node_ids.end(), *evicted_node_id) != node_ids.end(); -} - -// Create number_of_nodes random nodes, apply setup function candidate_setup_fn, -// apply eviction logic and then return true if any of the node ids in node_ids -// are selected for eviction. -bool IsEvicted(const int number_of_nodes, std::function<void(NodeEvictionCandidate&)> candidate_setup_fn, const std::vector<NodeId>& node_ids, FastRandomContext& random_context) -{ - std::vector<NodeEvictionCandidate> candidates = GetRandomNodeEvictionCandidates(number_of_nodes, random_context); - for (NodeEvictionCandidate& candidate : candidates) { - candidate_setup_fn(candidate); - } - return IsEvicted(candidates, node_ids, random_context); -} - -namespace { -constexpr int NODE_EVICTION_TEST_ROUNDS{10}; -constexpr int NODE_EVICTION_TEST_UP_TO_N_NODES{200}; -} // namespace - -BOOST_AUTO_TEST_CASE(node_eviction_test) -{ - FastRandomContext random_context{true}; - - for (int i = 0; i < NODE_EVICTION_TEST_ROUNDS; ++i) { - for (int number_of_nodes = 0; number_of_nodes < NODE_EVICTION_TEST_UP_TO_N_NODES; ++number_of_nodes) { - // Four nodes with the highest keyed netgroup values should be - // protected from eviction. - BOOST_CHECK(!IsEvicted( - number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { - candidate.nKeyedNetGroup = number_of_nodes - candidate.id; - }, - {0, 1, 2, 3}, random_context)); - - // Eight nodes with the lowest minimum ping time should be protected - // from eviction. - BOOST_CHECK(!IsEvicted( - number_of_nodes, [](NodeEvictionCandidate& candidate) { - candidate.m_min_ping_time = candidate.id; - }, - {0, 1, 2, 3, 4, 5, 6, 7}, random_context)); - - // Four nodes that most recently sent us novel transactions accepted - // into our mempool should be protected from eviction. - BOOST_CHECK(!IsEvicted( - number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { - candidate.nLastTXTime = number_of_nodes - candidate.id; - }, - {0, 1, 2, 3}, random_context)); - - // Up to eight non-tx-relay peers that most recently sent us novel - // blocks should be protected from eviction. - BOOST_CHECK(!IsEvicted( - number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { - candidate.nLastBlockTime = number_of_nodes - candidate.id; - if (candidate.id <= 7) { - candidate.fRelayTxes = false; - candidate.fRelevantServices = true; - } - }, - {0, 1, 2, 3, 4, 5, 6, 7}, random_context)); - - // Four peers that most recently sent us novel blocks should be - // protected from eviction. - BOOST_CHECK(!IsEvicted( - number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { - candidate.nLastBlockTime = number_of_nodes - candidate.id; - }, - {0, 1, 2, 3}, random_context)); - - // Combination of the previous two tests. - BOOST_CHECK(!IsEvicted( - number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { - candidate.nLastBlockTime = number_of_nodes - candidate.id; - if (candidate.id <= 7) { - candidate.fRelayTxes = false; - candidate.fRelevantServices = true; - } - }, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, random_context)); - - // Combination of all tests above. - BOOST_CHECK(!IsEvicted( - number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { - candidate.nKeyedNetGroup = number_of_nodes - candidate.id; // 4 protected - candidate.m_min_ping_time = candidate.id; // 8 protected - candidate.nLastTXTime = number_of_nodes - candidate.id; // 4 protected - candidate.nLastBlockTime = number_of_nodes - candidate.id; // 4 protected - }, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, random_context)); - - // An eviction is expected given >= 29 random eviction candidates. The eviction logic protects at most - // four peers by net group, eight by lowest ping time, four by last time of novel tx, up to eight non-tx-relay - // peers by last novel block time, and four more peers by last novel block time. - if (number_of_nodes >= 29) { - BOOST_CHECK(SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context))); - } - - // No eviction is expected given <= 20 random eviction candidates. The eviction logic protects at least - // four peers by net group, eight by lowest ping time, four by last time of novel tx and four peers by last - // novel block time. - if (number_of_nodes <= 20) { - BOOST_CHECK(!SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context))); - } - - // Cases left to test: - // * "Protect the half of the remaining nodes which have been connected the longest. [...]" - // * "Pick out up to 1/4 peers that are localhost, sorted by longest uptime. [...]" - // * "If any remaining peers are preferred for eviction consider only them. [...]" - // * "Identify the network group with the most connections and youngest member. [...]" - } - } -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 66ad7bb5ea..33b56624a8 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <net_permissions.h> +#include <netaddress.h> #include <netbase.h> #include <protocol.h> #include <serialize.h> @@ -83,31 +84,31 @@ BOOST_AUTO_TEST_CASE(netbase_properties) } -bool static TestSplitHost(std::string test, std::string host, int port) +bool static TestSplitHost(const std::string& test, const std::string& host, uint16_t port) { std::string hostOut; - int portOut = -1; + uint16_t portOut{0}; SplitHostPort(test, portOut, hostOut); return hostOut == host && port == portOut; } BOOST_AUTO_TEST_CASE(netbase_splithost) { - BOOST_CHECK(TestSplitHost("www.bitcoincore.org", "www.bitcoincore.org", -1)); - BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]", "www.bitcoincore.org", -1)); + BOOST_CHECK(TestSplitHost("www.bitcoincore.org", "www.bitcoincore.org", 0)); + BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]", "www.bitcoincore.org", 0)); BOOST_CHECK(TestSplitHost("www.bitcoincore.org:80", "www.bitcoincore.org", 80)); BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]:80", "www.bitcoincore.org", 80)); - BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1)); + BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", 0)); BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333)); - BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1)); + BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", 0)); BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333)); - BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1)); + BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", 0)); BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333)); BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333)); - BOOST_CHECK(TestSplitHost("::8333", "::8333", -1)); + BOOST_CHECK(TestSplitHost("::8333", "::8333", 0)); BOOST_CHECK(TestSplitHost(":8333", "", 8333)); BOOST_CHECK(TestSplitHost("[]:8333", "", 8333)); - BOOST_CHECK(TestSplitHost("", "", -1)); + BOOST_CHECK(TestSplitHost("", "", 0)); } bool static TestParse(std::string src, std::string canon) diff --git a/src/test/ref_tests.cpp b/src/test/ref_tests.cpp deleted file mode 100644 index 0ec0799fbc..0000000000 --- a/src/test/ref_tests.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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 946f993536..7c50c72041 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -10,9 +10,10 @@ #include <interfaces/chain.h> #include <node/context.h> #include <test/util/setup_common.h> -#include <util/ref.h> #include <util/time.h> +#include <any> + #include <boost/algorithm/string.hpp> #include <boost/test/unit_test.hpp> @@ -32,11 +33,10 @@ UniValue RPCTestingSetup::CallRPC(std::string args) boost::split(vArgs, args, boost::is_any_of(" \t")); std::string strMethod = vArgs[0]; vArgs.erase(vArgs.begin()); - util::Ref context{m_node}; + std::any context{&m_node}; JSONRPCRequest request(context); request.strMethod = strMethod; request.params = RPCConvertValues(strMethod, vArgs); - request.fHelp = false; if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); try { UniValue result = tableRPC.execute(request); @@ -174,6 +174,16 @@ BOOST_AUTO_TEST_CASE(rpc_format_monetary_values) BOOST_CHECK_EQUAL(ValueFromAmount(COIN/1000000).write(), "0.00000100"); BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10000000).write(), "0.00000010"); BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000000).write(), "0.00000001"); + + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max()).write(), "92233720368.54775807"); + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max() - 1).write(), "92233720368.54775806"); + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max() - 2).write(), "92233720368.54775805"); + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max() - 3).write(), "92233720368.54775804"); + // ... + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min() + 3).write(), "-92233720368.54775805"); + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min() + 2).write(), "-92233720368.54775806"); + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min() + 1).write(), "-92233720368.54775807"); + BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min()).write(), "-92233720368.54775808"); } static UniValue ValueFromString(const std::string &str) diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index 3e4b963fe3..496292875d 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -13,7 +13,6 @@ BOOST_FIXTURE_TEST_SUITE(sanity_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(basic_sanity) { - BOOST_CHECK_MESSAGE(glibc_sanity_test() == true, "libc sanity test"); BOOST_CHECK_MESSAGE(glibcxx_sanity_test() == true, "stdlib sanity test"); BOOST_CHECK_MESSAGE(ECC_InitSanityCheck() == true, "secp256k1 sanity test"); BOOST_CHECK_MESSAGE(ChronoSanityCheck() == true, "chrono epoch test"); diff --git a/src/test/sock_tests.cpp b/src/test/sock_tests.cpp index ed9780dfb5..400de875b7 100644 --- a/src/test/sock_tests.cpp +++ b/src/test/sock_tests.cpp @@ -4,11 +4,13 @@ #include <compat.h> #include <test/util/setup_common.h> +#include <threadinterrupt.h> #include <util/sock.h> #include <util/system.h> #include <boost/test/unit_test.hpp> +#include <cassert> #include <thread> using namespace std::chrono_literals; @@ -144,6 +146,35 @@ BOOST_AUTO_TEST_CASE(wait) waiter.join(); } +BOOST_AUTO_TEST_CASE(recv_until_terminator_limit) +{ + constexpr auto timeout = 1min; // High enough so that it is never hit. + CThreadInterrupt interrupt; + int s[2]; + CreateSocketPair(s); + + Sock sock_send(s[0]); + Sock sock_recv(s[1]); + + std::thread receiver([&sock_recv, &timeout, &interrupt]() { + constexpr size_t max_data{10}; + bool threw_as_expected{false}; + // BOOST_CHECK_EXCEPTION() writes to some variables shared with the main thread which + // creates a data race. So mimic it manually. + try { + sock_recv.RecvUntilTerminator('\n', timeout, interrupt, max_data); + } catch (const std::runtime_error& e) { + threw_as_expected = HasReason("too many bytes without a terminator")(e); + } + assert(threw_as_expected); + }); + + BOOST_REQUIRE_NO_THROW(sock_send.SendComplete("1234567", timeout, interrupt)); + BOOST_REQUIRE_NO_THROW(sock_send.SendComplete("89a\n", timeout, interrupt)); + + receiver.join(); +} + #endif /* WIN32 */ BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util/logging.cpp b/src/test/util/logging.cpp index c1dd47f06c..66f4efc139 100644 --- a/src/test/util/logging.cpp +++ b/src/test/util/logging.cpp @@ -7,7 +7,6 @@ #include <logging.h> #include <noui.h> #include <tinyformat.h> -#include <util/memory.h> #include <stdexcept> diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp index 0c6487fbfa..3fc3329da2 100644 --- a/src/test/util/mining.cpp +++ b/src/test/util/mining.cpp @@ -41,7 +41,7 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) { auto block = std::make_shared<CBlock>( - BlockAssembler{*Assert(node.mempool), Params()} + BlockAssembler{::ChainstateActive(), *Assert(node.mempool), Params()} .CreateNewBlock(coinbase_scriptPubKey) ->block); diff --git a/src/test/util/net.h b/src/test/util/net.h index e25036be26..2b7988413f 100644 --- a/src/test/util/net.h +++ b/src/test/util/net.h @@ -5,7 +5,13 @@ #ifndef BITCOIN_TEST_UTIL_NET_H #define BITCOIN_TEST_UTIL_NET_H +#include <compat.h> #include <net.h> +#include <util/sock.h> + +#include <cassert> +#include <cstring> +#include <string> struct ConnmanTestMsg : public CConnman { using CConnman::CConnman; @@ -61,4 +67,67 @@ constexpr ConnectionType ALL_CONNECTION_TYPES[]{ ConnectionType::ADDR_FETCH, }; +/** + * A mocked Sock alternative that returns a statically contained data upon read and succeeds + * and ignores all writes. The data to be returned is given to the constructor and when it is + * exhausted an EOF is returned by further reads. + */ +class StaticContentsSock : public Sock +{ +public: + explicit StaticContentsSock(const std::string& contents) : m_contents{contents}, m_consumed{0} + { + // Just a dummy number that is not INVALID_SOCKET. + static_assert(INVALID_SOCKET != 1000); + m_socket = 1000; + } + + ~StaticContentsSock() override { Reset(); } + + StaticContentsSock& operator=(Sock&& other) override + { + assert(false && "Move of Sock into MockSock not allowed."); + return *this; + } + + void Reset() override + { + m_socket = INVALID_SOCKET; + } + + ssize_t Send(const void*, size_t len, int) const override { return len; } + + ssize_t Recv(void* buf, size_t len, int flags) const override + { + const size_t consume_bytes{std::min(len, m_contents.size() - m_consumed)}; + std::memcpy(buf, m_contents.data() + m_consumed, consume_bytes); + if ((flags & MSG_PEEK) == 0) { + m_consumed += consume_bytes; + } + return consume_bytes; + } + + int Connect(const sockaddr*, socklen_t) const override { return 0; } + + int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override + { + std::memset(opt_val, 0x0, *opt_len); + return 0; + } + + bool Wait(std::chrono::milliseconds timeout, + Event requested, + Event* occurred = nullptr) const override + { + if (occurred != nullptr) { + *occurred = requested; + } + return true; + } + +private: + const std::string m_contents; + mutable size_t m_consumed; +}; + #endif // BITCOIN_TEST_UTIL_NET_H diff --git a/src/test/util/script.cpp b/src/test/util/script.cpp new file mode 100644 index 0000000000..a5852daa60 --- /dev/null +++ b/src/test/util/script.cpp @@ -0,0 +1,13 @@ +// Copyright (c) 2021 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 <script/interpreter.h> +#include <test/util/script.h> + +bool IsValidFlagCombination(unsigned flags) +{ + if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false; + if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false; + return true; +} diff --git a/src/test/util/script.h b/src/test/util/script.h index abd14c2067..428b3e10b3 100644 --- a/src/test/util/script.h +++ b/src/test/util/script.h @@ -18,4 +18,7 @@ static const CScript P2WSH_OP_TRUE{ return hash; }())}; +/** Flags that are not forbidden by an assert in script validation */ +bool IsValidFlagCombination(unsigned flags); + #endif // BITCOIN_TEST_UTIL_SCRIPT_H diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 1ffe435531..f7800aefca 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -4,6 +4,7 @@ #include <test/util/setup_common.h> +#include <addrman.h> #include <banman.h> #include <chainparams.h> #include <consensus/consensus.h> @@ -25,7 +26,6 @@ #include <script/sigcache.h> #include <streams.h> #include <txdb.h> -#include <util/memory.h> #include <util/strencodings.h> #include <util/string.h> #include <util/time.h> @@ -131,7 +131,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve { // We have to run a scheduler thread to prevent ActivateBestChain // from blocking due to queue overrun. - m_node.scheduler = MakeUnique<CScheduler>(); + m_node.scheduler = std::make_unique<CScheduler>(); m_node.scheduler->m_service_thread = std::thread([&] { TraceThread("scheduler", [&] { m_node.scheduler->serviceQueue(); }); }); GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler); @@ -156,6 +156,7 @@ ChainTestingSetup::~ChainTestingSetup() GetMainSignals().UnregisterBackgroundSignalScheduler(); m_node.connman.reset(); m_node.banman.reset(); + m_node.addrman.reset(); m_node.args = nullptr; UnloadBlockIndex(m_node.mempool.get(), *m_node.chainman); m_node.mempool.reset(); @@ -179,7 +180,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const assert(!::ChainstateActive().CanFlushToDisk()); ::ChainstateActive().InitCoinsCache(1 << 23); assert(::ChainstateActive().CanFlushToDisk()); - if (!LoadGenesisBlock(chainparams)) { + if (!::ChainstateActive().LoadGenesisBlock(chainparams)) { throw std::runtime_error("LoadGenesisBlock failed."); } @@ -188,11 +189,12 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString())); } - 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.peerman = PeerManager::make(chainparams, *m_node.connman, m_node.banman.get(), - *m_node.scheduler, *m_node.chainman, *m_node.mempool, - false); + m_node.addrman = std::make_unique<CAddrMan>(); + m_node.banman = std::make_unique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); + m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests. + m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman, + m_node.banman.get(), *m_node.scheduler, *m_node.chainman, + *m_node.mempool, false); { CConnman::Options options; options.m_msgproc = m_node.peerman.get(); @@ -245,13 +247,13 @@ CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransa { const CChainParams& chainparams = Params(); CTxMemPool empty_pool; - CBlock block = BlockAssembler(empty_pool, chainparams).CreateNewBlock(scriptPubKey)->block; + CBlock block = BlockAssembler(::ChainstateActive(), empty_pool, chainparams).CreateNewBlock(scriptPubKey)->block; Assert(block.vtx.size() == 1); for (const CMutableTransaction& tx : txns) { block.vtx.push_back(MakeTransactionRef(tx)); } - RegenerateCommitments(block); + RegenerateCommitments(block, WITH_LOCK(::cs_main, return std::ref(g_chainman.m_blockman))); while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index 33f24e7c44..7323f1f0b6 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -15,6 +15,7 @@ #include <txmempool.h> #include <util/check.h> #include <util/string.h> +#include <util/vector.h> #include <type_traits> #include <vector> @@ -152,6 +153,23 @@ struct TestChain100DeterministicSetup : public TestChain100Setup { TestChain100DeterministicSetup() : TestChain100Setup(true) { } }; +/** + * Make a test setup that has disk access to the debug.log file disabled. Can + * be used in "hot loops", for example fuzzing or benchmarking. + */ +template <class T = const BasicTestingSetup> +std::unique_ptr<T> MakeNoLogFileContext(const std::string& chain_name = CBaseChainParams::REGTEST, const std::vector<const char*>& extra_args = {}) +{ + const std::vector<const char*> arguments = Cat( + { + "-nodebuglogfile", + "-nodebug", + }, + extra_args); + + return std::make_unique<T>(chain_name, arguments); +} + class CTxMemPoolEntry; struct TestMemPoolEntryHelper diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 845854bd4b..5ac09b05db 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -7,7 +7,6 @@ #include <clientversion.h> #include <hash.h> // For Hash() #include <key.h> // For CKey -#include <optional.h> #include <sync.h> #include <test/util/logging.h> #include <test/util/setup_common.h> @@ -23,6 +22,7 @@ #include <util/vector.h> #include <array> +#include <optional> #include <stdint.h> #include <string.h> #include <thread> @@ -38,6 +38,7 @@ #include <boost/test/unit_test.hpp> using namespace std::literals; +static const std::string STRING_WITH_EMBEDDED_NULL_CHAR{"1"s "\0" "1"s}; /* defined in logging.cpp */ namespace BCLog { @@ -71,11 +72,14 @@ BOOST_AUTO_TEST_CASE(util_datadir) BOOST_AUTO_TEST_CASE(util_check) { // Check that Assert can forward - const std::unique_ptr<int> p_two = Assert(MakeUnique<int>(2)); + const std::unique_ptr<int> p_two = Assert(std::make_unique<int>(2)); // Check that Assert works on lvalues and rvalues const int two = *Assert(p_two); Assert(two == 2); Assert(true); + // Check that Assume can be used as unary expression + const bool result{Assume(two == 2)}; + Assert(result); } BOOST_AUTO_TEST_CASE(util_criticalsection) @@ -227,9 +231,9 @@ public: bool default_int = false; bool default_bool = false; const char* string_value = nullptr; - Optional<int64_t> int_value; - Optional<bool> bool_value; - Optional<std::vector<std::string>> list_value; + std::optional<int64_t> int_value; + std::optional<bool> bool_value; + std::optional<std::vector<std::string>> list_value; const char* error = nullptr; explicit Expect(util::SettingsValue s) : setting(std::move(s)) {} @@ -1180,6 +1184,16 @@ BOOST_AUTO_TEST_CASE(util_FormatMoney) BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001"); BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001"); BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001"); + + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max()), "92233720368.54775807"); + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 1), "92233720368.54775806"); + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 2), "92233720368.54775805"); + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::max() - 3), "92233720368.54775804"); + // ... + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 3), "-92233720368.54775805"); + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 2), "-92233720368.54775806"); + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min() + 1), "-92233720368.54775807"); + BOOST_CHECK_EQUAL(FormatMoney(std::numeric_limits<CAmount>::min()), "-92233720368.54775808"); } BOOST_AUTO_TEST_CASE(util_ParseMoney) @@ -1262,7 +1276,7 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney) // Parsing strings with embedded NUL characters should fail BOOST_CHECK(!ParseMoney("\0-1"s, ret)); - BOOST_CHECK(!ParseMoney("\0" "1"s, ret)); + BOOST_CHECK(!ParseMoney(STRING_WITH_EMBEDDED_NULL_CHAR, ret)); BOOST_CHECK(!ParseMoney("1\0"s, ret)); } @@ -1439,10 +1453,7 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32) BOOST_CHECK(!ParseInt32("1a", &n)); BOOST_CHECK(!ParseInt32("aap", &n)); BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex - BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex - const char test_bytes[] = {'1', 0, '1'}; - std::string teststr(test_bytes, sizeof(test_bytes)); - BOOST_CHECK(!ParseInt32(teststr, &n)); // no embedded NULs + BOOST_CHECK(!ParseInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); // Overflow and underflow BOOST_CHECK(!ParseInt32("-2147483649", nullptr)); BOOST_CHECK(!ParseInt32("2147483648", nullptr)); @@ -1470,9 +1481,7 @@ BOOST_AUTO_TEST_CASE(test_ParseInt64) BOOST_CHECK(!ParseInt64("1a", &n)); BOOST_CHECK(!ParseInt64("aap", &n)); BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex - const char test_bytes[] = {'1', 0, '1'}; - std::string teststr(test_bytes, sizeof(test_bytes)); - BOOST_CHECK(!ParseInt64(teststr, &n)); // no embedded NULs + BOOST_CHECK(!ParseInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); // Overflow and underflow BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr)); BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr)); @@ -1480,6 +1489,76 @@ BOOST_AUTO_TEST_CASE(test_ParseInt64) BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr)); } +BOOST_AUTO_TEST_CASE(test_ParseUInt8) +{ + uint8_t n; + // Valid values + BOOST_CHECK(ParseUInt8("255", nullptr)); + BOOST_CHECK(ParseUInt8("0", &n) && n == 0); + BOOST_CHECK(ParseUInt8("255", &n) && n == 255); + BOOST_CHECK(ParseUInt8("0255", &n) && n == 255); // no octal + BOOST_CHECK(ParseUInt8("255", &n) && n == static_cast<uint8_t>(255)); + BOOST_CHECK(ParseUInt8("+255", &n) && n == 255); + BOOST_CHECK(ParseUInt8("00000000000000000012", &n) && n == 12); + BOOST_CHECK(ParseUInt8("00000000000000000000", &n) && n == 0); + // Invalid values + BOOST_CHECK(!ParseUInt8("-00000000000000000000", &n)); + BOOST_CHECK(!ParseUInt8("", &n)); + BOOST_CHECK(!ParseUInt8(" 1", &n)); // no padding inside + BOOST_CHECK(!ParseUInt8(" -1", &n)); + BOOST_CHECK(!ParseUInt8("++1", &n)); + BOOST_CHECK(!ParseUInt8("+-1", &n)); + BOOST_CHECK(!ParseUInt8("-+1", &n)); + BOOST_CHECK(!ParseUInt8("--1", &n)); + BOOST_CHECK(!ParseUInt8("-1", &n)); + BOOST_CHECK(!ParseUInt8("1 ", &n)); + BOOST_CHECK(!ParseUInt8("1a", &n)); + BOOST_CHECK(!ParseUInt8("aap", &n)); + BOOST_CHECK(!ParseUInt8("0x1", &n)); // no hex + BOOST_CHECK(!ParseUInt8(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); + // Overflow and underflow + BOOST_CHECK(!ParseUInt8("-255", &n)); + BOOST_CHECK(!ParseUInt8("256", &n)); + BOOST_CHECK(!ParseUInt8("-123", &n)); + BOOST_CHECK(!ParseUInt8("-123", nullptr)); + BOOST_CHECK(!ParseUInt8("256", nullptr)); +} + +BOOST_AUTO_TEST_CASE(test_ParseUInt16) +{ + uint16_t n; + // Valid values + BOOST_CHECK(ParseUInt16("1234", nullptr)); + BOOST_CHECK(ParseUInt16("0", &n) && n == 0); + BOOST_CHECK(ParseUInt16("1234", &n) && n == 1234); + BOOST_CHECK(ParseUInt16("01234", &n) && n == 1234); // no octal + BOOST_CHECK(ParseUInt16("65535", &n) && n == static_cast<uint16_t>(65535)); + BOOST_CHECK(ParseUInt16("+65535", &n) && n == 65535); + BOOST_CHECK(ParseUInt16("00000000000000000012", &n) && n == 12); + BOOST_CHECK(ParseUInt16("00000000000000000000", &n) && n == 0); + // Invalid values + BOOST_CHECK(!ParseUInt16("-00000000000000000000", &n)); + BOOST_CHECK(!ParseUInt16("", &n)); + BOOST_CHECK(!ParseUInt16(" 1", &n)); // no padding inside + BOOST_CHECK(!ParseUInt16(" -1", &n)); + BOOST_CHECK(!ParseUInt16("++1", &n)); + BOOST_CHECK(!ParseUInt16("+-1", &n)); + BOOST_CHECK(!ParseUInt16("-+1", &n)); + BOOST_CHECK(!ParseUInt16("--1", &n)); + BOOST_CHECK(!ParseUInt16("-1", &n)); + BOOST_CHECK(!ParseUInt16("1 ", &n)); + BOOST_CHECK(!ParseUInt16("1a", &n)); + BOOST_CHECK(!ParseUInt16("aap", &n)); + BOOST_CHECK(!ParseUInt16("0x1", &n)); // no hex + BOOST_CHECK(!ParseUInt16(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); + // Overflow and underflow + BOOST_CHECK(!ParseUInt16("-65535", &n)); + BOOST_CHECK(!ParseUInt16("65536", &n)); + BOOST_CHECK(!ParseUInt16("-123", &n)); + BOOST_CHECK(!ParseUInt16("-123", nullptr)); + BOOST_CHECK(!ParseUInt16("65536", nullptr)); +} + BOOST_AUTO_TEST_CASE(test_ParseUInt32) { uint32_t n; @@ -1508,10 +1587,7 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt32) BOOST_CHECK(!ParseUInt32("1a", &n)); BOOST_CHECK(!ParseUInt32("aap", &n)); BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex - BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex - const char test_bytes[] = {'1', 0, '1'}; - std::string teststr(test_bytes, sizeof(test_bytes)); - BOOST_CHECK(!ParseUInt32(teststr, &n)); // no embedded NULs + BOOST_CHECK(!ParseUInt32(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); // Overflow and underflow BOOST_CHECK(!ParseUInt32("-2147483648", &n)); BOOST_CHECK(!ParseUInt32("4294967296", &n)); @@ -1540,9 +1616,7 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt64) BOOST_CHECK(!ParseUInt64("1a", &n)); BOOST_CHECK(!ParseUInt64("aap", &n)); BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex - const char test_bytes[] = {'1', 0, '1'}; - std::string teststr(test_bytes, sizeof(test_bytes)); - BOOST_CHECK(!ParseUInt64(teststr, &n)); // no embedded NULs + BOOST_CHECK(!ParseUInt64(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); // Overflow and underflow BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr)); BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr)); @@ -1572,9 +1646,7 @@ BOOST_AUTO_TEST_CASE(test_ParseDouble) BOOST_CHECK(!ParseDouble("1a", &n)); BOOST_CHECK(!ParseDouble("aap", &n)); BOOST_CHECK(!ParseDouble("0x1", &n)); // no hex - const char test_bytes[] = {'1', 0, '1'}; - std::string teststr(test_bytes, sizeof(test_bytes)); - BOOST_CHECK(!ParseDouble(teststr, &n)); // no embedded NULs + BOOST_CHECK(!ParseDouble(STRING_WITH_EMBEDDED_NULL_CHAR, &n)); // Overflow and underflow BOOST_CHECK(!ParseDouble("-1e10000", nullptr)); BOOST_CHECK(!ParseDouble("1e10000", nullptr)); diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 0c87c4d360..552be0a2da 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -63,7 +63,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash) static int i = 0; static uint64_t time = Params().GenesisBlock().nTime; - auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(CScript{} << i++ << OP_TRUE); + auto ptemplate = BlockAssembler(m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(CScript{} << i++ << OP_TRUE); auto pblock = std::make_shared<CBlock>(ptemplate->block); pblock->hashPrevBlock = prev_hash; pblock->nTime = ++time; @@ -325,7 +325,7 @@ BOOST_AUTO_TEST_CASE(witness_commitment_index) { CScript pubKey; pubKey << 1 << OP_TRUE; - auto ptemplate = BlockAssembler(*m_node.mempool, Params()).CreateNewBlock(pubKey); + auto ptemplate = BlockAssembler(m_node.chainman->ActiveChainstate(), *m_node.mempool, Params()).CreateNewBlock(pubKey); CBlock pblock = ptemplate->block; CTxOut witness; diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 50444f7bbe..8841a540f2 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -14,6 +14,18 @@ /* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */ static int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; } +static const std::string StateName(ThresholdState state) +{ + switch (state) { + case ThresholdState::DEFINED: return "DEFINED"; + case ThresholdState::STARTED: return "STARTED"; + case ThresholdState::LOCKED_IN: return "LOCKED_IN"; + case ThresholdState::ACTIVE: return "ACTIVE"; + case ThresholdState::FAILED: return "FAILED"; + } // no default case, so the compiler can warn about missing cases + return ""; +} + static const Consensus::Params paramsDummy = Consensus::Params(); class TestConditionChecker : public AbstractThresholdConditionChecker @@ -38,6 +50,13 @@ public: int64_t BeginTime(const Consensus::Params& params) const override { return Consensus::BIP9Deployment::ALWAYS_ACTIVE; } }; +class TestNeverActiveConditionChecker : public TestConditionChecker +{ +public: + int64_t BeginTime(const Consensus::Params& params) const override { return 0; } + int64_t EndTime(const Consensus::Params& params) const override { return 1230768000; } +}; + #define CHECKERS 6 class VersionBitsTester @@ -51,6 +70,8 @@ class VersionBitsTester TestConditionChecker checker[CHECKERS]; // Another 6 that assume always active activation TestAlwaysActiveConditionChecker checker_always[CHECKERS]; + // Another 6 that assume never active activation + TestNeverActiveConditionChecker checker_never[CHECKERS]; // Test counter (to identify failures) int num; @@ -65,6 +86,7 @@ public: for (unsigned int i = 0; i < CHECKERS; i++) { checker[i] = TestConditionChecker(); checker_always[i] = TestAlwaysActiveConditionChecker(); + checker_never[i] = TestNeverActiveConditionChecker(); } vpblock.clear(); return *this; @@ -92,66 +114,40 @@ public: if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num)); BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == 0, strprintf("Test %i for StateSinceHeight (always active)", num)); - } - } - num++; - return *this; - } - VersionBitsTester& TestDefined() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::DEFINED, strprintf("Test %i for DEFINED", num)); - BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); + // never active may go from DEFINED -> FAILED at the first period + const auto never_height = checker_never[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()); + BOOST_CHECK_MESSAGE(never_height == 0 || never_height == checker_never[i].Period(paramsDummy), strprintf("Test %i for StateSinceHeight (never active)", num)); } } num++; return *this; } - VersionBitsTester& TestStarted() { + VersionBitsTester& TestState(ThresholdState exp) { for (int i = 0; i < CHECKERS; i++) { if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::STARTED, strprintf("Test %i for STARTED", num)); - BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); + const CBlockIndex* pindex = vpblock.empty() ? nullptr : vpblock.back(); + ThresholdState got = checker[i].GetStateFor(pindex); + ThresholdState got_always = checker_always[i].GetStateFor(pindex); + ThresholdState got_never = checker_never[i].GetStateFor(pindex); + // nHeight of the next block. If vpblock is empty, the next (ie first) + // block should be the genesis block with nHeight == 0. + int height = pindex == nullptr ? 0 : pindex->nHeight + 1; + BOOST_CHECK_MESSAGE(got == exp, strprintf("Test %i for %s height %d (got %s)", num, StateName(exp), height, StateName(got))); + BOOST_CHECK_MESSAGE(got_always == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE height %d (got %s; always active case)", num, height, StateName(got_always))); + BOOST_CHECK_MESSAGE(got_never == ThresholdState::DEFINED|| got_never == ThresholdState::FAILED, strprintf("Test %i for DEFINED/FAILED height %d (got %s; never active case)", num, height, StateName(got_never))); } } num++; return *this; } - VersionBitsTester& TestLockedIn() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::LOCKED_IN, strprintf("Test %i for LOCKED_IN", num)); - BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); - } - } - num++; - return *this; - } - - VersionBitsTester& TestActive() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE", num)); - BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); - } - } - num++; - return *this; - } - - VersionBitsTester& TestFailed() { - for (int i = 0; i < CHECKERS; i++) { - if (InsecureRandBits(i) == 0) { - BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::FAILED, strprintf("Test %i for FAILED", num)); - BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); - } - } - num++; - return *this; - } + VersionBitsTester& TestDefined() { return TestState(ThresholdState::DEFINED); } + VersionBitsTester& TestStarted() { return TestState(ThresholdState::STARTED); } + VersionBitsTester& TestLockedIn() { return TestState(ThresholdState::LOCKED_IN); } + VersionBitsTester& TestActive() { return TestState(ThresholdState::ACTIVE); } + VersionBitsTester& TestFailed() { return TestState(ThresholdState::FAILED); } CBlockIndex * Tip() { return vpblock.size() ? vpblock.back() : nullptr; } }; |