/workdir/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 | 0 | { |
30 | 0 | if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) throw std::ios_base::failure("differential value overflow"); Branch (30:13): [True: 0, False: 0]
Branch (30:28): [True: 0, False: 0]
Branch (30:13): [True: 0, False: 0]
Branch (30:28): [True: 0, False: 0]
|
31 | 0 | WriteCompactSize(s, v - m_shift); |
32 | 0 | m_shift = uint64_t(v) + 1; |
33 | 0 | } Unexecuted instantiation: void DifferenceFormatter::Ser<DataStream, unsigned short>(DataStream&, unsigned short) Unexecuted instantiation: void DifferenceFormatter::Ser<VectorWriter, unsigned short>(VectorWriter&, unsigned short) |
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"); Branch (39:13): [True: 0, False: 0]
Branch (39:28): [True: 0, False: 0]
Branch (39:79): [True: 0, False: 0]
Branch (39:122): [True: 0, False: 0]
|
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 | 0 | { |
52 | 0 | READWRITE(obj.blockhash, Using<VectorFormatter<DifferenceFormatter>>(obj.indexes)); |
53 | 0 | } Unexecuted instantiation: void BlockTransactionsRequest::SerializationOps<DataStream, BlockTransactionsRequest, ActionUnserialize>(BlockTransactionsRequest&, DataStream&, ActionUnserialize) Unexecuted instantiation: void BlockTransactionsRequest::SerializationOps<DataStream, BlockTransactionsRequest const, ActionSerialize>(BlockTransactionsRequest const&, DataStream&, ActionSerialize) Unexecuted instantiation: void BlockTransactionsRequest::SerializationOps<VectorWriter, BlockTransactionsRequest const, ActionSerialize>(BlockTransactionsRequest const&, VectorWriter&, ActionSerialize) |
54 | | }; |
55 | | |
56 | | class BlockTransactions { |
57 | | public: |
58 | | // A BlockTransactions message |
59 | | uint256 blockhash; |
60 | | std::vector<CTransactionRef> txn; |
61 | | |
62 | 0 | BlockTransactions() = default; |
63 | | explicit BlockTransactions(const BlockTransactionsRequest& req) : |
64 | 0 | blockhash(req.blockhash), txn(req.indexes.size()) {} |
65 | | |
66 | | SERIALIZE_METHODS(BlockTransactions, obj) |
67 | 0 | { |
68 | 0 | READWRITE(obj.blockhash, TX_WITH_WITNESS(Using<VectorFormatter<TransactionCompression>>(obj.txn))); |
69 | 0 | } Unexecuted instantiation: void BlockTransactions::SerializationOps<DataStream, BlockTransactions, ActionUnserialize>(BlockTransactions&, DataStream&, ActionUnserialize) Unexecuted instantiation: void BlockTransactions::SerializationOps<DataStream, BlockTransactions const, ActionSerialize>(BlockTransactions const&, DataStream&, ActionSerialize) Unexecuted instantiation: void BlockTransactions::SerializationOps<VectorWriter, BlockTransactions const, ActionSerialize>(BlockTransactions const&, VectorWriter&, ActionSerialize) |
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 | 3.37k | SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } void PrefilledTransaction::SerializationOps<DataStream, PrefilledTransaction, ActionUnserialize>(PrefilledTransaction&, DataStream&, ActionUnserialize) Line | Count | Source | 79 | 1.68k | SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } |
Unexecuted instantiation: void PrefilledTransaction::SerializationOps<DataStream, PrefilledTransaction const, ActionSerialize>(PrefilledTransaction const&, DataStream&, ActionSerialize) void PrefilledTransaction::SerializationOps<ParamsStream<VectorWriter&, TransactionSerParams>, PrefilledTransaction const, ActionSerialize>(PrefilledTransaction const&, ParamsStream<VectorWriter&, TransactionSerParams>&, ActionSerialize) Line | Count | Source | 79 | 1.68k | SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), TX_WITH_WITNESS(Using<TransactionCompression>(obj.tx))); } |
Unexecuted instantiation: void PrefilledTransaction::SerializationOps<SizeComputer, PrefilledTransaction const, ActionSerialize>(PrefilledTransaction const&, SizeComputer&, ActionSerialize) Unexecuted instantiation: void PrefilledTransaction::SerializationOps<VectorWriter, PrefilledTransaction const, ActionSerialize>(PrefilledTransaction const&, VectorWriter&, ActionSerialize) |
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 | | protected: |
101 | | std::vector<uint64_t> shorttxids; |
102 | | std::vector<PrefilledTransaction> prefilledtxn; |
103 | | |
104 | | public: |
105 | | static constexpr int SHORTTXIDS_LENGTH = 6; |
106 | | |
107 | | CBlockHeader header; |
108 | | |
109 | | /** |
110 | | * Dummy for deserialization |
111 | | */ |
112 | 1.68k | CBlockHeaderAndShortTxIDs() = default; |
113 | | |
114 | | /** |
115 | | * @param[in] nonce This should be randomly generated, and is used for the siphash secret key |
116 | | */ |
117 | | CBlockHeaderAndShortTxIDs(const CBlock& block, const uint64_t nonce); |
118 | | |
119 | | uint64_t GetShortID(const Wtxid& wtxid) const; |
120 | | |
121 | 1.68k | size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); } |
122 | | |
123 | | SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj) |
124 | 3.37k | { |
125 | 3.37k | READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); |
126 | 3.37k | if (ser_action.ForRead()) { Branch (126:13): [Folded - Ignored]
Branch (126:13): [Folded - Ignored]
Branch (126:13): [Folded - Ignored]
Branch (126:13): [Folded - Ignored]
Branch (126:13): [Folded - Ignored]
|
127 | 1.68k | if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) { Branch (127:17): [True: 0, False: 1.68k]
Branch (127:17): [True: 0, False: 0]
Branch (127:17): [True: 0, False: 0]
Branch (127:17): [True: 0, False: 0]
Branch (127:17): [True: 0, False: 0]
|
128 | 0 | throw std::ios_base::failure("indexes overflowed 16 bits"); |
129 | 0 | } |
130 | 1.68k | obj.FillShortTxIDSelector(); |
131 | 1.68k | } |
132 | 3.37k | } void CBlockHeaderAndShortTxIDs::SerializationOps<DataStream, CBlockHeaderAndShortTxIDs, ActionUnserialize>(CBlockHeaderAndShortTxIDs&, DataStream&, ActionUnserialize) Line | Count | Source | 124 | 1.68k | { | 125 | 1.68k | READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); | 126 | 1.68k | if (ser_action.ForRead()) { Branch (126:13): [Folded - Ignored]
| 127 | 1.68k | if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) { Branch (127:17): [True: 0, False: 1.68k]
| 128 | 0 | throw std::ios_base::failure("indexes overflowed 16 bits"); | 129 | 0 | } | 130 | 1.68k | obj.FillShortTxIDSelector(); | 131 | 1.68k | } | 132 | 1.68k | } |
Unexecuted instantiation: void CBlockHeaderAndShortTxIDs::SerializationOps<DataStream, CBlockHeaderAndShortTxIDs const, ActionSerialize>(CBlockHeaderAndShortTxIDs const&, DataStream&, ActionSerialize) void CBlockHeaderAndShortTxIDs::SerializationOps<ParamsStream<VectorWriter&, TransactionSerParams>, CBlockHeaderAndShortTxIDs const, ActionSerialize>(CBlockHeaderAndShortTxIDs const&, ParamsStream<VectorWriter&, TransactionSerParams>&, ActionSerialize) Line | Count | Source | 124 | 1.68k | { | 125 | 1.68k | READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); | 126 | 1.68k | if (ser_action.ForRead()) { Branch (126:13): [Folded - Ignored]
| 127 | 0 | if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) { Branch (127:17): [True: 0, False: 0]
| 128 | 0 | throw std::ios_base::failure("indexes overflowed 16 bits"); | 129 | 0 | } | 130 | 0 | obj.FillShortTxIDSelector(); | 131 | 0 | } | 132 | 1.68k | } |
Unexecuted instantiation: void CBlockHeaderAndShortTxIDs::SerializationOps<SizeComputer, CBlockHeaderAndShortTxIDs const, ActionSerialize>(CBlockHeaderAndShortTxIDs const&, SizeComputer&, ActionSerialize) Unexecuted instantiation: void CBlockHeaderAndShortTxIDs::SerializationOps<VectorWriter, CBlockHeaderAndShortTxIDs const, ActionSerialize>(CBlockHeaderAndShortTxIDs const&, VectorWriter&, ActionSerialize) |
133 | | }; |
134 | | |
135 | | class PartiallyDownloadedBlock { |
136 | | protected: |
137 | | std::vector<CTransactionRef> txn_available; |
138 | | size_t prefilled_count = 0, mempool_count = 0, extra_count = 0; |
139 | | const CTxMemPool* pool; |
140 | | public: |
141 | | CBlockHeader header; |
142 | | |
143 | | // Can be overridden for testing |
144 | | using CheckBlockFn = std::function<bool(const CBlock&, BlockValidationState&, const Consensus::Params&, bool, bool)>; |
145 | | CheckBlockFn m_check_block_mock{nullptr}; |
146 | | |
147 | 0 | explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {} |
148 | | |
149 | | // extra_txn is a list of extra orphan/conflicted/etc transactions to look at |
150 | | ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector<CTransactionRef>& extra_txn); |
151 | | bool IsTxAvailable(size_t index) const; |
152 | | ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing); |
153 | | }; |
154 | | |
155 | | #endif // BITCOIN_BLOCKENCODINGS_H |