Skip to content
Open
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/parse_numbers.cpp \
test/fuzz/parse_script.cpp \
test/fuzz/parse_univalue.cpp \
test/fuzz/partially_downloaded_block.cpp \
test/fuzz/policy_estimator.cpp \
test/fuzz/policy_estimator_io.cpp \
test/fuzz/poolresource.cpp \
Expand Down
28 changes: 14 additions & 14 deletions src/blockencodings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MaxBlockSize() / MIN_TRANSACTION_SIZE)
return READ_STATUS_INVALID;

assert(header.IsNull() && txn_available.empty());
if (!header.IsNull() || !txn_available.empty()) return READ_STATUS_INVALID;

header = cmpctblock.header;
txn_available.resize(cmpctblock.BlockTxCount());

Expand Down Expand Up @@ -169,14 +170,18 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
return READ_STATUS_OK;
}

bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const {
assert(!header.IsNull());
bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const
{
if (header.IsNull()) return false;

assert(index < txn_available.size());
return txn_available[index] != nullptr;
}

ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing) {
assert(!header.IsNull());
ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing)
{
if (header.IsNull()) return READ_STATUS_INVALID;

uint256 hash = header.GetHash();
block = header;
block.vtx.resize(txn_available.size());
Expand All @@ -198,15 +203,10 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
if (vtx_missing.size() != tx_missing_offset)
return READ_STATUS_INVALID;

BlockValidationState state;
if (!CheckBlock(block, state, Params().GetConsensus())) {
// TODO: We really want to just check merkle tree manually here,
// but that is expensive, and CheckBlock caches a block's
// "checked-status" (in the CBlock?). CBlock should be able to
// check its own merkle root and cache that check.
if (state.GetResult() == BlockValidationResult::BLOCK_MUTATED)
return READ_STATUS_FAILED; // Possible Short ID collision
return READ_STATUS_CHECKBLOCK_FAILED;
// Check for possible mutations early now that we have a seemingly good block
IsBlockMutatedFn check_mutated{m_check_block_mutated_mock ? m_check_block_mutated_mock : IsBlockMutated};
if (check_mutated(/*block=*/block)) {
return READ_STATUS_FAILED; // Possible Short ID collision
}

LogPrint(BCLog::CMPCTBLOCK, "Successfully reconstructed block %s with %lu txn prefilled, %lu txn from mempool (incl at least %lu from extra pool) and %lu txn requested\n", hash.ToString(), prefilled_count, mempool_count, extra_count, vtx_missing.size());
Expand Down
12 changes: 10 additions & 2 deletions src/blockencodings.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@

#include <primitives/block.h>

#include <functional>

class CTxMemPool;
class BlockValidationState;
namespace Consensus {
struct Params;
};

// Transaction compression schemes for compact block relay can be introduced by writing
// an actual formatter here.
Expand Down Expand Up @@ -79,8 +84,6 @@ typedef enum ReadStatus_t
READ_STATUS_OK,
READ_STATUS_INVALID, // Invalid object, peer is sending bogus crap
READ_STATUS_FAILED, // Failed to process object
READ_STATUS_CHECKBLOCK_FAILED, // Used only by FillBlock to indicate a
// failure in CheckBlock.
} ReadStatus;

class CBlockHeaderAndShortTxIDs {
Expand Down Expand Up @@ -129,6 +132,11 @@ class PartiallyDownloadedBlock {
const CTxMemPool* pool;
public:
CBlockHeader header;

// Can be overriden for testing
using IsBlockMutatedFn = std::function<bool(const CBlock&)>;
IsBlockMutatedFn m_check_block_mutated_mock{nullptr};

explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {}

// extra_txn is a list of extra transactions to look at, in <hash, reference> form
Expand Down
2 changes: 2 additions & 0 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,9 @@ class CNodeStats
int nVersion;
std::string cleanSubVer;
bool fInbound;
// We requested high bandwidth connection to peer
bool m_bip152_highbandwidth_to;
// Peer requested high bandwidth connection
bool m_bip152_highbandwidth_from;
int m_starting_height;
uint64_t nSendBytes;
Expand Down
Loading
Loading