added claimtrie RPC parameter for minconf #178

Closed
BrannonKing wants to merge 289 commits from add_minconf into master
4 changed files with 120 additions and 55 deletions
Showing only changes of commit 5b5b80e002 - Show all commits

View file

@ -90,17 +90,28 @@ bool CClaimTrieNode::removeClaim(const COutPoint& outPoint, CClaimValue& claim)
return true;
}
bool CClaimTrieNode::getBestClaim(CClaimValue& claim) const
bool CClaimTrieNode::getBestClaim(CClaimValue& claim, int maxHeight) const
{
if (claims.empty())
{
return false;
}
else
else if (maxHeight < 0)
{
claim = claims.front();
return true;
}
else
{
// we are already sorted (with reorder getting called on insert/remove)
for (std::vector<CClaimValue>::const_iterator itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) {
if (itclaim->nHeight <= maxHeight) {
claim = *itclaim;
return true;
}
}
return false;
}
}
bool CClaimTrieNode::haveClaim(const COutPoint& outPoint) const
@ -133,8 +144,8 @@ void CClaimTrieNode::reorderClaims(supportMapEntryType& supports)
}
}
}
std::make_heap(claims.begin(), claims.end());
std::sort(claims.rbegin(), claims.rend()); // max of effectiveAmount should be first
}
uint256 CClaimTrie::getMerkleHash()
@ -438,12 +449,12 @@ const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const
return current;
}
bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim) const
bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim, int maxHeight) const
{
const CClaimTrieNode* current = getNodeForName(name);
if (current)
{
return current->getBestClaim(claim);
return current->getBestClaim(claim, maxHeight);
}
return false;
}

View file

@ -146,7 +146,7 @@ public:
bool insertClaim(CClaimValue claim);
bool removeClaim(const COutPoint& outPoint, CClaimValue& claim);
bool getBestClaim(CClaimValue& claim) const;
bool getBestClaim(CClaimValue& claim, int maxHeight = -1) const;
bool empty() const {return children.empty() && claims.empty();}
bool haveClaim(const COutPoint& outPoint) const;
void reorderClaims(supportMapEntryType& supports);
@ -316,7 +316,7 @@ public:
bool ReadFromDisk(bool check = false);
std::vector<namedNodeType> flattenTrie() const;
bool getInfoForName(const std::string& name, CClaimValue& claim) const;
bool getInfoForName(const std::string& name, CClaimValue& claim, int maxHeight = -1) const;
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
claimsForNameType getClaimsForName(const std::string& name) const;

View file

@ -25,12 +25,12 @@ uint160 ParseClaimtrieId(const UniValue& v, std::string strName)
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. minconf (optional numeric, default of 6) the number of required confirmations (aka, minimum block depth)\n"
"Result: \n"
"[\n"
" {\n"
@ -48,53 +48,61 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp)
" }\n"
"]\n"
);
LOCK(cs_main);
UniValue ret(UniValue::VARR);
int nCurrentHeight = chainActive.Height();
int maxHeight = nCurrentHeight - 6;
if (params.size() > 0)
maxHeight = nCurrentHeight - params[0].get_int();
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 claims(UniValue::VARR);
for (std::vector<CClaimValue>::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims)
{
if (itClaims->nHeight > maxHeight)
continue;
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"));
}
else if (coin->vout.size() < itClaims->outPoint.n || coin->vout[itClaims->outPoint.n].IsNull())
{
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);
}
if (!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"));
}
else if (coin->vout.size() < itClaims->outPoint.n || coin->vout[itClaims->outPoint.n].IsNull())
{
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);
}
node.push_back(Pair("claims", claims));
ret.push_back(node);
}
@ -104,12 +112,12 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp)
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. minconf (optional numeric, default of 6) the number of required confirmations (aka, minimum block depth)\n"
"Result: \n"
"{\n"
" \"name\" (string) the name of the node\n"
@ -124,6 +132,11 @@ UniValue getclaimtrie(const UniValue& params, bool fHelp)
LOCK(cs_main);
UniValue ret(UniValue::VARR);
int nCurrentHeight = chainActive.Height();
int maxHeight = nCurrentHeight - 6;
if (params.size() > 0)
maxHeight = nCurrentHeight - params[0].get_int();
std::vector<namedNodeType> nodes = pclaimTrie->flattenTrie();
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it)
{
@ -131,7 +144,8 @@ UniValue getclaimtrie(const UniValue& params, bool fHelp)
node.push_back(Pair("name", it->first));
node.push_back(Pair("hash", it->second.hash.GetHex()));
CClaimValue claim;
if (it->second.getBestClaim(claim))
if (it->second.getBestClaim(claim, maxHeight))
{
node.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
node.push_back(Pair("n", (int)claim.outPoint.n));
@ -180,12 +194,13 @@ 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"
"2. minconf (optional numeric, default of 6) the number of required confirmations (aka, minimum block depth)\n"
"Result: \n"
"\"value\" (string) the value of the name, if it exists\n"
"\"claimId\" (string) the claimId for this name claim\n"
@ -197,9 +212,15 @@ UniValue getvalueforname(const UniValue& params, bool fHelp)
);
LOCK(cs_main);
std::string name = params[0].get_str();
int nCurrentHeight = chainActive.Height();
int maxHeight = nCurrentHeight - 6;
if (params.size() > 1)
maxHeight = nCurrentHeight - params[1].get_int();
CClaimValue claim;
UniValue ret(UniValue::VOBJ);
if (!pclaimTrie->getInfoForName(name, claim))
if (!pclaimTrie->getInfoForName(name, claim, maxHeight))
return ret;
std::string sValue;
if (!getValueForClaim(claim.outPoint, sValue))
@ -260,7 +281,7 @@ UniValue claimsAndSupportsToJSON(claimSupportMapType::const_iterator itClaimsAnd
return ret;
}
UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims, int nCurrentHeight)
UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterator itSupportsWithoutClaims, int maxHeight)
{
const std::vector<CSupportValue> supports = itSupportsWithoutClaims->second;
UniValue ret(UniValue::VOBJ);
@ -268,6 +289,9 @@ UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterato
ret.push_back(Pair("claimId (no matching claim)", itSupportsWithoutClaims->first.GetHex()));
for (std::vector<CSupportValue>::const_iterator itSupports = supports.begin(); itSupports != supports.end(); ++itSupports)
{
if (itSupports->nHeight > maxHeight)
continue;
UniValue supportObj(UniValue::VOBJ);
supportObj.push_back(Pair("txid", itSupports->outPoint.hash.GetHex()));
supportObj.push_back(Pair("n", (int)itSupports->outPoint.n));
@ -282,12 +306,13 @@ UniValue supportsWithoutClaimsToJSON(supportsWithoutClaimsMapType::const_iterato
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"
"2. minconf (optional numeric, default of 6) the number of required confirmations (aka, minimum block depth)\n"
"Result:\n"
"{\n"
" \"nLastTakeoverheight\" (numeric) the last height at which ownership of the name changed\n"
@ -326,15 +351,23 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp)
claimsForNameType claimsForName = pclaimTrie->getClaimsForName(name);
int nCurrentHeight = chainActive.Height();
int maxHeight = nCurrentHeight - 6;
if (params.size() > 1)
maxHeight = nCurrentHeight - params[1].get_int();
claimSupportMapType claimSupportMap;
supportsWithoutClaimsMapType supportsWithoutClaims;
for (std::vector<CClaimValue>::const_iterator itClaims = claimsForName.claims.begin(); itClaims != claimsForName.claims.end(); ++itClaims)
{
if (itClaims->nHeight > maxHeight)
continue;
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)
{
if (itSupports->nHeight > maxHeight)
continue;
claimSupportMapType::iterator itClaimAndSupports = claimSupportMap.find(itSupports->supportedClaimId);
if (itClaimAndSupports == claimSupportMap.end())
{
@ -351,14 +384,14 @@ UniValue getclaimsforname(const UniValue& params, bool fHelp)
ret.push_back(Pair("nLastTakeoverHeight", claimsForName.nLastTakeoverHeight));
for (claimSupportMapType::const_iterator itClaimsAndSupports = claimSupportMap.begin(); itClaimsAndSupports != claimSupportMap.end(); ++itClaimsAndSupports)
{
UniValue claimAndSupportsObj = claimsAndSupportsToJSON(itClaimsAndSupports, nCurrentHeight);
UniValue claimAndSupportsObj = claimsAndSupportsToJSON(itClaimsAndSupports, maxHeight);
claimObjs.push_back(claimAndSupportsObj);
}
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);
UniValue supportsObj = supportsWithoutClaimsToJSON(itSupportsWithoutClaims, maxHeight);
unmatchedSupports.push_back(supportsObj);
}
ret.push_back(Pair("supports without claims", unmatchedSupports));

View file

@ -1064,4 +1064,25 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_disktest)
BOOST_CHECK(best_claim_effective_amount_equals("test2",1)); // the support expires one block before
}
BOOST_AUTO_TEST_CASE(claimtriebranching_getBest_supports_confirmations)
{
ClaimTrieChainFixture fixture;
int height = chainActive.Tip()->nHeight;
std::string name("test");
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),name,"one",42);
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),name,"two",43);
fixture.IncrementBlocks(1);
CClaimValue claim;
BOOST_CHECK(pclaimTrie->getInfoForName(name, claim));
BOOST_CHECK(claim.nAmount == 43);
BOOST_CHECK(pclaimTrie->getInfoForName(name, claim, height + 1));
BOOST_CHECK(!pclaimTrie->getInfoForName(name, claim, height));
fixture.IncrementBlocks(4);
BOOST_CHECK_EQUAL(height + 5, chainActive.Tip()->nHeight);
BOOST_CHECK(pclaimTrie->getInfoForName(name, claim, height + 2));
BOOST_CHECK(!pclaimTrie->getInfoForName(name, claim, height));
}
BOOST_AUTO_TEST_SUITE_END()