Merge pull request #4180 from UdjinM6/pre_pr4025_serialization

Various serialization backports
This commit is contained in:
UdjinM6 2021-05-29 23:23:19 +03:00 committed by GitHub
commit b4b24d370c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 862 additions and 1138 deletions

View File

@ -262,6 +262,7 @@ BITCOIN_CORE_H = \
utilasmap.h \
utilmemory.h \
utilmoneystr.h \
utilstring.h \
utiltime.h \
validation.h \
validationinterface.h \
@ -587,6 +588,7 @@ libdash_util_a_SOURCES = \
utilmoneystr.cpp \
utilstrencodings.cpp \
utiltime.cpp \
utilstring.cpp \
$(BITCOIN_CORE_H)
if GLIBC_BACK_COMPAT

View File

@ -6,6 +6,8 @@
#include <hash.h>
#include <uint256.h>
#include <utilstrencodings.h>
#include <utilstring.h>
#include <assert.h>
#include <stdint.h>
@ -127,6 +129,9 @@ std::string EncodeBase58(const std::vector<unsigned char>& vch)
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
{
if (!ValidAsCString(str)) {
return false;
}
return DecodeBase58(str.c_str(), vchRet);
}
@ -158,6 +163,9 @@ bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
{
if (!ValidAsCString(str)) {
return false;
}
return DecodeBase58Check(str.c_str(), vchRet);
}

View File

@ -12,9 +12,7 @@
struct nontrivial_t {
int x;
nontrivial_t() :x(-1) {}
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {READWRITE(x);}
SERIALIZE_METHODS(nontrivial_t, obj) { READWRITE(obj.x); }
};
static_assert(!IS_TRIVIALLY_CONSTRUCTIBLE<nontrivial_t>::value,
"expected nontrivial_t to not be trivially constructible");

View File

@ -93,12 +93,13 @@ private:
friend class PartiallyDownloadedBlock;
static const int SHORTTXIDS_LENGTH = 6;
protected:
std::vector<uint64_t> shorttxids;
std::vector<PrefilledTransaction> prefilledtxn;
public:
static constexpr int SHORTTXIDS_LENGTH = 6;
CBlockHeader header;
// Dummy for deserialization

View File

@ -76,15 +76,7 @@ public:
CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn);
CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vData);
READWRITE(nHashFuncs);
READWRITE(nTweak);
READWRITE(nFlags);
}
SERIALIZE_METHODS(CBloomFilter, obj) { READWRITE(obj.vData, obj.nHashFuncs, obj.nTweak, obj.nFlags); }
void insert(const std::vector<unsigned char>& vKey);
void insert(const COutPoint& outpoint);

View File

@ -18,14 +18,9 @@ public:
uint256 GetIV(size_t idx) const;
public:
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CBLSIESEncryptedBlob, obj)
{
READWRITE(ephemeralPubKey);
READWRITE(ivSeed);
READWRITE(data);
READWRITE(obj.ephemeralPubKey, obj.ivSeed, obj.data);
}
public:
@ -98,14 +93,9 @@ public:
bool Decrypt(size_t idx, const CBLSSecretKey& sk, Blob& blobRet) const;
public:
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CBLSIESMultiRecipientBlobs, obj)
{
READWRITE(ephemeralPubKey);
READWRITE(ivSeed);
READWRITE(blobs);
READWRITE(obj.ephemeralPubKey, obj.ivSeed, obj.blobs);
}
};

View File

@ -28,13 +28,9 @@ struct CacheItem
K key;
V value;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CacheItem, obj)
{
READWRITE(key);
READWRITE(value);
READWRITE(obj.key, obj.value);
}
};
@ -154,16 +150,10 @@ public:
return *this;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CacheMap, obj)
{
READWRITE(nMaxSize);
READWRITE(listItems);
if(ser_action.ForRead()) {
RebuildIndex();
}
READWRITE(obj.nMaxSize, obj.listItems);
SER_READ(obj, obj.RebuildIndex());
}
private:

View File

@ -192,16 +192,10 @@ public:
return *this;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CacheMultiMap, obj)
{
READWRITE(nMaxSize);
READWRITE(listItems);
if(ser_action.ForRead()) {
RebuildIndex();
}
READWRITE(obj.nMaxSize, obj.listItems);
SER_READ(obj, obj.RebuildIndex());
}
private:

View File

@ -85,12 +85,9 @@ struct CDiskBlockPos
int nFile;
unsigned int nPos;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED));
READWRITE(VARINT(nPos));
SERIALIZE_METHODS(CDiskBlockPos, obj)
{
READWRITE(VARINT(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED), VARINT(obj.nPos));
}
CDiskBlockPos() {

View File

@ -96,18 +96,13 @@ public:
nStatusUpdate(nStatusUpdate),
nMessageID(nMessageID) {};
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CCoinJoinStatusUpdate, obj)
{
READWRITE(nSessionID);
READWRITE(nState);
READWRITE(obj.nSessionID, obj.nState);
if (s.GetVersion() <= 702015) {
READWRITE(nEntriesCount);
READWRITE(obj.nEntriesCount);
}
READWRITE(nStatusUpdate);
READWRITE(nMessageID);
READWRITE(obj.nStatusUpdate, obj.nMessageID);
}
};
@ -152,13 +147,9 @@ public:
nDenom(nDenom),
txCollateral(txCollateral){};
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CCoinJoinAccept, obj)
{
READWRITE(nDenom);
READWRITE(txCollateral);
READWRITE(obj.nDenom, obj.txCollateral);
}
friend bool operator==(const CCoinJoinAccept& a, const CCoinJoinAccept& b)
@ -193,14 +184,9 @@ public:
{
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CCoinJoinEntry, obj)
{
READWRITE(vecTxDSIn);
READWRITE(txCollateral);
READWRITE(vecTxOut);
READWRITE(obj.vecTxDSIn, obj.txCollateral, obj.vecTxOut);
}
bool AddScriptSig(const CTxIn& txin);
@ -241,17 +227,11 @@ public:
{
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CCoinJoinQueue, obj)
{
READWRITE(nDenom);
READWRITE(masternodeOutpoint);
READWRITE(nTime);
READWRITE(fReady);
READWRITE(obj.nDenom, obj.masternodeOutpoint, obj.nTime, obj.fReady);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchSig);
READWRITE(obj.vchSig);
}
}
@ -317,17 +297,13 @@ public:
{
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CCoinJoinBroadcastTx, obj)
{
READWRITE(tx);
READWRITE(masternodeOutpoint);
READWRITE(obj.tx, obj.masternodeOutpoint);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchSig);
READWRITE(obj.vchSig);
}
READWRITE(sigTime);
READWRITE(obj.sigTime);
}
friend bool operator==(const CCoinJoinBroadcastTx& a, const CCoinJoinBroadcastTx& b)

View File

@ -26,17 +26,12 @@ public:
uint256 merkleRootQuorums;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CCbTx, obj)
{
READWRITE(nVersion);
READWRITE(nHeight);
READWRITE(merkleRootMNList);
READWRITE(obj.nVersion, obj.nHeight, obj.merkleRootMNList);
if (nVersion >= 2) {
READWRITE(merkleRootQuorums);
if (obj.nVersion >= 2) {
READWRITE(obj.merkleRootQuorums);
}
}

View File

@ -68,25 +68,24 @@ public:
s >> *this;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CDeterministicMNState, obj)
{
READWRITE(nRegisteredHeight);
READWRITE(nLastPaidHeight);
READWRITE(nPoSePenalty);
READWRITE(nPoSeRevivedHeight);
READWRITE(nPoSeBanHeight);
READWRITE(nRevocationReason);
READWRITE(confirmedHash);
READWRITE(confirmedHashWithProRegTxHash);
READWRITE(keyIDOwner);
READWRITE(pubKeyOperator);
READWRITE(keyIDVoting);
READWRITE(addr);
READWRITE(scriptPayout);
READWRITE(scriptOperatorPayout);
READWRITE(
obj.nRegisteredHeight,
obj.nLastPaidHeight,
obj.nPoSePenalty,
obj.nPoSeRevivedHeight,
obj.nPoSeBanHeight,
obj.nRevocationReason,
obj.confirmedHash,
obj.confirmedHashWithProRegTxHash,
obj.keyIDOwner,
obj.pubKeyOperator,
obj.keyIDVoting,
obj.addr,
obj.scriptPayout,
obj.scriptOperatorPayout
);
}
void ResetOperatorFields()
@ -182,13 +181,10 @@ public:
#undef DMN_STATE_DIFF_LINE
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CDeterministicMNStateDiff, obj)
{
READWRITE(VARINT(fields));
#define DMN_STATE_DIFF_LINE(f) if (fields & Field_##f) READWRITE(state.f);
READWRITE(VARINT(obj.fields));
#define DMN_STATE_DIFF_LINE(f) if (obj.fields & Field_##f) READWRITE(obj.state.f);
DMN_STATE_DIFF_ALL_FIELDS
#undef DMN_STATE_DIFF_LINE
}
@ -247,7 +243,7 @@ public:
template<typename Stream>
void Serialize(Stream& s) const
{
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), false);
const_cast<CDeterministicMN*>(this)->SerializationOp(s, CSerActionSerialize(), false);
}
template<typename Stream>
@ -338,7 +334,7 @@ public:
template<typename Stream>
void Serialize(Stream& s) const
{
NCONST_PTR(this)->SerializationOpBase(s, CSerActionSerialize());
const_cast<CDeterministicMNList*>(this)->SerializationOpBase(s, CSerActionSerialize());
// Serialize the map as a vector
WriteCompactSize(s, mnMap.size());
for (const auto& p : mnMap) {

View File

@ -40,13 +40,9 @@ public:
CBLSSignature sig;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CMNAuth, obj)
{
READWRITE(proRegTxHash);
READWRITE(sig);
READWRITE(obj.proRegTxHash, obj.sig);
}
static void PushMNAUTH(CNode* pnode, CConnman& connman);

View File

@ -37,24 +37,23 @@ public:
std::vector<unsigned char> vchSig;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CProRegTx, obj)
{
READWRITE(nVersion);
READWRITE(nType);
READWRITE(nMode);
READWRITE(collateralOutpoint);
READWRITE(addr);
READWRITE(keyIDOwner);
READWRITE(pubKeyOperator);
READWRITE(keyIDVoting);
READWRITE(nOperatorReward);
READWRITE(scriptPayout);
READWRITE(inputsHash);
READWRITE(
obj.nVersion,
obj.nType,
obj.nMode,
obj.collateralOutpoint,
obj.addr,
obj.keyIDOwner,
obj.pubKeyOperator,
obj.keyIDVoting,
obj.nOperatorReward,
obj.scriptPayout,
obj.inputsHash
);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchSig);
READWRITE(obj.vchSig);
}
}
@ -100,18 +99,11 @@ public:
CBLSSignature sig;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CProUpServTx, obj)
{
READWRITE(nVersion);
READWRITE(proTxHash);
READWRITE(addr);
READWRITE(scriptOperatorPayout);
READWRITE(inputsHash);
READWRITE(obj.nVersion, obj.proTxHash, obj.addr, obj.scriptOperatorPayout, obj.inputsHash);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(sig);
READWRITE(obj.sig);
}
}
@ -149,20 +141,19 @@ public:
std::vector<unsigned char> vchSig;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CProUpRegTx, obj)
{
READWRITE(nVersion);
READWRITE(proTxHash);
READWRITE(nMode);
READWRITE(pubKeyOperator);
READWRITE(keyIDVoting);
READWRITE(scriptPayout);
READWRITE(inputsHash);
READWRITE(
obj.nVersion,
obj.proTxHash,
obj.nMode,
obj.pubKeyOperator,
obj.keyIDVoting,
obj.scriptPayout,
obj.inputsHash
);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchSig);
READWRITE(obj.vchSig);
}
}
@ -207,17 +198,11 @@ public:
CBLSSignature sig;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CProUpRevTx, obj)
{
READWRITE(nVersion);
READWRITE(proTxHash);
READWRITE(nReason);
READWRITE(inputsHash);
READWRITE(obj.nVersion, obj.proTxHash, obj.nReason, obj.inputsHash);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(sig);
READWRITE(obj.sig);
}
}

View File

@ -47,17 +47,16 @@ public:
}
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CSimplifiedMNListEntry, obj)
{
READWRITE(proRegTxHash);
READWRITE(confirmedHash);
READWRITE(service);
READWRITE(pubKeyOperator);
READWRITE(keyIDVoting);
READWRITE(isValid);
READWRITE(
obj.proRegTxHash,
obj.confirmedHash,
obj.service,
obj.pubKeyOperator,
obj.keyIDVoting,
obj.isValid
);
}
public:
@ -89,13 +88,9 @@ public:
uint256 blockHash;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CGetSimplifiedMNListDiff, obj)
{
READWRITE(baseBlockHash);
READWRITE(blockHash);
READWRITE(obj.baseBlockHash, obj.blockHash);
}
};
@ -114,21 +109,12 @@ public:
std::vector<llmq::CFinalCommitment> newQuorums;
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CSimplifiedMNListDiff, obj)
{
READWRITE(baseBlockHash);
READWRITE(blockHash);
READWRITE(cbTxMerkleTree);
READWRITE(cbTx);
READWRITE(deletedMNs);
READWRITE(mnList);
READWRITE(obj.baseBlockHash, obj.blockHash, obj.cbTxMerkleTree, obj.cbTx, obj.deletedMNs, obj.mnList);
if (s.GetVersion() >= LLMQS_PROTO_VERSION) {
READWRITE(deletedQuorums);
READWRITE(newQuorums);
READWRITE(obj.deletedQuorums, obj.newQuorums);
}
}

View File

@ -61,18 +61,12 @@ struct vote_instance_t {
{
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(vote_instance_t, obj)
{
int nOutcome = int(eOutcome);
READWRITE(nOutcome);
READWRITE(nTime);
READWRITE(nCreationTime);
if (ser_action.ForRead()) {
eOutcome = vote_outcome_enum_t(nOutcome);
}
int nOutcome;
SER_WRITE(obj, nOutcome = int(obj.eOutcome));
READWRITE(nOutcome, obj.nTime, obj.nCreationTime);
SER_READ(obj, obj.eOutcome = vote_outcome_enum_t(nOutcome));
}
};
@ -81,12 +75,9 @@ typedef std::map<int, vote_instance_t> vote_instance_m_t;
struct vote_rec_t {
vote_instance_m_t mapInstances;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(vote_rec_t, obj)
{
READWRITE(mapInstances);
READWRITE(obj.mapInstances);
}
};
@ -292,30 +283,26 @@ public:
// SERIALIZER
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CGovernanceObject, obj)
{
// SERIALIZE DATA FOR SAVING/LOADING OR NETWORK FUNCTIONS
READWRITE(nHashParent);
READWRITE(nRevision);
READWRITE(nTime);
READWRITE(nCollateralHash);
READWRITE(vchData);
READWRITE(nObjectType);
READWRITE(masternodeOutpoint);
READWRITE(
obj.nHashParent,
obj.nRevision,
obj.nTime,
obj.nCollateralHash,
obj.vchData,
obj.nObjectType,
obj.masternodeOutpoint
);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchSig);
READWRITE(obj.vchSig);
}
if (s.GetType() & SER_DISK) {
// Only include these for the disk file format
LogPrint(BCLog::GOBJECT, "CGovernanceObject::SerializationOp Reading/writing votes from/to disk\n");
READWRITE(nDeletionTime);
READWRITE(fExpired);
READWRITE(mapCurrentMNVotes);
READWRITE(fileVotes);
LogPrint(BCLog::GOBJECT, "CGovernanceObject::SerializationOp hash = %s, vote count = %d\n", GetHash().ToString(), fileVotes.GetVoteCount());
READWRITE(obj.nDeletionTime, obj.fExpired, obj.mapCurrentMNVotes, obj.fileVotes);
LogPrint(BCLog::GOBJECT, "CGovernanceObject::SerializationOp hash = %s, vote count = %d\n", obj.GetHash().ToString(), obj.fileVotes.GetVoteCount());
}
// AFTER DESERIALIZATION OCCURS, CACHED VARIABLES MUST BE CALCULATED MANUALLY

View File

@ -117,21 +117,13 @@ public:
std::string ToString() const;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CGovernanceVote, obj)
{
READWRITE(masternodeOutpoint);
READWRITE(nParentHash);
READWRITE(nVoteOutcome);
READWRITE(nVoteSignal);
READWRITE(nTime);
READWRITE(obj.masternodeOutpoint, obj.nParentHash, obj.nVoteOutcome, obj.nVoteSignal, obj.nTime);
if (!(s.GetType() & SER_GETHASH)) {
READWRITE(vchSig);
READWRITE(obj.vchSig);
}
if (ser_action.ForRead())
UpdateHash();
SER_READ(obj, obj.UpdateHash());
}
};

View File

@ -65,16 +65,10 @@ public:
void RemoveVotesFromMasternode(const COutPoint& outpointMasternode);
std::set<uint256> RemoveInvalidVotes(const COutPoint& outpointMasternode, bool fProposal);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CGovernanceObjectVoteFile, obj)
{
READWRITE(nMemoryVotes);
READWRITE(listVotes);
if (ser_action.ForRead()) {
RebuildIndex();
}
READWRITE(obj.nMemoryVotes, obj.listVotes);
SER_READ(obj, obj.RebuildIndex());
}
private:

View File

@ -114,15 +114,9 @@ public:
return double(nCount) / double(nMax - nMin);
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CRateCheckBuffer, obj)
{
READWRITE(vecTimestamps);
READWRITE(nDataStart);
READWRITE(nDataEnd);
READWRITE(fBufferEmpty);
READWRITE(obj.vecTimestamps, obj.nDataStart, obj.nDataEnd, obj.fBufferEmpty);
}
};
@ -141,13 +135,9 @@ public: // Types
{
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(last_object_rec, obj)
{
READWRITE(triggerBuffer);
READWRITE(fStatusOK);
READWRITE(obj.triggerBuffer, obj.fStatusOK);
}
CRateCheckBuffer triggerBuffer;
@ -274,30 +264,37 @@ public:
std::string ToString() const;
UniValue ToJson() const;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
template<typename Stream>
void Serialize(Stream &s) const
{
LOCK(cs);
s << SERIALIZATION_VERSION_STRING
<< mapErasedGovernanceObjects
<< cmapInvalidVotes
<< cmmapOrphanVotes
<< mapObjects
<< mapLastMasternodeObject
<< *lastMNListForVotingKeys;
}
template<typename Stream>
void Unserialize(Stream &s)
{
LOCK(cs);
Clear();
std::string strVersion;
if (ser_action.ForRead()) {
Clear();
READWRITE(strVersion);
if (strVersion != SERIALIZATION_VERSION_STRING) {
return;
}
} else {
strVersion = SERIALIZATION_VERSION_STRING;
READWRITE(strVersion);
s >> strVersion;
if (strVersion != SERIALIZATION_VERSION_STRING) {
return;
}
READWRITE(mapErasedGovernanceObjects);
READWRITE(cmapInvalidVotes);
READWRITE(cmmapOrphanVotes);
READWRITE(mapObjects);
READWRITE(mapLastMasternodeObject);
READWRITE(*lastMNListForVotingKeys);
s >> mapErasedGovernanceObjects
>> cmapInvalidVotes
>> cmmapOrphanVotes
>> mapObjects
>> mapLastMasternodeObject
>> *lastMNListForVotingKeys;
}
void UpdatedBlockTip(const CBlockIndex* pindex, CConnman& connman);

View File

@ -15,12 +15,9 @@ public:
CHDAccount() : nExternalChainCounter(0), nInternalChainCounter(0) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CHDAccount, obj)
{
READWRITE(nExternalChainCounter);
READWRITE(nInternalChainCounter);
READWRITE(obj.nExternalChainCounter, obj.nInternalChainCounter);
}
};
@ -56,18 +53,18 @@ public:
mapAccounts(other.mapAccounts)
{}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CHDChain, obj)
{
LOCK(cs);
READWRITE(this->nVersion);
READWRITE(id);
READWRITE(fCrypted);
READWRITE(vchSeed);
READWRITE(vchMnemonic);
READWRITE(vchMnemonicPassphrase);
READWRITE(mapAccounts);
LOCK(obj.cs);
READWRITE(
obj.nVersion,
obj.id,
obj.fCrypted,
obj.vchSeed,
obj.vchMnemonic,
obj.vchMnemonicPassphrase,
obj.mapAccounts
);
}
void swap(CHDChain& first, CHDChain& second) // nothrow
@ -133,15 +130,9 @@ public:
CHDPubKey() : nVersion(CHDPubKey::CURRENT_VERSION), nAccountIndex(0), nChangeIndex(0) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CHDPubKey, obj)
{
READWRITE(this->nVersion);
READWRITE(extPubKey);
READWRITE(hdchainID);
READWRITE(nAccountIndex);
READWRITE(nChangeIndex);
READWRITE(obj.nVersion, obj.extPubKey, obj.hdchainID, obj.nAccountIndex, obj.nChangeIndex);
}
std::string GetKeyPath() const;

View File

@ -79,23 +79,19 @@ public:
nTime(GetTime()),
fProcessed(false) {}
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CQuorumDataRequest, obj)
{
READWRITE(llmqType);
READWRITE(quorumHash);
READWRITE(nDataMask);
READWRITE(proTxHash);
if (ser_action.ForRead()) {
bool fRead{false};
SER_READ(obj, fRead = true);
READWRITE(obj.llmqType, obj.quorumHash, obj.nDataMask, obj.proTxHash);
if (fRead) {
try {
READWRITE(nError);
READWRITE(obj.nError);
} catch (...) {
nError = UNDEFINED;
SER_READ(obj, obj.nError = UNDEFINED);
}
} else if (nError != UNDEFINED) {
READWRITE(nError);
} else if (obj.nError != UNDEFINED) {
READWRITE(obj.nError);
}
}

View File

@ -31,14 +31,9 @@ public:
CBLSSignature sig;
public:
ADD_SERIALIZE_METHODS
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CChainLockSig, obj)
{
READWRITE(nHeight);
READWRITE(blockHash);
READWRITE(sig);
READWRITE(obj.nHeight, obj.blockHash, obj.sig);
}
bool IsNull() const;

View File

@ -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:
@ -115,14 +114,9 @@ public:
CFinalCommitment commitment;
public:
ADD_SERIALIZE_METHODS
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CFinalCommitmentTxPayload, obj)
{
READWRITE(nVersion);
READWRITE(nHeight);
READWRITE(commitment);
READWRITE(obj.nVersion, obj.nHeight, obj.commitment);
}
void ToJson(UniValue& obj) const

View File

@ -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
@ -126,16 +125,9 @@ public:
CBLSSignature sig;
public:
ADD_SERIALIZE_METHODS
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CDKGJustification, obj)
{
READWRITE(llmqType);
READWRITE(quorumHash);
READWRITE(proTxHash);
READWRITE(contributions);
READWRITE(sig);
READWRITE(obj.llmqType, obj.quorumHash, obj.proTxHash, obj.contributions, obj.sig);
}
uint256 GetSignHash() const
@ -174,19 +166,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

View File

@ -26,14 +26,9 @@ public:
CBLSLazySignature sig;
public:
ADD_SERIALIZE_METHODS
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CInstantSendLock, obj)
{
READWRITE(inputs);
READWRITE(txid);
READWRITE(sig);
READWRITE(obj.inputs, obj.txid, obj.sig);
}
uint256 GetRequestId() const;

View File

@ -46,19 +46,10 @@ public:
public:
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CRecoveredSig, obj)
{
READWRITE(llmqType);
READWRITE(quorumHash);
READWRITE(id);
READWRITE(msgHash);
READWRITE(sig);
if (ser_action.ForRead()) {
UpdateHash();
}
READWRITE(obj.llmqType, obj.quorumHash, obj.id, obj.msgHash, obj.sig);
SER_READ(obj, obj.UpdateHash());
}
void UpdateHash()

View File

@ -48,20 +48,10 @@ public:
return key.first;
}
ADD_SERIALIZE_METHODS
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(llmqType);
READWRITE(quorumHash);
READWRITE(quorumMember);
READWRITE(id);
READWRITE(msgHash);
READWRITE(sigShare);
if (ser_action.ForRead()) {
UpdateKey();
}
SERIALIZE_METHODS(CSigShare, obj)
{
READWRITE(obj.llmqType, obj.quorumHash, obj.quorumMember, obj.id, obj.msgHash, obj.sigShare);
SER_READ(obj, obj.UpdateKey());
}
};
@ -77,15 +67,9 @@ public:
uint256 id;
uint256 msgHash;
ADD_SERIALIZE_METHODS
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(VARINT(sessionId));
READWRITE(llmqType);
READWRITE(quorumHash);
READWRITE(id);
READWRITE(msgHash);
SERIALIZE_METHODS(CSigSesAnn, obj)
{
READWRITE(VARINT(obj.sessionId), obj.llmqType, obj.quorumHash, obj.id, obj.msgHash);
}
std::string ToString() const;
@ -98,16 +82,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);
@ -128,13 +109,9 @@ public:
std::vector<std::pair<uint16_t, CBLSLazySignature>> sigShares;
public:
ADD_SERIALIZE_METHODS;
template<typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CBatchedSigShares, obj)
{
READWRITE(VARINT(sessionId));
READWRITE(sigShares);
READWRITE(VARINT(obj.sessionId), obj.sigShares);
}
std::string ToInvString() const;

View File

@ -50,17 +50,17 @@ public:
{
}
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CMasternodeMetaInfo, obj)
{
LOCK(cs);
READWRITE(proTxHash);
READWRITE(nLastDsq);
READWRITE(nMixingTxCount);
READWRITE(mapGovernanceObjectsVotedOn);
READWRITE(lastOutboundAttempt);
READWRITE(lastOutboundSuccess);
LOCK(obj.cs);
READWRITE(
obj.proTxHash,
obj.nLastDsq,
obj.nMixingTxCount,
obj.mapGovernanceObjectsVotedOn,
obj.lastOutboundAttempt,
obj.lastOutboundSuccess
);
}
UniValue ToJson() const;
@ -89,7 +89,7 @@ class CMasternodeMetaMan
private:
static const std::string SERIALIZATION_VERSION_STRING;
CCriticalSection cs;
mutable CCriticalSection cs;
std::map<uint256, CMasternodeMetaInfoPtr> metaInfos;
std::vector<uint256> vecDirtyGovernanceObjectHashes;
@ -98,41 +98,33 @@ private:
int64_t nDsqCount = 0;
public:
ADD_SERIALIZE_METHODS
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
template<typename Stream>
void Serialize(Stream &s) const
{
LOCK(cs);
std::string strVersion;
if(ser_action.ForRead()) {
Clear();
READWRITE(strVersion);
if (strVersion != SERIALIZATION_VERSION_STRING) {
return;
}
}
else {
strVersion = SERIALIZATION_VERSION_STRING;
READWRITE(strVersion);
}
std::vector<CMasternodeMetaInfo> tmpMetaInfo;
if (ser_action.ForRead()) {
READWRITE(tmpMetaInfo);
metaInfos.clear();
for (auto& mm : tmpMetaInfo) {
metaInfos.emplace(mm.GetProTxHash(), std::make_shared<CMasternodeMetaInfo>(std::move(mm)));
}
} else {
for (auto& p : metaInfos) {
tmpMetaInfo.emplace_back(*p.second);
}
READWRITE(tmpMetaInfo);
for (auto& p : metaInfos) {
tmpMetaInfo.emplace_back(*p.second);
}
s << SERIALIZATION_VERSION_STRING << tmpMetaInfo << nDsqCount;
}
READWRITE(nDsqCount);
template<typename Stream>
void Unserialize(Stream &s)
{
LOCK(cs);
Clear();
std::string strVersion;
s >> strVersion;
if (strVersion != SERIALIZATION_VERSION_STRING) {
return;
}
std::vector<CMasternodeMetaInfo> tmpMetaInfo;
s >> tmpMetaInfo >> nDsqCount;
metaInfos.clear();
for (auto& mm : tmpMetaInfo) {
metaInfos.emplace(mm.GetProTxHash(), std::make_shared<CMasternodeMetaInfo>(std::move(mm)));
}
}
public:

View File

@ -10,6 +10,24 @@
#include <utilstrencodings.h>
std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits)
{
std::vector<unsigned char> ret((bits.size() + 7) / 8);
for (unsigned int p = 0; p < bits.size(); p++) {
ret[p / 8] |= bits[p] << (p % 8);
}
return ret;
}
std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes)
{
std::vector<bool> ret(bytes.size() * 8);
for (unsigned int p = 0; p < ret.size(); p++) {
ret[p] = (bytes[p / 8] & (1 << (p % 8))) != 0;
}
return ret;
}
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids)
{
header = block.GetBlockHeader();

View File

@ -13,6 +13,10 @@
#include <vector>
// Helper functions for serialization.
std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits);
std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes);
/** Data structure that represents a partial merkle tree.
*
* It represents a subset of the txid's of a known block, in a way that
@ -81,27 +85,14 @@ protected:
public:
/** serialization implementation */
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nTransactions);
READWRITE(vHash);
std::vector<unsigned char> vBytes;
if (ser_action.ForRead()) {
READWRITE(vBytes);
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
us.vBits.resize(vBytes.size() * 8);
for (unsigned int p = 0; p < us.vBits.size(); p++)
us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
us.fBad = false;
} else {
vBytes.resize((vBits.size()+7)/8);
for (unsigned int p = 0; p < vBits.size(); p++)
vBytes[p / 8] |= vBits[p] << (p % 8);
READWRITE(vBytes);
}
SERIALIZE_METHODS(CPartialMerkleTree, obj)
{
READWRITE(obj.nTransactions, obj.vHash);
std::vector<unsigned char> bytes;
SER_WRITE(obj, bytes = BitsToBytes(obj.vBits));
READWRITE(bytes);
SER_READ(obj, obj.vBits = BytesToBits(bytes));
SER_READ(obj, obj.fBad = false);
}
/** Construct a partial merkle tree from a list of transaction ids, and a mask that selects a subset of them */
@ -157,13 +148,7 @@ public:
CMerkleBlock() {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(header);
READWRITE(txn);
}
SERIALIZE_METHODS(CMerkleBlock, obj) { READWRITE(obj.header, obj.txn); }
private:
// Combined constructor to consolidate code

View File

@ -316,14 +316,7 @@ class CSubNet
friend bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a == b); }
friend bool operator<(const CSubNet& a, const CSubNet& b);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(network);
READWRITE(netmask);
READWRITE(valid);
}
SERIALIZE_METHODS(CSubNet, obj) { READWRITE(obj.network, obj.netmask, obj.valid); }
};
/** A combination of a network address (CNetAddr) and a (TCP) port */
@ -352,24 +345,10 @@ class CService : public CNetAddr
CService(const struct in6_addr& ipv6Addr, unsigned short port);
explicit CService(const struct sockaddr_in6& addr);
/**
* Serialize to a stream.
*/
template <typename Stream>
void Serialize(Stream& s) const
SERIALIZE_METHODS(CService, obj)
{
SerializeV1Stream(s);
s << WrapBigEndian(port);
}
/**
* Unserialize from a stream.
*/
template <typename Stream>
void Unserialize(Stream& s)
{
UnserializeV1Stream(s);
s >> WrapBigEndian(port);
READWRITEAS(CNetAddr, obj);
READWRITE(Using<BigEndianFormatter<2>>(obj.port));
}
};

View File

@ -22,19 +22,17 @@ private:
//keep track of what node has/was asked for and when
fulfilledreqmap_t mapFulfilledRequests;
CCriticalSection cs_mapFulfilledRequests;
mutable CCriticalSection cs_mapFulfilledRequests;
void RemoveFulfilledRequest(const CService& addr, const std::string& strRequest);
public:
CNetFulfilledRequestManager() {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
LOCK(cs_mapFulfilledRequests);
READWRITE(mapFulfilledRequests);
SERIALIZE_METHODS(CNetFulfilledRequestManager, obj)
{
LOCK(obj.cs_mapFulfilledRequests);
READWRITE(obj.mapFulfilledRequests);
}
void AddFulfilledRequest(const CService& addr, const std::string& strRequest);

View File

@ -48,12 +48,7 @@ public:
CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
std::string ToString() const;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nSatoshisPerK);
}
SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); }
};
#endif // BITCOIN_POLICY_FEERATE_H

View File

@ -33,17 +33,7 @@ public:
SetNull();
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
}
SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
void SetNull()
{
@ -89,12 +79,10 @@ public:
*(static_cast<CBlockHeader*>(this)) = header;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITEAS(CBlockHeader, *this);
READWRITE(vtx);
SERIALIZE_METHODS(CBlock, obj)
{
READWRITEAS(CBlockHeader, obj);
READWRITE(obj.vtx);
}
void SetNull()
@ -132,14 +120,12 @@ struct CBlockLocator
explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
SERIALIZE_METHODS(CBlockLocator, obj)
{
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vHave);
READWRITE(obj.vHave);
}
void SetNull()

View File

@ -32,13 +32,7 @@ public:
COutPoint(): n((uint32_t) -1) { }
COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(hash);
READWRITE(n);
}
SERIALIZE_METHODS(COutPoint, obj) { READWRITE(obj.hash, obj.n); }
void SetNull() { hash.SetNull(); n = (uint32_t) -1; }
bool IsNull() const { return (hash.IsNull() && n == (uint32_t) -1); }
@ -109,14 +103,7 @@ public:
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(prevout);
READWRITE(scriptSig);
READWRITE(nSequence);
}
SERIALIZE_METHODS(CTxIn, obj) { READWRITE(obj.prevout, obj.scriptSig, obj.nSequence); }
friend bool operator==(const CTxIn& a, const CTxIn& b)
{
@ -154,13 +141,7 @@ public:
CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nValue);
READWRITE(scriptPubKey);
}
SERIALIZE_METHODS(CTxOut, obj) { READWRITE(obj.nValue, obj.scriptPubKey); }
void SetNull()
{
@ -297,21 +278,16 @@ struct CMutableTransaction
CMutableTransaction();
CMutableTransaction(const CTransaction& tx);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
int32_t n32bitVersion = this->nVersion | (this->nType << 16);
SERIALIZE_METHODS(CMutableTransaction, obj)
{
int32_t n32bitVersion;
SER_WRITE(obj, n32bitVersion = obj.nVersion | (obj.nType << 16));
READWRITE(n32bitVersion);
if (ser_action.ForRead()) {
this->nVersion = (int16_t) (n32bitVersion & 0xffff);
this->nType = (int16_t) ((n32bitVersion >> 16) & 0xffff);
}
READWRITE(vin);
READWRITE(vout);
READWRITE(nLockTime);
if (this->nVersion == 3 && this->nType != TRANSACTION_NORMAL) {
READWRITE(vExtraPayload);
SER_READ(obj, obj.nVersion = (int16_t) (n32bitVersion & 0xffff));
SER_READ(obj, obj.nType = (int16_t) ((n32bitVersion >> 16) & 0xffff));
READWRITE(obj.vin, obj.vout, obj.nLockTime);
if (obj.nVersion == 3 && obj.nType != TRANSACTION_NORMAL) {
READWRITE(obj.vExtraPayload);
}
}

View File

@ -43,16 +43,7 @@ public:
std::string GetCommand() const;
bool IsValid(const MessageStartChars& messageStart) const;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(pchMessageStart);
READWRITE(pchCommand);
READWRITE(nMessageSize);
READWRITE(pchChecksum);
}
SERIALIZE_METHODS(CMessageHeader, obj) { READWRITE(obj.pchMessageStart, obj.pchCommand, obj.nMessageSize, obj.pchChecksum); }
char pchMessageStart[MESSAGE_START_SIZE];
char pchCommand[COMMAND_SIZE];
@ -365,23 +356,19 @@ public:
void Init();
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CAddress, obj)
{
if (ser_action.ForRead())
Init();
SER_READ(obj, obj.Init());
int nVersion = s.GetVersion();
if (s.GetType() & SER_DISK)
if (s.GetType() & SER_DISK) {
READWRITE(nVersion);
}
if ((s.GetType() & SER_DISK) ||
(nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH)))
READWRITE(nTime);
uint64_t nServicesInt = nServices;
READWRITE(nServicesInt);
nServices = static_cast<ServiceFlags>(nServicesInt);
READWRITEAS(CService, *this);
(nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) {
READWRITE(obj.nTime);
}
READWRITE(Using<CustomUintFormatter<8>>(obj.nServices));
READWRITEAS(CService, obj);
}
// TODO: make private (improves encapsulation)
@ -434,14 +421,7 @@ public:
CInv();
CInv(int typeIn, const uint256& hashIn);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(type);
READWRITE(hash);
}
SERIALIZE_METHODS(CInv, obj) { READWRITE(obj.type, obj.hash); }
friend bool operator<(const CInv& a, const CInv& b);

View File

@ -22,19 +22,11 @@ public:
QDateTime date;
SendCoinsRecipient recipient;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
unsigned int nDate = date.toTime_t();
READWRITE(this->nVersion);
READWRITE(id);
READWRITE(nDate);
READWRITE(recipient);
if (ser_action.ForRead())
date = QDateTime::fromTime_t(nDate);
SERIALIZE_METHODS(RecentRequestEntry, obj) {
unsigned int date_timet;
SER_WRITE(obj, date_timet = obj.date.toTime_t());
READWRITE(obj.nVersion, obj.id, date_timet, obj.recipient);
SER_READ(obj, obj.date = QDateTime::fromTime_t(date_timet));
}
};

View File

@ -70,34 +70,28 @@ public:
static const int CURRENT_VERSION = 1;
int nVersion;
ADD_SERIALIZE_METHODS;
SERIALIZE_METHODS(SendCoinsRecipient, obj)
{
std::string address_str, label_str, message_str, auth_merchant_str, sPaymentRequest;
PaymentRequestPlus paymentRequest;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
std::string sAddress = address.toStdString();
std::string sLabel = label.toStdString();
std::string sMessage = message.toStdString();
std::string sPaymentRequest;
if (!ser_action.ForRead() && paymentRequest.IsInitialized())
SER_WRITE(obj, address_str = obj.address.toStdString());
SER_WRITE(obj, label_str = obj.label.toStdString());
SER_WRITE(obj, message_str = obj.message.toStdString());
SER_WRITE(obj, auth_merchant_str = obj.authenticatedMerchant.toStdString());
SER_WRITE(obj, paymentRequest = obj.paymentRequest);
if (paymentRequest.IsInitialized()) {
paymentRequest.SerializeToString(&sPaymentRequest);
std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString();
}
READWRITE(this->nVersion);
READWRITE(sAddress);
READWRITE(sLabel);
READWRITE(amount);
READWRITE(sMessage);
READWRITE(sPaymentRequest);
READWRITE(sAuthenticatedMerchant);
READWRITE(obj.nVersion, address_str, label_str, obj.amount, message_str, sPaymentRequest, auth_merchant_str);
if (ser_action.ForRead())
{
address = QString::fromStdString(sAddress);
label = QString::fromStdString(sLabel);
message = QString::fromStdString(sMessage);
if (!sPaymentRequest.empty())
paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
SER_READ(obj, obj.address = QString::fromStdString(address_str));
SER_READ(obj, obj.label = QString::fromStdString(label_str));
SER_READ(obj, obj.message = QString::fromStdString(message_str));
SER_READ(obj, obj.authenticatedMerchant = QString::fromStdString(auth_merchant_str));
if (!sPaymentRequest.empty()) {
SER_READ(obj, obj.paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size())));
}
}
};

View File

@ -46,18 +46,13 @@ struct CCoin {
uint32_t nHeight;
CTxOut out;
ADD_SERIALIZE_METHODS;
CCoin() : nHeight(0) {}
explicit CCoin(Coin&& in) : nHeight(in.nHeight), out(std::move(in.out)) {}
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(CCoin, obj)
{
uint32_t nTxVerDummy = 0;
READWRITE(nTxVerDummy);
READWRITE(nHeight);
READWRITE(out);
READWRITE(nTxVerDummy, obj.nHeight, obj.out);
}
};

View File

@ -414,12 +414,7 @@ public:
CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { }
CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { }
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITEAS(CScriptBase, *this);
}
SERIALIZE_METHODS(CScript, obj) { READWRITEAS(CScriptBase, obj); }
CScript& operator+=(const CScript& b)
{

View File

@ -46,26 +46,6 @@ static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
struct deserialize_type {};
constexpr deserialize_type deserialize {};
/**
* Used to bypass the rule against non-const reference to temporary
* where it makes sense with wrappers.
*/
template<typename T>
inline T& REF(const T& val)
{
return const_cast<T&>(val);
}
/**
* Used to acquire a non-const pointer "this" to generate bodies
* of const serialization operations from a template
*/
template<typename T>
inline T* NCONST_PTR(const T* val)
{
return const_cast<T*>(val);
}
//! Safely convert odd char pointer types to standard ones.
inline char* CharCast(char* c) { return c; }
inline char* CharCast(unsigned char* c) { return (char*)c; }
@ -189,22 +169,8 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
/**
* Implement three methods for serializable objects. These are actually wrappers over
* "SerializationOp" template, which implements the body of each class' serialization
* code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
* added as members.
*/
#define ADD_SERIALIZE_METHODS \
template<typename Stream> \
void Serialize(Stream& s) const { \
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
} \
template<typename Stream> \
void Unserialize(Stream& s) { \
SerializationOp(s, CSerActionUnserialize()); \
}
#define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
#define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
/**
* Implement the Ser and Unser methods needed for implementing a formatter (see Using below).
@ -473,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
@ -499,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) LimitedString< n >(REF(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);
}
};
@ -678,7 +658,16 @@ struct VarIntFormatter
}
};
template<int Bytes>
/** Serialization wrapper class for custom integers and enums.
*
* It permits specifying the serialized size (1 to 8 bytes) and endianness.
*
* Use the big endian mode for values that are stored in memory in native
* byte order, but serialized in big endian notation. This is only intended
* to implement serializers that are compatible with existing formats, and
* its use is not recommended for new data structures.
*/
template<int Bytes, bool BigEndian = false>
struct CustomUintFormatter
{
static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
@ -687,52 +676,31 @@ struct CustomUintFormatter
template <typename Stream, typename I> void Ser(Stream& s, I v)
{
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
uint64_t raw = htole64(v);
s.write((const char*)&raw, Bytes);
if (BigEndian) {
uint64_t raw = htobe64(v);
s.write(((const char*)&raw) + 8 - Bytes, Bytes);
} else {
uint64_t raw = htole64(v);
s.write((const char*)&raw, Bytes);
}
}
template <typename Stream, typename I> void Unser(Stream& s, I& v)
{
static_assert(std::numeric_limits<I>::max() >= MAX && std::numeric_limits<I>::min() <= 0, "CustomUintFormatter type too small");
using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
uint64_t raw = 0;
s.read((char*)&raw, Bytes);
v = le64toh(raw);
if (BigEndian) {
s.read(((char*)&raw) + 8 - Bytes, Bytes);
v = static_cast<I>(be64toh(raw));
} else {
s.read((char*)&raw, Bytes);
v = static_cast<I>(le64toh(raw));
}
}
};
/** Serialization wrapper class for big-endian integers.
*
* Use this wrapper around integer types that are stored in memory in native
* byte order, but serialized in big endian notation. This is only intended
* to implement serializers that are compatible with existing formats, and
* its use is not recommended for new data structures.
*
* Only 16-bit types are supported for now.
*/
template<typename I>
class BigEndian
{
protected:
I& m_val;
public:
explicit BigEndian(I& val) : m_val(val)
{
static_assert(std::is_unsigned<I>::value, "BigEndian type must be unsigned integer");
static_assert(sizeof(I) == 2 && std::numeric_limits<I>::min() == 0 && std::numeric_limits<I>::max() == std::numeric_limits<uint16_t>::max(), "Unsupported BigEndian size");
}
template<typename Stream>
void Serialize(Stream& s) const
{
ser_writedata16be(s, m_val);
}
template<typename Stream>
void Unserialize(Stream& s)
{
m_val = ser_readdata16be(s);
}
};
template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
/** Formatter for integers in CompactSize format. */
struct CompactSizeFormatter
@ -758,37 +726,26 @@ struct CompactSizeFormatter
};
template<size_t Limit>
class LimitedString
struct LimitedStringFormatter
{
protected:
std::string& string;
public:
explicit LimitedString(std::string& _string) : string(_string) {}
template<typename Stream>
void Unserialize(Stream& s)
void Unser(Stream& s, std::string& v)
{
size_t size = ReadCompactSize(s);
if (size > Limit) {
throw std::ios_base::failure("String length limit exceeded");
}
string.resize(size);
if (size != 0)
s.read((char*)string.data(), size);
v.resize(size);
if (size != 0) s.read((char*)v.data(), size);
}
template<typename Stream>
void Serialize(Stream& s) const
void Ser(Stream& s, const std::string& v)
{
WriteCompactSize(s, string.size());
if (!string.empty())
s.write((char*)string.data(), string.size());
s << v;
}
};
template<typename I>
BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); }
/** Formatter to serialize/deserialize vector elements using another formatter
*
* Example:
@ -1343,7 +1300,7 @@ void Unserialize(Stream& is, std::shared_ptr<T>& p)
/**
* Support for ADD_SERIALIZE_METHODS and READWRITE macro
* Support for SERIALIZE_METHODS and READWRITE macro.
*/
struct CSerActionSerialize
{
@ -1444,6 +1401,28 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&&
::UnserializeMany(s, args...);
}
template<typename Stream, typename Type, typename Fn>
inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&)
{
}
template<typename Stream, typename Type, typename Fn>
inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn)
{
fn(s, std::forward<Type>(obj));
}
template<typename Stream, typename Type, typename Fn>
inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn)
{
fn(s, std::forward<Type>(obj));
}
template<typename Stream, typename Type, typename Fn>
inline void SerWrite(Stream& s, CSerActionUnserialize ser_action, Type&&, Fn&&)
{
}
template<typename I>
inline void WriteVarInt(CSizeComputer &s, I n)
{

View File

@ -15,12 +15,9 @@ struct CSpentIndexKey {
uint256 txid;
unsigned int outputIndex;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(txid);
READWRITE(outputIndex);
SERIALIZE_METHODS(CSpentIndexKey, obj)
{
READWRITE(obj.txid, obj.outputIndex);
}
CSpentIndexKey(uint256 t, unsigned int i) {
@ -47,16 +44,9 @@ struct CSpentIndexValue {
int addressType;
uint160 addressHash;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(txid);
READWRITE(inputIndex);
READWRITE(blockHeight);
READWRITE(satoshis);
READWRITE(addressType);
READWRITE(addressHash);
SERIALIZE_METHODS(CSpentIndexValue, obj)
{
READWRITE(obj.txid, obj.inputIndex, obj.blockHeight, obj.satoshis, obj.addressType, obj.addressHash);
}
CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) {
@ -211,13 +201,9 @@ struct CAddressUnspentValue {
CScript script;
int blockHeight;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(satoshis);
READWRITE(script);
READWRITE(blockHeight);
SERIALIZE_METHODS(CAddressUnspentValue, obj)
{
READWRITE(obj.satoshis, obj.script, obj.blockHeight);
}
CAddressUnspentValue(CAmount sats, CScript scriptPubKey, int height) {

View File

@ -94,14 +94,9 @@ public:
{}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nSporkID);
READWRITE(nValue);
READWRITE(nTimeSigned);
READWRITE(vchSig);
SERIALIZE_METHODS(CSporkMessage, obj)
{
READWRITE(obj.nSporkID, obj.nValue, obj.nTimeSigned, obj.vchSig);
}
/**
@ -176,27 +171,27 @@ public:
CSporkManager();
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
std::string strVersion;
if(ser_action.ForRead()) {
READWRITE(strVersion);
if (strVersion != SERIALIZATION_VERSION_STRING) {
return;
}
} else {
strVersion = SERIALIZATION_VERSION_STRING;
READWRITE(strVersion);
}
// we don't serialize pubkey ids because pubkeys should be
template<typename Stream>
void Serialize(Stream &s) const
{
// We don't serialize pubkey ids because pubkeys should be
// hardcoded or be set with cmdline or options, should
// not reuse pubkeys from previous dashd run
// not reuse pubkeys from previous dashd run.
// We don't serialize private key to prevent its leakage.
LOCK(cs);
READWRITE(mapSporksByHash);
READWRITE(mapSporksActive);
// we don't serialize private key to prevent its leakage
s << SERIALIZATION_VERSION_STRING << mapSporksByHash << mapSporksActive;
}
template<typename Stream>
void Unserialize(Stream &s)
{
LOCK(cs);
std::string strVersion;
s >> strVersion;
if (strVersion != SERIALIZATION_VERSION_STRING) {
return;
}
s >> mapSporksByHash >> mapSporksActive;
}
/**

View File

@ -310,15 +310,9 @@ struct stackframe_info {
int lineno{-1};
std::string function;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(stackframe_info, obj)
{
READWRITE(pc);
READWRITE(filename);
READWRITE(lineno);
READWRITE(function);
READWRITE(obj.pc, obj.filename, obj.lineno, obj.function);
}
};
@ -376,14 +370,9 @@ struct crash_info_header
uint16_t version;
std::string exeFileName;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(crash_info_header, obj)
{
READWRITE(magic);
READWRITE(version);
READWRITE(exeFileName);
READWRITE(obj.magic, obj.version, obj.exeFileName);
}
};
@ -393,14 +382,9 @@ struct crash_info
std::vector<uint64_t> stackframes;
std::vector<stackframe_info> stackframeInfos;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
SERIALIZE_METHODS(crash_info, obj)
{
READWRITE(crashDescription);
READWRITE(stackframes);
READWRITE(stackframeInfos);
READWRITE(obj.crashDescription, obj.stackframes, obj.stackframeInfos);
}
void ConvertAddresses(int64_t offset)

View File

@ -22,6 +22,47 @@
#include <utility>
#include <vector>
template<typename Stream>
class OverrideStream
{
Stream* stream;
const int nType;
const int nVersion;
public:
OverrideStream(Stream* stream_, int nType_, int nVersion_) : stream(stream_), nType(nType_), nVersion(nVersion_) {}
template<typename T>
OverrideStream<Stream>& operator<<(const T& obj)
{
// Serialize to this stream
::Serialize(*this, obj);
return (*this);
}
template<typename T>
OverrideStream<Stream>& operator>>(T&& obj)
{
// Unserialize from this stream
::Unserialize(*this, obj);
return (*this);
}
void write(const char* pch, size_t nSize)
{
stream->write(pch, nSize);
}
void read(char* pch, size_t nSize)
{
stream->read(pch, nSize);
}
int GetVersion() const { return nVersion; }
int GetType() const { return nType; }
};
/* Minimal stream for overwriting and/or appending to an existing byte vector
*
* The referenced vector will grow as necessary

View File

@ -58,12 +58,24 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
}
BOOST_CHECK(!DecodeBase58("invalid", result));
BOOST_CHECK(!DecodeBase58(std::string("invalid"), result));
BOOST_CHECK(!DecodeBase58(std::string("\0invalid", 8), result));
BOOST_CHECK(DecodeBase58(std::string("good", 4), result));
BOOST_CHECK(!DecodeBase58(std::string("bad0IOl", 7), result));
BOOST_CHECK(!DecodeBase58(std::string("goodbad0IOl", 11), result));
BOOST_CHECK(!DecodeBase58(std::string("good\0bad0IOl", 12), result));
// check that DecodeBase58 skips whitespace, but still fails with unexpected non-whitespace at the end.
BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result));
BOOST_CHECK( DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t ", result));
std::vector<unsigned char> expected = ParseHex("971a55");
BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
BOOST_CHECK(DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh", 21), result));
BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oi", 21), result));
BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh0IOl", 25), result));
BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh\00IOl", 26), result));
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -136,24 +136,7 @@ public:
return base.GetShortID(txhash);
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(header);
READWRITE(nonce);
size_t shorttxids_size = shorttxids.size();
READWRITE(VARINT(shorttxids_size));
shorttxids.resize(shorttxids_size);
for (size_t i = 0; i < shorttxids.size(); i++) {
uint32_t lsb = shorttxids[i] & 0xffffffff;
uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
READWRITE(lsb);
READWRITE(msb);
shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
}
READWRITE(prefilledtxn);
}
SERIALIZE_METHODS(TestHeaderAndShortIDs, obj) { READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<CBlockHeaderAndShortTxIDs::SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); }
};
BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)

View File

@ -251,24 +251,26 @@ struct StringContentsSerializer {
}
StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
ADD_SERIALIZE_METHODS;
template<typename Stream>
void Serialize(Stream& s) const
{
for (size_t i = 0; i < str.size(); i++) {
s << str[i];
}
}
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
if (ser_action.ForRead()) {
str.clear();
char c = 0;
while (true) {
try {
READWRITE(c);
str.push_back(c);
} catch (const std::ios_base::failure& e) {
break;
}
template<typename Stream>
void Unserialize(Stream& s)
{
str.clear();
char c = 0;
while (true) {
try {
s >> c;
str.push_back(c);
} catch (const std::ios_base::failure&) {
break;
}
} else {
for (size_t i = 0; i < str.size(); i++)
READWRITE(str[i]);
}
}
};

View File

@ -28,15 +28,13 @@ public:
memcpy(charstrval, charstrvalin, sizeof(charstrval));
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(intval);
READWRITE(boolval);
READWRITE(stringval);
READWRITE(charstrval);
READWRITE(txval);
SERIALIZE_METHODS(CSerializeMethodsTestSingle, obj)
{
READWRITE(obj.intval);
READWRITE(obj.boolval);
READWRITE(obj.stringval);
READWRITE(obj.charstrval);
READWRITE(obj.txval);
}
bool operator==(const CSerializeMethodsTestSingle& rhs)
@ -53,11 +51,10 @@ class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
{
public:
using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(intval, boolval, stringval, charstrval, txval);
SERIALIZE_METHODS(CSerializeMethodsTestMany, obj)
{
READWRITE(obj.intval, obj.boolval, obj.stringval, obj.charstrval, obj.txval);
}
};
@ -357,29 +354,32 @@ struct old_version
{
int field1;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(field1);
SERIALIZE_METHODS(old_version, obj)
{
READWRITE(obj.field1);
}
};\
};
struct new_version
{
int field1;
int field2;
ADD_SERIALIZE_METHODS;
template<typename Stream>
void Serialize(Stream &s) const
{
s << field1 << field2;
}
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(field1);
if(ser_action.ForRead() && (s.size() == 0))
{
template<typename Stream>
void Unserialize(Stream &s)
{
s >> field1;
if (s.size() == 0) {
field2 = 0;
return;
}
READWRITE(field2);
s >> field2;
}
};

View File

@ -8,6 +8,7 @@
#include <primitives/transaction.h>
#include <sync.h>
#include <utilstrencodings.h>
#include <utilstring.h>
#include <utilmoneystr.h>
#include <test/test_dash.h>
@ -95,6 +96,13 @@ BOOST_AUTO_TEST_CASE(util_HexStr)
);
}
BOOST_AUTO_TEST_CASE(util_Join)
{
// Normal version
BOOST_CHECK_EQUAL(Join({}, ", "), "");
BOOST_CHECK_EQUAL(Join({"foo"}, ", "), "foo");
BOOST_CHECK_EQUAL(Join({"foo", "bar"}, ", "), "foo, bar");
}
BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
{

View File

@ -41,19 +41,7 @@ struct CoinEntry {
char key;
explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN) {}
template<typename Stream>
void Serialize(Stream &s) const {
s << key;
s << outpoint->hash;
s << VARINT(outpoint->n);
}
template<typename Stream>
void Unserialize(Stream& s) {
s >> key;
s >> outpoint->hash;
s >> VARINT(outpoint->n);
}
SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
};
}

View File

@ -46,12 +46,10 @@ struct CDiskTxPos : public CDiskBlockPos
{
unsigned int nTxOffset; // after header
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITEAS(CDiskBlockPos, *this);
READWRITE(VARINT(nTxOffset));
SERIALIZE_METHODS(CDiskTxPos, obj)
{
READWRITEAS(CDiskBlockPos, obj);
READWRITE(VARINT(obj.nTxOffset));
}
CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {

View File

@ -28,7 +28,7 @@ struct TxInUndoFormatter
// Required to maintain compatibility with older undo format.
::Serialize(s, (unsigned char)0);
}
::Serialize(s, Using<TxOutCompression>(REF(txout.out)));
::Serialize(s, Using<TxOutCompression>(txout.out));
}
template<typename Stream>
@ -44,7 +44,7 @@ struct TxInUndoFormatter
unsigned int nVersionDummy;
::Unserialize(s, VARINT(nVersionDummy));
}
::Unserialize(s, Using<TxOutCompression>(REF(txout.out)));
::Unserialize(s, Using<TxOutCompression>(txout.out));
}
};

View File

@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <utilstrencodings.h>
#include <utilstring.h>
#include <tinyformat.h>
@ -267,7 +268,7 @@ NODISCARD static bool ParsePrechecks(const std::string& str)
return false;
if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
return false;
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
if (!ValidAsCString(str)) // No embedded NUL characters allowed
return false;
return true;
}

5
src/utilstring.cpp Normal file
View File

@ -0,0 +1,5 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <utilstring.h>

63
src/utilstring.h Normal file
View File

@ -0,0 +1,63 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_UTILSTRING_H
#define BITCOIN_UTILSTRING_H
#include <attributes.h>
#include <cstring>
#include <string>
#include <vector>
NODISCARD inline std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v")
{
std::string::size_type front = str.find_first_not_of(pattern);
if (front == std::string::npos) {
return std::string();
}
std::string::size_type end = str.find_last_not_of(pattern);
return str.substr(front, end - front + 1);
}
/**
* Join a list of items
*
* @param list The list to join
* @param separator The separator
* @param unary_op Apply this operator to each item in the list
*/
template <typename T, typename BaseType, typename UnaryOp>
auto Join(const std::vector<T>& list, const BaseType& separator, UnaryOp unary_op)
-> decltype(unary_op(list.at(0)))
{
decltype(unary_op(list.at(0))) ret;
for (size_t i = 0; i < list.size(); ++i) {
if (i > 0) ret += separator;
ret += unary_op(list.at(i));
}
return ret;
}
template <typename T>
T Join(const std::vector<T>& list, const T& separator)
{
return Join(list, separator, [](const T& i) { return i; });
}
// Explicit overload needed for c_str arguments, which would otherwise cause a substitution failure in the template above.
inline std::string Join(const std::vector<std::string>& list, const std::string& separator)
{
return Join<std::string>(list, separator);
}
/**
* Check if a string does not contain any embedded NUL (\0) characters
*/
NODISCARD inline bool ValidAsCString(const std::string& str) noexcept
{
return str.size() == strlen(str.c_str());
}
#endif // BITCOIN_UTILSTRING_H

View File

@ -44,15 +44,9 @@ public:
//! such as the various parameters to scrypt
std::vector<unsigned char> vchOtherDerivationParameters;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vchCryptedKey);
READWRITE(vchSalt);
READWRITE(nDerivationMethod);
READWRITE(nDeriveIterations);
READWRITE(vchOtherDerivationParameters);
SERIALIZE_METHODS(CMasterKey, obj)
{
READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters);
}
CMasterKey()

View File

@ -116,27 +116,30 @@ public:
CKeyPool();
CKeyPool(const CPubKey& vchPubKeyIn, bool fInternalIn);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
template<typename Stream>
void Serialize(Stream& s) const
{
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(nTime);
READWRITE(vchPubKey);
if (ser_action.ForRead()) {
try {
READWRITE(fInternal);
}
catch (std::ios_base::failure&) {
/* flag as external address if we can't read the internal boolean
(this will be the case for any wallet before the HD chain split version) */
fInternal = false;
}
if (!(s.GetType() & SER_GETHASH)) {
s << nVersion;
}
else {
READWRITE(fInternal);
s << nTime << vchPubKey << fInternal;
}
template<typename Stream>
void Unserialize(Stream& s)
{
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH)) {
s >> nVersion;
}
s >> nTime >> vchPubKey;
try {
s >> fInternal;
} catch (std::ios_base::failure&) {
/* flag as external address if we can't read the internal boolean
(this will be the case for any wallet before the HD chain split version) */
fInternal = false;
}
}
};
@ -233,15 +236,10 @@ public:
tx = std::move(arg);
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
SERIALIZE_METHODS(CMerkleTx, obj)
{
std::vector<uint256> vMerkleBranch; // For compatibility with older versions.
READWRITE(tx);
READWRITE(hashBlock);
READWRITE(vMerkleBranch);
READWRITE(nIndex);
READWRITE(obj.tx, obj.hashBlock, vMerkleBranch, obj.nIndex);
}
void SetMerkleBranch(const CBlockIndex* pIndex, int posInBlock);
@ -578,17 +576,12 @@ public:
explicit CWalletKey(int64_t nExpires=0);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
SERIALIZE_METHODS(CWalletKey, obj)
{
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPrivKey);
READWRITE(nTimeCreated);
READWRITE(nTimeExpires);
READWRITE(LIMITED_STRING(strComment, 65536));
READWRITE(obj.vchPrivKey, obj.nTimeCreated, obj.nTimeExpires, LIMITED_STRING(obj.strComment, 65536));
}
};
@ -1317,14 +1310,12 @@ public:
vchPubKey = CPubKey();
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
SERIALIZE_METHODS(CAccount, obj)
{
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPubKey);
READWRITE(obj.vchPubKey);
}
};

View File

@ -74,12 +74,9 @@ public:
nCreateTime = nCreateTime_;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(nCreateTime);
SERIALIZE_METHODS(CKeyMetadata, obj)
{
READWRITE(obj.nVersion, obj.nCreateTime);
}
void SetNull()

View File

@ -127,10 +127,16 @@ def deser_vector(f, c):
return r
def ser_vector(l):
# ser_function_name: Allow for an alternate serialization function on the
# entries in the vector (we use this for serializing the vector of transactions
# for a witness block).
def ser_vector(l, ser_function_name=None):
r = ser_compact_size(len(l))
for i in l:
r += i.serialize()
if ser_function_name:
r += getattr(i, ser_function_name)()
else:
r += i.serialize()
return r