/Users/eugenesiegel/btc/bitcoin/src/blockencodings.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2016-2022 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 | | #include <functional> |
11 | | |
12 | | class CTxMemPool; |
13 | | class BlockValidationState; |
14 | | namespace Consensus { |
15 | | struct Params; |
16 | | }; |
17 | | |
18 | | // Transaction compression schemes for compact block relay can be introduced by writing |
19 | | // an actual formatter here. |
20 | | using TransactionCompression = DefaultFormatter; |
21 | | |
22 | | class DifferenceFormatter |
23 | | { |
24 | | uint64_t m_shift = 0; |
25 | | |
26 | | public: |
27 | | template<typename Stream, typename I> |
28 | | void Ser(Stream& s, I v) |
29 | 7.10k | { |
30 | 7.10k | if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) throw std::ios_base::failure("differential value overflow")0 ; |
31 | 7.10k | WriteCompactSize(s, v - m_shift); |
32 | 7.10k | m_shift = uint64_t(v) + 1; |
33 | 7.10k | } Unexecuted instantiation: _ZN19DifferenceFormatter3SerI10DataStreamtEEvRT_T0_ _ZN19DifferenceFormatter3SerI12VectorWritertEEvRT_T0_ Line | Count | Source | 29 | 7.10k | { | 30 | 7.10k | if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) throw std::ios_base::failure("differential value overflow")0 ; | 31 | 7.10k | WriteCompactSize(s, v - m_shift); | 32 | 7.10k | m_shift = uint64_t(v) + 1; | 33 | 7.10k | } |
|
34 | | template<typename Stream, typename I> |
35 | | void Unser(Stream& s, I& v) |
36 | 0 | { |
37 | 0 | uint64_t n = ReadCompactSize(s); |
38 | 0 | m_shift += n; |
39 | 0 | 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"); |
40 | 0 | v = I(m_shift++); |
41 | 0 | } |
42 | | }; |
43 | | |
44 | | class BlockTransactionsRequest { |
45 | | public: |
46 | | // A BlockTransactionsRequest message |
47 | | uint256 blockhash; |
48 | | std::vector<uint16_t> indexes; |
49 | | |
50 | | SERIALIZE_METHODS(BlockTransactionsRequest, obj) |
51 | 1.23k | { |
52 | 1.23k | READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes)); Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes)); Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes)); Line | Count | Source | 156 | 1.23k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
53 | 1.23k | } Unexecuted instantiation: _ZN24BlockTransactionsRequest16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_ Unexecuted instantiation: _ZN24BlockTransactionsRequest16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_ _ZN24BlockTransactionsRequest16SerializationOpsI12VectorWriterKS_15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 51 | 1.23k | { | 52 | 1.23k | READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes)); Line | Count | Source | 156 | 1.23k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| 53 | 1.23k | } |
|
54 | | }; |
55 | | |
56 | | class BlockTransactions { |
57 | | public: |
58 | | // A BlockTransactions message |
59 | | uint256 blockhash; |
60 | | std::vector<CTransactionRef> txn; |
61 | | |
62 | 260k | BlockTransactions() = default; |
63 | | explicit BlockTransactions(const BlockTransactionsRequest& req) : |
64 | 0 | blockhash(req.blockhash), txn(req.indexes.size()) {} |
65 | | |
66 | | SERIALIZE_METHODS(BlockTransactions, obj) |
67 | 218k | { |
68 | 218k | READWRITE(obj.blockhash, TX_WITH_WITNESS(Using<VectorFormatter<TransactionCompression>>(obj.txn))); Line | Count | Source | 156 | 123k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.blockhash, TX_WITH_WITNESS(Using<VectorFormatter<TransactionCompression>>(obj.txn))); Line | Count | Source | 156 | 94.7k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.blockhash, TX_WITH_WITNESS(Using<VectorFormatter<TransactionCompression>>(obj.txn))); Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
69 | 218k | } _ZN17BlockTransactions16SerializationOpsI12VectorWriterKS_15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 67 | 123k | { | 68 | 123k | READWRITE(obj.blockhash, TX_WITH_WITNESS(Using<VectorFormatter<TransactionCompression>>(obj.txn))); Line | Count | Source | 156 | 123k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| 69 | 123k | } |
_ZN17BlockTransactions16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_ Line | Count | Source | 67 | 94.7k | { | 68 | 94.7k | READWRITE(obj.blockhash, TX_WITH_WITNESS(Using<VectorFormatter<TransactionCompression>>(obj.txn))); Line | Count | Source | 156 | 94.7k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| 69 | 94.7k | } |
Unexecuted instantiation: _ZN17BlockTransactions16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_ |
70 | | }; |
71 | | |
72 | | // Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownloadedBlock |
73 | | struct PrefilledTransaction { |
74 | | // Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs, |
75 | | // as a proper transaction-in-block-index in PartiallyDownloadedBlock |
76 | | uint16_t index; |
77 | | CTransactionRef tx; |
78 | | |
79 | 366k | SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } Line | Count | Source | 156 | 224k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } Line | Count | Source | 156 | 142k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
_ZN20PrefilledTransaction16SerializationOpsI12VectorWriterKS_15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 79 | 224k | SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } Line | Count | Source | 156 | 224k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
_ZN20PrefilledTransaction16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_ Line | Count | Source | 79 | 142k | SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } Line | Count | Source | 156 | 142k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
Unexecuted instantiation: _ZN20PrefilledTransaction16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_ Unexecuted instantiation: _ZN20PrefilledTransaction16SerializationOpsI12ParamsStreamIR12VectorWriter20TransactionSerParamsEKS_15ActionSerializeEEvRT0_RT_T1_ Unexecuted instantiation: _ZN20PrefilledTransaction16SerializationOpsI12SizeComputerKS_15ActionSerializeEEvRT0_RT_T1_ |
80 | | }; |
81 | | |
82 | | typedef enum ReadStatus_t |
83 | | { |
84 | | READ_STATUS_OK, |
85 | | READ_STATUS_INVALID, // Invalid object, peer is sending bogus crap |
86 | | READ_STATUS_FAILED, // Failed to process object |
87 | | READ_STATUS_CHECKBLOCK_FAILED, // Used only by FillBlock to indicate a |
88 | | // failure in CheckBlock. |
89 | | } ReadStatus; |
90 | | |
91 | | class CBlockHeaderAndShortTxIDs { |
92 | | private: |
93 | | mutable uint64_t shorttxidk0, shorttxidk1; |
94 | | uint64_t nonce; |
95 | | |
96 | | void FillShortTxIDSelector() const; |
97 | | |
98 | | friend class PartiallyDownloadedBlock; |
99 | | |
100 | | public: |
101 | | static constexpr int SHORTTXIDS_LENGTH = 6; |
102 | | |
103 | | CBlockHeader header; |
104 | | |
105 | | std::vector<uint64_t> shorttxids; |
106 | | std::vector<PrefilledTransaction> prefilledtxn; |
107 | | |
108 | | /** |
109 | | * Dummy for deserialization |
110 | | */ |
111 | 115k | CBlockHeaderAndShortTxIDs() = default; |
112 | | |
113 | | /** |
114 | | * @param[in] nonce This should be randomly generated, and is used for the siphash secret key |
115 | | */ |
116 | | CBlockHeaderAndShortTxIDs(const CBlock& block, const uint64_t nonce); |
117 | | |
118 | | uint64_t GetShortID(const Wtxid& wtxid) const; |
119 | | |
120 | 257k | size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); } |
121 | | |
122 | | SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj) |
123 | 280k | { |
124 | 280k | READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); Line | Count | Source | 156 | 164k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); Line | Count | Source | 156 | 115k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); Line | Count | Source | 156 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
125 | 280k | if (ser_action.ForRead()) { |
126 | 105k | if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) { |
127 | 0 | throw std::ios_base::failure("indexes overflowed 16 bits"); |
128 | 0 | } |
129 | 105k | obj.FillShortTxIDSelector(); |
130 | 105k | } |
131 | 280k | } _ZN25CBlockHeaderAndShortTxIDs16SerializationOpsI12VectorWriterKS_15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 123 | 164k | { | 124 | 164k | READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); Line | Count | Source | 156 | 164k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| 125 | 164k | if (ser_action.ForRead()) { | 126 | 0 | if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) { | 127 | 0 | throw std::ios_base::failure("indexes overflowed 16 bits"); | 128 | 0 | } | 129 | 0 | obj.FillShortTxIDSelector(); | 130 | 0 | } | 131 | 164k | } |
_ZN25CBlockHeaderAndShortTxIDs16SerializationOpsI10DataStreamS_17ActionUnserializeEEvRT0_RT_T1_ Line | Count | Source | 123 | 115k | { | 124 | 115k | READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); Line | Count | Source | 156 | 115k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
| 125 | 115k | if (ser_action.ForRead()) { | 126 | 105k | if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) { | 127 | 0 | throw std::ios_base::failure("indexes overflowed 16 bits"); | 128 | 0 | } | 129 | 105k | obj.FillShortTxIDSelector(); | 130 | 105k | } | 131 | 115k | } |
Unexecuted instantiation: _ZN25CBlockHeaderAndShortTxIDs16SerializationOpsI10DataStreamKS_15ActionSerializeEEvRT0_RT_T1_ Unexecuted instantiation: _ZN25CBlockHeaderAndShortTxIDs16SerializationOpsI12ParamsStreamIR12VectorWriter20TransactionSerParamsEKS_15ActionSerializeEEvRT0_RT_T1_ Unexecuted instantiation: _ZN25CBlockHeaderAndShortTxIDs16SerializationOpsI12SizeComputerKS_15ActionSerializeEEvRT0_RT_T1_ |
132 | | }; |
133 | | |
134 | | class PartiallyDownloadedBlock { |
135 | | protected: |
136 | | std::vector<CTransactionRef> txn_available; |
137 | | size_t prefilled_count = 0, mempool_count = 0, extra_count = 0; |
138 | | const CTxMemPool* pool; |
139 | | public: |
140 | | CBlockHeader header; |
141 | | |
142 | | // Can be overridden for testing |
143 | | using CheckBlockFn = std::function<bool(const CBlock&, BlockValidationState&, const Consensus::Params&, bool, bool)>; |
144 | | CheckBlockFn m_check_block_mock{nullptr}; |
145 | | |
146 | 47.2k | explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {} |
147 | | |
148 | | // extra_txn is a list of extra orphan/conflicted/etc transactions to look at |
149 | | ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector<CTransactionRef>& extra_txn); |
150 | | bool IsTxAvailable(size_t index) const; |
151 | | ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing); |
152 | | }; |
153 | | |
154 | | #endif // BITCOIN_BLOCKENCODINGS_H |