Branch data Line data Source code
# 1 : : // Copyright (c) 2016-2020 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : #ifndef BITCOIN_BLOCKENCODINGS_H
# 6 : : #define BITCOIN_BLOCKENCODINGS_H
# 7 : :
# 8 : : #include <primitives/block.h>
# 9 : :
# 10 : :
# 11 : : class CTxMemPool;
# 12 : :
# 13 : : // Transaction compression schemes for compact block relay can be introduced by writing
# 14 : : // an actual formatter here.
# 15 : : using TransactionCompression = DefaultFormatter;
# 16 : :
# 17 : : class DifferenceFormatter
# 18 : : {
# 19 : : uint64_t m_shift = 0;
# 20 : :
# 21 : : public:
# 22 : : template<typename Stream, typename I>
# 23 : : void Ser(Stream& s, I v)
# 24 : 5609 : {
# 25 [ - + ][ - + ]: 5609 : if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) throw std::ios_base::failure("differential value overflow");
# [ - + ][ - + ]
# 26 : 5609 : WriteCompactSize(s, v - m_shift);
# 27 : 5609 : m_shift = uint64_t(v) + 1;
# 28 : 5609 : }
# 29 : : template<typename Stream, typename I>
# 30 : : void Unser(Stream& s, I& v)
# 31 : 5667 : {
# 32 : 5667 : uint64_t n = ReadCompactSize(s);
# 33 : 5667 : m_shift += n;
# 34 [ - + ][ - + ]: 5667 : if (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");
# [ - + ][ + + ]
# 35 : 5665 : v = I(m_shift++);
# 36 : 5665 : }
# 37 : : };
# 38 : :
# 39 : : class BlockTransactionsRequest {
# 40 : : public:
# 41 : : // A BlockTransactionsRequest message
# 42 : : uint256 blockhash;
# 43 : : std::vector<uint16_t> indexes;
# 44 : :
# 45 : : SERIALIZE_METHODS(BlockTransactionsRequest, obj)
# 46 : 7716 : {
# 47 : 7716 : READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes));
# 48 : 7716 : }
# 49 : : };
# 50 : :
# 51 : : class BlockTransactions {
# 52 : : public:
# 53 : : // A BlockTransactions message
# 54 : : uint256 blockhash;
# 55 : : std::vector<CTransactionRef> txn;
# 56 : :
# 57 : 29318 : BlockTransactions() {}
# 58 : : explicit BlockTransactions(const BlockTransactionsRequest& req) :
# 59 : 3858 : blockhash(req.blockhash), txn(req.indexes.size()) {}
# 60 : :
# 61 : : SERIALIZE_METHODS(BlockTransactions, obj)
# 62 : 33176 : {
# 63 : 33176 : READWRITE(obj.blockhash, Using<VectorFormatter<TransactionCompression>>(obj.txn));
# 64 : 33176 : }
# 65 : : };
# 66 : :
# 67 : : // Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownloadedBlock
# 68 : : struct PrefilledTransaction {
# 69 : : // Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs,
# 70 : : // as a proper transaction-in-block-index in PartiallyDownloadedBlock
# 71 : : uint16_t index;
# 72 : : CTransactionRef tx;
# 73 : :
# 74 : 58651 : SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), Using<TransactionCompression>(obj.tx)); }
# 75 : : };
# 76 : :
# 77 : : typedef enum ReadStatus_t
# 78 : : {
# 79 : : READ_STATUS_OK,
# 80 : : READ_STATUS_INVALID, // Invalid object, peer is sending bogus crap
# 81 : : READ_STATUS_FAILED, // Failed to process object
# 82 : : READ_STATUS_CHECKBLOCK_FAILED, // Used only by FillBlock to indicate a
# 83 : : // failure in CheckBlock.
# 84 : : } ReadStatus;
# 85 : :
# 86 : : class CBlockHeaderAndShortTxIDs {
# 87 : : private:
# 88 : : mutable uint64_t shorttxidk0, shorttxidk1;
# 89 : : uint64_t nonce;
# 90 : :
# 91 : : void FillShortTxIDSelector() const;
# 92 : :
# 93 : : friend class PartiallyDownloadedBlock;
# 94 : :
# 95 : : protected:
# 96 : : std::vector<uint64_t> shorttxids;
# 97 : : std::vector<PrefilledTransaction> prefilledtxn;
# 98 : :
# 99 : : public:
# 100 : : static constexpr int SHORTTXIDS_LENGTH = 6;
# 101 : :
# 102 : : CBlockHeader header;
# 103 : :
# 104 : : // Dummy for deserialization
# 105 : 20749 : CBlockHeaderAndShortTxIDs() {}
# 106 : :
# 107 : : CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID);
# 108 : :
# 109 : : uint64_t GetShortID(const uint256& txhash) const;
# 110 : :
# 111 : 85821 : size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); }
# 112 : :
# 113 : : SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj)
# 114 : 58609 : {
# 115 : 58609 : READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn);
# 116 : 58609 : if (ser_action.ForRead()) {
# 117 [ # # ][ - + ]: 20749 : if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) {
# [ # # ][ # # ]
# 118 : 0 : throw std::ios_base::failure("indexes overflowed 16 bits");
# 119 : 0 : }
# 120 : 20749 : obj.FillShortTxIDSelector();
# 121 : 20749 : }
# 122 : 58609 : }
# 123 : : };
# 124 : :
# 125 : : class PartiallyDownloadedBlock {
# 126 : : protected:
# 127 : : std::vector<CTransactionRef> txn_available;
# 128 : : size_t prefilled_count = 0, mempool_count = 0, extra_count = 0;
# 129 : : const CTxMemPool* pool;
# 130 : : public:
# 131 : : CBlockHeader header;
# 132 : 16741 : explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {}
# 133 : :
# 134 : : // extra_txn is a list of extra transactions to look at, in <witness hash, reference> form
# 135 : : ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector<std::pair<uint256, CTransactionRef>>& extra_txn);
# 136 : : bool IsTxAvailable(size_t index) const;
# 137 : : ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing);
# 138 : : };
# 139 : :
# 140 : : #endif // BITCOIN_BLOCKENCODINGS_H
|