Skip to content

Commit 40fdd5f

Browse files
committed
Convert blockencodings.h to new serialization framework
1 parent 0e599c2 commit 40fdd5f

File tree

1 file changed

+49
-106
lines changed

1 file changed

+49
-106
lines changed

src/blockencodings.h

Lines changed: 49 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,46 @@
77

88
#include <primitives/block.h>
99

10+
// Transaction compression schemes for compact block relay can be introduced by writing
11+
// an actual formatter here.
12+
using TransactionCompression = DefaultFormatter;
1013

1114
class CTxMemPool;
1215

13-
// Dumb helper to handle CTransaction compression at serialize-time
14-
struct TransactionCompressor {
15-
private:
16-
CTransactionRef& tx;
17-
public:
18-
explicit TransactionCompressor(CTransactionRef& txIn) : tx(txIn) {}
16+
struct Uint48Formatter
17+
{
18+
template <typename Stream, typename I> void Ser(Stream& s, I v)
19+
{
20+
if (v < 0 || (v >> 48) != 0) throw std::ios_base::failure("Uint48Formatter value out of range");
21+
22+
uint32_t lsb = v & 0xffffffff;
23+
uint16_t msb = (v >> 32) & 0xffff;
24+
s << lsb << msb;
25+
}
1926

20-
ADD_SERIALIZE_METHODS;
27+
template <typename Stream, typename I> void Unser(Stream& s, I& v)
28+
{
29+
static_assert(std::numeric_limits<I>::max() >= 0xffffffffffff && std::numeric_limits<I>::min() <= 0, "Uint48Formatter needs a 48+ bit type");
2130

22-
template <typename Stream, typename Operation>
23-
inline void SerializationOp(Stream& s, Operation ser_action) {
24-
READWRITE(tx); //TODO: Compress tx encoding
31+
uint32_t lsb;
32+
uint16_t msb;
33+
s >> lsb >> msb;
34+
v = (uint64_t(msb) << 32) | uint64_t(lsb);
35+
}
36+
};
37+
38+
template<bool Unser>
39+
class DifferenceTransform
40+
{
41+
int32_t m_shift = 0;
42+
43+
public:
44+
uint16_t operator()(uint16_t val)
45+
{
46+
int32_t out = m_shift + val;
47+
if (out < 0 || out > 0xffff) throw std::ios_base::failure("differential value overflow");
48+
m_shift = Unser ? out + 1 : (-(int32_t)val) - 1;
49+
return uint16_t(out);
2550
}
2651
};
2752

@@ -31,39 +56,9 @@ class BlockTransactionsRequest {
3156
uint256 blockhash;
3257
std::vector<uint16_t> indexes;
3358

34-
ADD_SERIALIZE_METHODS;
35-
36-
template <typename Stream, typename Operation>
37-
inline void SerializationOp(Stream& s, Operation ser_action) {
38-
READWRITE(blockhash);
39-
uint64_t indexes_size = (uint64_t)indexes.size();
40-
READWRITE(COMPACTSIZE(indexes_size));
41-
if (ser_action.ForRead()) {
42-
size_t i = 0;
43-
while (indexes.size() < indexes_size) {
44-
indexes.resize(std::min((uint64_t)(1000 + indexes.size()), indexes_size));
45-
for (; i < indexes.size(); i++) {
46-
uint64_t index = 0;
47-
READWRITE(COMPACTSIZE(index));
48-
if (index > std::numeric_limits<uint16_t>::max())
49-
throw std::ios_base::failure("index overflowed 16 bits");
50-
indexes[i] = index;
51-
}
52-
}
53-
54-
int32_t offset = 0;
55-
for (size_t j = 0; j < indexes.size(); j++) {
56-
if (int32_t(indexes[j]) + offset > std::numeric_limits<uint16_t>::max())
57-
throw std::ios_base::failure("indexes overflowed 16 bits");
58-
indexes[j] = indexes[j] + offset;
59-
offset = int32_t(indexes[j]) + 1;
60-
}
61-
} else {
62-
for (size_t i = 0; i < indexes.size(); i++) {
63-
uint64_t index = indexes[i] - (i == 0 ? 0 : (indexes[i - 1] + 1));
64-
READWRITE(COMPACTSIZE(index));
65-
}
66-
}
59+
SERIALIZE_METHODS(BlockTransactionsRequest, obj)
60+
{
61+
READWRITE(obj.blockhash, Using<VectorFormatter<CompactSizeFormatter, DifferenceTransform<false>, DifferenceTransform<true>>>(obj.indexes));
6762
}
6863
};
6964

@@ -77,24 +72,9 @@ class BlockTransactions {
7772
explicit BlockTransactions(const BlockTransactionsRequest& req) :
7873
blockhash(req.blockhash), txn(req.indexes.size()) {}
7974

80-
ADD_SERIALIZE_METHODS;
81-
82-
template <typename Stream, typename Operation>
83-
inline void SerializationOp(Stream& s, Operation ser_action) {
84-
READWRITE(blockhash);
85-
uint64_t txn_size = (uint64_t)txn.size();
86-
READWRITE(COMPACTSIZE(txn_size));
87-
if (ser_action.ForRead()) {
88-
size_t i = 0;
89-
while (txn.size() < txn_size) {
90-
txn.resize(std::min((uint64_t)(1000 + txn.size()), txn_size));
91-
for (; i < txn.size(); i++)
92-
READWRITE(TransactionCompressor(txn[i]));
93-
}
94-
} else {
95-
for (size_t i = 0; i < txn.size(); i++)
96-
READWRITE(TransactionCompressor(txn[i]));
97-
}
75+
SERIALIZE_METHODS(BlockTransactions, obj)
76+
{
77+
READWRITE(obj.blockhash, Using<VectorFormatter<TransactionCompression>>(obj.txn));
9878
}
9979
};
10080

@@ -105,17 +85,7 @@ struct PrefilledTransaction {
10585
uint16_t index;
10686
CTransactionRef tx;
10787

108-
ADD_SERIALIZE_METHODS;
109-
110-
template <typename Stream, typename Operation>
111-
inline void SerializationOp(Stream& s, Operation ser_action) {
112-
uint64_t idx = index;
113-
READWRITE(COMPACTSIZE(idx));
114-
if (idx > std::numeric_limits<uint16_t>::max())
115-
throw std::ios_base::failure("index overflowed 16-bits");
116-
index = idx;
117-
READWRITE(TransactionCompressor(tx));
118-
}
88+
SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), Using<TransactionCompression>(obj.tx)); }
11989
};
12090

12191
typedef enum ReadStatus_t
@@ -153,43 +123,16 @@ class CBlockHeaderAndShortTxIDs {
153123

154124
size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); }
155125

156-
ADD_SERIALIZE_METHODS;
157-
158-
template <typename Stream, typename Operation>
159-
inline void SerializationOp(Stream& s, Operation ser_action) {
160-
READWRITE(header);
161-
READWRITE(nonce);
162-
163-
uint64_t shorttxids_size = (uint64_t)shorttxids.size();
164-
READWRITE(COMPACTSIZE(shorttxids_size));
126+
SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj)
127+
{
128+
static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids serialization assumes 6-byte shorttxids");
129+
READWRITE(obj.header, obj.nonce, Using<VectorFormatter<Uint48Formatter>>(obj.shorttxids), obj.prefilledtxn);
165130
if (ser_action.ForRead()) {
166-
size_t i = 0;
167-
while (shorttxids.size() < shorttxids_size) {
168-
shorttxids.resize(std::min((uint64_t)(1000 + shorttxids.size()), shorttxids_size));
169-
for (; i < shorttxids.size(); i++) {
170-
uint32_t lsb = 0; uint16_t msb = 0;
171-
READWRITE(lsb);
172-
READWRITE(msb);
173-
shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
174-
static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids serialization assumes 6-byte shorttxids");
175-
}
176-
}
177-
} else {
178-
for (size_t i = 0; i < shorttxids.size(); i++) {
179-
uint32_t lsb = shorttxids[i] & 0xffffffff;
180-
uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
181-
READWRITE(lsb);
182-
READWRITE(msb);
131+
if (obj.BlockTxCount() > std::numeric_limits<uint16_t>::max()) {
132+
throw std::ios_base::failure("indexes overflowed 16 bits");
183133
}
134+
obj.FillShortTxIDSelector();
184135
}
185-
186-
READWRITE(prefilledtxn);
187-
188-
if (BlockTxCount() > std::numeric_limits<uint16_t>::max())
189-
throw std::ios_base::failure("indexes overflowed 16 bits");
190-
191-
if (ser_action.ForRead())
192-
FillShortTxIDSelector();
193136
}
194137
};
195138

0 commit comments

Comments
 (0)