Rudimentary Claimtrie node leak fixes to fix test corruption.
Misc cleanups and code improvements. Additional updates from Brannon's branch.
This commit is contained in:
parent
6dd2df3a0c
commit
da42a0516c
12 changed files with 1019 additions and 491 deletions
|
@ -5,7 +5,7 @@ define(_CLIENT_VERSION_MINOR, 17)
|
|||
define(_CLIENT_VERSION_REVISION, 1)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2018)
|
||||
define(_COPYRIGHT_YEAR, 2019)
|
||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[LBRYcrd Core]])
|
||||
AC_INIT([LBRYcrd Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/])
|
||||
|
@ -14,7 +14,7 @@ AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
|
|||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([build-aux/m4])
|
||||
|
||||
BITCOIN_DAEMON_NAME=lbrycrd
|
||||
BITCOIN_DAEMON_NAME=lbrycrdd
|
||||
BITCOIN_GUI_NAME=lbrycrd-qt
|
||||
BITCOIN_CLI_NAME=lbrycrd-cli
|
||||
BITCOIN_TX_NAME=lbrycrd-tx
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
|
||||
boost::ptr_vector<CClaimTrieNode> nodes;
|
||||
|
||||
static const std::string rootClaimName = "";
|
||||
static const std::string rootClaimHash = "0000000000000000000000000000000000000000000000000000000000000001";
|
||||
|
@ -94,14 +97,10 @@ bool CClaimTrieNode::removeClaim(const COutPoint& outPoint, CClaimValue& claim)
|
|||
bool CClaimTrieNode::getBestClaim(CClaimValue& claim) const
|
||||
{
|
||||
if (claims.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
claim = claims.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
claim = claims.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClaimTrieNode::haveClaim(const COutPoint& outPoint) const
|
||||
|
@ -119,9 +118,7 @@ void CClaimTrieNode::reorderClaims(supportMapEntryType& supports)
|
|||
std::vector<CClaimValue>::iterator itclaim;
|
||||
|
||||
for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim)
|
||||
{
|
||||
itclaim->nEffectiveAmount = itclaim->nAmount;
|
||||
}
|
||||
|
||||
for (supportMapEntryType::iterator itsupport = supports.begin(); itsupport != supports.end(); ++itsupport)
|
||||
{
|
||||
|
@ -148,7 +145,7 @@ bool CClaimTrie::empty() const
|
|||
return root.empty();
|
||||
}
|
||||
|
||||
template<typename K> bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const
|
||||
template<typename K> bool CClaimTrie::keyTypeEmpty(char keyType, K& /* throwaway */) const
|
||||
{
|
||||
boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
|
||||
pcursor->SeekToFirst();
|
||||
|
@ -156,17 +153,12 @@ template<typename K> bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const
|
|||
while (pcursor->Valid())
|
||||
{
|
||||
std::pair<char, K> key;
|
||||
if (pcursor->GetKey(key))
|
||||
{
|
||||
if (key.first == keyType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pcursor->GetKey(key))
|
||||
break;
|
||||
}
|
||||
|
||||
if (key.first == keyType)
|
||||
return false;
|
||||
|
||||
pcursor->Next();
|
||||
}
|
||||
return true;
|
||||
|
@ -179,8 +171,8 @@ bool CClaimTrie::queueEmpty() const
|
|||
if (!itRow->second.empty())
|
||||
return false;
|
||||
}
|
||||
int dummy;
|
||||
return keyTypeEmpty(CLAIM_QUEUE_ROW, dummy);
|
||||
int throwaway;
|
||||
return keyTypeEmpty(CLAIM_QUEUE_ROW, throwaway);
|
||||
}
|
||||
|
||||
bool CClaimTrie::expirationQueueEmpty() const
|
||||
|
@ -190,8 +182,8 @@ bool CClaimTrie::expirationQueueEmpty() const
|
|||
if (!itRow->second.empty())
|
||||
return false;
|
||||
}
|
||||
int dummy;
|
||||
return keyTypeEmpty(EXP_QUEUE_ROW, dummy);
|
||||
int throwaway;
|
||||
return keyTypeEmpty(EXP_QUEUE_ROW, throwaway);
|
||||
}
|
||||
|
||||
bool CClaimTrie::supportEmpty() const
|
||||
|
@ -201,8 +193,8 @@ bool CClaimTrie::supportEmpty() const
|
|||
if (!itNode->second.empty())
|
||||
return false;
|
||||
}
|
||||
std::string dummy;
|
||||
return keyTypeEmpty(SUPPORT, dummy);
|
||||
std::string throwaway;
|
||||
return keyTypeEmpty(SUPPORT, throwaway);
|
||||
}
|
||||
|
||||
bool CClaimTrie::supportQueueEmpty() const
|
||||
|
@ -212,8 +204,8 @@ bool CClaimTrie::supportQueueEmpty() const
|
|||
if (!itRow->second.empty())
|
||||
return false;
|
||||
}
|
||||
int dummy;
|
||||
return keyTypeEmpty(SUPPORT_QUEUE_ROW, dummy);
|
||||
int throwaway;
|
||||
return keyTypeEmpty(SUPPORT_QUEUE_ROW, throwaway);
|
||||
}
|
||||
|
||||
void CClaimTrie::setExpirationTime(int t)
|
||||
|
@ -232,7 +224,17 @@ void CClaimTrie::clear(CClaimTrieNode* current)
|
|||
for (nodeMapType::const_iterator itchildren = current->children.begin(); itchildren != current->children.end(); ++itchildren)
|
||||
{
|
||||
clear(itchildren->second);
|
||||
delete itchildren->second;
|
||||
|
||||
auto matcher = [&itchildren](const CClaimTrieNode& a)
|
||||
{
|
||||
return const_cast<CClaimTrieNode*>(&a) == itchildren->second;
|
||||
};
|
||||
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), matcher);
|
||||
if (it != nodes.end())
|
||||
nodes.erase(it);
|
||||
else
|
||||
delete itchildren->second;
|
||||
}
|
||||
current->children.clear();
|
||||
}
|
||||
|
@ -254,9 +256,8 @@ bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint)
|
|||
{
|
||||
supportMapEntryType node;
|
||||
if (!getSupportNode(name, node))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (supportMapEntryType::const_iterator itnode = node.begin(); itnode != node.end(); ++itnode)
|
||||
{
|
||||
if (itnode->outPoint == outPoint)
|
||||
|
@ -308,9 +309,8 @@ bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& ou
|
|||
{
|
||||
queueNameRowType nameRow;
|
||||
if (!getSupportQueueNameRow(name, nameRow))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
queueNameRowType::const_iterator itNameRow;
|
||||
for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow)
|
||||
{
|
||||
|
@ -321,9 +321,8 @@ bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& ou
|
|||
}
|
||||
}
|
||||
if (itNameRow == nameRow.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
supportQueueRowType row;
|
||||
if (getSupportQueueRow(nValidAtHeight, row))
|
||||
{
|
||||
|
@ -407,7 +406,7 @@ CAmount CClaimTrie::getTotalValueOfClaimsRecursive(const CClaimTrieNode* current
|
|||
|
||||
const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const
|
||||
{
|
||||
const CClaimTrieNode* current = &root;
|
||||
auto current = const_cast<CClaimTrieNode*>(&root);
|
||||
for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname)
|
||||
{
|
||||
nodeMapType::const_iterator itchildren = current->children.find(*itname);
|
||||
|
@ -421,11 +420,7 @@ const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const
|
|||
bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim) const
|
||||
{
|
||||
const CClaimTrieNode* current = getNodeForName(name);
|
||||
if (current)
|
||||
{
|
||||
return current->getBestClaim(claim);
|
||||
}
|
||||
return false;
|
||||
return current ? current->getBestClaim(claim) : false;
|
||||
}
|
||||
|
||||
bool CClaimTrie::getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const
|
||||
|
@ -448,9 +443,7 @@ std::vector<CClaimValue> CClaimTrie::getClaimsForName(const std::string& name) c
|
|||
|
||||
bool CClaimTrie::checkConsistency() const
|
||||
{
|
||||
if (empty())
|
||||
return true;
|
||||
return recursiveCheckConsistency(&root);
|
||||
return empty() ? true : recursiveCheckConsistency(&root);
|
||||
}
|
||||
|
||||
bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const
|
||||
|
@ -459,13 +452,11 @@ bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const
|
|||
|
||||
for (nodeMapType::const_iterator it = node->children.begin(); it != node->children.end(); ++it)
|
||||
{
|
||||
if (recursiveCheckConsistency(it->second))
|
||||
{
|
||||
vchToHash.push_back(it->first);
|
||||
vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end());
|
||||
}
|
||||
else
|
||||
if (!recursiveCheckConsistency(it->second))
|
||||
return false;
|
||||
|
||||
vchToHash.push_back(it->first);
|
||||
vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end());
|
||||
}
|
||||
|
||||
CClaimValue claim;
|
||||
|
@ -499,14 +490,15 @@ bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimVa
|
|||
CClaimIndexElement element;
|
||||
if (db.Read(std::make_pair(CLAIM_BY_ID, claimId), element))
|
||||
{
|
||||
if (element.claim.claimId == claimId) {
|
||||
if (element.claim.claimId == claimId)
|
||||
{
|
||||
name = element.name;
|
||||
claim = element.claim;
|
||||
return true;
|
||||
} else {
|
||||
LogPrintf("%s: ClaimIndex[%s] returned unmatched claimId %s when looking for %s\n",
|
||||
__func__, claimId.GetHex(), element.claim.claimId.GetHex(), name);
|
||||
}
|
||||
|
||||
LogPrintf("%s: ClaimIndex[%s] returned unmatched claimId %s when looking for %s\n",
|
||||
__func__, claimId.GetHex(), element.claim.claimId.GetHex(), name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -761,14 +753,13 @@ bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode
|
|||
nodeMapType::iterator itchild = current->children.find(*itname);
|
||||
if (itchild == current->children.end())
|
||||
{
|
||||
if (itname + 1 == name.end())
|
||||
{
|
||||
CClaimTrieNode* newNode = new CClaimTrieNode();
|
||||
current->children[*itname] = newNode;
|
||||
current = newNode;
|
||||
}
|
||||
else
|
||||
if (itname + 1 != name.end())
|
||||
return false;
|
||||
|
||||
nodes.push_back(new CClaimTrieNode());
|
||||
CClaimTrieNode& newNode = nodes[nodes.size() - 1];
|
||||
current->children[*itname] = &newNode;
|
||||
current = &newNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -792,7 +783,9 @@ bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode
|
|||
current->children.erase(itchild++);
|
||||
}
|
||||
else
|
||||
{
|
||||
++itchild;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -809,7 +802,17 @@ bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, const std::string& name)
|
|||
}
|
||||
node->children.clear();
|
||||
markNodeDirty(name, nullptr);
|
||||
delete node;
|
||||
|
||||
auto matcher = [node](const CClaimTrieNode& a)
|
||||
{
|
||||
return const_cast<CClaimTrieNode*>(&a) == node;
|
||||
};
|
||||
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), matcher);
|
||||
if (it != nodes.end())
|
||||
nodes.erase(it);
|
||||
else
|
||||
delete node;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -984,11 +987,11 @@ bool CClaimTrie::WriteToDisk()
|
|||
return db.WriteBatch(batch);
|
||||
}
|
||||
|
||||
bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node)
|
||||
bool CClaimTrie::InsertFromDisk(const std::string& name, const CClaimTrieNode& node)
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
root = *node;
|
||||
root = node;
|
||||
return true;
|
||||
}
|
||||
CClaimTrieNode* current = &root;
|
||||
|
@ -999,7 +1002,7 @@ bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node)
|
|||
return false;
|
||||
current = itchild->second;
|
||||
}
|
||||
current->children[name[name.size()-1]] = node;
|
||||
current->children[name[name.size() - 1]] = const_cast<CClaimTrieNode*>(&node);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1021,8 +1024,9 @@ bool CClaimTrie::ReadFromDisk(bool check)
|
|||
{
|
||||
if (key.first == TRIE_NODE)
|
||||
{
|
||||
CClaimTrieNode* node = new CClaimTrieNode();
|
||||
if (pcursor->GetValue(*node))
|
||||
nodes.push_back(new CClaimTrieNode());
|
||||
const CClaimTrieNode& node = nodes[nodes.size() - 1];
|
||||
if (pcursor->GetValue(const_cast<CClaimTrieNode&>(node)))
|
||||
{
|
||||
if (!InsertFromDisk(key.second, node))
|
||||
{
|
||||
|
@ -1054,7 +1058,8 @@ bool CClaimTrie::ReadFromDisk(bool check)
|
|||
|
||||
bool CClaimTrieCacheBase::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, const std::string& sPos, bool forceCompute) const
|
||||
{
|
||||
if ((sPos == rootClaimName) && tnCurrent->empty()) {
|
||||
if ((sPos == rootClaimName) && tnCurrent->empty())
|
||||
{
|
||||
cacheHashes[rootClaimName] = uint256S(rootClaimHash);
|
||||
return true;
|
||||
}
|
||||
|
@ -1135,16 +1140,21 @@ bool CClaimTrieCacheBase::empty() const
|
|||
CClaimTrieNode* CClaimTrieCacheBase::addNodeToCache(const std::string& position, CClaimTrieNode* original) const
|
||||
{
|
||||
// create a copy of the node in the cache, if new node, create empty node
|
||||
CClaimTrieNode* cacheCopy = (original ? new CClaimTrieNode(*original) : new CClaimTrieNode());
|
||||
cache[position] = cacheCopy;
|
||||
nodes.push_back(original ? new CClaimTrieNode(*original) : new CClaimTrieNode());
|
||||
CClaimTrieNode& cacheCopy = nodes[nodes.size() - 1];
|
||||
cache[position] = &cacheCopy;
|
||||
|
||||
// check to see if there is the original node in block_originals,
|
||||
// if not, add it to block_originals cache
|
||||
nodeCacheType::const_iterator itOriginals = block_originals.find(position);
|
||||
if (block_originals.end() == itOriginals)
|
||||
block_originals[position] = (original ? new CClaimTrieNode(*original) : new CClaimTrieNode());
|
||||
{
|
||||
nodes.push_back(original ? new CClaimTrieNode(*original) : new CClaimTrieNode());
|
||||
CClaimTrieNode& block_originalsCopy = nodes[nodes.size() - 1];
|
||||
block_originals[position] = &block_originalsCopy;
|
||||
}
|
||||
|
||||
return cacheCopy;
|
||||
return &cacheCopy;
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::getOriginalInfoForName(const std::string& name, CClaimValue& claim) const
|
||||
|
@ -1320,7 +1330,9 @@ bool CClaimTrieCacheBase::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned
|
|||
CClaimTrieNode* tnNext = nullptr;
|
||||
nodeCacheType::iterator cachedNode = cache.find(sNextSubstring);
|
||||
if (cachedNode != cache.end())
|
||||
{
|
||||
tnNext = cachedNode->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeMapType::iterator childNode = tnCurrent->children.find(cNext);
|
||||
|
@ -1370,7 +1382,17 @@ bool CClaimTrieCacheBase::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned
|
|||
if (cachedNode != cache.end())
|
||||
{
|
||||
assert(tnCurrent == cachedNode->second);
|
||||
delete tnCurrent;
|
||||
auto matcher = [tnCurrent](const CClaimTrieNode& a)
|
||||
{
|
||||
return const_cast<CClaimTrieNode*>(&a) == tnCurrent;
|
||||
};
|
||||
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), matcher);
|
||||
if (it != nodes.end())
|
||||
nodes.erase(it);
|
||||
else
|
||||
delete tnCurrent;
|
||||
|
||||
cache.erase(cachedNode);
|
||||
}
|
||||
fNullified = true;
|
||||
|
@ -1389,9 +1411,8 @@ claimQueueType::iterator CClaimTrieCacheBase::getQueueCacheRow(int nHeight, bool
|
|||
claimQueueRowType queueRow;
|
||||
// If the row exists in the base, copy its claims into the new row.
|
||||
bool exists = base->getQueueRow(nHeight, queueRow);
|
||||
if (!exists)
|
||||
if (!createIfNotExists)
|
||||
return itQueueRow;
|
||||
if (!exists && !createIfNotExists)
|
||||
return itQueueRow;
|
||||
// Stick the new row in the cache
|
||||
std::pair<claimQueueType::iterator, bool> ret;
|
||||
ret = claimQueueCache.insert(std::pair<int, claimQueueRowType >(nHeight, queueRow));
|
||||
|
@ -1410,9 +1431,8 @@ queueNameType::iterator CClaimTrieCacheBase::getQueueCacheNameRow(const std::str
|
|||
queueNameRowType queueNameRow;
|
||||
// If the row exists in the base, copy its claims into the new row.
|
||||
bool exists = base->getQueueNameRow(name, queueNameRow);
|
||||
if (!exists)
|
||||
if (!createIfNotExists)
|
||||
return itQueueNameRow;
|
||||
if (!exists && !createIfNotExists)
|
||||
return itQueueNameRow;
|
||||
// Stick the new row in the cache
|
||||
std::pair<queueNameType::iterator, bool> ret;
|
||||
ret = claimQueueNameCache.insert(std::pair<std::string, queueNameRowType>(name, queueNameRow));
|
||||
|
@ -1430,7 +1450,7 @@ bool CClaimTrieCacheBase::addClaim(const std::string& name, const COutPoint& out
|
|||
int delayForClaim = getDelayForName(name, claimId);
|
||||
CClaimValue claim(outPoint, claimId, nAmount, nHeight, nHeight + delayForClaim);
|
||||
addClaimToQueues(name, claim);
|
||||
CClaimIndexElement element = {name, claim};
|
||||
CClaimIndexElement element = { name, claim };
|
||||
claimsToAdd.push_back(element);
|
||||
return true;
|
||||
}
|
||||
|
@ -1448,7 +1468,7 @@ bool CClaimTrieCacheBase::undoSpendClaim(const std::string& name, const COutPoin
|
|||
return insertClaimIntoTrie(name, claim, false);
|
||||
}
|
||||
addClaimToQueues(name, claim);
|
||||
CClaimIndexElement element = {name, claim};
|
||||
CClaimIndexElement element = { name, claim };
|
||||
claimsToAdd.push_back(element);
|
||||
return true;
|
||||
}
|
||||
|
@ -1474,21 +1494,17 @@ bool CClaimTrieCacheBase::removeClaimFromQueue(const std::string& name, const CO
|
|||
{
|
||||
queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(name, false);
|
||||
if (itQueueNameRow == claimQueueNameCache.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
queueNameRowType::iterator itQueueName;
|
||||
for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName)
|
||||
{
|
||||
if (itQueueName->outPoint == outPoint)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itQueueName == itQueueNameRow->second.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, false);
|
||||
if (itQueueRow != claimQueueCache.end())
|
||||
{
|
||||
|
@ -1497,9 +1513,7 @@ bool CClaimTrieCacheBase::removeClaimFromQueue(const std::string& name, const CO
|
|||
for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue)
|
||||
{
|
||||
if (itQueue->second.outPoint == outPoint && name == itQueue->first)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itQueue != itQueueRow->second.end())
|
||||
{
|
||||
|
@ -1532,13 +1546,13 @@ bool CClaimTrieCacheBase::removeClaim(const std::string& name, const COutPoint&
|
|||
nValidAtHeight = nHeight + getDelayForName(name);
|
||||
std::string adjusted = adjustNameForValidHeight(name, nValidAtHeight);
|
||||
|
||||
if (removeClaimFromQueue(adjusted, outPoint, claim)) {
|
||||
if (removeClaimFromQueue(adjusted, outPoint, claim))
|
||||
// assert(claim.nValidAtHeight == nValidAtHeight); probably better to leak than to crash
|
||||
removed = true;
|
||||
}
|
||||
if (removed == false && removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) {
|
||||
|
||||
if (removed == false && removeClaimFromTrie(name, outPoint, claim, fCheckTakeover))
|
||||
removed = true;
|
||||
}
|
||||
|
||||
if (removed == true)
|
||||
{
|
||||
int expirationHeight = claim.nHeight + base->nExpirationTime;
|
||||
|
@ -1563,14 +1577,12 @@ void CClaimTrieCacheBase::removeFromExpirationQueue(const std::string& name, con
|
|||
{
|
||||
for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue)
|
||||
{
|
||||
if (name == itQueue->name && outPoint == itQueue->outPoint)
|
||||
if (outPoint == itQueue->outPoint && name == itQueue->name)
|
||||
break;
|
||||
}
|
||||
|
||||
if (itQueue != itQueueRow->second.end())
|
||||
{
|
||||
itQueueRow->second.erase(itQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1583,9 +1595,8 @@ expirationQueueType::iterator CClaimTrieCacheBase::getExpirationQueueCacheRow(in
|
|||
expirationQueueRowType queueRow;
|
||||
// If the row exists in the base, copy its claims into the new row.
|
||||
bool exists = base->getExpirationQueueRow(nHeight, queueRow);
|
||||
if (!exists)
|
||||
if (!createIfNotExists)
|
||||
return itQueueRow;
|
||||
if (!exists && !createIfNotExists)
|
||||
return itQueueRow;
|
||||
// Stick the new row in the cache
|
||||
std::pair<expirationQueueType::iterator, bool> ret;
|
||||
ret = expirationQueueCache.insert(std::pair<int, expirationQueueRowType >(nHeight, queueRow));
|
||||
|
@ -1625,7 +1636,8 @@ bool CClaimTrieCacheBase::reorderTrieNode(const std::string& name, bool fCheckTa
|
|||
return true;
|
||||
}
|
||||
|
||||
currentNode = new CClaimTrieNode(*currentNode);
|
||||
nodes.push_back(new CClaimTrieNode(*currentNode));
|
||||
currentNode = &nodes[nodes.size() - 1];
|
||||
std::pair<nodeCacheType::iterator, bool> ret;
|
||||
ret = cache.insert(std::pair<std::string, CClaimTrieNode*>(name, currentNode));
|
||||
assert(ret.second);
|
||||
|
@ -1700,11 +1712,9 @@ bool CClaimTrieCacheBase::removeSupportFromMap(const std::string& name, const CO
|
|||
if (cachedNode == supportCache.end())
|
||||
{
|
||||
supportMapEntryType node;
|
||||
if (!base->getSupportNode(name, node))
|
||||
{
|
||||
// clearly, this support does not exist
|
||||
if (!base->getSupportNode(name, node)) // clearly, this support does not exist
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<supportMapType::iterator, bool> ret;
|
||||
ret = supportCache.insert(std::pair<std::string, supportMapEntryType>(name, node));
|
||||
assert(ret.second);
|
||||
|
@ -1714,9 +1724,7 @@ bool CClaimTrieCacheBase::removeSupportFromMap(const std::string& name, const CO
|
|||
for (itSupport = cachedNode->second.begin(); itSupport != cachedNode->second.end(); ++itSupport)
|
||||
{
|
||||
if (itSupport->outPoint == outPoint)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itSupport != cachedNode->second.end())
|
||||
{
|
||||
|
@ -1724,11 +1732,9 @@ bool CClaimTrieCacheBase::removeSupportFromMap(const std::string& name, const CO
|
|||
cachedNode->second.erase(itSupport);
|
||||
return reorderTrieNode(name, fCheckTakeover);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrintf("CClaimTrieCacheBase::%s() : asked to remove a support that doesn't exist\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
LogPrintf("CClaimTrieCacheBase::%s() : asked to remove a support that doesn't exist\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
supportQueueType::iterator CClaimTrieCacheBase::getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const
|
||||
|
@ -1757,9 +1763,8 @@ queueNameType::iterator CClaimTrieCacheBase::getSupportQueueCacheNameRow(const s
|
|||
{
|
||||
queueNameRowType queueNameRow;
|
||||
bool exists = base->getSupportQueueNameRow(name, queueNameRow);
|
||||
if (!exists)
|
||||
if (!createIfNotExists)
|
||||
return itQueueNameRow;
|
||||
if (!exists && !createIfNotExists)
|
||||
return itQueueNameRow;
|
||||
// Stick the new row in the name cache
|
||||
std::pair<queueNameType::iterator, bool> ret;
|
||||
ret = supportQueueNameCache.insert(std::pair<std::string, queueNameRowType>(name, queueNameRow));
|
||||
|
@ -1786,21 +1791,17 @@ bool CClaimTrieCacheBase::removeSupportFromQueue(const std::string& name, const
|
|||
{
|
||||
queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, false);
|
||||
if (itQueueNameRow == supportQueueNameCache.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
queueNameRowType::iterator itQueueName;
|
||||
for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName)
|
||||
{
|
||||
if (itQueueName->outPoint == outPoint)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itQueueName == itQueueNameRow->second.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(itQueueName->nHeight, false);
|
||||
if (itQueueRow != supportQueueCache.end())
|
||||
{
|
||||
|
@ -1809,9 +1810,7 @@ bool CClaimTrieCacheBase::removeSupportFromQueue(const std::string& name, const
|
|||
{
|
||||
CSupportValue& support = itQueue->second;
|
||||
if (support.outPoint == outPoint && name == itQueue->first)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itQueue != itQueueRow->second.end())
|
||||
{
|
||||
|
@ -1845,10 +1844,8 @@ bool CClaimTrieCacheBase::undoSpendSupport(const std::string& name, const COutPo
|
|||
addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, entry);
|
||||
return insertSupportIntoMap(name, support, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return addSupportToQueues(name, support);
|
||||
}
|
||||
|
||||
return addSupportToQueues(name, support);
|
||||
}
|
||||
|
||||
bool CClaimTrieCacheBase::removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const
|
||||
|
@ -1890,9 +1887,7 @@ void CClaimTrieCacheBase::removeSupportFromExpirationQueue(const std::string& na
|
|||
}
|
||||
}
|
||||
if (itQueue != itQueueRow->second.end())
|
||||
{
|
||||
itQueueRow->second.erase(itQueue);
|
||||
}
|
||||
}
|
||||
|
||||
expirationQueueType::iterator CClaimTrieCacheBase::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const
|
||||
|
@ -1904,9 +1899,8 @@ expirationQueueType::iterator CClaimTrieCacheBase::getSupportExpirationQueueCach
|
|||
expirationQueueRowType queueRow;
|
||||
// If the row exists in the base, copy its claims into the new row.
|
||||
bool exists = base->getSupportExpirationQueueRow(nHeight, queueRow);
|
||||
if (!exists)
|
||||
if (!createIfNotExists)
|
||||
return itQueueRow;
|
||||
if (!exists && !createIfNotExists)
|
||||
return itQueueRow;
|
||||
// Stick the new row in the cache
|
||||
std::pair<expirationQueueType::iterator, bool> ret;
|
||||
ret = supportExpirationQueueCache.insert(std::pair<int, expirationQueueRowType >(nHeight, queueRow));
|
||||
|
@ -2057,12 +2051,22 @@ bool CClaimTrieCacheBase::incrementBlock(insertUndoType& insertUndo, claimQueueR
|
|||
|
||||
for (nodeCacheType::const_iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals)
|
||||
{
|
||||
delete itOriginals->second;
|
||||
auto matcher = [&itOriginals](const CClaimTrieNode& a)
|
||||
{
|
||||
return const_cast<CClaimTrieNode*>(&a) == itOriginals->second;
|
||||
};
|
||||
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), matcher);
|
||||
if (it != nodes.end())
|
||||
nodes.erase(it);
|
||||
else
|
||||
delete itOriginals->second;
|
||||
}
|
||||
block_originals.clear();
|
||||
for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache)
|
||||
{
|
||||
block_originals[itCache->first] = new CClaimTrieNode(*itCache->second);
|
||||
nodes.push_back(new CClaimTrieNode(*itCache->second));
|
||||
block_originals[itCache->first] = &nodes[nodes.size() - 1];
|
||||
}
|
||||
nCurrentHeight++;
|
||||
|
||||
|
@ -2259,12 +2263,14 @@ bool CClaimTrieCacheBase::decrementBlock(insertUndoType& insertUndo, claimQueueR
|
|||
if (!expireUndo.empty())
|
||||
{
|
||||
expirationQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true);
|
||||
for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo)
|
||||
for (claimQueueRowType::reverse_iterator itExpireUndo = expireUndo.rbegin(); itExpireUndo != expireUndo.rend(); ++itExpireUndo)
|
||||
{
|
||||
insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second, false);
|
||||
CClaimIndexElement element = {itExpireUndo->first, itExpireUndo->second};
|
||||
CClaimIndexElement element = { itExpireUndo->first, itExpireUndo->second };
|
||||
claimsToAdd.push_back(element);
|
||||
itExpireRow->second.push_back(nameOutPointType(itExpireUndo->first, itExpireUndo->second.outPoint));
|
||||
// Check if it expired at this height rather than being a rename/normalization
|
||||
if (nCurrentHeight == itExpireUndo->second.nHeight + base->nExpirationTime)
|
||||
itExpireRow->second.push_back(nameOutPointType(itExpireUndo->first, itExpireUndo->second.outPoint));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2300,12 +2306,22 @@ bool CClaimTrieCacheBase::finalizeDecrement() const
|
|||
{
|
||||
for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals)
|
||||
{
|
||||
delete itOriginals->second;
|
||||
auto matcher = [&itOriginals](const CClaimTrieNode& a)
|
||||
{
|
||||
return const_cast<CClaimTrieNode*>(&a) == itOriginals->second;
|
||||
};
|
||||
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), matcher);
|
||||
if (it != nodes.end())
|
||||
nodes.erase(it);
|
||||
else
|
||||
delete itOriginals->second;
|
||||
}
|
||||
block_originals.clear();
|
||||
for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache)
|
||||
{
|
||||
block_originals[itCache->first] = new CClaimTrieNode(*itCache->second);
|
||||
nodes.push_back(new CClaimTrieNode(*itCache->second));
|
||||
block_originals[itCache->first] = &nodes[nodes.size() - 1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2329,7 +2345,8 @@ bool CClaimTrieCacheBase::getLastTakeoverForName(const std::string& name, int& n
|
|||
int CClaimTrieCacheBase::getNumBlocksOfContinuousOwnership(const std::string& name) const
|
||||
{
|
||||
const CClaimTrieNode* node = getNodeForName(name);
|
||||
if (!node || node->claims.empty()) return 0;
|
||||
if (!node || node->claims.empty())
|
||||
return 0;
|
||||
int nLastTakeoverHeight;
|
||||
assert(getLastTakeoverForName(name, nLastTakeoverHeight));
|
||||
return nCurrentHeight - nLastTakeoverHeight;
|
||||
|
@ -2337,8 +2354,20 @@ int CClaimTrieCacheBase::getNumBlocksOfContinuousOwnership(const std::string& na
|
|||
|
||||
const CClaimTrieNode* CClaimTrieCacheBase::getNodeForName(const std::string& name) const
|
||||
{
|
||||
/* CClaimTrieNode* node = nullptr; */
|
||||
/* nodeCacheType::const_iterator itCache = cache.find(name); */
|
||||
/* if (itCache != cache.end()) */
|
||||
/* node = itCache->second; */
|
||||
/* return (node ? node : base->getNodeForName(name)); */
|
||||
const CClaimTrieNode* node = nullptr;
|
||||
nodeCacheType::const_iterator itCache = cache.find(name);
|
||||
return ((itCache != cache.end()) ? itCache->second : base->getNodeForName(name));
|
||||
if (itCache != cache.end()) {
|
||||
node = itCache->second;
|
||||
}
|
||||
if (!node) {
|
||||
node = base->getNodeForName(name);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// "name" is already normalized if needed
|
||||
|
@ -2364,9 +2393,8 @@ int CClaimTrieCacheBase::getDelayForName(const std::string& name, const uint160&
|
|||
|
||||
uint256 CClaimTrieCacheBase::getBestBlock()
|
||||
{
|
||||
if (hashBlock.IsNull())
|
||||
if (base != nullptr)
|
||||
hashBlock = base->hashBlock;
|
||||
if (hashBlock.IsNull() && base != nullptr)
|
||||
hashBlock = base->hashBlock;
|
||||
return hashBlock;
|
||||
}
|
||||
|
||||
|
@ -2379,12 +2407,30 @@ bool CClaimTrieCacheBase::clear() const
|
|||
{
|
||||
for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache)
|
||||
{
|
||||
delete itcache->second;
|
||||
auto matcher = [&itcache](const CClaimTrieNode& a)
|
||||
{
|
||||
return const_cast<CClaimTrieNode*>(&a) == itcache->second;
|
||||
};
|
||||
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), matcher);
|
||||
if (it != nodes.end())
|
||||
nodes.erase(it);
|
||||
else
|
||||
delete itcache->second;
|
||||
}
|
||||
cache.clear();
|
||||
for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals)
|
||||
{
|
||||
delete itOriginals->second;
|
||||
auto matcher = [&itOriginals](const CClaimTrieNode& a)
|
||||
{
|
||||
return const_cast<CClaimTrieNode*>(&a) == itOriginals->second;
|
||||
};
|
||||
|
||||
auto it = std::find_if(nodes.begin(), nodes.end(), matcher);
|
||||
if (it != nodes.end())
|
||||
nodes.erase(it);
|
||||
else
|
||||
delete itOriginals->second;
|
||||
}
|
||||
block_originals.clear();
|
||||
dirtyHashes.clear();
|
||||
|
@ -2445,11 +2491,14 @@ void CClaimTrieCacheBase::recursiveIterateTrie(std::string& name, const CClaimTr
|
|||
|
||||
bool CClaimTrieCacheBase::iterateTrie(CNodeCallback& callback) const
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
std::string name;
|
||||
recursiveIterateTrie(name, getRoot(), callback);
|
||||
assert(name.empty());
|
||||
} catch (const CNodeCallback::CRecursionInterruptionException& ex) {
|
||||
}
|
||||
catch (const CNodeCallback::CRecursionInterruptionException& ex)
|
||||
{
|
||||
return ex.success;
|
||||
}
|
||||
return true;
|
||||
|
@ -2459,7 +2508,8 @@ claimsForNameType CClaimTrieCacheBase::getClaimsForName(const std::string& name)
|
|||
{
|
||||
int nLastTakeoverHeight = 0;
|
||||
std::vector<CClaimValue> claims;
|
||||
if (const CClaimTrieNode* node = getNodeForName(name)) {
|
||||
if (const CClaimTrieNode* node = getNodeForName(name))
|
||||
{
|
||||
claims = node->claims;
|
||||
getLastTakeoverForName(name, nLastTakeoverHeight);
|
||||
}
|
||||
|
@ -2476,13 +2526,18 @@ CAmount CClaimTrieCacheBase::getEffectiveAmountForClaim(const std::string& name,
|
|||
CAmount CClaimTrieCacheBase::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) {
|
||||
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) {
|
||||
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);
|
||||
if (supports)
|
||||
supports->push_back(*it);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2499,7 +2554,8 @@ bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& c
|
|||
CClaimTrieNode* current = getRoot();
|
||||
nodeCacheType::const_iterator cachedNode;
|
||||
|
||||
for (std::string::const_iterator itName = name.begin(); current; ++itName) {
|
||||
for (std::string::const_iterator itName = name.begin(); current; ++itName)
|
||||
{
|
||||
std::string currentPosition(name.begin(), itName);
|
||||
cachedNode = cache.find(currentPosition);
|
||||
if (cachedNode != cache.end())
|
||||
|
@ -2509,9 +2565,8 @@ bool CClaimTrieCacheBase::getInfoForName(const std::string& name, CClaimValue& c
|
|||
return current->getBestClaim(claim);
|
||||
|
||||
nodeMapType::const_iterator itChildren = current->children.find(*itName);
|
||||
if (itChildren != current->children.end()) {
|
||||
if (itChildren != current->children.end())
|
||||
current = itChildren->second;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
103
src/claimtrie.h
103
src/claimtrie.h
|
@ -139,7 +139,6 @@ class CClaimTrieNode;
|
|||
class CClaimTrie;
|
||||
|
||||
typedef std::vector<CSupportValue> supportMapEntryType;
|
||||
|
||||
typedef std::map<unsigned char, CClaimTrieNode*> nodeMapType;
|
||||
|
||||
class CClaimTrieNode
|
||||
|
@ -150,16 +149,18 @@ public:
|
|||
CClaimTrieNode(const CClaimTrieNode&) = default;
|
||||
CClaimTrieNode(CClaimTrieNode&& other)
|
||||
{
|
||||
hash = other.hash;
|
||||
hash = std::move(other.hash);
|
||||
claims = std::move(other.claims);
|
||||
children = std::move(other.children);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
}
|
||||
|
||||
CClaimTrieNode& operator=(const CClaimTrieNode&) = default;
|
||||
CClaimTrieNode& operator=(CClaimTrieNode&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
hash = other.hash;
|
||||
if (this != &other)
|
||||
{
|
||||
hash = std::move(other.hash);
|
||||
claims = std::move(other.claims);
|
||||
children = std::move(other.children);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
|
@ -323,7 +324,7 @@ struct claimsForNameType
|
|||
|
||||
claimsForNameType(std::vector<CClaimValue> claims, std::vector<CSupportValue> supports,
|
||||
int nLastTakeoverHeight, const std::string& name)
|
||||
: claims(std::move(claims)), supports(std::move(supports)),
|
||||
: claims(std::move(claims)), supports(std::move(supports)),
|
||||
nLastTakeoverHeight(nLastTakeoverHeight), name(name) {}
|
||||
|
||||
claimsForNameType(const claimsForNameType&) = default;
|
||||
|
@ -331,8 +332,8 @@ struct claimsForNameType
|
|||
{
|
||||
claims = std::move(other.claims);
|
||||
supports = std::move(other.supports);
|
||||
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
||||
name = std::move(other.name);
|
||||
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
||||
}
|
||||
|
||||
claimsForNameType& operator=(const claimsForNameType&) = default;
|
||||
|
@ -342,8 +343,8 @@ struct claimsForNameType
|
|||
{
|
||||
claims = std::move(other.claims);
|
||||
supports = std::move(other.supports);
|
||||
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
||||
name = std::move(other.name);
|
||||
nLastTakeoverHeight = other.nLastTakeoverHeight;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -358,10 +359,10 @@ class CClaimTrie
|
|||
{
|
||||
public:
|
||||
CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32)
|
||||
: db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false), nCurrentHeight(0),
|
||||
nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime),
|
||||
nProportionalDelayFactor(nProportionalDelayFactor),
|
||||
root(uint256S("0000000000000000000000000000000000000000000000000000000000000001"))
|
||||
: db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false)
|
||||
, nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime)
|
||||
, nProportionalDelayFactor(nProportionalDelayFactor)
|
||||
, root(uint256S("0000000000000000000000000000000000000000000000000000000000000001"))
|
||||
{}
|
||||
|
||||
uint256 getMerkleHash();
|
||||
|
@ -411,7 +412,7 @@ public:
|
|||
int nExpirationTime;
|
||||
int nProportionalDelayFactor;
|
||||
|
||||
private:
|
||||
private:
|
||||
void clear(CClaimTrieNode* current);
|
||||
|
||||
const CClaimTrieNode* getNodeForName(const std::string& name) const;
|
||||
|
@ -432,7 +433,7 @@ public:
|
|||
|
||||
bool recursiveCheckConsistency(const CClaimTrieNode* node) const;
|
||||
|
||||
bool InsertFromDisk(const std::string& name, CClaimTrieNode* node);
|
||||
bool InsertFromDisk(const std::string& name, const CClaimTrieNode& node);
|
||||
|
||||
unsigned int getTotalNamesRecursive(const CClaimTrieNode* current) const;
|
||||
unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const;
|
||||
|
@ -490,25 +491,27 @@ public:
|
|||
CClaimTrieProofNode() {};
|
||||
CClaimTrieProofNode(std::vector<std::pair<unsigned char, uint256> > children,
|
||||
bool hasValue, uint256 valHash)
|
||||
: children(std::move(children)), hasValue(hasValue), valHash(valHash)
|
||||
: children(std::move(children)), hasValue(hasValue), valHash(std::move(valHash))
|
||||
{};
|
||||
CClaimTrieProofNode(const CClaimTrieProofNode&) = default;
|
||||
CClaimTrieProofNode(CClaimTrieProofNode&& other)
|
||||
{
|
||||
hasValue = other.hasValue;
|
||||
valHash = other.valHash;
|
||||
valHash = std::move(other.valHash);
|
||||
children = std::move(other.children);
|
||||
}
|
||||
CClaimTrieProofNode& operator=(const CClaimTrieProofNode&) = default;
|
||||
CClaimTrieProofNode& operator=(CClaimTrieProofNode&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (this != &other)
|
||||
{
|
||||
hasValue = other.hasValue;
|
||||
valHash = other.valHash;
|
||||
valHash = std::move(other.valHash);
|
||||
children = std::move(other.children);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<std::pair<unsigned char, uint256> > children;
|
||||
bool hasValue;
|
||||
uint256 valHash;
|
||||
|
@ -523,21 +526,24 @@ public:
|
|||
CClaimTrieProof(CClaimTrieProof&& other)
|
||||
{
|
||||
hasValue = other.hasValue;
|
||||
outPoint = other.outPoint;
|
||||
outPoint = std::move(other.outPoint);
|
||||
nodes = std::move(other.nodes);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
}
|
||||
|
||||
CClaimTrieProof& operator=(const CClaimTrieProof&) = default;
|
||||
CClaimTrieProof& operator=(CClaimTrieProof&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (this != &other)
|
||||
{
|
||||
hasValue = other.hasValue;
|
||||
outPoint = other.outPoint;
|
||||
outPoint = std::move(other.outPoint);
|
||||
nodes = std::move(other.nodes);
|
||||
nHeightOfLastTakeover = other.nHeightOfLastTakeover;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<CClaimTrieProofNode> nodes;
|
||||
bool hasValue;
|
||||
COutPoint outPoint;
|
||||
|
@ -569,8 +575,7 @@ class CClaimTrieCacheBase
|
|||
{
|
||||
public:
|
||||
CClaimTrieCacheBase(CClaimTrie* base, bool fRequireTakeoverHeights = true)
|
||||
: base(base),
|
||||
fRequireTakeoverHeights(fRequireTakeoverHeights)
|
||||
: base(base), fRequireTakeoverHeights(fRequireTakeoverHeights)
|
||||
{
|
||||
assert(base);
|
||||
nCurrentHeight = base->nCurrentHeight;
|
||||
|
@ -584,7 +589,7 @@ public:
|
|||
|
||||
CClaimTrieNode* getRoot() const
|
||||
{
|
||||
const nodeCacheType::iterator iter = cache.find("");
|
||||
const auto iter = cache.find("");
|
||||
return iter == cache.end() ? &(base->root) : iter->second;
|
||||
}
|
||||
|
||||
|
@ -611,15 +616,15 @@ public:
|
|||
void setBestBlock(const uint256& hashBlock);
|
||||
|
||||
virtual bool incrementBlock(insertUndoType& insertUndo,
|
||||
claimQueueRowType& expireUndo,
|
||||
insertUndoType& insertSupportUndo,
|
||||
supportQueueRowType& expireSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
||||
claimQueueRowType& expireUndo,
|
||||
insertUndoType& insertSupportUndo,
|
||||
supportQueueRowType& expireSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
||||
virtual bool decrementBlock(insertUndoType& insertUndo,
|
||||
claimQueueRowType& expireUndo,
|
||||
insertUndoType& insertSupportUndo,
|
||||
supportQueueRowType& expireSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
||||
claimQueueRowType& expireUndo,
|
||||
insertUndoType& insertSupportUndo,
|
||||
supportQueueRowType& expireSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo);
|
||||
|
||||
virtual ~CClaimTrieCacheBase() { clear(); }
|
||||
|
||||
|
@ -632,31 +637,33 @@ public:
|
|||
|
||||
virtual 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;
|
||||
CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId,
|
||||
std::vector<CSupportValue>* supports = nullptr) const;
|
||||
CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId,
|
||||
std::vector<CSupportValue>* supports = nullptr) const;
|
||||
|
||||
protected:
|
||||
// Should be private: Do not use unless you know what you're doing.
|
||||
CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original) const;
|
||||
bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent,
|
||||
const std::string& sPos,
|
||||
bool forceCompute = false) const;
|
||||
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified = NULL) const;
|
||||
const std::string& sPos,
|
||||
bool forceCompute = false) const;
|
||||
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, const std::string& sName, bool* pfNullified = nullptr) const;
|
||||
void checkNamesForTakeover(insertUndoType& insertUndo, insertUndoType& insertSupportUndo,
|
||||
std::vector<std::pair<std::string, int> >& takeoverHeightUndo) const;
|
||||
|
||||
virtual bool insertClaimIntoTrie(const std::string& name, CClaimValue claim,
|
||||
bool fCheckTakeover = false) const;
|
||||
bool fCheckTakeover = false) const;
|
||||
virtual bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint,
|
||||
CClaimValue& claim,
|
||||
bool fCheckTakeover = false) const;
|
||||
CClaimValue& claim,
|
||||
bool fCheckTakeover = false) const;
|
||||
|
||||
virtual bool insertSupportIntoMap(const std::string& name,
|
||||
CSupportValue support,
|
||||
bool fCheckTakeover) const;
|
||||
CSupportValue support,
|
||||
bool fCheckTakeover) const;
|
||||
virtual bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint,
|
||||
CSupportValue& support,
|
||||
bool fCheckTakeover) const;
|
||||
CSupportValue& support,
|
||||
bool fCheckTakeover) const;
|
||||
|
||||
virtual void addClaimToQueues(const std::string& name, CClaimValue& claim) const;
|
||||
virtual bool addSupportToQueues(const std::string& name, CSupportValue& support) const;
|
||||
|
@ -726,9 +733,9 @@ private:
|
|||
supportQueueType::iterator getSupportQueueCacheRow(int nHeight,
|
||||
bool createIfNotExists) const;
|
||||
queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name,
|
||||
bool createIfNotExists) const;
|
||||
bool createIfNotExists) const;
|
||||
expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight,
|
||||
bool createIfNotExists) const;
|
||||
bool createIfNotExists) const;
|
||||
|
||||
bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint,
|
||||
CSupportValue& support) const;
|
||||
|
@ -749,9 +756,9 @@ private:
|
|||
};
|
||||
|
||||
class CClaimTrieCacheExpirationFork: public CClaimTrieCacheBase {
|
||||
public:
|
||||
public:
|
||||
CClaimTrieCacheExpirationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true)
|
||||
: CClaimTrieCacheBase(base, fRequireTakeoverHeights) {}
|
||||
: CClaimTrieCacheBase(base, fRequireTakeoverHeights) {}
|
||||
|
||||
virtual ~CClaimTrieCacheExpirationFork() {}
|
||||
|
||||
|
@ -765,7 +772,7 @@ private:
|
|||
};
|
||||
|
||||
class CClaimTrieCacheNormalizationFork: public CClaimTrieCacheExpirationFork {
|
||||
public:
|
||||
public:
|
||||
CClaimTrieCacheNormalizationFork(CClaimTrie* base, bool fRequireTakeoverHeights = true)
|
||||
: CClaimTrieCacheExpirationFork(base, fRequireTakeoverHeights),
|
||||
overrideInsertNormalization(false), overrideRemoveNormalization(false) {}
|
||||
|
|
|
@ -205,10 +205,9 @@ bool CClaimTrieCacheNormalizationFork::normalizeAllNamesInTrieIfNecessary(insert
|
|||
|
||||
if (nCurrentHeight == Params().GetConsensus().nNormalizedNameForkHeight) {
|
||||
|
||||
std::cout << "RUNNING NORMALIZATION NOW" << std::endl;
|
||||
// run the one-time upgrade of all names that need to change
|
||||
// it modifies the (cache) trie as it goes, so we need to grab everything to be modified first
|
||||
|
||||
// it modifies the (cache) trie as it goes, so we need to grab
|
||||
// everything to be modified first
|
||||
CNameChangeDetector detector(this);
|
||||
iterateTrie(detector);
|
||||
|
||||
|
|
|
@ -532,7 +532,7 @@ void SetupServerArgs()
|
|||
std::string LicenseInfo()
|
||||
{
|
||||
const std::string URL_SOURCE_CODE = "<https://github.com/lbryio/lbrycrd>";
|
||||
const std::string URL_WEBSITE = "<https://lbry.io>";
|
||||
const std::string URL_WEBSITE = "<https://lbry.com>";
|
||||
|
||||
return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2009, COPYRIGHT_YEAR) + " ") + "\n" +
|
||||
"\n" +
|
||||
|
@ -1430,6 +1430,7 @@ bool AppInitMain()
|
|||
nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache
|
||||
nTotalCache -= nCoinDBCache;
|
||||
nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache
|
||||
std::cout << "nTotalCache: " << nTotalCache << ", nCoinCacheUsage: " << nCoinCacheUsage << ", nCoinDBCache: " << nCoinDBCache << std::endl;
|
||||
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
|
||||
LogPrintf("Cache configuration:\n");
|
||||
LogPrintf("* Using %.1fMiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024));
|
||||
|
|
|
@ -454,6 +454,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
|
||||
if (DecodeClaimScript(scriptPubKey, op, vvchParams))
|
||||
{
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
uint160 claimId;
|
||||
|
@ -467,7 +468,6 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
assert(vvchParams.size() == 3);
|
||||
claimId = uint160(vvchParams[1]);
|
||||
}
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
int throwaway;
|
||||
if (trieCache.spendClaim(name, COutPoint(txin.prevout.hash, txin.prevout.n), coin.nHeight, throwaway))
|
||||
{
|
||||
|
@ -482,7 +482,6 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
int throwaway;
|
||||
if (!trieCache.spendSupport(name, COutPoint(txin.prevout.hash, txin.prevout.n), coin.nHeight, throwaway))
|
||||
{
|
||||
|
@ -500,10 +499,10 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
int op;
|
||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
if (!trieCache.addClaim(name, COutPoint(tx.GetHash(), i), ClaimIdHash(tx.GetHash(), i), txout.nValue, nHeight))
|
||||
{
|
||||
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||
|
@ -512,13 +511,12 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 3);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 claimId(vvchParams[1]);
|
||||
spentClaimsType::iterator itSpent;
|
||||
for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent)
|
||||
{
|
||||
if ((itSpent->first == name && itSpent->second == claimId) &&
|
||||
(trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)))
|
||||
if (itSpent->second == claimId &&
|
||||
trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first))
|
||||
break;
|
||||
}
|
||||
if (itSpent != spentClaims.end())
|
||||
|
@ -537,7 +535,6 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
|
|||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
if (!trieCache.addSupport(name, COutPoint(tx.GetHash(), i), txout.nValue, supportedClaimId, nHeight))
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||
// Special difficulty rule for testnet:
|
||||
// If the new block's timestamp is twice the target block time
|
||||
// then allow mining of a min-difficulty block.
|
||||
// This is to prevent the testnet from gettig stuck when a large amount
|
||||
// This is to prevent the testnet from getting stuck when a large amount
|
||||
// of hashrate drops off the network.
|
||||
// This rule was not implemented properly until testnet block 277299.
|
||||
if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2){
|
||||
|
|
|
@ -275,7 +275,7 @@ static bool getValueForOutPoint(const CCoinsViewCache& coinsCache, const COutPoi
|
|||
sValue = HexStr(vvchParams[1].begin(), vvchParams[1].end());
|
||||
return true;
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
else if (vvchParams.size() > 2) // both UPDATE and SUPPORT
|
||||
{
|
||||
sValue = HexStr(vvchParams[2].begin(), vvchParams[2].end());
|
||||
return true;
|
||||
|
@ -431,6 +431,7 @@ UniValue getclaimsforname(const JSONRPCRequest& request)
|
|||
" \"nAmount\" (numeric) the amount of the support\n"
|
||||
" \"value\" (string) the metadata of the support if any\n"
|
||||
" ]\n"
|
||||
" \"name\" (string) the original name of this claim before normalization\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"supports without claims\": [ (array of object) supports that did not match a claim for this name\n"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2105,10 +2105,10 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (DecodeClaimScript(coin.out.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
if (op == OP_CLAIM_NAME || op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
uint160 claimId;
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
std::string value(vvchParams[1].begin(), vvchParams[1].end());
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
|
@ -2141,7 +2141,6 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
LogPrintf("+++ %s[%lu]: OP_SUPPORT_CLAIM \"%s\" with claimId %s and tx prevout %s at index %d\n",
|
||||
__func__, pindex->nHeight, name,
|
||||
|
@ -2166,10 +2165,10 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
LogPrintf("%s: Inserting %s into the claim trie. Tx: %s, nOut: %d\n",
|
||||
__func__, name, tx.GetHash().GetHex(), j);
|
||||
if (!trieCache.addClaim(name, COutPoint(tx.GetHash(), j), ClaimIdHash(tx.GetHash(), j), txout.nValue, pindex->nHeight))
|
||||
|
@ -2180,15 +2179,14 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 3);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 claimId(vvchParams[1]);
|
||||
LogPrintf("%s: Got a claim update. Name: %s, claimId: %s, new txid: %s, nOut: %d\n",
|
||||
__func__, name, claimId.GetHex(), tx.GetHash().GetHex(), j);
|
||||
spentClaimsType::iterator itSpent;
|
||||
for (itSpent = spentClaims.begin(); itSpent != spentClaims.end(); ++itSpent)
|
||||
{
|
||||
if ((itSpent->first == name && itSpent->second == claimId) &&
|
||||
(trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first)))
|
||||
if (itSpent->second == claimId &&
|
||||
trieCache.normalizeClaimName(name) == trieCache.normalizeClaimName(itSpent->first))
|
||||
break;
|
||||
}
|
||||
if (itSpent != spentClaims.end())
|
||||
|
@ -2203,7 +2201,6 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
|||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
assert(vvchParams.size() == 2);
|
||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||
uint160 supportedClaimId(vvchParams[1]);
|
||||
if (!trieCache.addSupport(name, COutPoint(tx.GetHash(), j), txout.nValue, supportedClaimId, pindex->nHeight))
|
||||
{
|
||||
|
|
|
@ -462,8 +462,9 @@ static UniValue getaddressesbyaccount(const JSONRPCRequest& request)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue, std::string fromAccount)
|
||||
{
|
||||
static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue,
|
||||
bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue, std::string fromAccount,
|
||||
const CScript& prefix = CScript()){
|
||||
CAmount curBalance = pwallet->GetBalance();
|
||||
|
||||
// Check amount
|
||||
|
@ -478,7 +479,7 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
|
|||
}
|
||||
|
||||
// Parse Bitcoin address
|
||||
CScript scriptPubKey = GetScriptForDestination(address);
|
||||
CScript scriptPubKey = prefix + GetScriptForDestination(address);
|
||||
|
||||
// Create and send the transaction
|
||||
CReserveKey reservekey(pwallet);
|
||||
|
@ -502,6 +503,468 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
|
|||
return tx;
|
||||
}
|
||||
|
||||
UniValue claimname(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 3)
|
||||
throw std::runtime_error(
|
||||
"claimname \"name\" \"value\" amount\n"
|
||||
"\nCreate a transaction which issues a claim assigning a value to a name. The claim will be authoritative if the transaction amount is greater than the transaction amount of all other unspent transactions which issue a claim over the same name, and it will remain au\
|
||||
thoritative as long as it remains unspent and there are no other greater unspent transactions issuing a claim over the same name. The amount is a real and is rounded to the nearest 0.00000001\n"
|
||||
+ HelpRequiringPassphrase(pwallet) +
|
||||
"\nArguments:\n"
|
||||
"1. \"name\" (string, required) The name to be assigned the value.\n"
|
||||
"2. \"value\" (string, required) The value to assign to the name encoded in hexadecimal.\n"
|
||||
"3. \"amount\" (numeric, required) The amount in LBRYcrd to send. eg 0.1\n"
|
||||
"\nResult:\n"
|
||||
"\"transactionid\" (string) The transaction id.\n");
|
||||
auto sName = request.params[0].get_str();
|
||||
auto sValue = request.params[1].get_str();
|
||||
|
||||
if (!IsHex(sValue))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "value must be hexadecimal");
|
||||
|
||||
std::vector<unsigned char> vchName (sName.begin(), sName.end());
|
||||
std::vector<unsigned char> vchValue(ParseHex(sValue));
|
||||
|
||||
CAmount nAmount = AmountFromValue(request.params[2]);
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
CScript claimScript = CScript() << OP_CLAIM_NAME << vchName << vchValue << OP_2DROP << OP_DROP;
|
||||
|
||||
//Get new address
|
||||
CPubKey newKey;
|
||||
if (!pwallet->GetKeyFromPool(newKey))
|
||||
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
|
||||
|
||||
CCoinControl cc;
|
||||
cc.m_change_type = DEFAULT_ADDRESS_TYPE;
|
||||
auto tx = SendMoney(pwallet, CTxDestination(newKey.GetID()), nAmount, false, cc, {}, {}, claimScript);
|
||||
return tx->GetHash().GetHex();
|
||||
}
|
||||
|
||||
UniValue updateclaim(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 3)
|
||||
throw std::runtime_error(
|
||||
"updateclaim \"txid\" \"value\" amount\n"
|
||||
"Create a transaction which issues a claim assigning a value to a name, spending the previous txout which issued a claim over the same name and therefore superseding that claim. The claim will be authoritative if the transaction amount is greater than the transaction amount of all other unspent transactions which issue a claim over the same name, and it will remain authoritative as long as it remains unspent and there are no greater unspent transactions issuing a claim over the same name.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n"
|
||||
"Arguments:\n"
|
||||
"1. \"txid\" (string, required) The transaction containing the unspent txout which should be spent.\n"
|
||||
"2. \"value\" (string, required) The value to assign to the name encoded in hexadecimal.\n"
|
||||
"3. \"amount\" (numeric, required) The amount in LBRYcrd to use to bid for the name. eg 0.1\n"
|
||||
"\nResult:\n"
|
||||
"\"transactionid\" (string) The new transaction id.\n");
|
||||
|
||||
uint256 hash;
|
||||
hash.SetHex(request.params[0].get_str());
|
||||
|
||||
auto sValue = request.params[1].get_str();
|
||||
if (!IsHex(sValue))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "value must be hexadecimal");
|
||||
|
||||
std::vector<unsigned char> vchValue(ParseHex(sValue));
|
||||
CAmount nAmount = AmountFromValue(request.params[2]);
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
auto it = pwallet->mapWallet.find(hash);
|
||||
if (it == pwallet->mapWallet.end()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
|
||||
}
|
||||
const auto& wtx = it->second;
|
||||
CTransactionRef wtxNew = nullptr;
|
||||
for (uint32_t i = 0; i < wtx.tx->vout.size(); ++i)
|
||||
{
|
||||
const auto& out = wtx.tx->vout[i];
|
||||
if (pwallet->IsMine(out) & isminetype::ISMINE_SPENDABLE)
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vvchParams;
|
||||
int op;
|
||||
if (DecodeClaimScript(out.scriptPubKey, op, vvchParams))
|
||||
{
|
||||
if (op == OP_SUPPORT_CLAIM)
|
||||
continue;
|
||||
|
||||
const auto& vchName = vvchParams[0];
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
uint160 claimId;
|
||||
if (op == OP_CLAIM_NAME) {
|
||||
claimId = ClaimIdHash(wtx.GetHash(), i);
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM) {
|
||||
claimId = uint160(vvchParams[1]);
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Error: op not implemented");
|
||||
}
|
||||
std::vector<unsigned char> vchClaimId(claimId.begin(), claimId.end());
|
||||
auto updateScript = CScript() << OP_UPDATE_CLAIM << vchName << vchClaimId << vchValue << OP_2DROP << OP_2DROP;
|
||||
|
||||
CPubKey newKey;
|
||||
if (!pwallet->GetKeyFromPool(newKey))
|
||||
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
|
||||
|
||||
CCoinControl cc;
|
||||
cc.m_change_type = DEFAULT_ADDRESS_TYPE;
|
||||
wtxNew = SendMoney(pwallet, CTxDestination(newKey.GetID()), nAmount, false, cc, {}, {}, updateScript);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wtxNew == nullptr)
|
||||
throw std::runtime_error("Error: The given transaction contains no claim scripts owned by this wallet");
|
||||
return wtxNew->GetHash().GetHex();
|
||||
}
|
||||
|
||||
UniValue abandonclaim(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 2)
|
||||
throw std::runtime_error(
|
||||
"abandonclaim \"txid\" \"address\"\n"
|
||||
"Create a transaction which spends a txout which assigned a value to a name, effectively abandoning that claim.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) +
|
||||
"\nArguments:\n"
|
||||
"1. \"txid\" (string, required) The transaction containing the unspent txout which should be spent.\n"
|
||||
"2. \"address\" (string, required) The lbrycrd address to send to.\n"
|
||||
"\nResult:\n"
|
||||
"\"transactionid\" (string) The new transaction id.\n");
|
||||
|
||||
uint256 hash;
|
||||
hash.SetHex(request.params[0].get_str());
|
||||
|
||||
CKeyID address;
|
||||
address.SetHex(request.params[1].get_str());
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
auto it = pwallet->mapWallet.find(hash);
|
||||
if (it == pwallet->mapWallet.end()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
|
||||
}
|
||||
const auto& wtx = it->second;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
CTransactionRef wtxNew = nullptr;
|
||||
for (uint32_t i = 0; i < wtx.tx->vout.size(); ++i)
|
||||
{
|
||||
auto mine = pwallet->IsMine(wtx.tx->vout[i]);
|
||||
if (mine & isminetype::ISMINE_CLAIM)
|
||||
{
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
CCoinControl cc;
|
||||
cc.m_change_type = DEFAULT_ADDRESS_TYPE;
|
||||
cc.Select(COutPoint(wtx.tx->GetHash(), i));
|
||||
wtxNew = SendMoney(pwallet, address, wtx.tx->vout[i].nValue, true, cc, {}, {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wtxNew == nullptr)
|
||||
throw std::runtime_error("Error: The given transaction contains no claim scripts owned by this wallet");
|
||||
return wtxNew->GetHash().GetHex();
|
||||
}
|
||||
|
||||
static void MaybePushAddress(UniValue& entry, const CTxDestination &dest);
|
||||
|
||||
|
||||
void ListNameClaims(const CWalletTx& wtx, CWallet* const pwallet, const std::string& strAccount, int nMinDepth,
|
||||
UniValue& ret, const bool include_supports, bool list_spent)
|
||||
{
|
||||
CAmount nFee;
|
||||
std::string strSentAccount;
|
||||
std::list<COutputEntry> listSent;
|
||||
std::list<COutputEntry> listReceived;
|
||||
|
||||
isminefilter filter = isminetype::ISMINE_CLAIM;
|
||||
if (include_supports)
|
||||
filter |= isminetype::ISMINE_SUPPORT;
|
||||
wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
|
||||
|
||||
bool fAllAccounts = (strAccount == std::string("*"));
|
||||
|
||||
if ((!listReceived.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
|
||||
{
|
||||
for (const COutputEntry& s: listReceived)
|
||||
{
|
||||
if (!list_spent && pwallet->IsSpent(wtx.GetHash(), s.vout))
|
||||
continue;
|
||||
|
||||
UniValue entry(UniValue::VOBJ);
|
||||
const CScript& scriptPubKey = wtx.tx->vout[s.vout].scriptPubKey;
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char>> vvchParams;
|
||||
if (!DecodeClaimScript(scriptPubKey, op, vvchParams)) {
|
||||
continue;
|
||||
}
|
||||
std::string sName (vvchParams[0].begin(), vvchParams[0].end());
|
||||
entry.pushKV("name", sName);
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
uint160 claimId = ClaimIdHash(wtx.GetHash(), s.vout);
|
||||
entry.pushKV("claimId", claimId.GetHex());
|
||||
entry.pushKV("value", HexStr(vvchParams[1].begin(), vvchParams[1].end()));
|
||||
}
|
||||
else if (op == OP_UPDATE_CLAIM)
|
||||
{
|
||||
uint160 claimId(vvchParams[1]);
|
||||
entry.pushKV("claimId", claimId.GetHex());
|
||||
entry.pushKV("value", HexStr(vvchParams[2].begin(), vvchParams[2].end()));
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
uint160 claimId(vvchParams[1]);
|
||||
entry.pushKV("supported_claimid", claimId.GetHex());
|
||||
if (vvchParams.size() > 2) {
|
||||
entry.pushKV("value", HexStr(vvchParams[2].begin(), vvchParams[2].end()));
|
||||
}
|
||||
}
|
||||
entry.pushKV("txid", wtx.GetHash().ToString());
|
||||
entry.pushKV("account", strSentAccount);
|
||||
MaybePushAddress(entry, s.destination);
|
||||
entry.pushKV("amount", ValueFromAmount(s.amount));
|
||||
entry.pushKV("vout", s.vout);
|
||||
entry.pushKV("fee", ValueFromAmount(nFee));
|
||||
auto it = mapBlockIndex.find(wtx.hashBlock);
|
||||
if (it != mapBlockIndex.end())
|
||||
{
|
||||
CBlockIndex* pindex = it->second;
|
||||
if (pindex)
|
||||
{
|
||||
entry.pushKV("height", pindex->nHeight);
|
||||
entry.pushKV("expiration height", pindex->nHeight + pclaimTrie->nExpirationTime);
|
||||
if (pindex->nHeight + pclaimTrie->nExpirationTime > chainActive.Height())
|
||||
{
|
||||
entry.pushKV("expired", false);
|
||||
entry.pushKV("blocks to expiration", pindex->nHeight + pclaimTrie->nExpirationTime - chainActive.Height());
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.pushKV("expired", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
entry.pushKV("confirmations", wtx.GetDepthInMainChain());
|
||||
entry.pushKV("is spent", pwallet->IsSpent(wtx.GetHash(), s.vout));
|
||||
if (op == OP_CLAIM_NAME)
|
||||
{
|
||||
entry.pushKV("is in name trie", pclaimTrie->haveClaim(sName, COutPoint(wtx.GetHash(), s.vout)));
|
||||
}
|
||||
else if (op == OP_SUPPORT_CLAIM)
|
||||
{
|
||||
entry.pushKV("is in support map", pclaimTrie->haveSupport(sName, COutPoint(wtx.GetHash(), s.vout)));
|
||||
}
|
||||
ret.push_back(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UniValue listnameclaims(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() > 3)
|
||||
throw std::runtime_error(
|
||||
"listnameclaims includesuppports activeonly minconf\n"
|
||||
"Return a list of all transactions claiming names.\n"
|
||||
"\nArguments\n"
|
||||
"1. includesupports (bool, optional) Whether to also include claim supports. Default is true.\n"
|
||||
"2. activeonly (bool, optional, not implemented) Whether to only include transactions which are still active, i.e. have n\
|
||||
ot been spent. Default is false.\n"
|
||||
"3. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
|
||||
"\nResult:\n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"name\":\"claimedname\", (string) The name that is claimed.\n"
|
||||
" \"claimtype\":\"claimtype\", (string) CLAIM or SUPPORT.\n"
|
||||
" \"claimId\":\"claimId\", (string) The claimId of the claim.\n"
|
||||
" \"value\":\"value\" (string) The value assigned to the name, if claimtype is CLAIM.\n"
|
||||
" \"account\":\"accountname\", (string) The account name associated with the transaction. \n"
|
||||
" It will be \"\" for the default account.\n"
|
||||
" \"address\":\"lbrycrdaddress\", (string) The lbrycrd address of the transaction.\n"
|
||||
" \"category\":\"name\" (string) Always name\n"
|
||||
" \"amount\": x.xxx, (numeric) The amount in LBC.\n"
|
||||
" \"vout\": n, (numeric) The vout value\n"
|
||||
" \"fee\": x.xxx, (numeric) The amount of the fee in LBC.\n"
|
||||
" \"height\": n (numeric) The height of the block in which this transaction was included.\n"
|
||||
" \"confirmations\": n, (numeric) The number of confirmations for the transaction\n"
|
||||
" \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction.\n"
|
||||
" \"blockindex\": n, (numeric) The block index containing the transaction.\n"
|
||||
" \"txid\": \"transactionid\", (string) The transaction id.\n"
|
||||
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
|
||||
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT).\n"
|
||||
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
|
||||
" }\n"
|
||||
"]\n");
|
||||
|
||||
std::string strAccount = "*";
|
||||
|
||||
auto include_supports = request.params.size() < 1 || request.params[0].get_bool();
|
||||
bool fListSpent = request.params.size() > 1 && request.params[1].get_bool();
|
||||
|
||||
// Minimum confirmations
|
||||
int nMinDepth = 1;
|
||||
if (request.params.size() > 2)
|
||||
nMinDepth = request.params[2].get_int();
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
const auto& txOrdered = pwallet->wtxOrdered;
|
||||
|
||||
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
|
||||
{
|
||||
auto *const pwtx = (*it).second.first;
|
||||
if (pwtx != nullptr && pwtx->GetDepthInMainChain() >= nMinDepth)
|
||||
ListNameClaims(*pwtx, pwallet, strAccount, 0, ret, include_supports, fListSpent);
|
||||
}
|
||||
|
||||
auto arrTmp = ret.getValues();
|
||||
std::reverse(arrTmp.begin(), arrTmp.end()); // Return oldest to newest
|
||||
|
||||
ret.clear();
|
||||
ret.setArray();
|
||||
ret.push_backV(arrTmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue supportclaim(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || (request.params.size() != 3 && request.params.size() != 4))
|
||||
throw std::runtime_error(
|
||||
"supportclaim \"name\" \"claimid\" \"amount\" \"value\"\n"
|
||||
"Increase the value of a claim. Whichever claim has the greatest value, including all support values, will be the authoritative claim, according to the rest of the rules. The name is the name which is claimed by the claim that will be supported, the txid is the txid\
|
||||
of the claim that will be supported, nout is the transaction output which contains the claim to be supported, and amount is the amount which will be added to the value of the claim. If the claim is currently the authoritative claim, this support will go into effect immediately \
|
||||
. Otherwise, it will go into effect after 100 blocks. The support will be in effect until it is spent, and will lose its effect when the claim is spent or expires. The amount is a real and is rounded to the nearest .00000001\n"
|
||||
+ HelpRequiringPassphrase(pwallet) +
|
||||
"\nArguments:\n"
|
||||
"1. \"name\" (string, required) The name claimed by the claim to support.\n"
|
||||
"2. \"claimid\" (string, required) The claimid of the claim to support. This can be obtained by TODO PUT IN PLACE THAT SHOWS THIS.\n"
|
||||
"3. \"amount\" (numeric, required) The amount in LBC to use to support the claim.\n"
|
||||
"4. \"value\" (string, optional) The metadata of the support encoded in hexadecimal.\n"
|
||||
"\nResult:\n"
|
||||
"\"transactionid\" (string) The transaction id of the support.\n");
|
||||
|
||||
auto sName = request.params[0].get_str();
|
||||
auto sClaimId = request.params[1].get_str();
|
||||
|
||||
const size_t claimLength = 40;
|
||||
|
||||
if (!IsHex(sClaimId))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "claimid must be a 20-character hexadecimal string (not '" + sClaimId + "')");
|
||||
if (sClaimId.length() != claimLength)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("claimid must be of length %d", claimLength));
|
||||
|
||||
uint160 claimId;
|
||||
claimId.SetHex(sClaimId);
|
||||
std::vector<unsigned char> vchName (sName.begin(), sName.end());
|
||||
std::vector<unsigned char> vchClaimId (claimId.begin(), claimId.end());
|
||||
CAmount nAmount = AmountFromValue(request.params[2]);
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
CScript supportScript = CScript() << OP_SUPPORT_CLAIM << vchName << vchClaimId;
|
||||
auto lastOp = OP_DROP;
|
||||
if (request.params.size() > 3) {
|
||||
auto hex = request.params[3].get_str();
|
||||
if (!IsHex(hex))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "value/metadata must be of hexadecimal data");
|
||||
supportScript = supportScript << ParseHex(hex);
|
||||
lastOp = OP_2DROP;
|
||||
}
|
||||
|
||||
supportScript = supportScript << OP_2DROP << lastOp;
|
||||
|
||||
CPubKey newKey;
|
||||
if (!pwallet->GetKeyFromPool(newKey))
|
||||
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
|
||||
|
||||
CCoinControl cc;
|
||||
cc.m_change_type = DEFAULT_ADDRESS_TYPE;
|
||||
auto tx = SendMoney(pwallet, CTxDestination(newKey.GetID()), nAmount, false, cc, {}, {}, supportScript);
|
||||
return tx->GetHash().GetHex();
|
||||
}
|
||||
|
||||
UniValue abandonsupport(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 2)
|
||||
throw std::runtime_error(
|
||||
"abandonsupport \"txid\" \"address\"\n"
|
||||
"Create a transaction which spends a txout which supported a name claim, effectively abandoning that support.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) +
|
||||
"\nArguments:\n"
|
||||
"1. \"txid\" (string, required) The transaction containing the unspent txout which should be spent.\n"
|
||||
"2. \"address\" (string, required) The lbrycrd address to send to.\n"
|
||||
"\nResult:\n"
|
||||
"\"transactionid\" (string) The new transaction id.\n");
|
||||
|
||||
uint256 hash;
|
||||
hash.SetHex(request.params[0].get_str());
|
||||
|
||||
CKeyID address;
|
||||
address.SetHex(request.params[1].get_str());
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
auto it = pwallet->mapWallet.find(hash);
|
||||
if (it == pwallet->mapWallet.end()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
|
||||
}
|
||||
const auto& wtx = it->second;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
CTransactionRef wtxNew = nullptr;
|
||||
for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i)
|
||||
{
|
||||
auto mine = pwallet->IsMine(wtx.tx->vout[i]);
|
||||
if (mine & isminetype::ISMINE_SUPPORT)
|
||||
{
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
CCoinControl cc;
|
||||
cc.m_change_type = DEFAULT_ADDRESS_TYPE;
|
||||
cc.Select(COutPoint(wtx.tx->GetHash(), i));
|
||||
wtxNew = SendMoney(pwallet, address, wtx.tx->vout[i].nValue, true, cc, {}, {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wtxNew == nullptr)
|
||||
throw std::runtime_error("Error: The given transaction contains no support scripts owned by this wallet");
|
||||
return wtxNew->GetHash().GetHex();
|
||||
}
|
||||
|
||||
static UniValue sendtoaddress(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
|
@ -4830,6 +5293,13 @@ static const CRPCCommand commands[] =
|
|||
{ "wallet", "setlabel", &setlabel, {"address","label"} },
|
||||
|
||||
{ "generating", "generate", &generate, {"nblocks","maxtries"} },
|
||||
|
||||
{ "Claimtrie", "claimname", &claimname, {"name","value","amount"} },
|
||||
{ "Claimtrie", "updateclaim", &updateclaim, {"txid","value","amount"} },
|
||||
{ "Claimtrie", "abandonclaim", &abandonclaim, {"txid","address"} },
|
||||
{ "Claimtrie", "listnameclaims", &listnameclaims, {"includesuppports","activeonly","minconf"} },
|
||||
{ "Claimtrie", "supportclaim", &supportclaim, {"name","claimid","amount","value"} },
|
||||
{ "Claimtrie", "abandonsupport", &abandonsupport, {"txid","address"} },
|
||||
};
|
||||
|
||||
void RegisterWalletRPCCommands(CRPCTable &t)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <key_io.h>
|
||||
#include <keystore.h>
|
||||
#include <validation.h>
|
||||
#include <nameclaim.h>
|
||||
#include <net.h>
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
|
@ -1381,7 +1382,13 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
|
|||
|
||||
isminetype CWallet::IsMine(const CTxOut& txout) const
|
||||
{
|
||||
return ::IsMine(*this, txout.scriptPubKey);
|
||||
int op = 0;
|
||||
auto script = StripClaimScriptPrefix(txout.scriptPubKey, op);
|
||||
if (op == OP_CLAIM_NAME)
|
||||
return isminetype::ISMINE_CLAIM;
|
||||
if (op == OP_SUPPORT_CLAIM)
|
||||
return isminetype::ISMINE_SUPPORT;
|
||||
return ::IsMine(*this, script);
|
||||
}
|
||||
|
||||
CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) const
|
||||
|
@ -1403,11 +1410,13 @@ bool CWallet::IsChange(const CTxOut& txout) const
|
|||
if (::IsMine(*this, txout.scriptPubKey))
|
||||
{
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(txout.scriptPubKey, address))
|
||||
const CScript& scriptPubKey = StripClaimScriptPrefix(txout.scriptPubKey);
|
||||
|
||||
if (!ExtractDestination(scriptPubKey, address))
|
||||
return true;
|
||||
|
||||
LOCK(cs_wallet);
|
||||
if (!mapAddressBook.count(address))
|
||||
if (!mapAddressBook.count(address) && (scriptPubKey == txout.scriptPubKey))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1690,18 +1699,19 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
|
|||
|
||||
// In either case, we need to get the destination address
|
||||
CTxDestination address;
|
||||
const CScript& scriptPubKey = StripClaimScriptPrefix(txout.scriptPubKey);
|
||||
|
||||
if (!ExtractDestination(txout.scriptPubKey, address) && !txout.scriptPubKey.IsUnspendable())
|
||||
if (!ExtractDestination(scriptPubKey, address) && !scriptPubKey.IsUnspendable())
|
||||
{
|
||||
pwallet->WalletLogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
|
||||
this->GetHash().ToString());
|
||||
LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
|
||||
this->GetHash().ToString());
|
||||
address = CNoDestination();
|
||||
}
|
||||
|
||||
COutputEntry output = {address, txout.nValue, (int)i};
|
||||
|
||||
// If we are debited by the transaction, add the output as a "sent" entry
|
||||
if (nDebit > 0)
|
||||
if (nDebit > 0 || filter & ISMINE_CLAIM || filter & ISMINE_SUPPORT)
|
||||
listSent.push_back(output);
|
||||
|
||||
// If we are receiving the output, add it as a "received" entry
|
||||
|
@ -2371,8 +2381,12 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
|
|||
continue;
|
||||
}
|
||||
|
||||
// spending claims or supports requires specific selection:
|
||||
auto claimSpendRequested = (mine & ISMINE_CLAIM) || (mine & ISMINE_SUPPORT);
|
||||
claimSpendRequested &= coinControl && coinControl->IsSelected(COutPoint(entry.first, i));
|
||||
|
||||
bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
|
||||
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
|
||||
bool spendable = claimSpendRequested || ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
|
||||
|
||||
vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx, (coinControl && coinControl->fAllowWatchOnly)));
|
||||
|
||||
|
@ -2950,6 +2964,9 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
|||
strFailReason = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
|
||||
return false;
|
||||
}
|
||||
// Make sure we meet the minimum claimtrie fee, pick which ever one is largest
|
||||
CAmount minClaimTrieFee = CalcMinClaimTrieFee(txNew, minFeePerNameClaimChar);
|
||||
nFeeNeeded = std::max(nFeeNeeded, minClaimTrieFee);
|
||||
|
||||
// If we made it here and we aren't even able to meet the relay fee on the next pass, give up
|
||||
// because we must be at the maximum allowed fee.
|
||||
|
|
Loading…
Add table
Reference in a new issue