2018-08-06 15:40:20 -04:00
|
|
|
#ifndef BITCOIN_CLAIMTRIE_H
|
|
|
|
#define BITCOIN_CLAIMTRIE_H
|
|
|
|
|
|
|
|
#include <amount.h>
|
|
|
|
#include <serialize.h>
|
|
|
|
#include <uint256.h>
|
|
|
|
#include <util.h>
|
|
|
|
#include <dbwrapper.h>
|
|
|
|
#include <chainparams.h>
|
|
|
|
#include <primitives/transaction.h>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
// leveldb keys
|
|
|
|
#define HASH_BLOCK 'h'
|
|
|
|
#define CURRENT_HEIGHT 't'
|
|
|
|
#define TRIE_NODE 'n'
|
|
|
|
#define CLAIM_BY_ID 'i'
|
|
|
|
#define CLAIM_QUEUE_ROW 'r'
|
|
|
|
#define CLAIM_QUEUE_NAME_ROW 'm'
|
|
|
|
#define EXP_QUEUE_ROW 'e'
|
|
|
|
#define SUPPORT 's'
|
|
|
|
#define SUPPORT_QUEUE_ROW 'u'
|
|
|
|
#define SUPPORT_QUEUE_NAME_ROW 'p'
|
|
|
|
#define SUPPORT_EXP_QUEUE_ROW 'x'
|
|
|
|
|
|
|
|
uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover);
|
|
|
|
|
|
|
|
class CClaimValue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
COutPoint outPoint;
|
|
|
|
uint160 claimId;
|
|
|
|
CAmount nAmount;
|
|
|
|
CAmount nEffectiveAmount;
|
|
|
|
int nHeight;
|
|
|
|
int nValidAtHeight;
|
|
|
|
|
|
|
|
CClaimValue() {};
|
|
|
|
|
|
|
|
CClaimValue(COutPoint outPoint, uint160 claimId, CAmount nAmount, int nHeight,
|
|
|
|
int nValidAtHeight)
|
|
|
|
: outPoint(outPoint), claimId(claimId)
|
|
|
|
, nAmount(nAmount), nEffectiveAmount(nAmount)
|
|
|
|
, nHeight(nHeight), nValidAtHeight(nValidAtHeight)
|
|
|
|
{}
|
|
|
|
|
|
|
|
CClaimValue(CClaimValue&&) = default;
|
|
|
|
CClaimValue(const CClaimValue&) = default;
|
|
|
|
CClaimValue& operator=(CClaimValue&&) = default;
|
|
|
|
CClaimValue& operator=(const CClaimValue&) = default;
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
|
|
READWRITE(outPoint);
|
|
|
|
READWRITE(claimId);
|
|
|
|
READWRITE(nAmount);
|
|
|
|
READWRITE(nHeight);
|
|
|
|
READWRITE(nValidAtHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator<(const CClaimValue& other) const
|
|
|
|
{
|
|
|
|
if (nEffectiveAmount < other.nEffectiveAmount)
|
|
|
|
return true;
|
|
|
|
else if (nEffectiveAmount == other.nEffectiveAmount)
|
|
|
|
{
|
|
|
|
if (nHeight > other.nHeight)
|
|
|
|
return true;
|
|
|
|
else if (nHeight == other.nHeight)
|
|
|
|
{
|
|
|
|
if (outPoint != other.outPoint && !(outPoint < other.outPoint))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const CClaimValue& other) const
|
|
|
|
{
|
|
|
|
return outPoint == other.outPoint && claimId == other.claimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const CClaimValue& other) const
|
|
|
|
{
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CSupportValue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
COutPoint outPoint;
|
|
|
|
uint160 supportedClaimId;
|
|
|
|
CAmount nAmount;
|
|
|
|
int nHeight;
|
|
|
|
int nValidAtHeight;
|
|
|
|
|
|
|
|
CSupportValue() {};
|
|
|
|
CSupportValue(COutPoint outPoint, uint160 supportedClaimId,
|
|
|
|
CAmount nAmount, int nHeight, int nValidAtHeight)
|
|
|
|
: outPoint(outPoint), supportedClaimId(supportedClaimId)
|
|
|
|
, nAmount(nAmount), nHeight(nHeight)
|
|
|
|
, nValidAtHeight(nValidAtHeight)
|
|
|
|
{}
|
|
|
|
|
|
|
|
CSupportValue(CSupportValue&&) = default;
|
|
|
|
CSupportValue(const CSupportValue&) = default;
|
|
|
|
CSupportValue& operator=(CSupportValue&&) = default;
|
|
|
|
CSupportValue& operator=(const CSupportValue&) = default;
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
|
|
READWRITE(outPoint);
|
|
|
|
READWRITE(supportedClaimId);
|
|
|
|
READWRITE(nAmount);
|
|
|
|
READWRITE(nHeight);
|
|
|
|
READWRITE(nValidAtHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const CSupportValue& other) const
|
|
|
|
{
|
|
|
|
return outPoint == other.outPoint && supportedClaimId == other.supportedClaimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const CSupportValue& other) const
|
|
|
|
{
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimTrieNode;
|
|
|
|
class CClaimTrie;
|
|
|
|
|
|
|
|
typedef std::vector<CSupportValue> supportMapEntryType;
|
|
|
|
typedef std::map<unsigned char, CClaimTrieNode*> nodeMapType;
|
|
|
|
|
|
|
|
class CClaimTrieNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CClaimTrieNode() : nHeightOfLastTakeover(0) {}
|
|
|
|
CClaimTrieNode(uint256 hash) : hash(hash), nHeightOfLastTakeover(0) {}
|
|
|
|
CClaimTrieNode(const CClaimTrieNode&) = default;
|
|
|
|
CClaimTrieNode(CClaimTrieNode&& other)
|
|
|
|
{
|
|
|
|
hash = std::move(other.hash);
|
|
|
|
claims = std::move(other.claims);
|
|
|
|
children = std::move(other.children);
|
|
|
|
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
|
|
|
}
|
|
|
|
|
|
|
|
CClaimTrieNode& operator=(const CClaimTrieNode&) = default;
|
|
|
|
CClaimTrieNode& operator=(CClaimTrieNode&& other)
|
|
|
|
{
|
|
|
|
if (this != &other)
|
|
|
|
{
|
|
|
|
hash = std::move(other.hash);
|
|
|
|
claims = std::move(other.claims);
|
|
|
|
children = std::move(other.children);
|
|
|
|
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint256 hash;
|
|
|
|
nodeMapType children;
|
|
|
|
int nHeightOfLastTakeover;
|
|
|
|
std::vector<CClaimValue> claims;
|
|
|
|
|
|
|
|
bool insertClaim(CClaimValue claim);
|
|
|
|
bool removeClaim(const COutPoint& outPoint, CClaimValue& claim);
|
|
|
|
bool getBestClaim(CClaimValue& claim) const;
|
|
|
|
bool empty() const {return children.empty() && claims.empty();}
|
|
|
|
bool haveClaim(const COutPoint& outPoint) const;
|
|
|
|
void reorderClaims(supportMapEntryType& supports);
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
|
|
READWRITE(hash);
|
|
|
|
READWRITE(claims);
|
|
|
|
READWRITE(nHeightOfLastTakeover);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const CClaimTrieNode& other) const
|
|
|
|
{
|
|
|
|
return hash == other.hash && claims == other.claims;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const CClaimTrieNode& other) const
|
|
|
|
{
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct nodenamecompare
|
|
|
|
{
|
|
|
|
bool operator() (const std::string& i, const std::string& j) const
|
|
|
|
{
|
|
|
|
if (i.size() == j.size())
|
|
|
|
return i < j;
|
|
|
|
return i.size() < j.size();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct outPointHeightType
|
|
|
|
{
|
|
|
|
COutPoint outPoint;
|
|
|
|
int nHeight;
|
|
|
|
|
|
|
|
outPointHeightType() {}
|
|
|
|
|
|
|
|
outPointHeightType(COutPoint outPoint, int nHeight)
|
|
|
|
: outPoint(outPoint), nHeight(nHeight) {}
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action)
|
|
|
|
{
|
|
|
|
READWRITE(outPoint);
|
|
|
|
READWRITE(nHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct nameOutPointHeightType
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
COutPoint outPoint;
|
|
|
|
int nHeight;
|
|
|
|
|
|
|
|
nameOutPointHeightType() {}
|
|
|
|
|
|
|
|
nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight)
|
|
|
|
: name(std::move(name)), outPoint(outPoint), nHeight(nHeight) {}
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action)
|
|
|
|
{
|
|
|
|
READWRITE(name);
|
|
|
|
READWRITE(outPoint);
|
|
|
|
READWRITE(nHeight);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct nameOutPointType
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
COutPoint outPoint;
|
|
|
|
|
|
|
|
nameOutPointType() {}
|
|
|
|
|
|
|
|
nameOutPointType(std::string name, COutPoint outPoint)
|
|
|
|
: name(std::move(name)), outPoint(outPoint) {}
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action)
|
|
|
|
{
|
|
|
|
READWRITE(name);
|
|
|
|
READWRITE(outPoint);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimIndexElement
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
|
|
READWRITE(name);
|
|
|
|
READWRITE(claim);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string name;
|
|
|
|
CClaimValue claim;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef std::pair<std::string, CClaimValue> claimQueueEntryType;
|
|
|
|
|
|
|
|
typedef std::pair<std::string, CSupportValue> supportQueueEntryType;
|
|
|
|
|
|
|
|
typedef std::map<std::string, supportMapEntryType> supportMapType;
|
|
|
|
|
|
|
|
typedef std::vector<outPointHeightType> queueNameRowType;
|
|
|
|
typedef std::map<std::string, queueNameRowType> queueNameType;
|
|
|
|
|
|
|
|
typedef std::vector<nameOutPointHeightType> insertUndoType;
|
|
|
|
|
|
|
|
typedef std::vector<nameOutPointType> expirationQueueRowType;
|
|
|
|
typedef std::map<int, expirationQueueRowType> expirationQueueType;
|
|
|
|
|
|
|
|
typedef std::vector<claimQueueEntryType> claimQueueRowType;
|
|
|
|
typedef std::map<int, claimQueueRowType> claimQueueType;
|
|
|
|
|
|
|
|
typedef std::vector<supportQueueEntryType> supportQueueRowType;
|
|
|
|
typedef std::map<int, supportQueueRowType> supportQueueType;
|
|
|
|
|
|
|
|
typedef std::map<std::string, CClaimTrieNode*, nodenamecompare> nodeCacheType;
|
|
|
|
|
|
|
|
typedef std::map<std::string, uint256> hashMapType;
|
|
|
|
|
|
|
|
typedef std::set<CClaimValue> claimIndexClaimListType;
|
|
|
|
typedef std::vector<CClaimIndexElement> claimIndexElementListType;
|
|
|
|
|
|
|
|
struct claimsForNameType
|
|
|
|
{
|
|
|
|
std::vector<CClaimValue> claims;
|
|
|
|
std::vector<CSupportValue> supports;
|
|
|
|
int nLastTakeoverHeight;
|
|
|
|
std::string name;
|
|
|
|
|
|
|
|
claimsForNameType(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports,
|
|
|
|
int nLastTakeoverHeight, const std::string& name)
|
|
|
|
: claims(std::move(claims)), supports(std::move(supports)),
|
|
|
|
nLastTakeoverHeight(nLastTakeoverHeight), name(name) {}
|
|
|
|
|
|
|
|
claimsForNameType(const claimsForNameType&) = default;
|
|
|
|
claimsForNameType(claimsForNameType&& other)
|
|
|
|
{
|
|
|
|
claims = std::move(other.claims);
|
|
|
|
supports = std::move(other.supports);
|
|
|
|
name = std::move(other.name);
|
|
|
|
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
claimsForNameType& operator=(const claimsForNameType&) = default;
|
|
|
|
claimsForNameType& operator=(claimsForNameType&& other)
|
|
|
|
{
|
|
|
|
if (this != &other)
|
|
|
|
{
|
|
|
|
claims = std::move(other.claims);
|
|
|
|
supports = std::move(other.supports);
|
|
|
|
name = std::move(other.name);
|
|
|
|
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~claimsForNameType() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimTrieCacheBase;
|
|
|
|
class CClaimTrieCacheExpirationFork;
|
|
|
|
|
|
|
|
class CClaimTrie
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32)
|
2019-05-28 15:18:50 -06:00
|
|
|
: db(GetDataDir() / "claimtrie", 20 * 1024 * 1024, fMemory, fWipe, false)
|
2018-08-06 15:40:20 -04:00
|
|
|
, nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime)
|
|
|
|
, nProportionalDelayFactor(nProportionalDelayFactor)
|
|
|
|
, root(uint256S("0000000000000000000000000000000000000000000000000000000000000001"))
|
|
|
|
{}
|
|
|
|
|
|
|
|
uint256 getMerkleHash();
|
|
|
|
|
|
|
|
bool empty() const;
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
bool checkConsistency() const;
|
|
|
|
|
|
|
|
bool WriteToDisk();
|
|
|
|
bool ReadFromDisk(bool check = false);
|
|
|
|
|
|
|
|
bool getInfoForName(const std::string& name, CClaimValue& claim) const;
|
|
|
|
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
|
|
|
|
|
|
|
|
std::vector<CClaimValue> getClaimsForName(const std::string& name) const;
|
|
|
|
|
|
|
|
bool queueEmpty() const;
|
|
|
|
bool supportEmpty() const;
|
|
|
|
bool supportQueueEmpty() const;
|
|
|
|
bool expirationQueueEmpty() const;
|
|
|
|
|
|
|
|
void setExpirationTime(int t);
|
|
|
|
|
|
|
|
void addToClaimIndex(const std::string& name, const CClaimValue& claim);
|
|
|
|
void removeFromClaimIndex(const CClaimValue& claim);
|
|
|
|
|
|
|
|
bool getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const;
|
|
|
|
|
|
|
|
bool haveClaim(const std::string& name, const COutPoint& outPoint) const;
|
|
|
|
bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint,
|
|
|
|
int& nValidAtHeight) const;
|
|
|
|
|
|
|
|
bool haveSupport(const std::string& name, const COutPoint& outPoint) const;
|
|
|
|
bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint,
|
|
|
|
int& nValidAtHeight) const;
|
|
|
|
|
|
|
|
unsigned int getTotalNamesInTrie() const;
|
|
|
|
unsigned int getTotalClaimsInTrie() const;
|
|
|
|
CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const;
|
|
|
|
|
|
|
|
friend class CClaimTrieCacheBase;
|
|
|
|
friend class CClaimTrieCacheExpirationFork;
|
|
|
|
|
|
|
|
CDBWrapper db;
|
|
|
|
int nCurrentHeight;
|
|
|
|
int nExpirationTime;
|
|
|
|
int nProportionalDelayFactor;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void clear(CClaimTrieNode* current);
|
|
|
|
|
|
|
|
const CClaimTrieNode* getNodeForName(const std::string& name) const;
|
|
|
|
|
|
|
|
bool update(nodeCacheType& cache, hashMapType& hashes,
|
|
|
|
std::map<std::string, int>& takeoverHeights,
|
|
|
|
const uint256& hashBlock, claimQueueType& queueCache,
|
|
|
|
queueNameType& queueNameCache,
|
|
|
|
expirationQueueType& expirationQueueCache, int nNewHeight,
|
|
|
|
supportMapType& supportCache,
|
|
|
|
supportQueueType& supportQueueCache,
|
|
|
|
queueNameType& supportQueueNameCache,
|
|
|
|
expirationQueueType& supportExpirationQueueCache);
|
|
|
|
bool updateName(const std::string& name, CClaimTrieNode* updatedNode);
|
|
|
|
bool updateHash(const std::string& name, uint256& hash);
|
|
|
|
bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight);
|
|
|
|
bool recursiveNullify(CClaimTrieNode* node, const std::string& name);
|
|
|
|
|
|
|
|
bool recursiveCheckConsistency(const CClaimTrieNode* node) const;
|
|
|
|
|
|
|
|
bool InsertFromDisk(const std::string& name, CClaimTrieNode* node);
|
|
|
|
|
|
|
|
unsigned int getTotalNamesRecursive(const CClaimTrieNode* current) const;
|
|
|
|
unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const;
|
|
|
|
CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current,
|
|
|
|
bool fControllingOnly) const;
|
|
|
|
|
|
|
|
bool getQueueRow(int nHeight, claimQueueRowType& row) const;
|
|
|
|
bool getQueueNameRow(const std::string& name, queueNameRowType& row) const;
|
|
|
|
bool getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const;
|
|
|
|
bool getSupportNode(std::string name, supportMapEntryType& node) const;
|
|
|
|
bool getSupportQueueRow(int nHeight, supportQueueRowType& row) const;
|
|
|
|
bool getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const;
|
|
|
|
bool getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const;
|
|
|
|
|
|
|
|
void markNodeDirty(const std::string& name, CClaimTrieNode* node);
|
|
|
|
void updateQueueRow(int nHeight, claimQueueRowType& row);
|
|
|
|
void updateQueueNameRow(const std::string& name,
|
|
|
|
queueNameRowType& row);
|
|
|
|
void updateExpirationRow(int nHeight, expirationQueueRowType& row);
|
|
|
|
void updateSupportMap(const std::string& name, supportMapEntryType& node);
|
|
|
|
void updateSupportQueue(int nHeight, supportQueueRowType& row);
|
|
|
|
void updateSupportNameQueue(const std::string& name,
|
|
|
|
queueNameRowType& row);
|
|
|
|
void updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row);
|
|
|
|
|
|
|
|
void BatchWriteNode(CDBBatch& batch, const std::string& name,
|
|
|
|
const CClaimTrieNode* pNode) const;
|
|
|
|
void BatchWriteQueueRows(CDBBatch& batch);
|
|
|
|
void BatchWriteQueueNameRows(CDBBatch& batch);
|
|
|
|
void BatchWriteExpirationQueueRows(CDBBatch& batch);
|
|
|
|
void BatchWriteSupportNodes(CDBBatch& batch);
|
|
|
|
void BatchWriteSupportQueueRows(CDBBatch& batch);
|
|
|
|
void BatchWriteSupportQueueNameRows(CDBBatch& batch);
|
|
|
|
void BatchWriteSupportExpirationQueueRows(CDBBatch& batch);
|
|
|
|
template<typename K> bool keyTypeEmpty(char key, K& dummy) const;
|
|
|
|
|
|
|
|
CClaimTrieNode root;
|
|
|
|
uint256 hashBlock;
|
|
|
|
|
|
|
|
claimQueueType dirtyQueueRows;
|
|
|
|
queueNameType dirtyQueueNameRows;
|
|
|
|
expirationQueueType dirtyExpirationQueueRows;
|
|
|
|
|
|
|
|
supportQueueType dirtySupportQueueRows;
|
|
|
|
queueNameType dirtySupportQueueNameRows;
|
|
|
|
expirationQueueType dirtySupportExpirationQueueRows;
|
|
|
|
|
|
|
|
nodeCacheType dirtyNodes;
|
|
|
|
supportMapType dirtySupportNodes;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimTrieProofNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CClaimTrieProofNode() {};
|
|
|
|
CClaimTrieProofNode(std::vector<std::pair<unsigned char, uint256> > children,
|
|
|
|
bool hasValue, uint256 valHash)
|
|
|
|
: children(std::move(children)), hasValue(hasValue), valHash(std::move(valHash))
|
|
|
|
{};
|
|
|
|
CClaimTrieProofNode(const CClaimTrieProofNode&) = default;
|
|
|
|
CClaimTrieProofNode(CClaimTrieProofNode&& other)
|
|
|
|
{
|
|
|
|
hasValue = other.hasValue;
|
|
|
|
valHash = std::move(other.valHash);
|
|
|
|
children = std::move(other.children);
|
|
|
|
}
|
|
|
|
CClaimTrieProofNode& operator=(const CClaimTrieProofNode&) = default;
|
|
|
|
CClaimTrieProofNode& operator=(CClaimTrieProofNode&& other)
|
|
|
|
{
|
|
|
|
if (this != &other)
|
|
|
|
{
|
|
|
|
hasValue = other.hasValue;
|
|
|
|
valHash = std::move(other.valHash);
|
|
|
|
children = std::move(other.children);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::pair<unsigned char, uint256> > children;
|
|
|
|
bool hasValue;
|
|
|
|
uint256 valHash;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimTrieProof
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CClaimTrieProof() {};
|
|
|
|
CClaimTrieProof(std::vector<CClaimTrieProofNode> nodes, bool hasValue, COutPoint outPoint, int nHeightOfLastTakeover) : nodes(std::move(nodes)), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) {}
|
|
|
|
CClaimTrieProof(const CClaimTrieProof&) = default;
|
|
|
|
CClaimTrieProof(CClaimTrieProof&& other)
|
|
|
|
{
|
|
|
|
hasValue = other.hasValue;
|
|
|
|
outPoint = std::move(other.outPoint);
|
|
|
|
nodes = std::move(other.nodes);
|
|
|
|
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
|
|
|
}
|
|
|
|
|
|
|
|
CClaimTrieProof& operator=(const CClaimTrieProof&) = default;
|
|
|
|
CClaimTrieProof& operator=(CClaimTrieProof&& other)
|
|
|
|
{
|
|
|
|
if (this != &other)
|
|
|
|
{
|
|
|
|
hasValue = other.hasValue;
|
|
|
|
outPoint = std::move(other.outPoint);
|
|
|
|
nodes = std::move(other.nodes);
|
|
|
|
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<CClaimTrieProofNode> nodes;
|
|
|
|
bool hasValue;
|
|
|
|
COutPoint outPoint;
|
|
|
|
int nHeightOfLastTakeover;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CNodeCallback {
|
|
|
|
struct CRecursionInterruptionException : public std::exception {
|
|
|
|
const bool success;
|
|
|
|
explicit CRecursionInterruptionException(bool success) : success(success) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual ~CNodeCallback()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback to be called on every trie node
|
|
|
|
* @param[in] name full name of the node
|
|
|
|
* @param[in] node pointer to node itself
|
|
|
|
*
|
|
|
|
* To breakout early throw an exception.
|
|
|
|
* Throwing CRecursionInterruptionException will allow you to set the return value of iterateTrie.
|
|
|
|
*/
|
|
|
|
virtual void visit(const std::string& name, const CClaimTrieNode* node) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimTrieCacheBase
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CClaimTrieCacheBase(CClaimTrie* base, bool fRequireTakeoverHeights = true)
|
|
|
|
: base(base), fRequireTakeoverHeights(fRequireTakeoverHeights)
|
|
|
|
{
|
|
|
|
assert(base);
|
|
|
|
nCurrentHeight = base->nCurrentHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint256 getMerkleHash(bool forceCompute = false) const;
|
|
|
|
|
|
|
|
bool empty() const;
|
|
|
|
bool flush();
|
|
|
|
bool dirty() const { return !dirtyHashes.empty(); }
|
|
|
|
|
|
|
|
CClaimTrieNode* getRoot() const
|
|
|
|
{
|
|
|
|
const auto iter = cache.find("");
|
|
|
|
return iter == cache.end() ? &(base->root) : iter->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool addClaim(const std::string& name, const COutPoint& outPoint,
|
|
|
|
uint160 claimId, CAmount nAmount, int nHeight) const;
|
|
|
|
bool undoAddClaim(const std::string& name, const COutPoint& outPoint, int nHeight) const;
|
|
|
|
bool spendClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const;
|
|
|
|
bool undoSpendClaim(const std::string& name, const COutPoint& outPoint,
|
|
|
|
uint160 claimId, CAmount nAmount, int nHeight,
|
|
|
|
int nValidAtHeight) const;
|
|
|
|
|
|
|
|
bool addSupport(const std::string& name, const COutPoint& outPoint,
|
|
|
|
CAmount nAmount, uint160 supportedClaimId,
|
|
|
|
int nHeight) const;
|
|
|
|
bool undoAddSupport(const std::string& name, const COutPoint& outPoint,
|
|
|
|
int nHeight) const;
|
|
|
|
bool spendSupport(const std::string& name, const COutPoint& outPoint,
|
|
|
|
int nHeight, int& nValidAtHeight) const;
|
|
|
|
bool undoSpendSupport(const std::string& name, const COutPoint& outPoint,
|
|
|
|
uint160 supportedClaimId, CAmount nAmount,
|
|
|
|
int nHeight, int nValidAtHeight) const;
|
|
|
|
|
|
|
|
uint256 getBestBlock();
|
|
|
|
void setBestBlock(const uint256& hashBlock);
|
|
|
|
|
|
|
|
virtual bool incrementBlock(insertUndoType& insertUndo,
|
|
|
|
claimQueueRowType& expireUndo,
|
|
|
|
insertUndoType& insertSupportUndo,
|
|
|
|
supportQueueRowType& expireSupportUndo,
|
|
|
|
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
|
|
|
virtual bool decrementBlock(insertUndoType& insertUndo,
|
|
|
|
claimQueueRowType& expireUndo,
|
|
|
|
insertUndoType& insertSupportUndo,
|
|
|
|
supportQueueRowType& expireSupportUndo,
|
|
|
|
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
|
|
|
|
|
|
|
virtual ~CClaimTrieCacheBase() { clear(); }
|
|
|
|
|
|
|
|
virtual bool getProofForName(const std::string& name, CClaimTrieProof& proof) const;
|
|
|
|
virtual bool getInfoForName(const std::string& name, CClaimValue& claim) const;
|
|
|
|
|
|
|
|
bool finalizeDecrement() const;
|
|
|
|
|
|
|
|
bool iterateTrie(CNodeCallback& callback) const;
|
|
|
|
|
|
|
|
virtual claimsForNameType getClaimsForName(const std::string& name) const;
|
|
|
|
|
|
|
|
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId,
|
|
|
|
std::vector<CSupportValue>* supports = nullptr) const;
|
|
|
|
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId,
|
|
|
|
std::vector<CSupportValue>* supports = nullptr) const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// Should be private: Do not use unless you know what you're doing.
|
|
|
|
CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original) const;
|
|
|
|
bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent,
|
|
|
|
const std::string& sPos,
|
|
|
|
bool forceCompute = false) const;
|
|
|
|
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified = nullptr) const;
|
|
|
|
void checkNamesForTakeover(insertUndoType& insertUndo, insertUndoType& insertSupportUndo,
|
|
|
|
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
|
|
|
|
|
|
|
|
virtual bool insertClaimIntoTrie(const std::string& name, CClaimValue claim,
|
|
|
|
bool fCheckTakeover = false) const;
|
|
|
|
virtual bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
|
|
|
|
CClaimValue& claim,
|
|
|
|
bool fCheckTakeover = false) const;
|
|
|
|
|
|
|
|
virtual bool insertSupportIntoMap(const std::string& name,
|
|
|
|
CSupportValue support,
|
|
|
|
bool fCheckTakeover) const;
|
|
|
|
virtual bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint,
|
|
|
|
CSupportValue& support,
|
|
|
|
bool fCheckTakeover) const;
|
|
|
|
|
|
|
|
virtual void addClaimToQueues(const std::string& name, CClaimValue& claim) const;
|
|
|
|
virtual bool addSupportToQueues(const std::string& name, CSupportValue& support) const;
|
|
|
|
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
|
|
|
|
|
|
|
|
void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const;
|
|
|
|
void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint,
|
|
|
|
int nHeight) const;
|
|
|
|
|
|
|
|
void addSupportToExpirationQueue(int nExpirationHeight,
|
|
|
|
nameOutPointType& entry) const;
|
|
|
|
void removeSupportFromExpirationQueue(const std::string& name,
|
|
|
|
const COutPoint& outPoint,
|
|
|
|
int nHeight) const;
|
|
|
|
|
|
|
|
bool getSupportsForName(const std::string& name,
|
|
|
|
supportMapEntryType& supports) const;
|
|
|
|
|
|
|
|
virtual int getDelayForName(const std::string& name, const uint160& claimId) const;
|
|
|
|
|
|
|
|
mutable nodeCacheType cache;
|
|
|
|
CClaimTrie* base;
|
|
|
|
mutable int nCurrentHeight; // Height of the block that is being worked on, which is
|
|
|
|
// one greater than the height of the chain's tip
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
bool fRequireTakeoverHeights;
|
|
|
|
|
|
|
|
mutable nodeCacheType block_originals;
|
|
|
|
mutable std::set<std::string> dirtyHashes;
|
|
|
|
mutable hashMapType cacheHashes;
|
|
|
|
mutable claimQueueType claimQueueCache;
|
|
|
|
mutable queueNameType claimQueueNameCache;
|
|
|
|
mutable expirationQueueType expirationQueueCache;
|
|
|
|
mutable supportMapType supportCache;
|
|
|
|
mutable supportQueueType supportQueueCache;
|
|
|
|
mutable queueNameType supportQueueNameCache;
|
|
|
|
mutable expirationQueueType supportExpirationQueueCache;
|
|
|
|
mutable std::set<std::string> namesToCheckForTakeover;
|
|
|
|
mutable std::map<std::string, int> cacheTakeoverHeights;
|
|
|
|
mutable claimIndexElementListType claimsToAdd;
|
|
|
|
mutable claimIndexClaimListType claimsToDelete;
|
|
|
|
|
|
|
|
uint256 hashBlock;
|
|
|
|
|
|
|
|
bool reorderTrieNode(const std::string& name, bool fCheckTakeover) const;
|
|
|
|
|
|
|
|
bool clear() const;
|
|
|
|
|
|
|
|
// generally the opposite of addClaimToQueues, but they aren't perfectly symmetrical:
|
|
|
|
bool removeClaim(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const;
|
|
|
|
bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint,
|
|
|
|
CClaimValue& claim) const;
|
|
|
|
|
|
|
|
claimQueueType::iterator getQueueCacheRow(int nHeight,
|
|
|
|
bool createIfNotExists) const;
|
|
|
|
queueNameType::iterator getQueueCacheNameRow(const std::string& name,
|
|
|
|
bool createIfNotExists) const;
|
|
|
|
expirationQueueType::iterator getExpirationQueueCacheRow(int nHeight,
|
|
|
|
bool createIfNotExists) const;
|
|
|
|
|
|
|
|
bool removeSupport(const std::string& name, const COutPoint& outPoint,
|
|
|
|
int nHeight, int& nValidAtHeight,
|
|
|
|
bool fCheckTakeover) const;
|
|
|
|
|
|
|
|
supportQueueType::iterator getSupportQueueCacheRow(int nHeight,
|
|
|
|
bool createIfNotExists) const;
|
|
|
|
queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name,
|
|
|
|
bool createIfNotExists) const;
|
|
|
|
expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight,
|
|
|
|
bool createIfNotExists) const;
|
|
|
|
|
|
|
|
bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint,
|
|
|
|
CSupportValue& support) const;
|
|
|
|
|
|
|
|
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
|
|
|
|
|
|
|
|
int getDelayForName(const std::string& name) const;
|
|
|
|
|
|
|
|
uint256 getLeafHashForProof(const std::string& currentPosition, const CClaimTrieNode* currentNode) const;
|
|
|
|
|
|
|
|
bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const;
|
|
|
|
|
|
|
|
int getNumBlocksOfContinuousOwnership(const std::string& name) const;
|
|
|
|
|
|
|
|
void recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const;
|
|
|
|
|
|
|
|
const CClaimTrieNode* getNodeForName(const std::string& name) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimTrieCacheExpirationFork: public CClaimTrieCacheBase {
|
|
|
|
public:
|
|
|
|
CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true)
|
|
|
|
: CClaimTrieCacheBase(base, fRequireTakeoverHeights) {}
|
|
|
|
|
|
|
|
virtual ~CClaimTrieCacheExpirationFork() {}
|
|
|
|
|
|
|
|
bool forkForExpirationChange(bool increment) const;
|
|
|
|
|
|
|
|
// TODO: move the expiration fork code from main.cpp to overrides of increment/decrement block
|
|
|
|
|
|
|
|
private:
|
|
|
|
void removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const;
|
|
|
|
void removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CClaimTrieCacheNormalizationFork: public CClaimTrieCacheExpirationFork {
|
|
|
|
public:
|
|
|
|
CClaimTrieCacheNormalizationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true)
|
|
|
|
: CClaimTrieCacheExpirationFork(base, fRequireTakeoverHeights),
|
|
|
|
overrideInsertNormalization(false), overrideRemoveNormalization(false) {}
|
|
|
|
|
|
|
|
virtual ~CClaimTrieCacheNormalizationFork() {}
|
|
|
|
|
|
|
|
bool shouldNormalize() const;
|
|
|
|
|
|
|
|
// lower-case and normalize any input string name
|
|
|
|
// see: https://unicode.org/reports/tr15/#Norm_Forms
|
|
|
|
std::string normalizeClaimName(const std::string& name, bool force = false) const; // public only for validating name field on update op
|
|
|
|
|
|
|
|
virtual bool incrementBlock(insertUndoType& insertUndo,
|
|
|
|
claimQueueRowType& expireUndo,
|
|
|
|
insertUndoType& insertSupportUndo,
|
|
|
|
supportQueueRowType& expireSupportUndo,
|
|
|
|
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
|
|
|
virtual bool decrementBlock(insertUndoType& insertUndo,
|
|
|
|
claimQueueRowType& expireUndo,
|
|
|
|
insertUndoType& insertSupportUndo,
|
|
|
|
supportQueueRowType& expireSupportUndo,
|
|
|
|
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
|
|
|
|
|
|
|
virtual bool getProofForName(const std::string& name, CClaimTrieProof& proof) const;
|
|
|
|
virtual bool getInfoForName(const std::string& name, CClaimValue& claim) const;
|
|
|
|
virtual claimsForNameType getClaimsForName(const std::string& name) const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual bool insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover = false) const;
|
|
|
|
virtual bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
|
|
|
|
CClaimValue& claim, bool fCheckTakeover = false) const;
|
|
|
|
|
|
|
|
virtual bool insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const;
|
|
|
|
virtual bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint,
|
|
|
|
CSupportValue& support, bool fCheckTakeover) const;
|
|
|
|
virtual int getDelayForName(const std::string& name, const uint160& claimId) const;
|
|
|
|
|
|
|
|
virtual void addClaimToQueues(const std::string& name, CClaimValue& claim) const;
|
|
|
|
virtual bool addSupportToQueues(const std::string& name, CSupportValue& support) const;
|
|
|
|
virtual std::string adjustNameForValidHeight(const std::string& name, int validHeight) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool overrideInsertNormalization, overrideRemoveNormalization;
|
|
|
|
bool normalizeAllNamesInTrieIfNecessary(insertUndoType& insertUndo, claimQueueRowType& removeUndo,
|
|
|
|
insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo,
|
|
|
|
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef CClaimTrieCacheNormalizationFork CClaimTrieCache;
|
|
|
|
|
|
|
|
#endif // BITCOIN_CLAIMTRIE_H
|