From 8a50e9a3163079a5d251ae46d75f5abbf3dfc6e2 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 11 Jun 2019 20:10:25 -0400 Subject: [PATCH 01/13] [tests] Remove unnecessary cs_mains in denialofservice_tests 9fdf05d70cac4a62d1aeeb4299e2c3a9a866f8af resolved some lock inversion warnings in denialofservice_tests, but left in a number of cs_main locks that are unnecessary (introducing lock inversion warnings in future changes). --- src/test/denialofservice_tests.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 632151793ec0..21c8c34323bb 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -98,11 +98,11 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) // Test starts here { - LOCK2(cs_main, dummyNode1.cs_sendProcessing); + LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders } { - LOCK2(cs_main, dummyNode1.cs_vSend); + LOCK(dummyNode1.cs_vSend); BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); dummyNode1.vSendMsg.clear(); } @@ -111,17 +111,17 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) // Wait 21 minutes SetMockTime(nStartTime+21*60); { - LOCK2(cs_main, dummyNode1.cs_sendProcessing); + LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders } { - LOCK2(cs_main, dummyNode1.cs_vSend); + LOCK(dummyNode1.cs_vSend); BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); } // Wait 3 more minutes SetMockTime(nStartTime+24*60); { - LOCK2(cs_main, dummyNode1.cs_sendProcessing); + LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect } BOOST_CHECK(dummyNode1.fDisconnect == true); @@ -235,7 +235,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) Misbehaving(dummyNode1.GetId(), 100); // Should get banned } { - LOCK2(cs_main, dummyNode1.cs_sendProcessing); + LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } BOOST_CHECK(banman->IsBanned(addr1)); @@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) Misbehaving(dummyNode2.GetId(), 50); } { - LOCK2(cs_main, dummyNode2.cs_sendProcessing); + LOCK(dummyNode2.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode2)); } BOOST_CHECK(!banman->IsBanned(addr2)); // 2 not banned yet... @@ -262,7 +262,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) Misbehaving(dummyNode2.GetId(), 50); } { - LOCK2(cs_main, dummyNode2.cs_sendProcessing); + LOCK(dummyNode2.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode2)); } BOOST_CHECK(banman->IsBanned(addr2)); @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) Misbehaving(dummyNode1.GetId(), 100); } { - LOCK2(cs_main, dummyNode1.cs_sendProcessing); + LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } BOOST_CHECK(!banman->IsBanned(addr1)); @@ -300,7 +300,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) Misbehaving(dummyNode1.GetId(), 10); } { - LOCK2(cs_main, dummyNode1.cs_sendProcessing); + LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } BOOST_CHECK(!banman->IsBanned(addr1)); @@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) Misbehaving(dummyNode1.GetId(), 1); } { - LOCK2(cs_main, dummyNode1.cs_sendProcessing); + LOCK(dummyNode1.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); } BOOST_CHECK(banman->IsBanned(addr1)); @@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) Misbehaving(dummyNode.GetId(), 100); } { - LOCK2(cs_main, dummyNode.cs_sendProcessing); + LOCK(dummyNode.cs_sendProcessing); BOOST_CHECK(peerLogic->SendMessages(&dummyNode)); } BOOST_CHECK(banman->IsBanned(addr)); From 8cd7501997228031e0021aa9f19a7fb1227f5b72 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Thu, 14 Nov 2019 14:47:55 -0500 Subject: [PATCH 02/13] [net processing] Deduplicate post-block-processing code Co-authored-by: Carl Dong --- src/net_processing.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index f42a26ca3ea4..9e9377fbf5ed 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1880,6 +1880,20 @@ void static ProcessOrphanTx(CConnman* connman, std::set& orphan_work_se } } +/** + * A block has been processed. If this is the first time we've seen the block, + * update the node's nLastBlockTime. Otherwise erase it from mapBlockSource. + */ +void static BlockProcessed(CNode* pfrom, std::shared_ptr pblock, bool new_block) +{ + if (new_block) { + pfrom->nLastBlockTime = GetTime(); + } else { + LOCK(cs_main); + ::mapBlockSource.erase(pblock->GetHash()); + } +} + bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, BanMan* banman, const std::atomic& interruptMsgProc) { LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId()); @@ -2819,12 +2833,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // compact blocks with less work than our tip, it is safe to treat // reconstructed compact blocks as having been requested. ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); - if (fNewBlock) { - pfrom->nLastBlockTime = GetTime(); - } else { - LOCK(cs_main); - mapBlockSource.erase(pblock->GetHash()); - } + BlockProcessed(pfrom, pblock, fNewBlock); + LOCK(cs_main); // hold cs_main for CBlockIndex::IsValid() if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS)) { // Clear download state for this block, which is in @@ -2909,12 +2919,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // protections in the compact block handler -- see related comment // in compact block optimistic reconstruction handling. ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); - if (fNewBlock) { - pfrom->nLastBlockTime = GetTime(); - } else { - LOCK(cs_main); - mapBlockSource.erase(pblock->GetHash()); - } + BlockProcessed(pfrom, pblock, fNewBlock); } return true; } @@ -2972,12 +2977,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } bool fNewBlock = false; ProcessNewBlock(chainparams, pblock, forceProcessing, &fNewBlock); - if (fNewBlock) { - pfrom->nLastBlockTime = GetTime(); - } else { - LOCK(cs_main); - mapBlockSource.erase(pblock->GetHash()); - } + BlockProcessed(pfrom, pblock, fNewBlock); return true; } From 57782d5f70c072cfc70568a3db58a04831454576 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 15 Nov 2019 13:26:28 -0500 Subject: [PATCH 03/13] [validation] Add BlockValidationState inout param to ProcessNewBlock This is a pure refactor commit. This commit enables the caller of ProcessNewBlock to access the final BlockValidationState passed around between CheckBlock(), AcceptBlock(), and BlockChecked() inside ProcessNewBlock(). This is useful because in a future commit, we will move the BlockChecked() call out of ProcessNewBlock(), and BlockChecked() still needs to be able to access the BlockValidationState. Co-authored-by: John Newbery Co-authored-by: Carl Dong --- src/net_processing.cpp | 9 ++++++--- src/rpc/mining.cpp | 6 ++++-- src/test/blockfilter_index_tests.cpp | 15 +++++++++------ src/test/miner_tests.cpp | 4 +++- src/test/util.cpp | 4 +++- src/test/util/setup_common.cpp | 3 ++- src/test/validation_block_tests.cpp | 12 ++++++++---- src/validation.cpp | 11 +++++------ src/validation.h | 11 ++++++----- 9 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 9e9377fbf5ed..ffbc850ae12e 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2832,7 +2832,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // we have a chain with at least nMinimumChainWork), and we ignore // compact blocks with less work than our tip, it is safe to treat // reconstructed compact blocks as having been requested. - ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); + BlockValidationState dos_state; + ProcessNewBlock(chainparams, pblock, dos_state, /*fForceProcessing=*/true, &fNewBlock); BlockProcessed(pfrom, pblock, fNewBlock); LOCK(cs_main); // hold cs_main for CBlockIndex::IsValid() @@ -2918,7 +2919,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // disk-space attacks), but this should be safe due to the // protections in the compact block handler -- see related comment // in compact block optimistic reconstruction handling. - ProcessNewBlock(chainparams, pblock, /*fForceProcessing=*/true, &fNewBlock); + BlockValidationState dos_state; + ProcessNewBlock(chainparams, pblock, dos_state, /*fForceProcessing=*/true, &fNewBlock); BlockProcessed(pfrom, pblock, fNewBlock); } return true; @@ -2976,7 +2978,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true)); } bool fNewBlock = false; - ProcessNewBlock(chainparams, pblock, forceProcessing, &fNewBlock); + BlockValidationState dos_state; + ProcessNewBlock(chainparams, pblock, dos_state, forceProcessing, &fNewBlock); BlockProcessed(pfrom, pblock, fNewBlock); return true; } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index ab22155651e1..c4b3a7ea343a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -135,7 +135,8 @@ static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, ui continue; } std::shared_ptr shared_pblock = std::make_shared(*pblock); - if (!ProcessNewBlock(Params(), shared_pblock, true, nullptr)) + BlockValidationState state; + if (!ProcessNewBlock(Params(), shared_pblock, state, true, nullptr)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); @@ -777,7 +778,8 @@ static UniValue submitblock(const JSONRPCRequest& request) bool new_block; submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block); + BlockValidationState dos_state; + bool accepted = ProcessNewBlock(Params(), blockptr, dos_state, /* fForceProcessing */ true, /* fNewBlock */ &new_block); UnregisterValidationInterface(&sc); if (!new_block && accepted) { return "duplicate"; diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index 2b616f4c2ba7..aecd02dd2369 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -164,7 +164,8 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) uint256 chainA_last_header = last_header; for (size_t i = 0; i < 2; i++) { const auto& block = chainA[i]; - BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); + BlockValidationState dos_state; + BOOST_REQUIRE(ProcessNewBlock(Params(), block, dos_state, true, nullptr)); } for (size_t i = 0; i < 2; i++) { const auto& block = chainA[i]; @@ -182,7 +183,8 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) uint256 chainB_last_header = last_header; for (size_t i = 0; i < 3; i++) { const auto& block = chainB[i]; - BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); + BlockValidationState dos_state; + BOOST_REQUIRE(ProcessNewBlock(Params(), block, dos_state, true, nullptr)); } for (size_t i = 0; i < 3; i++) { const auto& block = chainB[i]; @@ -211,10 +213,11 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, TestChain100Setup) } // Reorg back to chain A. - for (size_t i = 2; i < 4; i++) { - const auto& block = chainA[i]; - BOOST_REQUIRE(ProcessNewBlock(Params(), block, true, nullptr)); - } + for (size_t i = 2; i < 4; i++) { + const auto& block = chainA[i]; + BlockValidationState dos_state; + BOOST_REQUIRE(ProcessNewBlock(Params(), block, dos_state, true, nullptr)); + } // Check that chain A and B blocks can be retrieved. chainA_last_header = last_header; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 6ed7350ea237..2bd09321cf98 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include