Add block hash parameter to claimtrie rpc methods
Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
parent
24da3ac57a
commit
f86eb54077
6 changed files with 650 additions and 291 deletions
|
@ -527,39 +527,26 @@ claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const
|
|||
}
|
||||
|
||||
//return effective amount from claim, retuns 0 if claim is not found
|
||||
CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const
|
||||
CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports) const
|
||||
{
|
||||
std::vector<CSupportValue> supports;
|
||||
return getEffectiveAmountForClaimWithSupports(name, claimId, supports);
|
||||
return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports);
|
||||
}
|
||||
|
||||
//return effective amount from claim and the supports used as inputs, retuns 0 if claim is not found
|
||||
CAmount CClaimTrie::getEffectiveAmountForClaimWithSupports(const std::string& name, uint160 claimId,
|
||||
std::vector<CSupportValue>& supports) const
|
||||
CAmount CClaimTrie::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports) const
|
||||
{
|
||||
claimsForNameType claims = getClaimsForName(name);
|
||||
CAmount effectiveAmount = 0;
|
||||
bool claim_found = false;
|
||||
for (std::vector<CClaimValue>::iterator it=claims.claims.begin(); it!=claims.claims.end(); ++it)
|
||||
{
|
||||
if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight)
|
||||
{
|
||||
for (std::vector<CClaimValue>::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) {
|
||||
if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) {
|
||||
effectiveAmount += it->nAmount;
|
||||
claim_found = true;
|
||||
for (std::vector<CSupportValue>::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) {
|
||||
if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) {
|
||||
effectiveAmount += it->nAmount;
|
||||
if (supports) supports->push_back(*it);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!claim_found)
|
||||
return effectiveAmount;
|
||||
|
||||
for (std::vector<CSupportValue>::iterator it=claims.supports.begin(); it!=claims.supports.end(); ++it)
|
||||
{
|
||||
if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight)
|
||||
{
|
||||
effectiveAmount += it->nAmount;
|
||||
supports.push_back(*it);
|
||||
}
|
||||
}
|
||||
return effectiveAmount;
|
||||
}
|
||||
|
||||
|
@ -2463,25 +2450,26 @@ bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLast
|
|||
|
||||
int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) const
|
||||
{
|
||||
const CClaimTrieNode* node = NULL;
|
||||
nodeCacheType::const_iterator itCache = cache.find(name);
|
||||
if (itCache != cache.end())
|
||||
{
|
||||
node = itCache->second;
|
||||
}
|
||||
if (!node)
|
||||
{
|
||||
node = base->getNodeForName(name);
|
||||
}
|
||||
if (!node || node->claims.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const CClaimTrieNode* node = getNodeForName(name);
|
||||
if (!node || node->claims.empty()) return 0;
|
||||
int nLastTakeoverHeight;
|
||||
assert(getLastTakeoverForName(name, nLastTakeoverHeight));
|
||||
return nCurrentHeight - nLastTakeoverHeight;
|
||||
}
|
||||
|
||||
const CClaimTrieNode* CClaimTrieCache::getNodeForName(const std::string& name) const
|
||||
{
|
||||
const CClaimTrieNode* node = NULL;
|
||||
nodeCacheType::const_iterator itCache = cache.find(name);
|
||||
if (itCache != cache.end()) {
|
||||
node = itCache->second;
|
||||
}
|
||||
if (!node) {
|
||||
node = base->getNodeForName(name);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
int CClaimTrieCache::getDelayForName(const std::string& name) const
|
||||
{
|
||||
if (!fRequireTakeoverHeights)
|
||||
|
@ -2570,10 +2558,125 @@ uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition,
|
|||
}
|
||||
}
|
||||
|
||||
CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const
|
||||
void CClaimTrieCache::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const
|
||||
{
|
||||
nodes.push_back(std::make_pair(name, *current));
|
||||
nodeCacheType::const_iterator cachedNode;
|
||||
for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) {
|
||||
const std::string str = name + char(it->first);
|
||||
cachedNode = cache.find(str);
|
||||
if (cachedNode != cache.end())
|
||||
recursiveFlattenTrie(str, cachedNode->second, nodes);
|
||||
else
|
||||
recursiveFlattenTrie(str, it->second, nodes);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<namedNodeType> CClaimTrieCache::flattenTrie() const
|
||||
{
|
||||
std::vector<namedNodeType> nodes;
|
||||
recursiveFlattenTrie("", &(base->root), nodes);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
claimsForNameType CClaimTrieCache::getClaimsForName(const std::string& name) const
|
||||
{
|
||||
int nLastTakeoverHeight = 0;
|
||||
std::vector<CClaimValue> claims;
|
||||
if (const CClaimTrieNode* node = getNodeForName(name)) {
|
||||
claims = node->claims;
|
||||
getLastTakeoverForName(name, nLastTakeoverHeight);
|
||||
}
|
||||
supportMapEntryType supports;
|
||||
getSupportsForName(name, supports);
|
||||
queueNameType::const_iterator itQueueNameCache = getQueueCacheNameRow(name, false);
|
||||
if (itQueueNameCache != claimQueueNameCache.end()) {
|
||||
const queueNameRowType& namedClaimRow = itQueueNameCache->second;
|
||||
for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) {
|
||||
claimQueueType::const_iterator itQueueCache = getQueueCacheRow(itClaimsForName->nHeight, false);
|
||||
if (itQueueCache != claimQueueCache.end()) {
|
||||
const claimQueueRowType& claimRow = itQueueCache->second;
|
||||
for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) {
|
||||
if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) {
|
||||
claims.push_back(itClaimRow->second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
queueNameType::const_iterator itSupportQueueNameCache = getSupportQueueCacheNameRow(name, false);
|
||||
if (itSupportQueueNameCache != supportQueueNameCache.end()) {
|
||||
const queueNameRowType& namedSupportRow = itSupportQueueNameCache->second;
|
||||
for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) {
|
||||
supportQueueType::const_iterator itSupportQueueCache = getSupportQueueCacheRow(itSupportsForName->nHeight, false);
|
||||
if (itSupportQueueCache != supportQueueCache.end()) {
|
||||
const supportQueueRowType& supportRow = itSupportQueueCache->second;
|
||||
for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) {
|
||||
if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) {
|
||||
supports.push_back(itSupportRow->second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return claimsForNameType(claims, supports, nLastTakeoverHeight);
|
||||
}
|
||||
|
||||
CAmount CClaimTrieCache::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports) const
|
||||
{
|
||||
return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports);
|
||||
}
|
||||
|
||||
CAmount CClaimTrieCache::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports) const
|
||||
{
|
||||
CAmount effectiveAmount = 0;
|
||||
for (std::vector<CClaimValue>::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) {
|
||||
if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) {
|
||||
effectiveAmount += it->nAmount;
|
||||
for (std::vector<CSupportValue>::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) {
|
||||
if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) {
|
||||
effectiveAmount += it->nAmount;
|
||||
if (supports) supports->push_back(*it);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return effectiveAmount;
|
||||
}
|
||||
|
||||
bool CClaimTrieCache::getInfoForName(const std::string& name, CClaimValue& claim) const
|
||||
{
|
||||
if (dirty())
|
||||
getMerkleHash();
|
||||
|
||||
CClaimTrieNode* current = &(base->root);
|
||||
nodeCacheType::const_iterator cachedNode;
|
||||
|
||||
for (std::string::const_iterator itName = name.begin(); current; ++itName) {
|
||||
std::string currentPosition(name.begin(), itName);
|
||||
cachedNode = cache.find(currentPosition);
|
||||
if (cachedNode != cache.end())
|
||||
current = cachedNode->second;
|
||||
|
||||
if (itName == name.end())
|
||||
return current->getBestClaim(claim);
|
||||
|
||||
nodeMapType::const_iterator itChildren = current->children.find(*itName);
|
||||
if (itChildren != current->children.end()) {
|
||||
current = itChildren->second;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& proof) const
|
||||
{
|
||||
if (dirty())
|
||||
getMerkleHash();
|
||||
|
||||
std::vector<CClaimTrieProofNode> nodes;
|
||||
CClaimTrieNode* current = &(base->root);
|
||||
nodeCacheType::const_iterator cachedNode;
|
||||
|
@ -2592,7 +2695,8 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const
|
|||
if (fNodeHasValue)
|
||||
{
|
||||
int nHeightOfLastTakeover;
|
||||
assert(getLastTakeoverForName(currentPosition, nHeightOfLastTakeover));
|
||||
if (!getLastTakeoverForName(currentPosition, nHeightOfLastTakeover))
|
||||
return false;
|
||||
valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover);
|
||||
}
|
||||
std::vector<std::pair<unsigned char, uint256> > children;
|
||||
|
@ -2617,7 +2721,8 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const
|
|||
if (fNameHasValue)
|
||||
{
|
||||
outPoint = claim.outPoint;
|
||||
assert(getLastTakeoverForName(name, nHeightOfLastTakeover));
|
||||
if (!getLastTakeoverForName(name, nHeightOfLastTakeover))
|
||||
return false;
|
||||
}
|
||||
valueHash.SetNull();
|
||||
}
|
||||
|
@ -2625,8 +2730,8 @@ CClaimTrieProof CClaimTrieCache::getProofForName(const std::string& name) const
|
|||
nodes.push_back(node);
|
||||
current = nextCurrent;
|
||||
}
|
||||
return CClaimTrieProof(nodes, fNameHasValue, outPoint,
|
||||
nHeightOfLastTakeover);
|
||||
proof = CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -323,9 +323,8 @@ public:
|
|||
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
|
||||
|
||||
claimsForNameType getClaimsForName(const std::string& name) const;
|
||||
CAmount getEffectiveAmountForClaim(const std::string& name, uint160 claimId) const;
|
||||
CAmount getEffectiveAmountForClaimWithSupports(const std::string& name, uint160 claimId,
|
||||
std::vector<CSupportValue>& supports) const;
|
||||
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
|
||||
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
|
||||
|
||||
bool queueEmpty() const;
|
||||
bool supportEmpty() const;
|
||||
|
@ -519,7 +518,9 @@ public:
|
|||
bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
|
||||
CClaimValue& claim,
|
||||
bool fCheckTakeover = false) const;
|
||||
CClaimTrieProof getProofForName(const std::string& name) const;
|
||||
|
||||
bool getProofForName(const std::string& name, CClaimTrieProof& proof) const;
|
||||
bool getInfoForName(const std::string& name, CClaimValue& claim) const;
|
||||
|
||||
bool finalizeDecrement() const;
|
||||
|
||||
|
@ -528,6 +529,12 @@ public:
|
|||
|
||||
bool forkForExpirationChange(bool increment) const;
|
||||
|
||||
std::vector<namedNodeType> flattenTrie() const;
|
||||
|
||||
claimsForNameType getClaimsForName(const std::string& name) const;
|
||||
|
||||
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
|
||||
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector<CSupportValue>* supports = NULL) const;
|
||||
|
||||
protected:
|
||||
CClaimTrie* base;
|
||||
|
@ -625,6 +632,10 @@ protected:
|
|||
bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const;
|
||||
|
||||
int getNumBlocksOfContinuousOwnership(const std::string& name) const;
|
||||
|
||||
void recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const;
|
||||
|
||||
const CClaimTrieNode* getNodeForName(const std::string& name) const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_CLAIMTRIE_H
|
||||
|
|
59
src/main.cpp
59
src/main.cpp
|
@ -4267,40 +4267,43 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
for (CBlockIndex* index = chainActive.Tip(); index && index != targetIndex; index = index->pprev) {
|
||||
boost::this_thread::interruption_point();
|
||||
CBlock block;
|
||||
|
||||
if (!ReadBlockFromDisk(block, index, Params().GetConsensus()))
|
||||
return false; // return error() instead?
|
||||
|
||||
if (coinsCache.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage() > nCoinCacheUsage)
|
||||
return false; // don't allow a single query to chew up all our memory?
|
||||
|
||||
if (ShutdownRequested())
|
||||
return false;
|
||||
|
||||
CValidationState state;
|
||||
if (!DisconnectBlock(block, state, index, coinsCache, trieCache))
|
||||
return false;
|
||||
|
||||
if (state.IsError())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
if (!chainActive.Contains(pindexProof))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CCoinsViewCache coins(pcoinsTip);
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
CBlockIndex* pindexState = chainActive.Tip();
|
||||
CValidationState state;
|
||||
for (CBlockIndex *pindex = chainActive.Tip(); pindex && pindex->pprev && pindexState != pindexProof; pindex=pindex->pprev)
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
CBlock block;
|
||||
if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage)
|
||||
{
|
||||
bool fClean = true;
|
||||
if (!DisconnectBlock(block, state, pindex, coins, trieCache, &fClean))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
pindexState = pindex->pprev;
|
||||
}
|
||||
if (ShutdownRequested())
|
||||
return false;
|
||||
}
|
||||
assert(pindexState == pindexProof);
|
||||
proof = trieCache.getProofForName(name);
|
||||
return true;
|
||||
if (RollBackTo(pindexProof, coinsCache, trieCache))
|
||||
return trieCache.getProofForName(name, proof);
|
||||
return false;
|
||||
}
|
||||
|
||||
void UnloadBlockIndex()
|
||||
|
|
|
@ -225,6 +225,8 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
|||
FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
||||
/** Translation to a filesystem path */
|
||||
boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
|
||||
/** Utility method for going back to a previous state **/
|
||||
bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache);
|
||||
/** Get a cryptographic proof that a name maps to a value **/
|
||||
bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof);
|
||||
/** Import blocks from an external file */
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#include "boost/scope_exit.hpp"
|
||||
#include "consensus/validation.h"
|
||||
#include "main.h"
|
||||
#include "nameclaim.h"
|
||||
#include "rpc/server.h"
|
||||
#include "univalue.h"
|
||||
#include "txmempool.h"
|
||||
#include "univalue.h"
|
||||
|
||||
// Maximum block decrement that is allowed from rpc calls
|
||||
const int MAX_RPC_BLOCK_DECREMENTS = 50;
|
||||
|
@ -22,143 +24,177 @@ uint160 ParseClaimtrieId(const UniValue& v, const std::string& strName)
|
|||
return result;
|
||||
}
|
||||
|
||||
static CBlockIndex* BlockHashIndex(const uint256& blockHash)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
if (mapBlockIndex.count(blockHash) == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
||||
CBlockIndex* pblockIndex = mapBlockIndex[blockHash];
|
||||
if (!chainActive.Contains(pblockIndex))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain");
|
||||
|
||||
if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to regenerate it");
|
||||
|
||||
return pblockIndex;
|
||||
}
|
||||
|
||||
UniValue getclaimsintrie(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 0)
|
||||
if (fHelp || params.size() > 1)
|
||||
throw std::runtime_error(
|
||||
"getclaimsintrie\n"
|
||||
"Return all claims in the name trie.\n"
|
||||
"Arguments:\n"
|
||||
"None\n"
|
||||
"1. \"blockhash\" (string, optional) get claims in the trie\n"
|
||||
" at the block specified\n"
|
||||
" by this block hash.\n"
|
||||
" If none is given,\n"
|
||||
" the latest active\n"
|
||||
" block will be used.\n"
|
||||
"Result: \n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"name\" (string) the name claimed\n"
|
||||
" \"claims\": [ (array of object) the claims for this name\n"
|
||||
" \"name\" (string) the name claimed\n"
|
||||
" \"claims\": [ (array of object) the claims for this name\n"
|
||||
" {\n"
|
||||
" \"claimId\" (string) the claimId of the claim\n"
|
||||
" \"txid\" (string) the txid of the claim\n"
|
||||
" \"n\" (numeric) the vout value of the claim\n"
|
||||
" \"amount\" (numeric) txout amount\n"
|
||||
" \"height\" (numeric) the height of the block in which this transaction is located\n"
|
||||
" \"value\" (string) the value of this claim\n"
|
||||
" \"claimId\" (string) the claimId of the claim\n"
|
||||
" \"txid\" (string) the txid of the claim\n"
|
||||
" \"n\" (numeric) the vout value of the claim\n"
|
||||
" \"amount\" (numeric) txout amount\n"
|
||||
" \"height\" (numeric) the height of the block in which this transaction is located\n"
|
||||
" \"value\" (string) the value of this claim\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
"]\n"
|
||||
);
|
||||
|
||||
"]\n");
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (!params.empty()) {
|
||||
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)"));
|
||||
if (!RollBackTo(blockIndex, coinsCache, trieCache))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure");
|
||||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
std::vector<namedNodeType> nodes = trieCache.flattenTrie();
|
||||
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
|
||||
if (it->second.claims.empty()) continue;
|
||||
|
||||
CCoinsViewCache view(pcoinsTip);
|
||||
std::vector<namedNodeType> nodes = pclaimTrie->flattenTrie();
|
||||
|
||||
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it)
|
||||
{
|
||||
if (!it->second.claims.empty())
|
||||
{
|
||||
UniValue node(UniValue::VOBJ);
|
||||
node.push_back(Pair("name", it->first));
|
||||
UniValue claims(UniValue::VARR);
|
||||
for (std::vector<CClaimValue>::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims)
|
||||
{
|
||||
UniValue claim(UniValue::VOBJ);
|
||||
claim.push_back(Pair("claimId", itClaims->claimId.GetHex()));
|
||||
claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex()));
|
||||
claim.push_back(Pair("n", (int)itClaims->outPoint.n));
|
||||
claim.push_back(Pair("amount", ValueFromAmount(itClaims->nAmount)));
|
||||
claim.push_back(Pair("height", itClaims->nHeight));
|
||||
const CCoins* coin = view.AccessCoins(itClaims->outPoint.hash);
|
||||
if (!coin)
|
||||
{
|
||||
LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n",
|
||||
__func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "No value found for claim"));
|
||||
UniValue claims(UniValue::VARR);
|
||||
for (std::vector<CClaimValue>::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims) {
|
||||
UniValue claim(UniValue::VOBJ);
|
||||
claim.push_back(Pair("claimId", itClaims->claimId.GetHex()));
|
||||
claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex()));
|
||||
claim.push_back(Pair("n", (int)itClaims->outPoint.n));
|
||||
claim.push_back(Pair("amount", ValueFromAmount(itClaims->nAmount)));
|
||||
claim.push_back(Pair("height", itClaims->nHeight));
|
||||
const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash);
|
||||
if (!coin) {
|
||||
LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n",
|
||||
__func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "No value found for claim"));
|
||||
} else if (!coin->IsAvailable(itClaims->outPoint.n)) {
|
||||
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "Txout spent"));
|
||||
} else {
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) {
|
||||
LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
}
|
||||
else if (!coin->IsAvailable(itClaims->outPoint.n))
|
||||
{
|
||||
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "Txout spent"));
|
||||
}
|
||||
else
|
||||
{
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams))
|
||||
{
|
||||
LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
}
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
claim.push_back(Pair("value", sValue));
|
||||
}
|
||||
claims.push_back(claim);
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
claim.push_back(Pair("value", sValue));
|
||||
}
|
||||
node.push_back(Pair("claims", claims));
|
||||
ret.push_back(node);
|
||||
claims.push_back(claim);
|
||||
}
|
||||
|
||||
UniValue node(UniValue::VOBJ);
|
||||
node.push_back(Pair("name", it->first));
|
||||
node.push_back(Pair("claims", claims));
|
||||
ret.push_back(node);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue getclaimtrie(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 0)
|
||||
if (fHelp || params.size() > 1)
|
||||
throw std::runtime_error(
|
||||
"getclaimtrie\n"
|
||||
"Return the entire name trie.\n"
|
||||
"Arguments:\n"
|
||||
"None\n"
|
||||
"1. \"blockhash\" (string, optional) get claim in the trie\n"
|
||||
" at the block specified\n"
|
||||
" by this block hash.\n"
|
||||
" If none is given,\n"
|
||||
" the latest active\n"
|
||||
" block will be used.\n"
|
||||
"Result: \n"
|
||||
"{\n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"name\" (string) the name of the node\n"
|
||||
" \"hash\" (string) the hash of the node\n"
|
||||
" \"txid\" (string) (if value exists) the hash of the transaction which has successfully claimed this name\n"
|
||||
" \"n\" (numeric) (if value exists) vout value\n"
|
||||
" \"value\" (numeric) (if value exists) txout value\n"
|
||||
" \"height\" (numeric) (if value exists) the height of the block in which this transaction is located\n"
|
||||
"}\n"
|
||||
);
|
||||
" }\n"
|
||||
"]\n");
|
||||
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VARR);
|
||||
|
||||
std::vector<namedNodeType> nodes = pclaimTrie->flattenTrie();
|
||||
CCoinsViewCache coinsCache(pcoinsTip);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (!params.empty()) {
|
||||
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[0], "blockhash (optional parameter 1)"));
|
||||
if (!RollBackTo(blockIndex, coinsCache, trieCache))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure");
|
||||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
std::vector<namedNodeType> nodes = trieCache.flattenTrie();
|
||||
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it)
|
||||
{
|
||||
UniValue node(UniValue::VOBJ);
|
||||
node.push_back(Pair("name", it->first));
|
||||
node.push_back(Pair("name", it->first));
|
||||
node.push_back(Pair("hash", it->second.hash.GetHex()));
|
||||
CClaimValue claim;
|
||||
if (it->second.getBestClaim(claim))
|
||||
{
|
||||
node.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
|
||||
node.push_back(Pair("n", (int)claim.outPoint.n));
|
||||
node.push_back(Pair("value", ValueFromAmount(claim.nAmount)));
|
||||
node.push_back(Pair("height", claim.nHeight));
|
||||
node.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
|
||||
node.push_back(Pair("n", (int)claim.outPoint.n));
|
||||
node.push_back(Pair("value", ValueFromAmount(claim.nAmount)));
|
||||
node.push_back(Pair("height", claim.nHeight));
|
||||
}
|
||||
ret.push_back(node);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool getValueForClaim(const COutPoint& out, std::string& sValue)
|
||||
bool getValueForClaim(const CCoinsViewCache& coinsCache, const COutPoint& out, std::string& sValue)
|
||||
{
|
||||
CCoinsViewCache view(pcoinsTip);
|
||||
const CCoins* coin = view.AccessCoins(out.hash);
|
||||
const CCoins* coin = coinsCache.AccessCoins(out.hash);
|
||||
if (!coin)
|
||||
{
|
||||
LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n",
|
||||
__func__, out.hash.GetHex());
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!coin->IsAvailable(out.n))
|
||||
{
|
||||
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, out.hash.GetHex());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(coin->vout[out.n].scriptPubKey, op, vvchParams))
|
||||
|
@ -180,118 +216,113 @@ bool getValueForClaim(const COutPoint& out, std::string& sValue)
|
|||
|
||||
UniValue getvalueforname(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
if (fHelp || params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
"getvalueforname \"name\"\n"
|
||||
"Return the value associated with a name, if one exists\n"
|
||||
"Arguments:\n"
|
||||
"1. \"name\" (string) the name to look up\n"
|
||||
"1. \"name\" (string) the name to look up\n"
|
||||
"2. \"blockhash\" (string, optional) get the value\n"
|
||||
" associated with the name\n"
|
||||
" at the block specified\n"
|
||||
" by this block hash.\n"
|
||||
" If none is given,\n"
|
||||
" the latest active\n"
|
||||
" block will be used.\n"
|
||||
"Result: \n"
|
||||
"\"value\" (string) the value of the name, if it exists\n"
|
||||
"\"claimId\" (string) the claimId for this name claim\n"
|
||||
"\"txid\" (string) the hash of the transaction which successfully claimed the name\n"
|
||||
"\"n\" (numeric) vout value\n"
|
||||
"\"amount\" (numeric) txout amount\n"
|
||||
"\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n"
|
||||
"\"height\" (numeric) the height of the block in which this transaction is located\n"
|
||||
);
|
||||
"\"value\" (string) the value of the name, if it exists\n"
|
||||
"\"claimId\" (string) the claimId for this name claim\n"
|
||||
"\"txid\" (string) the hash of the transaction which successfully claimed the name\n"
|
||||
"\"n\" (numeric) vout value\n"
|
||||
"\"amount\" (numeric) txout amount\n"
|
||||
"\"effective amount\" (numeric) txout amount plus amount from all supports associated with the claim\n"
|
||||
"\"height\" (numeric) the height of the block in which this transaction is located\n");
|
||||
|
||||
LOCK(cs_main);
|
||||
std::string name = params[0].get_str();
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (params.size() > 1) {
|
||||
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)"));
|
||||
if (!RollBackTo(blockIndex, coinsCache, trieCache))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure");
|
||||
}
|
||||
|
||||
CClaimValue claim;
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
if (!pclaimTrie->getInfoForName(name, claim))
|
||||
return ret;
|
||||
std::string name = params[0].get_str();
|
||||
if (!trieCache.getInfoForName(name, claim))
|
||||
return ret; // they may have asked for a name that doesn't exist (which is not an error)
|
||||
|
||||
std::string sValue;
|
||||
if (!getValueForClaim(claim.outPoint, sValue))
|
||||
if (!getValueForClaim(coinsCache, claim.outPoint, sValue))
|
||||
return ret;
|
||||
|
||||
CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(name, claim.claimId);
|
||||
|
||||
ret.push_back(Pair("value", sValue));
|
||||
ret.push_back(Pair("claimId", claim.claimId.GetHex()));
|
||||
ret.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
|
||||
ret.push_back(Pair("n", (int)claim.outPoint.n));
|
||||
ret.push_back(Pair("amount", claim.nAmount));
|
||||
ret.push_back(Pair("effective amount", pclaimTrie->getEffectiveAmountForClaim(name, claim.claimId)));
|
||||
ret.push_back(Pair("effective amount", nEffectiveAmount));
|
||||
ret.push_back(Pair("height", claim.nHeight));
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef std::pair<CClaimValue, std::vector<CSupportValue> > claimAndSupportsType;
|
||||
typedef std::map<uint160, claimAndSupportsType> claimSupportMapType;
|
||||
typedef std::map<uint160, std::vector<CSupportValue> > supportsWithoutClaimsMapType;
|
||||
|
||||
UniValue claimsAndSupportsToJSON(claimSupportMapType::const_iterator itClaimsAndSupports, int nCurrentHeight)
|
||||
UniValue supportToJSON(const CSupportValue& support)
|
||||
{
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
ret.push_back(Pair("txid", support.outPoint.hash.GetHex()));
|
||||
ret.push_back(Pair("n", (int)support.outPoint.n));
|
||||
ret.push_back(Pair("nHeight", support.nHeight));
|
||||
ret.push_back(Pair("nValidAtHeight", support.nValidAtHeight));
|
||||
ret.push_back(Pair("nAmount", support.nAmount));
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue claimAndSupportsToJSON(CAmount nEffectiveAmount, claimSupportMapType::const_iterator itClaimsAndSupports)
|
||||
{
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
const CClaimValue& claim = itClaimsAndSupports->second.first;
|
||||
const std::vector<CSupportValue>& supports = itClaimsAndSupports->second.second;
|
||||
CAmount nEffectiveAmount = 0;
|
||||
UniValue supportObjs(UniValue::VARR);
|
||||
for (std::vector<CSupportValue>::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports)
|
||||
{
|
||||
UniValue supportObj(UniValue::VOBJ);
|
||||
supportObj.push_back(Pair("txid", itSupports->outPoint.hash.GetHex()));
|
||||
supportObj.push_back(Pair("n", (int)itSupports->outPoint.n));
|
||||
supportObj.push_back(Pair("nHeight", itSupports->nHeight));
|
||||
supportObj.push_back(Pair("nValidAtHeight", itSupports->nValidAtHeight));
|
||||
if (itSupports->nValidAtHeight < nCurrentHeight)
|
||||
{
|
||||
nEffectiveAmount += itSupports->nAmount;
|
||||
}
|
||||
supportObj.push_back(Pair("nAmount", itSupports->nAmount));
|
||||
supportObjs.push_back(supportObj);
|
||||
for (std::vector<CSupportValue>::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports) {
|
||||
supportObjs.push_back(supportToJSON(*itSupports));
|
||||
}
|
||||
ret.push_back(Pair("claimId", itClaimsAndSupports->first.GetHex()));
|
||||
ret.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
|
||||
ret.push_back(Pair("n", (int)claim.outPoint.n));
|
||||
ret.push_back(Pair("nHeight", claim.nHeight));
|
||||
ret.push_back(Pair("nValidAtHeight", claim.nValidAtHeight));
|
||||
if (claim.nValidAtHeight < nCurrentHeight)
|
||||
{
|
||||
nEffectiveAmount += claim.nAmount;
|
||||
}
|
||||
ret.push_back(Pair("nAmount", claim.nAmount));
|
||||
std::string sValue;
|
||||
if (getValueForClaim(claim.outPoint, sValue))
|
||||
{
|
||||
ret.push_back(Pair("value", sValue));
|
||||
}
|
||||
ret.push_back(Pair("nEffectiveAmount", nEffectiveAmount));
|
||||
ret.push_back(Pair("supports", supportObjs));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims, int nCurrentHeight)
|
||||
{
|
||||
const std::vector<CSupportValue>& supports = itSupportsWithoutClaims->second;
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
UniValue supportObjs(UniValue::VARR);
|
||||
ret.push_back(Pair("claimId (no matching claim)", itSupportsWithoutClaims->first.GetHex()));
|
||||
for (std::vector<CSupportValue>::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports)
|
||||
{
|
||||
UniValue supportObj(UniValue::VOBJ);
|
||||
supportObj.push_back(Pair("txid", itSupports->outPoint.hash.GetHex()));
|
||||
supportObj.push_back(Pair("n", (int)itSupports->outPoint.n));
|
||||
supportObj.push_back(Pair("nHeight", itSupports->nHeight));
|
||||
supportObj.push_back(Pair("nValidAtHeight", itSupports->nValidAtHeight));
|
||||
supportObj.push_back(Pair("nAmount", itSupports->nAmount));
|
||||
supportObjs.push_back(supportObj);
|
||||
}
|
||||
ret.push_back(Pair("supports", supportObjs));
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue getclaimsforname(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
if (fHelp || params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
"getclaimsforname\n"
|
||||
"Return all claims and supports for a name\n"
|
||||
"Arguments: \n"
|
||||
"1. \"name\" (string) the name for which to get claims and supports\n"
|
||||
"1. \"name\" (string) the name for which to get claims and supports\n"
|
||||
"2. \"blockhash\" (string, optional) get claims for name\n"
|
||||
" at the block specified\n"
|
||||
" by this block hash.\n"
|
||||
" If none is given,\n"
|
||||
" the latest active\n"
|
||||
" block will be used.\n"
|
||||
"Result:\n"
|
||||
"{\n"
|
||||
" \"nLastTakeoverheight\" (numeric) the last height at which ownership of the name changed\n"
|
||||
" \"claims\": [ (array of object) claims for this name\n"
|
||||
" \"nLastTakeoverHeight\" (numeric) the last height at which ownership of the name changed\n"
|
||||
" \"claims\": [ (array of object) claims for this name\n"
|
||||
" {\n"
|
||||
" \"claimId\" (string) the claimId of this claim\n"
|
||||
" \"txid\" (string) the txid of this claim\n"
|
||||
|
@ -318,50 +349,51 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp)
|
|||
" \"nAmount\" (numeric) the amount of the support\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
"}\n"
|
||||
);
|
||||
"}\n");
|
||||
|
||||
LOCK(cs_main);
|
||||
std::string name = params[0].get_str();
|
||||
claimsForNameType claimsForName = pclaimTrie->getClaimsForName(name);
|
||||
int nCurrentHeight = chainActive.Height();
|
||||
|
||||
CCoinsViewCache coinsCache(pcoinsTip);
|
||||
CClaimTrieCache trieCache(pclaimTrie);
|
||||
|
||||
if (params.size() > 1) {
|
||||
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)"));
|
||||
if (!RollBackTo(blockIndex, coinsCache, trieCache))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Rollback failure");
|
||||
}
|
||||
|
||||
std::string name = params[0].get_str();
|
||||
claimsForNameType claimsForName = trieCache.getClaimsForName(name);
|
||||
|
||||
UniValue claimObjs(UniValue::VARR);
|
||||
claimSupportMapType claimSupportMap;
|
||||
supportsWithoutClaimsMapType supportsWithoutClaims;
|
||||
for (std::vector<CClaimValue>::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims)
|
||||
{
|
||||
UniValue unmatchedSupports(UniValue::VARR);
|
||||
|
||||
for (std::vector<CClaimValue>::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims) {
|
||||
claimAndSupportsType claimAndSupports = std::make_pair(*itClaims, std::vector<CSupportValue>());
|
||||
claimSupportMap.insert(std::pair<uint160, claimAndSupportsType>(itClaims->claimId, claimAndSupports));
|
||||
}
|
||||
for (std::vector<CSupportValue>::const_iterator itSupports = claimsForName.supports.begin(); itSupports != claimsForName.supports.end(); ++itSupports)
|
||||
{
|
||||
|
||||
for (std::vector<CSupportValue>::const_iterator itSupports = claimsForName.supports.begin(); itSupports != claimsForName.supports.end(); ++itSupports) {
|
||||
claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId);
|
||||
if (itClaimAndSupports == claimSupportMap.end())
|
||||
{
|
||||
std::pair<supportsWithoutClaimsMapType::iterator, bool> ret = supportsWithoutClaims.insert(std::pair<uint160, std::vector<CSupportValue> >(itSupports->supportedClaimId, std::vector<CSupportValue>()));
|
||||
ret.first->second.push_back(*itSupports);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (itClaimAndSupports == claimSupportMap.end()) {
|
||||
unmatchedSupports.push_back(supportToJSON(*itSupports));
|
||||
} else {
|
||||
itClaimAndSupports->second.second.push_back(*itSupports);
|
||||
}
|
||||
}
|
||||
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
UniValue claimObjs(UniValue::VARR);
|
||||
ret.push_back(Pair("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight));
|
||||
for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports)
|
||||
{
|
||||
UniValue claimAndSupportsObj = claimsAndSupportsToJSON(itClaimsAndSupports, nCurrentHeight);
|
||||
claimObjs.push_back(claimAndSupportsObj);
|
||||
|
||||
for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports) {
|
||||
CAmount nEffectiveAmount = trieCache.getEffectiveAmountForClaim(claimsForName, itClaimsAndSupports->first);
|
||||
UniValue claimObj = claimAndSupportsToJSON(nEffectiveAmount, itClaimsAndSupports);
|
||||
claimObjs.push_back(claimObj);
|
||||
}
|
||||
|
||||
ret.push_back(Pair("claims", claimObjs));
|
||||
UniValue unmatchedSupports(UniValue::VARR);
|
||||
for (supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims = supportsWithoutClaims.begin(); itSupportsWithoutClaims != supportsWithoutClaims.end(); ++itSupportsWithoutClaims)
|
||||
{
|
||||
UniValue supportsObj = supportsWithoutClaimsToJSON(itSupportsWithoutClaims, nCurrentHeight);
|
||||
unmatchedSupports.push_back(supportsObj);
|
||||
}
|
||||
ret.push_back(Pair("supports without claims", unmatchedSupports));
|
||||
ret.push_back(Pair("unmatched supports", unmatchedSupports));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -403,11 +435,11 @@ UniValue getclaimbyid(const UniValue& params, bool fHelp)
|
|||
if (claimValue.claimId == claimId)
|
||||
{
|
||||
std::vector<CSupportValue> supports;
|
||||
CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaimWithSupports(
|
||||
name, claimValue.claimId, supports);
|
||||
CAmount effectiveAmount = pclaimTrie->getEffectiveAmountForClaim(name, claimValue.claimId, &supports);
|
||||
|
||||
std::string sValue;
|
||||
getValueForClaim(claimValue.outPoint, sValue);
|
||||
CCoinsViewCache coins(pcoinsTip);
|
||||
getValueForClaim(coins, claimValue.outPoint, sValue);
|
||||
claim.push_back(Pair("name", name));
|
||||
claim.push_back(Pair("value", sValue));
|
||||
claim.push_back(Pair("claimId", claimValue.claimId.GetHex()));
|
||||
|
@ -448,7 +480,7 @@ UniValue gettotalclaimednames(const UniValue& params, bool fHelp)
|
|||
if (!pclaimTrie)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
unsigned int num_names = pclaimTrie->getTotalNamesInTrie();
|
||||
return int(num_names);
|
||||
}
|
||||
|
@ -531,7 +563,7 @@ UniValue getclaimsfortx(const UniValue& params, bool fHelp)
|
|||
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
|
||||
|
||||
CCoinsViewCache view(pcoinsTip);
|
||||
const CCoins* coin = view.AccessCoins(hash);
|
||||
std::vector<CTxOut> txouts;
|
||||
|
@ -730,7 +762,7 @@ UniValue getnameproof(const UniValue& params, bool fHelp)
|
|||
" this will not\n"
|
||||
" exist whether\n"
|
||||
" the node has a\n"
|
||||
" value or not\n"
|
||||
" value or not\n"
|
||||
" ]\n"
|
||||
" \"txhash\" : \"hash\" (string, if exists) the txid of the\n"
|
||||
" claim which controls\n"
|
||||
|
@ -749,25 +781,12 @@ UniValue getnameproof(const UniValue& params, bool fHelp)
|
|||
|
||||
LOCK(cs_main);
|
||||
std::string strName = params[0].get_str();
|
||||
uint256 blockHash;
|
||||
if (params.size() == 2)
|
||||
{
|
||||
blockHash = ParseHashV(params[1], "blockhash (optional parameter 2)");
|
||||
CBlockIndex* pblockIndex;
|
||||
if (params.size() == 2) {
|
||||
pblockIndex = BlockHashIndex(ParseHashV(params[1], "blockhash (optional parameter 2)"));
|
||||
} else {
|
||||
pblockIndex = mapBlockIndex[chainActive.Tip()->GetBlockHash()];
|
||||
}
|
||||
else
|
||||
{
|
||||
blockHash = chainActive.Tip()->GetBlockHash();
|
||||
}
|
||||
|
||||
if (mapBlockIndex.count(blockHash) == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
||||
CBlockIndex* pblockIndex = mapBlockIndex[blockHash];
|
||||
if (!chainActive.Contains(pblockIndex))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain");
|
||||
|
||||
if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + MAX_RPC_BLOCK_DECREMENTS))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to generate proof");
|
||||
|
||||
CClaimTrieProof proof;
|
||||
if (!GetProofForName(pblockIndex, strName, proof))
|
||||
|
|
|
@ -2,21 +2,22 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||
|
||||
#include "main.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "consensus/merkle.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "miner.h"
|
||||
#include "txmempool.h"
|
||||
#include "claimtrie.h"
|
||||
#include "nameclaim.h"
|
||||
#include "coins.h"
|
||||
#include "streams.h"
|
||||
#include "chainparams.h"
|
||||
#include "claimtrie.h"
|
||||
#include "coins.h"
|
||||
#include "consensus/merkle.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "main.h"
|
||||
#include "miner.h"
|
||||
#include "nameclaim.h"
|
||||
#include "policy/policy.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "rpc/server.h"
|
||||
#include "streams.h"
|
||||
#include "test/test_bitcoin.h"
|
||||
#include "txmempool.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <iostream>
|
||||
#include "test/test_bitcoin.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -2931,31 +2932,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test)
|
|||
|
||||
CClaimTrieProof proof;
|
||||
|
||||
proof = cache.getProofForName(sName1);
|
||||
BOOST_CHECK(cache.getProofForName(sName1, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1));
|
||||
BOOST_CHECK(proof.outPoint == tx1OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName2);
|
||||
BOOST_CHECK(cache.getProofForName(sName2, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2));
|
||||
BOOST_CHECK(proof.outPoint == tx2OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName3);
|
||||
BOOST_CHECK(cache.getProofForName(sName3, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3));
|
||||
BOOST_CHECK(proof.outPoint == tx3OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName4);
|
||||
BOOST_CHECK(cache.getProofForName(sName4, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4));
|
||||
BOOST_CHECK(proof.outPoint == tx4OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName5);
|
||||
BOOST_CHECK(cache.getProofForName(sName5, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
proof = cache.getProofForName(sName6);
|
||||
BOOST_CHECK(cache.getProofForName(sName6, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
proof = cache.getProofForName(sName7);
|
||||
BOOST_CHECK(cache.getProofForName(sName7, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
|
@ -2969,31 +2970,31 @@ BOOST_AUTO_TEST_CASE(value_proof_test)
|
|||
|
||||
cache = CClaimTrieCache(pclaimTrie);
|
||||
|
||||
proof = cache.getProofForName(sName1);
|
||||
BOOST_CHECK(cache.getProofForName(sName1, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1));
|
||||
BOOST_CHECK(proof.outPoint == tx1OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName2);
|
||||
BOOST_CHECK(cache.getProofForName(sName2, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2));
|
||||
BOOST_CHECK(proof.outPoint == tx2OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName3);
|
||||
BOOST_CHECK(cache.getProofForName(sName3, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3));
|
||||
BOOST_CHECK(proof.outPoint == tx3OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName4);
|
||||
BOOST_CHECK(cache.getProofForName(sName4, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4));
|
||||
BOOST_CHECK(proof.outPoint == tx4OutPoint);
|
||||
|
||||
proof = cache.getProofForName(sName5);
|
||||
BOOST_CHECK(cache.getProofForName(sName5, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
proof = cache.getProofForName(sName6);
|
||||
BOOST_CHECK(cache.getProofForName(sName6, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
proof = cache.getProofForName(sName7);
|
||||
BOOST_CHECK(cache.getProofForName(sName7, proof));
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7));
|
||||
BOOST_CHECK(proof.outPoint == tx5OutPoint);
|
||||
|
||||
|
@ -3133,4 +3134,222 @@ BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3)
|
|||
BOOST_CHECK(claimValue.claimId == claimId2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(getclaimsintrie_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("test");
|
||||
std::string sValue1("test");
|
||||
std::string sName2("test2");
|
||||
std::string sValue2("test2");
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, 43);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimsintrie = tableRPC["getclaimsintrie"]->actor;
|
||||
UniValue params(UniValue::VARR);
|
||||
|
||||
UniValue results = getclaimsintrie(params, false);
|
||||
BOOST_CHECK(results.size() == 2U);
|
||||
BOOST_CHECK(results[0]["name"].get_str() == sName1);
|
||||
BOOST_CHECK(results[1]["name"].get_str() == sName2);
|
||||
|
||||
params.push_back(blockHash.GetHex());
|
||||
|
||||
results = getclaimsintrie(params, false);
|
||||
BOOST_CHECK(results.size() == 1U);
|
||||
BOOST_CHECK(results[0]["name"].get_str() == sName1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(getclaimtrie_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("test");
|
||||
std::string sValue1("test");
|
||||
std::string sName2("test2");
|
||||
std::string sValue2("test2");
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, 43);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimtrie = tableRPC["getclaimtrie"]->actor;
|
||||
UniValue params(UniValue::VARR);
|
||||
|
||||
UniValue results = getclaimtrie(params, false);
|
||||
BOOST_CHECK(results.size() == 6U);
|
||||
BOOST_CHECK(results[4]["name"].get_str() == sName1);
|
||||
BOOST_CHECK(results[5]["name"].get_str() == sName2);
|
||||
BOOST_CHECK(results[4]["height"].get_int() == height + 1);
|
||||
BOOST_CHECK(results[5]["height"].get_int() == height + 2);
|
||||
|
||||
params.push_back(blockHash.GetHex());
|
||||
|
||||
results = getclaimtrie(params, false);
|
||||
BOOST_CHECK(results.size() == 5U);
|
||||
BOOST_CHECK(results[4]["name"].get_str() == sName1);
|
||||
BOOST_CHECK(results[4]["height"].get_int() == height + 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(getvalueforname_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("testV");
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 3);
|
||||
fixture.IncrementBlocks(10);
|
||||
|
||||
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||
UniValue params(UniValue::VARR);
|
||||
params.push_back(UniValue(sName1));
|
||||
|
||||
UniValue results = getvalueforname(params, false);
|
||||
BOOST_CHECK(results["value"].get_str() == sValue1);
|
||||
BOOST_CHECK(results["amount"].get_int() == 2);
|
||||
BOOST_CHECK(results["effective amount"].get_int() == 5);
|
||||
|
||||
params.push_back(blockHash.GetHex());
|
||||
|
||||
results = getvalueforname(params, false);
|
||||
BOOST_CHECK(results["amount"].get_int() == 2);
|
||||
BOOST_CHECK(results["effective amount"].get_int() == 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(getclaimsforname_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("test1");
|
||||
std::string sValue2("test2");
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
UniValue params(UniValue::VARR);
|
||||
params.push_back(UniValue(sName1));
|
||||
|
||||
UniValue results = getclaimsforname(params, false);
|
||||
UniValue claims = results["claims"];
|
||||
BOOST_CHECK(claims.size() == 2U);
|
||||
BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 1);
|
||||
BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 0);
|
||||
BOOST_CHECK(claims[1]["nEffectiveAmount"].get_int() == 2);
|
||||
BOOST_CHECK(claims[0]["supports"].size() == 0U);
|
||||
BOOST_CHECK(claims[1]["supports"].size() == 0U);
|
||||
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
results = getclaimsforname(params, false);
|
||||
claims = results["claims"];
|
||||
BOOST_CHECK(claims.size() == 2U);
|
||||
BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 3);
|
||||
BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 3);
|
||||
BOOST_CHECK(claims[1]["nEffectiveAmount"].get_int() == 2);
|
||||
BOOST_CHECK(claims[0]["supports"].size() == 0U);
|
||||
BOOST_CHECK(claims[1]["supports"].size() == 0U);
|
||||
|
||||
params.push_back(blockHash.GetHex());
|
||||
|
||||
results = getclaimsforname(params, false);
|
||||
claims = results["claims"];
|
||||
BOOST_CHECK(claims.size() == 1U);
|
||||
BOOST_CHECK(results["nLastTakeoverHeight"].get_int() == height + 1);
|
||||
BOOST_CHECK(claims[0]["nEffectiveAmount"].get_int() == 2);
|
||||
BOOST_CHECK(claims[0]["supports"].size() == 0U);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claim_rpcs_rollback2_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("test1");
|
||||
std::string sValue2("test2");
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 1);
|
||||
fixture.IncrementBlocks(2);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||
fixture.IncrementBlocks(3);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sValue1, 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||
|
||||
UniValue params(UniValue::VARR);
|
||||
params.push_back(UniValue(sName1));
|
||||
params.push_back(blockHash.GetHex());
|
||||
|
||||
UniValue claimsResults = getclaimsforname(params, false);
|
||||
BOOST_CHECK(claimsResults["nLastTakeoverHeight"].get_int() == height + 5);
|
||||
BOOST_CHECK(claimsResults["claims"][0]["supports"].size() == 0U);
|
||||
BOOST_CHECK(claimsResults["claims"][1]["supports"].size() == 0U);
|
||||
|
||||
UniValue valueResults = getvalueforname(params, false);
|
||||
BOOST_CHECK(valueResults["value"].get_str() == sValue2);
|
||||
BOOST_CHECK(valueResults["amount"].get_int() == 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(claim_rpcs_rollback3_test)
|
||||
{
|
||||
ClaimTrieChainFixture fixture;
|
||||
std::string sName1("testN");
|
||||
std::string sValue1("test1");
|
||||
std::string sValue2("test2");
|
||||
|
||||
int height = chainActive.Height();
|
||||
|
||||
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 3);
|
||||
fixture.IncrementBlocks(1);
|
||||
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||
fixture.IncrementBlocks(2);
|
||||
|
||||
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||
|
||||
CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim
|
||||
fixture.IncrementBlocks(1);
|
||||
|
||||
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||
|
||||
UniValue params(UniValue::VARR);
|
||||
params.push_back(UniValue(sName1));
|
||||
params.push_back(blockHash.GetHex());
|
||||
|
||||
UniValue claimsResults = getclaimsforname(params, false);
|
||||
BOOST_CHECK(claimsResults["nLastTakeoverHeight"].get_int() == height + 1);
|
||||
|
||||
UniValue valueResults = getvalueforname(params, false);
|
||||
BOOST_CHECK(valueResults["value"].get_str() == sValue1);
|
||||
BOOST_CHECK(valueResults["amount"].get_int() == 3);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Reference in a new issue