[tests] Add -blocknotify functional test
[bitcoinplatinum.git] / src / blockencodings.h
blob50478f9f321e4bc3e02a193c6fc47581fad8d202
1 // Copyright (c) 2016 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.
5 #ifndef BITCOIN_BLOCK_ENCODINGS_H
6 #define BITCOIN_BLOCK_ENCODINGS_H
8 #include "primitives/block.h"
10 #include <memory>
12 class CTxMemPool;
14 // Dumb helper to handle CTransaction compression at serialize-time
15 struct TransactionCompressor {
16 private:
17 CTransactionRef& tx;
18 public:
19 explicit TransactionCompressor(CTransactionRef& txIn) : tx(txIn) {}
21 ADD_SERIALIZE_METHODS;
23 template <typename Stream, typename Operation>
24 inline void SerializationOp(Stream& s, Operation ser_action) {
25 READWRITE(tx); //TODO: Compress tx encoding
29 class BlockTransactionsRequest {
30 public:
31 // A BlockTransactionsRequest message
32 uint256 blockhash;
33 std::vector<uint16_t> indexes;
35 ADD_SERIALIZE_METHODS;
37 template <typename Stream, typename Operation>
38 inline void SerializationOp(Stream& s, Operation ser_action) {
39 READWRITE(blockhash);
40 uint64_t indexes_size = (uint64_t)indexes.size();
41 READWRITE(COMPACTSIZE(indexes_size));
42 if (ser_action.ForRead()) {
43 size_t i = 0;
44 while (indexes.size() < indexes_size) {
45 indexes.resize(std::min((uint64_t)(1000 + indexes.size()), indexes_size));
46 for (; i < indexes.size(); i++) {
47 uint64_t index = 0;
48 READWRITE(COMPACTSIZE(index));
49 if (index > std::numeric_limits<uint16_t>::max())
50 throw std::ios_base::failure("index overflowed 16 bits");
51 indexes[i] = index;
55 uint16_t offset = 0;
56 for (size_t j = 0; j < indexes.size(); j++) {
57 if (uint64_t(indexes[j]) + uint64_t(offset) > std::numeric_limits<uint16_t>::max())
58 throw std::ios_base::failure("indexes overflowed 16 bits");
59 indexes[j] = indexes[j] + offset;
60 offset = indexes[j] + 1;
62 } else {
63 for (size_t i = 0; i < indexes.size(); i++) {
64 uint64_t index = indexes[i] - (i == 0 ? 0 : (indexes[i - 1] + 1));
65 READWRITE(COMPACTSIZE(index));
71 class BlockTransactions {
72 public:
73 // A BlockTransactions message
74 uint256 blockhash;
75 std::vector<CTransactionRef> txn;
77 BlockTransactions() {}
78 explicit BlockTransactions(const BlockTransactionsRequest& req) :
79 blockhash(req.blockhash), txn(req.indexes.size()) {}
81 ADD_SERIALIZE_METHODS;
83 template <typename Stream, typename Operation>
84 inline void SerializationOp(Stream& s, Operation ser_action) {
85 READWRITE(blockhash);
86 uint64_t txn_size = (uint64_t)txn.size();
87 READWRITE(COMPACTSIZE(txn_size));
88 if (ser_action.ForRead()) {
89 size_t i = 0;
90 while (txn.size() < txn_size) {
91 txn.resize(std::min((uint64_t)(1000 + txn.size()), txn_size));
92 for (; i < txn.size(); i++)
93 READWRITE(REF(TransactionCompressor(txn[i])));
95 } else {
96 for (size_t i = 0; i < txn.size(); i++)
97 READWRITE(REF(TransactionCompressor(txn[i])));
102 // Dumb serialization/storage-helper for CBlockHeaderAndShortTxIDs and PartiallyDownloadedBlock
103 struct PrefilledTransaction {
104 // Used as an offset since last prefilled tx in CBlockHeaderAndShortTxIDs,
105 // as a proper transaction-in-block-index in PartiallyDownloadedBlock
106 uint16_t index;
107 CTransactionRef tx;
109 ADD_SERIALIZE_METHODS;
111 template <typename Stream, typename Operation>
112 inline void SerializationOp(Stream& s, Operation ser_action) {
113 uint64_t idx = index;
114 READWRITE(COMPACTSIZE(idx));
115 if (idx > std::numeric_limits<uint16_t>::max())
116 throw std::ios_base::failure("index overflowed 16-bits");
117 index = idx;
118 READWRITE(REF(TransactionCompressor(tx)));
122 typedef enum ReadStatus_t
124 READ_STATUS_OK,
125 READ_STATUS_INVALID, // Invalid object, peer is sending bogus crap
126 READ_STATUS_FAILED, // Failed to process object
127 READ_STATUS_CHECKBLOCK_FAILED, // Used only by FillBlock to indicate a
128 // failure in CheckBlock.
129 } ReadStatus;
131 class CBlockHeaderAndShortTxIDs {
132 private:
133 mutable uint64_t shorttxidk0, shorttxidk1;
134 uint64_t nonce;
136 void FillShortTxIDSelector() const;
138 friend class PartiallyDownloadedBlock;
140 static const int SHORTTXIDS_LENGTH = 6;
141 protected:
142 std::vector<uint64_t> shorttxids;
143 std::vector<PrefilledTransaction> prefilledtxn;
145 public:
146 CBlockHeader header;
148 // Dummy for deserialization
149 CBlockHeaderAndShortTxIDs() {}
151 CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID);
153 uint64_t GetShortID(const uint256& txhash) const;
155 size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); }
157 ADD_SERIALIZE_METHODS;
159 template <typename Stream, typename Operation>
160 inline void SerializationOp(Stream& s, Operation ser_action) {
161 READWRITE(header);
162 READWRITE(nonce);
164 uint64_t shorttxids_size = (uint64_t)shorttxids.size();
165 READWRITE(COMPACTSIZE(shorttxids_size));
166 if (ser_action.ForRead()) {
167 size_t i = 0;
168 while (shorttxids.size() < shorttxids_size) {
169 shorttxids.resize(std::min((uint64_t)(1000 + shorttxids.size()), shorttxids_size));
170 for (; i < shorttxids.size(); i++) {
171 uint32_t lsb = 0; uint16_t msb = 0;
172 READWRITE(lsb);
173 READWRITE(msb);
174 shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
175 static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids serialization assumes 6-byte shorttxids");
178 } else {
179 for (size_t i = 0; i < shorttxids.size(); i++) {
180 uint32_t lsb = shorttxids[i] & 0xffffffff;
181 uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
182 READWRITE(lsb);
183 READWRITE(msb);
187 READWRITE(prefilledtxn);
189 if (ser_action.ForRead())
190 FillShortTxIDSelector();
194 class PartiallyDownloadedBlock {
195 protected:
196 std::vector<CTransactionRef> txn_available;
197 size_t prefilled_count = 0, mempool_count = 0, extra_count = 0;
198 CTxMemPool* pool;
199 public:
200 CBlockHeader header;
201 explicit PartiallyDownloadedBlock(CTxMemPool* poolIn) : pool(poolIn) {}
203 // extra_txn is a list of extra transactions to look at, in <witness hash, reference> form
204 ReadStatus InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector<std::pair<uint256, CTransactionRef>>& extra_txn);
205 bool IsTxAvailable(size_t index) const;
206 ReadStatus FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing);
209 #endif