mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-20 13:37:28 +02:00
Merge 448bdff263 into merged_master (Bitcoin PR #18317)
This commit is contained in:
commit
f89b990b78
22 changed files with 301 additions and 387 deletions
|
|
@ -20,9 +20,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");
|
||||
|
|
|
|||
|
|
@ -92,12 +92,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
|
||||
|
|
|
|||
10
src/bloom.h
10
src/bloom.h
|
|
@ -64,15 +64,7 @@ public:
|
|||
CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn);
|
||||
CBloomFilter() : 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);
|
||||
|
|
|
|||
|
|
@ -16,13 +16,7 @@ struct FlatFilePos
|
|||
int nFile;
|
||||
unsigned int nPos;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(VARINT_MODE(nFile, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
READWRITE(VARINT(nPos));
|
||||
}
|
||||
SERIALIZE_METHODS(FlatFilePos, obj) { READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED), VARINT(obj.nPos)); }
|
||||
|
||||
FlatFilePos() : nFile(-1), nPos(0) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,14 +39,7 @@ struct DBVal {
|
|||
uint256 header;
|
||||
FlatFilePos pos;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(hash);
|
||||
READWRITE(header);
|
||||
READWRITE(pos);
|
||||
}
|
||||
SERIALIZE_METHODS(DBVal, obj) { READWRITE(obj.hash, obj.header, obj.pos); }
|
||||
};
|
||||
|
||||
struct DBHeightKey {
|
||||
|
|
@ -78,17 +71,14 @@ struct DBHashKey {
|
|||
|
||||
explicit DBHashKey(const uint256& hash_in) : hash(hash_in) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
SERIALIZE_METHODS(DBHashKey, obj) {
|
||||
char prefix = DB_BLOCK_HASH;
|
||||
READWRITE(prefix);
|
||||
if (prefix != DB_BLOCK_HASH) {
|
||||
throw std::ios_base::failure("Invalid format for block filter index DB hash key");
|
||||
}
|
||||
|
||||
READWRITE(hash);
|
||||
READWRITE(obj.hash);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,10 @@ struct CDiskTxPos : public FlatFilePos
|
|||
{
|
||||
unsigned int nTxOffset; // after header
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITEAS(FlatFilePos, *this);
|
||||
READWRITE(VARINT(nTxOffset));
|
||||
SERIALIZE_METHODS(CDiskTxPos, obj)
|
||||
{
|
||||
READWRITEAS(FlatFilePos, obj);
|
||||
READWRITE(VARINT(obj.nTxOffset));
|
||||
}
|
||||
|
||||
CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,24 @@
|
|||
#include <consensus/consensus.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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -99,12 +99,7 @@ class CNetAddr
|
|||
friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); }
|
||||
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(ip);
|
||||
}
|
||||
SERIALIZE_METHODS(CNetAddr, obj) { READWRITE(obj.ip); }
|
||||
|
||||
friend class CSubNet;
|
||||
};
|
||||
|
|
@ -136,14 +131,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 */
|
||||
|
|
@ -171,13 +159,7 @@ class CService : public CNetAddr
|
|||
CService(const struct in6_addr& ipv6Addr, unsigned short port);
|
||||
explicit CService(const struct sockaddr_in6& addr);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(ip);
|
||||
READWRITE(WrapBigEndian(port));
|
||||
}
|
||||
SERIALIZE_METHODS(CService, obj) { READWRITE(obj.ip, Using<BigEndianFormatter<2>>(obj.port)); }
|
||||
};
|
||||
|
||||
bool SanityCheckASMap(const std::vector<bool>& asmap);
|
||||
|
|
|
|||
|
|
@ -35,16 +35,7 @@ public:
|
|||
m_coins_count(coins_count),
|
||||
m_nchaintx(nchaintx) { }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(m_base_blockhash);
|
||||
READWRITE(m_coins_count);
|
||||
READWRITE(m_nchaintx);
|
||||
}
|
||||
|
||||
SERIALIZE_METHODS(SnapshotMetadata, obj) { READWRITE(obj.m_base_blockhash, obj.m_coins_count, obj.m_nchaintx); }
|
||||
};
|
||||
|
||||
#endif // BITCOIN_NODE_UTXO_SNAPSHOT_H
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -210,54 +210,86 @@ public:
|
|||
SetNull();
|
||||
}
|
||||
|
||||
// ELEMENTS: we give explicit serialization methods so that we can
|
||||
// mask in the dynafed bit and to selectively embed the blocktime
|
||||
|
||||
// HF bit to detect dynamic federation blocks
|
||||
static const uint32_t DYNAFED_HF_MASK = 1 << 31;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
template <typename Stream>
|
||||
inline void Serialize(Stream& s) const {
|
||||
const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
// Detect dynamic federation block serialization using "HF bit",
|
||||
// or the signed bit which is invalid in Bitcoin
|
||||
bool is_dyna = false;
|
||||
int32_t nVersion = this->nVersion;
|
||||
if (!m_dynafed_params.IsNull()) {
|
||||
nVersion |= DYNAFED_HF_MASK;
|
||||
is_dyna = true;
|
||||
}
|
||||
s << (nVersion);
|
||||
|
||||
if (is_dyna) {
|
||||
s << hashPrevBlock;
|
||||
s << hashMerkleRoot;
|
||||
s << nTime;
|
||||
s << block_height;
|
||||
s << m_dynafed_params;
|
||||
// We do not serialize witness for hashes, or weight calculation
|
||||
if (!(s.GetType() & SER_GETHASH) && fAllowWitness) {
|
||||
s << m_signblock_witness.stack;
|
||||
}
|
||||
} else {
|
||||
s << hashPrevBlock;
|
||||
s << hashMerkleRoot;
|
||||
s << nTime;
|
||||
if (g_con_blockheightinheader) {
|
||||
s << block_height;
|
||||
}
|
||||
if (g_signed_blocks) {
|
||||
s << proof;
|
||||
} else {
|
||||
s << nBits;
|
||||
s << nNonce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline void Unserialize(Stream& s) {
|
||||
const bool fAllowWitness = !(s.GetVersion() & SERIALIZE_TRANSACTION_NO_WITNESS);
|
||||
|
||||
// Detect dynamic federation block serialization using "HF bit",
|
||||
// or the signed bit which is invalid in Bitcoin
|
||||
bool is_dyna = false;
|
||||
int32_t nVersion;
|
||||
if (ser_action.ForRead()) {
|
||||
READWRITE(nVersion);
|
||||
is_dyna = nVersion < 0;
|
||||
this->nVersion = ~DYNAFED_HF_MASK & nVersion;
|
||||
} else {
|
||||
nVersion = this->nVersion;
|
||||
if (!m_dynafed_params.IsNull()) {
|
||||
nVersion |= DYNAFED_HF_MASK;
|
||||
is_dyna = true;
|
||||
}
|
||||
READWRITE(nVersion);
|
||||
}
|
||||
s >> nVersion;
|
||||
is_dyna = nVersion < 0;
|
||||
this->nVersion = ~DYNAFED_HF_MASK & nVersion;
|
||||
|
||||
if (is_dyna) {
|
||||
READWRITE(hashPrevBlock);
|
||||
READWRITE(hashMerkleRoot);
|
||||
READWRITE(nTime);
|
||||
READWRITE(block_height);
|
||||
READWRITE(m_dynafed_params);
|
||||
s >> hashPrevBlock;
|
||||
s >> hashMerkleRoot;
|
||||
s >> nTime;
|
||||
s >> block_height;
|
||||
s >> m_dynafed_params;
|
||||
// We do not serialize witness for hashes, or weight calculation
|
||||
if (!(s.GetType() & SER_GETHASH) && fAllowWitness) {
|
||||
READWRITE(m_signblock_witness.stack);
|
||||
s >> m_signblock_witness.stack;
|
||||
}
|
||||
} else {
|
||||
READWRITE(hashPrevBlock);
|
||||
READWRITE(hashMerkleRoot);
|
||||
READWRITE(nTime);
|
||||
s >> hashPrevBlock;
|
||||
s >> hashMerkleRoot;
|
||||
s >> nTime;
|
||||
if (g_con_blockheightinheader) {
|
||||
READWRITE(block_height);
|
||||
s >> block_height;
|
||||
}
|
||||
if (g_signed_blocks) {
|
||||
READWRITE(proof);
|
||||
s >> proof;
|
||||
} else {
|
||||
READWRITE(nBits);
|
||||
READWRITE(nNonce);
|
||||
s >> nBits;
|
||||
s >> nNonce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -312,12 +344,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()
|
||||
|
|
@ -357,14 +387,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()
|
||||
|
|
|
|||
|
|
@ -51,13 +51,7 @@ public:
|
|||
COutPoint(): n(NULL_INDEX) { }
|
||||
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 = NULL_INDEX; }
|
||||
bool IsNull() const { return (hash.IsNull() && n == NULL_INDEX); }
|
||||
|
|
@ -139,83 +133,83 @@ 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) {
|
||||
|
||||
//
|
||||
// ELEMENTS:
|
||||
|
||||
// ELEMENTS: explicit serialization methods for selective asset/pegin encoding
|
||||
template <typename Stream>
|
||||
inline void Serialize(Stream& s) const {
|
||||
bool fHasAssetIssuance;
|
||||
COutPoint outpoint;
|
||||
if (!ser_action.ForRead()) {
|
||||
if (prevout.n == (uint32_t) -1) {
|
||||
// Coinbase inputs do not have asset issuances attached
|
||||
// to them.
|
||||
fHasAssetIssuance = false;
|
||||
outpoint = prevout;
|
||||
} else {
|
||||
// The issuance and pegin bits can't be set as it is used to indicate
|
||||
// the presence of the asset issuance or pegin objects. They should
|
||||
// never be set anyway as that would require a parent
|
||||
// transaction with over one billion outputs.
|
||||
assert(!(prevout.n & ~COutPoint::OUTPOINT_INDEX_MASK));
|
||||
// The assetIssuance object is used to represent both new
|
||||
// asset generation and reissuance of existing asset types.
|
||||
fHasAssetIssuance = !assetIssuance.IsNull();
|
||||
// The mode is placed in the upper bits of the outpoint's
|
||||
// index field. The IssuanceMode enum values are chosen to
|
||||
// make this as simple as a bitwise-OR.
|
||||
outpoint.hash = prevout.hash;
|
||||
outpoint.n = prevout.n & COutPoint::OUTPOINT_INDEX_MASK;
|
||||
if (fHasAssetIssuance) {
|
||||
outpoint.n |= COutPoint::OUTPOINT_ISSUANCE_FLAG;
|
||||
}
|
||||
if (m_is_pegin) {
|
||||
outpoint.n |= COutPoint::OUTPOINT_PEGIN_FLAG;
|
||||
}
|
||||
if (prevout.n == (uint32_t) -1) {
|
||||
// Coinbase inputs do not have asset issuances attached
|
||||
// to them.
|
||||
fHasAssetIssuance = false;
|
||||
outpoint = prevout;
|
||||
} else {
|
||||
// The issuance and pegin bits can't be set as it is used to indicate
|
||||
// the presence of the asset issuance or pegin objects. They should
|
||||
// never be set anyway as that would require a parent
|
||||
// transaction with over one billion outputs.
|
||||
assert(!(prevout.n & ~COutPoint::OUTPOINT_INDEX_MASK));
|
||||
// The assetIssuance object is used to represent both new
|
||||
// asset generation and reissuance of existing asset types.
|
||||
fHasAssetIssuance = !assetIssuance.IsNull();
|
||||
// The mode is placed in the upper bits of the outpoint's
|
||||
// index field. The IssuanceMode enum values are chosen to
|
||||
// make this as simple as a bitwise-OR.
|
||||
outpoint.hash = prevout.hash;
|
||||
outpoint.n = prevout.n & COutPoint::OUTPOINT_INDEX_MASK;
|
||||
if (fHasAssetIssuance) {
|
||||
outpoint.n |= COutPoint::OUTPOINT_ISSUANCE_FLAG;
|
||||
}
|
||||
if (m_is_pegin) {
|
||||
outpoint.n |= COutPoint::OUTPOINT_PEGIN_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
READWRITE(outpoint);
|
||||
|
||||
if (ser_action.ForRead()) {
|
||||
if (outpoint.n == (uint32_t) -1) {
|
||||
// No asset issuance for Coinbase inputs.
|
||||
fHasAssetIssuance = false;
|
||||
prevout = outpoint;
|
||||
m_is_pegin = false;
|
||||
} else {
|
||||
// The presence of the asset issuance object is indicated by
|
||||
// a bit set in the outpoint index field.
|
||||
fHasAssetIssuance = !!(outpoint.n & COutPoint::OUTPOINT_ISSUANCE_FLAG);
|
||||
// The interpretation of this input as a peg-in is indicated by
|
||||
// a bit set in the outpoint index field.
|
||||
m_is_pegin = !!(outpoint.n & COutPoint::OUTPOINT_PEGIN_FLAG);
|
||||
// The mode, if set, must be masked out of the outpoint so
|
||||
// that the in-memory index field retains its traditional
|
||||
// meaning of identifying the index into the output array
|
||||
// of the previous transaction.
|
||||
prevout.hash = outpoint.hash;
|
||||
prevout.n = outpoint.n & COutPoint::OUTPOINT_INDEX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
// END ELEMENTS
|
||||
//
|
||||
|
||||
READWRITE(scriptSig);
|
||||
READWRITE(nSequence);
|
||||
|
||||
// ELEMENTS:
|
||||
// The asset fields are deserialized only if they are present.
|
||||
// These are the same as bitcoin...
|
||||
s << outpoint;
|
||||
s << scriptSig;
|
||||
s << nSequence;
|
||||
// ...but then we add asset issuance data for issuances
|
||||
if (fHasAssetIssuance) {
|
||||
READWRITE(assetIssuance);
|
||||
s << assetIssuance;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline void Unserialize(Stream& s) {
|
||||
bool fHasAssetIssuance;
|
||||
COutPoint outpoint;
|
||||
s >> outpoint;
|
||||
|
||||
if (outpoint.n == (uint32_t) -1) {
|
||||
// No asset issuance for Coinbase inputs.
|
||||
fHasAssetIssuance = false;
|
||||
prevout = outpoint;
|
||||
m_is_pegin = false;
|
||||
} else {
|
||||
// The presence of the asset issuance object is indicated by
|
||||
// a bit set in the outpoint index field.
|
||||
fHasAssetIssuance = !!(outpoint.n & COutPoint::OUTPOINT_ISSUANCE_FLAG);
|
||||
// The interpretation of this input as a peg-in is indicated by
|
||||
// a bit set in the outpoint index field.
|
||||
m_is_pegin = !!(outpoint.n & COutPoint::OUTPOINT_PEGIN_FLAG);
|
||||
// The mode, if set, must be masked out of the outpoint so
|
||||
// that the in-memory index field retains its traditional
|
||||
// meaning of identifying the index into the output array
|
||||
// of the previous transaction.
|
||||
prevout.hash = outpoint.hash;
|
||||
prevout.n = outpoint.n & COutPoint::OUTPOINT_INDEX_MASK;
|
||||
}
|
||||
|
||||
s >> scriptSig;
|
||||
s >> nSequence;
|
||||
|
||||
if (fHasAssetIssuance) {
|
||||
s >> assetIssuance;
|
||||
if (assetIssuance.IsNull()) {
|
||||
throw std::ios_base::failure("Superfluous issuance record");
|
||||
}
|
||||
} else if (ser_action.ForRead()) {
|
||||
} else {
|
||||
assetIssuance.SetNull();
|
||||
}
|
||||
}
|
||||
|
|
@ -254,26 +248,31 @@ public:
|
|||
|
||||
CTxOut(const CConfidentialAsset& nAssetIn, const CConfidentialValue& nValueIn, CScript scriptPubKeyIn);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
// ELEMENTS: explicit serialization methods for different g_con_elementsmode serializations
|
||||
template <typename Stream>
|
||||
inline void Serialize(Stream& s) const {
|
||||
if (g_con_elementsmode) {
|
||||
READWRITE(nAsset);
|
||||
READWRITE(nValue);
|
||||
READWRITE(nNonce);
|
||||
READWRITE(scriptPubKey);
|
||||
s << nAsset;
|
||||
s << nValue;
|
||||
s << nNonce;
|
||||
} else {
|
||||
s << nValue.GetAmount();
|
||||
}
|
||||
s << scriptPubKey;
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
inline void Unserialize(Stream& s) {
|
||||
if (g_con_elementsmode) {
|
||||
s >> nAsset;
|
||||
s >> nValue;
|
||||
s >> nNonce;
|
||||
} else {
|
||||
CAmount value;
|
||||
if (!ser_action.ForRead()) {
|
||||
value = nValue.GetAmount();
|
||||
}
|
||||
READWRITE(value);
|
||||
if (ser_action.ForRead()) {
|
||||
nValue.SetToAmount(value);
|
||||
}
|
||||
READWRITE(scriptPubKey);
|
||||
s >> value;
|
||||
nValue.SetToAmount(value);
|
||||
}
|
||||
s >> scriptPubKey;
|
||||
}
|
||||
|
||||
void SetNull()
|
||||
|
|
|
|||
|
|
@ -46,16 +46,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];
|
||||
|
|
@ -345,23 +336,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);
|
||||
}
|
||||
|
||||
ServiceFlags nServices;
|
||||
|
|
@ -397,14 +384,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,18 +49,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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,7 @@ struct KeyOriginInfo
|
|||
return std::equal(std::begin(a.fingerprint), std::end(a.fingerprint), std::begin(b.fingerprint)) && a.path == b.path;
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
||||
{
|
||||
READWRITE(fingerprint);
|
||||
READWRITE(path);
|
||||
}
|
||||
SERIALIZE_METHODS(KeyOriginInfo, obj) { READWRITE(obj.fingerprint, obj.path); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -424,12 +424,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); }
|
||||
|
||||
explicit CScript(int64_t b) { operator<<(b); }
|
||||
explicit CScript(opcodetype b) { operator<<(b); }
|
||||
|
|
|
|||
|
|
@ -190,6 +190,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)))
|
||||
#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 three methods for serializable objects. These are actually wrappers over
|
||||
|
|
@ -518,7 +520,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");
|
||||
|
|
@ -527,52 +538,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
|
||||
|
|
@ -626,9 +616,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<typename I>
|
||||
BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); }
|
||||
|
||||
/** Formatter to serialize/deserialize vector elements using another formatter
|
||||
*
|
||||
* Example:
|
||||
|
|
@ -1127,6 +1114,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -132,24 +132,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)
|
||||
|
|
|
|||
|
|
@ -331,24 +331,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&) {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,15 +29,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)
|
||||
|
|
@ -54,11 +52,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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
14
src/txdb.cpp
14
src/txdb.cpp
|
|
@ -44,19 +44,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)); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue