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 8946 : class DifferenceFormatter 18 : { 19 4473 : uint64_t m_shift = 0; 20 : 21 : public: 22 : template<typename Stream, typename I> 23 3565 : void Ser(Stream& s, I v) 24 : { 25 3565 : if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) throw std::ios_base::failure("differential value overflow"); 26 3565 : WriteCompactSize(s, v - m_shift); 27 3565 : m_shift = uint64_t(v) + 1; 28 3565 : } 29 : template<typename Stream, typename I> 30 3616 : void Unser(Stream& s, I& v) 31 : { 32 3616 : uint64_t n = ReadCompactSize(s); 33 3616 : m_shift += n; 34 3616 : 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 3615 : v = I(m_shift++); 36 3616 : } 37 : }; 38 : 39 49208 : class BlockTransactionsRequest { 40 : public: 41 : // A BlockTransactionsRequest message 42 : uint256 blockhash; 43 : std::vector<uint16_t> indexes; 44 : 45 13419 : SERIALIZE_METHODS(BlockTransactionsRequest, obj) 46 : { 47 4473 : READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes)); 48 4473 : } 49 : }; 50 : 51 40238 : class BlockTransactions { 52 : public: 53 : // A BlockTransactions message 54 : uint256 blockhash; 55 : std::vector<CTransactionRef> txn; 56 : 57 35760 : BlockTransactions() {} 58 4478 : explicit BlockTransactions(const BlockTransactionsRequest& req) : 59 4478 : blockhash(req.blockhash), txn(req.indexes.size()) {} 60 : 61 60357 : SERIALIZE_METHODS(BlockTransactions, obj) 62 : { 63 20119 : READWRITE(obj.blockhash, Using<VectorFormatter<TransactionCompression>>(obj.txn)); 64 20119 : } 65 : }; 66 : 67 : // Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownloadedBlock 68 436274 : 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 103233 : 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 95600 : 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 23970 : CBlockHeaderAndShortTxIDs() {} 106 : 107 : CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID); 108 : 109 : uint64_t GetShortID(const uint256& txhash) const; 110 : 111 55023 : size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); } 112 : 113 103143 : SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj) 114 : { 115 34381 : READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); 116 : if (ser_action.ForRead()) { 117 11985 : if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) { 118 0 : throw std::ios_base::failure("indexes overflowed 16 bits"); 119 : } 120 11985 : obj.FillShortTxIDSelector(); 121 : } 122 34381 : } 123 : }; 124 : 125 20266 : class PartiallyDownloadedBlock { 126 : protected: 127 : std::vector<CTransactionRef> txn_available; 128 10119 : size_t prefilled_count = 0, mempool_count = 0, extra_count = 0; 129 : const CTxMemPool* pool; 130 : public: 131 : CBlockHeader header; 132 20238 : 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