Commit f86eb540 authored by Anthony Fieroni's avatar Anthony Fieroni Committed by Brannon King
Browse files

Add block hash parameter to claimtrie rpc methods


Signed-off-by: default avatarAnthony Fieroni <bvbfan@abv.bg>
parent 24da3ac5
......@@ -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;
}
......@@ -2462,24 +2449,25 @@ bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLast
}
int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) const
{
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())
{
if (itCache != cache.end()) {
node = itCache->second;
}
if (!node)
{
if (!node) {
node = base->getNodeForName(name);
}
if (!node || node->claims.empty())
{
return 0;
}
int nLastTakeoverHeight;
assert(getLastTakeoverForName(name, nLastTakeoverHeight));
return nCurrentHeight - nLastTakeoverHeight;
return node;
}
int CClaimTrieCache::getDelayForName(const std::string& name) const
......@@ -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
......@@ -4267,42 +4267,45 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
return true;
}
bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof)
bool RollBackTo(const CBlockIndex* targetIndex, CCoinsViewCache& coinsCache, CClaimTrieCache& trieCache)
{
AssertLockHeld(cs_main);
if (!chainActive.Contains(pindexProof))
{
return false;
}
CCoinsViewCache coins(pcoinsTip);
CClaimTrieCache trieCache(pclaimTrie);
CBlockIndex* pindexState = chainActive.Tip();
CValidationState state;
for (CBlockIndex *pindex = chainActive.Tip(); pindex && pindex->pprev && pindexState != pindexProof; pindex=pindex->pprev)
{
for (CBlockIndex* index = chainActive.Tip(); index && index != targetIndex; index = index->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 (!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;
}
assert(pindexState == pindexProof);
proof = trieCache.getProofForName(name);
return true;
}
bool GetProofForName(const CBlockIndex* pindexProof, const std::string& name, CClaimTrieProof& proof)
{
AssertLockHeld(cs_main);
if (!chainActive.Contains(pindexProof))
return false;
CCoinsViewCache coinsCache(pcoinsTip);
CClaimTrieCache trieCache(pclaimTrie);
if (RollBackTo(pindexProof, coinsCache, trieCache))
return trieCache.getProofForName(name, proof);
return false;
}
void UnloadBlockIndex()
{
LOCK(cs_main);
......
......@@ -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 */
......
This diff is collapsed.
......@@ -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 "chainparams.h"
#include "claimtrie.h"
#include "coins.h"
#include "consensus/merkle.h"
#include "primitives/transaction.h"
#include "consensus/validation.h"
#include "main.h"
#include "miner.h"
#include "txmempool.h"
#include "claimtrie.h"
#include "nameclaim.h"
#include "coins.h"
#include "streams.h"
#include "chainparams.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");