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,11 @@ bool Processor::addBlockToReconcile(const CBlockIndex *pindex) { bool isAccepted; + if (!pindex) { + // IsWorthPolling expects this to be non-null, so bail early. + return false; + } + { LOCK(cs_main); if (!IsWorthPolling(pindex)) { @@ -314,6 +319,11 @@ } bool Processor::isAccepted(const CBlockIndex *pindex) const { + if (!pindex) { + // CBlockIndexWorkComparator expects this to be non-null, so bail early. + return false; + } + auto r = blockVoteRecords.getReadView(); auto it = r->find(pindex); if (it == r.end()) { @@ -334,6 +344,11 @@ } int Processor::getConfidence(const CBlockIndex *pindex) const { + if (!pindex) { + // CBlockIndexWorkComparator expects this to be non-null, so bail early. + 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;