Skip to content

Commit

Permalink
Merge pull request #15 from jimmykiselak/claimid_rpc_updates
Browse files Browse the repository at this point in the history
Claimid rpc updates
  • Loading branch information
jackrobison authored Aug 7, 2016
2 parents 3e26b5f + 93eb2e3 commit 774246d
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 42 deletions.
67 changes: 67 additions & 0 deletions src/claimtrie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,73 @@ bool CClaimTrie::getLastTakeoverForName(const std::string& name, int& lastTakeov
return false;
}

claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const
{
std::vector<CClaimValue> claims;
std::vector<CSupportValue> supports;
int nLastTakeoverHeight = 0;
const CClaimTrieNode* current = getNodeForName(name);
if (current)
{
if (!current->claims.empty())
{
nLastTakeoverHeight = current->nHeightOfLastTakeover;
}
for (std::vector<CClaimValue>::const_iterator itClaims = current->claims.begin(); itClaims != current->claims.end(); ++itClaims)
{
claims.push_back(*itClaims);
}
}
supportMapEntryType supportNode;
if (getSupportNode(name, supportNode))
{
for (std::vector<CSupportValue>::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports)
{
supports.push_back(*itSupports);
}
}
queueNameRowType namedClaimRow;
if (getQueueNameRow(name, namedClaimRow))
{
for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName)
{
claimQueueRowType claimRow;
if (getQueueRow(itClaimsForName->nHeight, claimRow))
{
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;
}
}
}
}
}
queueNameRowType namedSupportRow;
if (getSupportQueueNameRow(name, namedSupportRow))
{
for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName)
{
supportQueueRowType supportRow;
if (getSupportQueueRow(itSupportsForName->nHeight, supportRow))
{
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;
}
}
}
}
}
claimsForNameType allClaims(claims, supports, nLastTakeoverHeight);
return allClaims;
}

bool CClaimTrie::checkConsistency() const
{
if (empty())
Expand Down
12 changes: 12 additions & 0 deletions src/claimtrie.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,16 @@ typedef std::map<std::string, CClaimTrieNode*, nodenamecompare> nodeCacheType;

typedef std::map<std::string, uint256> hashMapType;

struct claimsForNameType
{
std::vector<CClaimValue> claims;
std::vector<CSupportValue> supports;
int nLastTakeoverHeight;

claimsForNameType(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports, int nLastTakeoverHeight)
: claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) {}
};

class CClaimTrieCache;

class CClaimTrie
Expand All @@ -290,6 +300,8 @@ class CClaimTrie
std::vector<namedNodeType> flattenTrie() const;
bool getInfoForName(const std::string& name, CClaimValue& claim) const;
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;

claimsForNameType getClaimsForName(const std::string& name) const;

bool queueEmpty() const;
bool supportEmpty() const;
Expand Down
210 changes: 190 additions & 20 deletions src/rpc/claimtrie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,41 @@ UniValue getclaimtrie(const UniValue& params, bool fHelp)
return ret;
}

bool getValueForClaim(const COutPoint& out, std::string& sValue)
{
CCoinsViewCache view(pcoinsTip);
const CCoins* coin = view.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->vout.size() < out.n || coin->vout[out.n].IsNull())
{
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))
{
LogPrintf("%s: the specified txout of %s does not have a name claim command\n", __func__, out.hash.GetHex());
return false;
}
if (op == OP_CLAIM_NAME)
{
sValue = std::string(vvchParams[1].begin(), vvchParams[1].end());
}
else if (op == OP_UPDATE_CLAIM)
{
sValue = std::string(vvchParams[2].begin(), vvchParams[2].end());
}
return true;
}


UniValue getvalueforname(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
Expand All @@ -145,27 +180,9 @@ UniValue getvalueforname(const UniValue& params, bool fHelp)
UniValue ret(UniValue::VOBJ);
if (!pclaimTrie->getInfoForName(name, claim))
return ret;
CCoinsViewCache view(pcoinsTip);
const CCoins* coin = view.AccessCoins(claim.outPoint.hash);
if (!coin)
{
LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n",
__func__, claim.outPoint.hash.GetHex());
return ret;
}
if (coin->vout.size() < claim.outPoint.n || coin->vout[claim.outPoint.n].IsNull())
{
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, claim.outPoint.hash.GetHex());
std::string sValue;
if (!getValueForClaim(claim.outPoint, sValue))
return ret;
}

int op;
std::vector<std::vector<unsigned char> > vvchParams;
if (!DecodeClaimScript(coin->vout[claim.outPoint.n].scriptPubKey, op, vvchParams))
{
LogPrintf("%s: the specified txout of %s does not have a name claim command\n", __func__, claim.outPoint.hash.GetHex());
}
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
ret.push_back(Pair("value", sValue));
ret.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
ret.push_back(Pair("n", (int)claim.outPoint.n));
Expand All @@ -175,6 +192,158 @@ UniValue getvalueforname(const UniValue& params, bool fHelp)
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 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);
}
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)
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"
"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"
" {\n"
" \"claimId\" (string) the claimId of this claim\n"
" \"txid\" (string) the txid of this claim\n"
" \"n\" (numeric) the index of the claim in the transaction's list of outputs\n"
" \"nHeight\" (numeric) the height at which the claim was included in the blockchain\n"
" \"nValidAtHeight\" (numeric) the height at which the claim became/becomes valid\n"
" \"nAmount\" (numeric) the amount of the claim\n"
" \"nEffectiveAmount\" (numeric) the total effective amount of the claim, taking into effect whether the claim or support has reached its nValidAtHeight\n"
" \"supports\" : [ (array of object) supports for this claim\n"
" \"txid\" (string) the txid of the support\n"
" \"n\" (numeric) the index of the support in the transaction's list of outputs\n"
" \"nHeight\" (numeric) the height at which the support was included in the blockchain\n"
" \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n"
" \"nAmount\" (numeric) the amount of the support\n"
" ]\n"
" }\n"
" ],\n"
" \"unmatched supports\": [ (array of object) supports that did not match a claim for this name\n"
" {\n"
" \"txid\" (string) the txid of the support\n"
" \"n\" (numeric) the index of the support in the transaction's list of outputs\n"
" \"nHeight\" (numeric) the height at which the support was included in the blockchain\n"
" \"nValidAtHeight\" (numeric) the height at which the support became/becomes valid\n"
" \"nAmount\" (numeric) the amount of the support\n"
" }\n"
" ]\n"
"}\n"
);

LOCK(cs_main);
std::string name = params[0].get_str();
claimsForNameType claimsForName = pclaimTrie->getClaimsForName(name);
int nCurrentHeight = chainActive.Height();

claimSupportMapType claimSupportMap;
supportsWithoutClaimsMapType supportsWithoutClaims;
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)
{
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
{
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);
}
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));
return ret;
}


UniValue gettotalclaimednames(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
Expand Down Expand Up @@ -529,6 +698,7 @@ static const CRPCCommand commands[] =
{ "Claimtrie", "getclaimsintrie", &getclaimsintrie, true },
{ "Claimtrie", "getclaimtrie", &getclaimtrie, true },
{ "Claimtrie", "getvalueforname", &getvalueforname, true },
{ "Claimtrie", "getclaimsforname", &getclaimsforname, true },
{ "Claimtrie", "gettotalclaimednames", &gettotalclaimednames, true },
{ "Claimtrie", "gettotalclaims", &gettotalclaims, true },
{ "Claimtrie", "gettotalvalueofclaims", &gettotalvalueofclaims, true },
Expand Down
Loading

0 comments on commit 774246d

Please sign in to comment.