Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2016-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_BLOCKENCODINGS_H6#define BITCOIN_BLOCKENCODINGS_H8#include <crypto/siphash.h>9#include <primitives/block.h>11#include <functional>13class CTxMemPool;14class BlockValidationState;15namespace Consensus {16struct Params;17};19// Transaction compression schemes for compact block relay can be introduced by writing20// an actual formatter here.21using TransactionCompression = DefaultFormatter;23class DifferenceFormatter24{25uint64_t m_shift = 0;27public:28template<typename Stream, typename I>29void Ser(Stream& s, I v)30{31if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) throw std::ios_base::failure("differential value overflow");32WriteCompactSize(s, v - m_shift);33m_shift = uint64_t(v) + 1;34}35template<typename Stream, typename I>36void Unser(Stream& s, I& v)37{38uint64_t n = ReadCompactSize(s);39m_shift += n;40if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() || m_shift < std::numeric_limits<I>::min() || m_shift > std::numeric_limits<I>::max()) throw std::ios_base::failure("differential value overflow");41v = I(m_shift++);42}43};45class BlockTransactionsRequest {46public:47// A BlockTransactionsRequest message48uint256 blockhash;49std::vector<uint16_t> indexes;51SERIALIZE_METHODS(BlockTransactionsRequest, obj)52{53READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes));54}55};57class BlockTransactions {58public:59// A BlockTransactions message60uint256 blockhash;61std::vector<CTransactionRef> txn;63BlockTransactions() = default;64explicit BlockTransactions(const BlockTransactionsRequest& req) :65blockhash(req.blockhash), txn(req.indexes.size()) {}67SERIALIZE_METHODS(BlockTransactions, obj)68{69READWRITE(obj.blockhash, TX_WITH_WITNESS(Using<VectorFormatter<TransactionCompression>>(obj.txn)));70}71};73// Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownloadedBlock74struct PrefilledTransaction {75// Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs,76// as a proper transaction-in-block-index in PartiallyDownloadedBlock77uint16_t index;78CTransactionRef tx;80SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); }81};83typedef enum ReadStatus_t84{85READ_STATUS_OK,86READ_STATUS_INVALID, // Invalid object, peer is sending bogus crap87READ_STATUS_FAILED, // Failed to process object88} ReadStatus;90class CBlockHeaderAndShortTxIDs {91mutable std::optional<PresaltedSipHasher> m_hasher;92uint64_t nonce;94void FillShortTxIDSelector() const;96friend class PartiallyDownloadedBlock;98protected:99std::vector<uint64_t> shorttxids;100std::vector<PrefilledTransaction> prefilledtxn;102public:103static constexpr int SHORTTXIDS_LENGTH = 6;105CBlockHeader header;107/**108* Dummy for deserialization109*/110CBlockHeaderAndShortTxIDs() = default;112/**113* @param[in] nonce This should be randomly generated, and is used for the siphash secret key114*/115CBlockHeaderAndShortTxIDs(const CBlock& block, uint64_t nonce);117uint64_t GetShortID(const Wtxid& wtxid) const;119size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); }121SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj)122{123READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn);124if (ser_action.ForRead()) {125if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) {126throw std::ios_base::failure("indexes overflowed 16 bits");127}128obj.FillShortTxIDSelector();129}130}131};133class PartiallyDownloadedBlock {134protected:135std::vector<CTransactionRef> txn_available;136size_t prefilled_count = 0, mempool_count = 0, extra_count = 0;137const CTxMemPool* pool;138public:139CBlockHeader header;141// Can be overridden for testing142using IsBlockMutatedFn = std::function<bool(const CBlock&, bool)>;143IsBlockMutatedFn m_check_block_mutated_mock{nullptr};145explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {}147// extra_txn is a list of extra transactions to look at, in <witness hash, reference> form148ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector<std::pair<Wtxid, CTransactionRef>>& extra_txn);149bool IsTxAvailable(size_t index) const;150// segwit_active enforces witness mutation checks just before reporting a healthy status151ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing, bool segwit_active);152};154#endif // BITCOIN_BLOCKENCODINGS_H