diff --git a/src/avalanche/processor.cpp b/src/avalanche/processor.cpp --- a/src/avalanche/processor.cpp +++ b/src/avalanche/processor.cpp @@ -287,6 +287,10 @@ bool Processor::addBlockToReconcile(const CBlockIndex *pindex) { bool isAccepted; + if (!pindex) { + return false; + } + { LOCK(cs_main); if (!IsWorthPolling(pindex)) { @@ -314,6 +318,10 @@ } bool Processor::isAccepted(const CBlockIndex *pindex) const { + if (!pindex) { + return false; + } + auto r = blockVoteRecords.getReadView(); auto it = r->find(pindex); if (it == r.end()) { @@ -334,6 +342,10 @@ } int Processor::getConfidence(const CBlockIndex *pindex) const { + if (!pindex) { + return -1; + } + auto r = blockVoteRecords.getReadView(); auto it = r->find(pindex); if (it == r.end()) { diff --git a/src/avalanche/test/processor_tests.cpp b/src/avalanche/test/processor_tests.cpp --- a/src/avalanche/test/processor_tests.cpp +++ b/src/avalanche/test/processor_tests.cpp @@ -455,6 +455,29 @@ BOOST_CHECK(m_processor->isAccepted(pindex)); } +BOOST_AUTO_TEST_CASE(block_null) { + // Check that null case is handled on the public interface + BOOST_CHECK(!m_processor->isAccepted(nullptr)); + BOOST_CHECK_EQUAL(m_processor->getConfidence(nullptr), -1); + + BOOST_CHECK(!m_processor->addBlockToReconcile(nullptr)); + + // Check that adding blocks to vote on doesn't change the outcome. A + // comparator is used under the hood, and this is skipped if there are no + // vote records. + CBlock block = CreateAndProcessBlock({}, CScript()); + const BlockHash blockHash = block.GetHash(); + CBlockIndex *pindex; + { + LOCK(cs_main); + pindex = g_chainman.m_blockman.LookupBlockIndex(blockHash); + } + BOOST_CHECK(m_processor->addBlockToReconcile(pindex)); + + BOOST_CHECK(!m_processor->isAccepted(nullptr)); + BOOST_CHECK_EQUAL(m_processor->getConfidence(nullptr), -1); +} + namespace { Response next(Response &r) { auto copy = r;