mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Convert bitset serializationis to use formatters
This commit is contained in:
parent
64d4a48a09
commit
d60a6d1729
@ -54,20 +54,19 @@ public:
|
||||
bool VerifySizes(const Consensus::LLMQParams& params) const;
|
||||
|
||||
public:
|
||||
ADD_SERIALIZE_METHODS
|
||||
|
||||
template<typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
SERIALIZE_METHODS(CFinalCommitment, obj)
|
||||
{
|
||||
READWRITE(nVersion);
|
||||
READWRITE(llmqType);
|
||||
READWRITE(quorumHash);
|
||||
READWRITE(DYNBITSET(signers));
|
||||
READWRITE(DYNBITSET(validMembers));
|
||||
READWRITE(quorumPublicKey);
|
||||
READWRITE(quorumVvecHash);
|
||||
READWRITE(quorumSig);
|
||||
READWRITE(membersSig);
|
||||
READWRITE(
|
||||
obj.nVersion,
|
||||
obj.llmqType,
|
||||
obj.quorumHash,
|
||||
DYNBITSET(obj.signers),
|
||||
DYNBITSET(obj.validMembers),
|
||||
obj.quorumPublicKey,
|
||||
obj.quorumVvecHash,
|
||||
obj.quorumSig,
|
||||
obj.membersSig
|
||||
);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -95,17 +95,16 @@ public:
|
||||
CDKGComplaint() = default;
|
||||
explicit CDKGComplaint(const Consensus::LLMQParams& params);
|
||||
|
||||
ADD_SERIALIZE_METHODS
|
||||
|
||||
template<typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
SERIALIZE_METHODS(CDKGComplaint, obj)
|
||||
{
|
||||
READWRITE(llmqType);
|
||||
READWRITE(quorumHash);
|
||||
READWRITE(proTxHash);
|
||||
READWRITE(DYNBITSET(badMembers));
|
||||
READWRITE(DYNBITSET(complainForMembers));
|
||||
READWRITE(sig);
|
||||
READWRITE(
|
||||
obj.llmqType,
|
||||
obj.quorumHash,
|
||||
obj.proTxHash,
|
||||
DYNBITSET(obj.badMembers),
|
||||
DYNBITSET(obj.complainForMembers),
|
||||
obj.sig
|
||||
);
|
||||
}
|
||||
|
||||
uint256 GetSignHash() const
|
||||
@ -174,19 +173,18 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
ADD_SERIALIZE_METHODS
|
||||
|
||||
template<typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
SERIALIZE_METHODS(CDKGPrematureCommitment, obj)
|
||||
{
|
||||
READWRITE(llmqType);
|
||||
READWRITE(quorumHash);
|
||||
READWRITE(proTxHash);
|
||||
READWRITE(DYNBITSET(validMembers));
|
||||
READWRITE(quorumPublicKey);
|
||||
READWRITE(quorumVvecHash);
|
||||
READWRITE(quorumSig);
|
||||
READWRITE(sig);
|
||||
READWRITE(
|
||||
obj.llmqType,
|
||||
obj.quorumHash,
|
||||
obj.proTxHash,
|
||||
DYNBITSET(obj.validMembers),
|
||||
obj.quorumPublicKey,
|
||||
obj.quorumVvecHash,
|
||||
obj.quorumSig,
|
||||
obj.sig
|
||||
);
|
||||
}
|
||||
|
||||
uint256 GetSignHash() const
|
||||
|
@ -98,16 +98,13 @@ public:
|
||||
std::vector<bool> inv;
|
||||
|
||||
public:
|
||||
ADD_SERIALIZE_METHODS
|
||||
|
||||
template<typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
SERIALIZE_METHODS(CSigSharesInv, obj)
|
||||
{
|
||||
uint64_t invSize = inv.size();
|
||||
|
||||
READWRITE(VARINT(sessionId));
|
||||
READWRITE(COMPACTSIZE(invSize));
|
||||
READWRITE(AUTOBITSET(inv, (size_t)invSize));
|
||||
uint64_t invSize = obj.inv.size();
|
||||
READWRITE(VARINT(obj.sessionId), COMPACTSIZE(invSize));
|
||||
autobitset_t bitset = std::make_pair(obj.inv, (size_t)invSize);
|
||||
READWRITE(AUTOBITSET(bitset));
|
||||
SER_READ(obj, obj.inv = bitset.first);
|
||||
}
|
||||
|
||||
void Init(size_t size);
|
||||
|
286
src/serialize.h
286
src/serialize.h
@ -439,6 +439,143 @@ I ReadVarInt(Stream& is)
|
||||
}
|
||||
}
|
||||
|
||||
/** TODO: describe FixedBitSet */
|
||||
inline unsigned int GetSizeOfFixedBitSet(size_t size)
|
||||
{
|
||||
return (size + 7) / 8;
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void WriteFixedBitSet(Stream& s, const std::vector<bool>& vec, size_t size)
|
||||
{
|
||||
std::vector<unsigned char> vBytes((size + 7) / 8);
|
||||
size_t ms = std::min(size, vec.size());
|
||||
for (size_t p = 0; p < ms; p++)
|
||||
vBytes[p / 8] |= vec[p] << (p % 8);
|
||||
s.write((char*)vBytes.data(), vBytes.size());
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void ReadFixedBitSet(Stream& s, std::vector<bool>& vec, size_t size)
|
||||
{
|
||||
vec.resize(size);
|
||||
|
||||
std::vector<unsigned char> vBytes((size + 7) / 8);
|
||||
s.read((char*)vBytes.data(), vBytes.size());
|
||||
for (size_t p = 0; p < size; p++)
|
||||
vec[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
|
||||
if (vBytes.size() * 8 != size) {
|
||||
size_t rem = vBytes.size() * 8 - size;
|
||||
uint8_t m = ~(uint8_t)(0xff >> rem);
|
||||
if (vBytes[vBytes.size() - 1] & m) {
|
||||
throw std::ios_base::failure("Out-of-range bits set");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a fixed size bitset as a series of VarInts. Each VarInt is an offset from the last entry and the sum of the
|
||||
* last entry and the offset gives an index into the bitset for a set bit. The series of VarInts ends with a 0.
|
||||
*/
|
||||
template<typename Stream>
|
||||
void WriteFixedVarIntsBitSet(Stream& s, const std::vector<bool>& vec, size_t size)
|
||||
{
|
||||
int32_t last = -1;
|
||||
for (int32_t i = 0; i < (int32_t)vec.size(); i++) {
|
||||
if (vec[i]) {
|
||||
WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, (uint32_t)(i - last));
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, 0); // stopper
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void ReadFixedVarIntsBitSet(Stream& s, std::vector<bool>& vec, size_t size)
|
||||
{
|
||||
vec.assign(size, false);
|
||||
|
||||
int32_t last = -1;
|
||||
while(true) {
|
||||
uint32_t offset = ReadVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s);
|
||||
if (offset == 0) {
|
||||
break;
|
||||
}
|
||||
int32_t idx = last + offset;
|
||||
if (idx >= size) {
|
||||
throw std::ios_base::failure("out of bounds index");
|
||||
}
|
||||
if (last != -1 && idx <= last) {
|
||||
throw std::ios_base::failure("offset overflow");
|
||||
}
|
||||
vec[idx] = true;
|
||||
last = idx;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes either as a CFixedBitSet or CFixedVarIntsBitSet, depending on which would give a smaller size
|
||||
*/
|
||||
typedef std::pair<std::vector<bool>, size_t> autobitset_t;
|
||||
|
||||
struct CFixedBitSet
|
||||
{
|
||||
const std::vector<bool>& vec;
|
||||
size_t size;
|
||||
CFixedBitSet(const std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const { WriteFixedBitSet(s, vec, size); }
|
||||
};
|
||||
|
||||
struct CFixedVarIntsBitSet
|
||||
{
|
||||
const std::vector<bool>& vec;
|
||||
size_t size;
|
||||
CFixedVarIntsBitSet(const std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const { WriteFixedVarIntsBitSet(s, vec, vec.size()); }
|
||||
};
|
||||
|
||||
template<typename Stream>
|
||||
void WriteAutoBitSet(Stream& s, const autobitset_t& item)
|
||||
{
|
||||
auto& vec = item.first;
|
||||
auto& size = item.second;
|
||||
|
||||
assert(vec.size() == size);
|
||||
|
||||
size_t size1 = ::GetSerializeSize(s, CFixedBitSet(vec, size));
|
||||
size_t size2 = ::GetSerializeSize(s, CFixedVarIntsBitSet(vec, size));
|
||||
|
||||
assert(size1 == GetSizeOfFixedBitSet(size));
|
||||
|
||||
if (size1 < size2) {
|
||||
ser_writedata8(s, 0);
|
||||
WriteFixedBitSet(s, vec, vec.size());
|
||||
} else {
|
||||
ser_writedata8(s, 1);
|
||||
WriteFixedVarIntsBitSet(s, vec, vec.size());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void ReadAutoBitSet(Stream& s, autobitset_t& item)
|
||||
{
|
||||
uint8_t isVarInts = ser_readdata8(s);
|
||||
if (isVarInts != 0 && isVarInts != 1) {
|
||||
throw std::ios_base::failure("invalid value for isVarInts byte");
|
||||
}
|
||||
|
||||
auto& vec = item.first;
|
||||
auto& size = item.second;
|
||||
|
||||
if (!isVarInts) {
|
||||
ReadFixedBitSet(s, vec, size);
|
||||
} else {
|
||||
ReadFixedVarIntsBitSet(s, vec, size);
|
||||
}
|
||||
}
|
||||
|
||||
/** Simple wrapper class to serialize objects using a formatter; used by Using(). */
|
||||
template<typename Formatter, typename T>
|
||||
class Wrapper
|
||||
@ -465,167 +602,44 @@ public:
|
||||
template<typename Formatter, typename T>
|
||||
static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
|
||||
|
||||
#define FIXEDBITSET(obj, size) CFixedBitSet(REF(obj), (size))
|
||||
#define DYNBITSET(obj) CDynamicBitSet(REF(obj))
|
||||
#define FIXEDVARINTSBITSET(obj, size) CFixedVarIntsBitSet(REF(obj), (size))
|
||||
#define AUTOBITSET(obj, size) CAutoBitSet(REF(obj), (size))
|
||||
#define DYNBITSET(obj) Using<DynamicBitSetFormatter>(obj)
|
||||
#define AUTOBITSET(obj) Using<AutoBitSetFormatter>(obj)
|
||||
#define VARINT(obj, ...) Using<VarIntFormatter<__VA_ARGS__>>(obj)
|
||||
#define COMPACTSIZE(obj) Using<CompactSizeFormatter>(obj)
|
||||
#define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
|
||||
|
||||
class CFixedBitSet
|
||||
/** TODO: describe DynamicBitSet */
|
||||
struct DynamicBitSetFormatter
|
||||
{
|
||||
protected:
|
||||
std::vector<bool>& vec;
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
CFixedBitSet(std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const
|
||||
{
|
||||
std::vector<unsigned char> vBytes((size + 7) / 8);
|
||||
size_t ms = std::min(size, vec.size());
|
||||
for (size_t p = 0; p < ms; p++)
|
||||
vBytes[p / 8] |= vec[p] << (p % 8);
|
||||
s.write((char*)vBytes.data(), vBytes.size());
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s)
|
||||
{
|
||||
vec.resize(size);
|
||||
|
||||
std::vector<unsigned char> vBytes((size + 7) / 8);
|
||||
s.read((char*)vBytes.data(), vBytes.size());
|
||||
for (size_t p = 0; p < size; p++)
|
||||
vec[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
|
||||
if (vBytes.size() * 8 != size) {
|
||||
size_t rem = vBytes.size() * 8 - size;
|
||||
uint8_t m = ~(uint8_t)(0xff >> rem);
|
||||
if (vBytes[vBytes.size() - 1] & m) {
|
||||
throw std::ios_base::failure("Out-of-range bits set");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CDynamicBitSet
|
||||
{
|
||||
protected:
|
||||
std::vector<bool>& vec;
|
||||
|
||||
public:
|
||||
explicit CDynamicBitSet(std::vector<bool>& vecIn) : vec(vecIn) {}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const
|
||||
void Ser(Stream& s, const std::vector<bool>& vec) const
|
||||
{
|
||||
WriteCompactSize(s, vec.size());
|
||||
CFixedBitSet(REF(vec), vec.size()).Serialize(s);
|
||||
WriteFixedBitSet(s, vec, vec.size());
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s)
|
||||
void Unser(Stream& s, std::vector<bool>& vec)
|
||||
{
|
||||
vec.resize(ReadCompactSize(s));
|
||||
CFixedBitSet(vec, vec.size()).Unserialize(s);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores a fixed size bitset as a series of VarInts. Each VarInt is an offset from the last entry and the sum of the
|
||||
* last entry and the offset gives an index into the bitset for a set bit. The series of VarInts ends with a 0.
|
||||
*/
|
||||
class CFixedVarIntsBitSet
|
||||
{
|
||||
protected:
|
||||
std::vector<bool>& vec;
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
CFixedVarIntsBitSet(std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const
|
||||
{
|
||||
int32_t last = -1;
|
||||
for (int32_t i = 0; i < (int32_t)vec.size(); i++) {
|
||||
if (vec[i]) {
|
||||
WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, (uint32_t)(i - last));
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, 0); // stopper
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s)
|
||||
{
|
||||
vec.assign(size, false);
|
||||
|
||||
int32_t last = -1;
|
||||
while(true) {
|
||||
uint32_t offset = ReadVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s);
|
||||
if (offset == 0) {
|
||||
break;
|
||||
}
|
||||
int32_t idx = last + offset;
|
||||
if (idx >= size) {
|
||||
throw std::ios_base::failure("out of bounds index");
|
||||
}
|
||||
if (last != -1 && idx <= last) {
|
||||
throw std::ios_base::failure("offset overflow");
|
||||
}
|
||||
vec[idx] = true;
|
||||
last = idx;
|
||||
}
|
||||
ReadFixedBitSet(s, vec, ReadCompactSize(s));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Serializes either as a CFixedBitSet or CFixedVarIntsBitSet, depending on which would give a smaller size
|
||||
*/
|
||||
class CAutoBitSet
|
||||
struct AutoBitSetFormatter
|
||||
{
|
||||
protected:
|
||||
std::vector<bool>& vec;
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
explicit CAutoBitSet(std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s) const
|
||||
void Ser(Stream& s, const autobitset_t& item) const
|
||||
{
|
||||
assert(vec.size() == size);
|
||||
|
||||
size_t size1 = ::GetSerializeSize(s, CFixedBitSet(vec, size));
|
||||
size_t size2 = ::GetSerializeSize(s, CFixedVarIntsBitSet(vec, size));
|
||||
|
||||
if (size1 < size2) {
|
||||
ser_writedata8(s, 0);
|
||||
s << FIXEDBITSET(vec, vec.size());
|
||||
} else {
|
||||
ser_writedata8(s, 1);
|
||||
s << FIXEDVARINTSBITSET(vec, vec.size());
|
||||
}
|
||||
WriteAutoBitSet(s, item);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s)
|
||||
void Unser(Stream& s, autobitset_t& item)
|
||||
{
|
||||
uint8_t isVarInts = ser_readdata8(s);
|
||||
if (isVarInts != 0 && isVarInts != 1) {
|
||||
throw std::ios_base::failure("invalid value for isVarInts byte");
|
||||
}
|
||||
|
||||
if (!isVarInts) {
|
||||
s >> FIXEDBITSET(vec, size);
|
||||
} else {
|
||||
s >> FIXEDVARINTSBITSET(vec, size);
|
||||
}
|
||||
ReadAutoBitSet(s, item);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user