Implement a hard fork for extended/infinite claim expiration times #112
7 changed files with 953 additions and 174 deletions
|
@ -28,35 +28,35 @@ uint256 CNodeValue::GetHash() const
|
||||||
return valHash;
|
return valHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieNode::insertValue(CNodeValue val, bool * pfChanged)
|
bool CClaimTrieNode::insertValue(CNodeValue val)//, bool * pfChanged)
|
||||||
{
|
{
|
||||||
LogPrintf("%s: Inserting %s:%d (amount: %d) into the claim trie\n", __func__, val.txhash.ToString(), val.nOut, val.nAmount);
|
LogPrintf("%s: Inserting %s:%d (amount: %d) into the claim trie\n", __func__, val.txhash.ToString(), val.nOut, val.nAmount);
|
||||||
bool fChanged = false;
|
//bool fChanged = false;
|
||||||
|
|
||||||
if (values.empty())
|
//if (values.empty())
|
||||||
{
|
//{
|
||||||
values.push_back(val);
|
values.push_back(val);
|
||||||
fChanged = true;
|
// fChanged = true;
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
CNodeValue currentTop = values.front();
|
// CNodeValue currentTop = values.front();
|
||||||
values.push_back(val);
|
// values.push_back(val);
|
||||||
std::make_heap(values.begin(), values.end());
|
// std::make_heap(values.begin(), values.end());
|
||||||
if (currentTop != values.front())
|
// if (currentTop != values.front())
|
||||||
fChanged = true;
|
// fChanged = true;
|
||||||
}
|
//}
|
||||||
if (pfChanged)
|
//if (pfChanged)
|
||||||
*pfChanged = fChanged;
|
// *pfChanged = fChanged;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieNode::removeValue(uint256& txhash, uint32_t nOut, CNodeValue& val, bool * pfChanged)
|
bool CClaimTrieNode::removeValue(uint256& txhash, uint32_t nOut, CNodeValue& val)//, bool * pfChanged)
|
||||||
{
|
{
|
||||||
LogPrintf("%s: Removing txid: %s, nOut: %d from the claim trie\n", __func__, txhash.ToString(), nOut);
|
LogPrintf("%s: Removing txid: %s, nOut: %d from the claim trie\n", __func__, txhash.ToString(), nOut);
|
||||||
bool fChanged = false;
|
//bool fChanged = false;
|
||||||
|
|
||||||
CNodeValue currentTop = values.front();
|
//CNodeValue currentTop = values.front();
|
||||||
|
|
||||||
std::vector<CNodeValue>::iterator position;
|
std::vector<CNodeValue>::iterator position;
|
||||||
for (position = values.begin(); position != values.end(); ++position)
|
for (position = values.begin(); position != values.end(); ++position)
|
||||||
|
@ -77,18 +77,19 @@ bool CClaimTrieNode::removeValue(uint256& txhash, uint32_t nOut, CNodeValue& val
|
||||||
{
|
{
|
||||||
LogPrintf("\ttxid: %s, nOut: %d\n", values[i].txhash.ToString(), values[i].nOut);
|
LogPrintf("\ttxid: %s, nOut: %d\n", values[i].txhash.ToString(), values[i].nOut);
|
||||||
}
|
}
|
||||||
|
std::cout << "couldnt find the thing" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!values.empty())
|
//if (!values.empty())
|
||||||
{
|
//{
|
||||||
std::make_heap(values.begin(), values.end());
|
// std::make_heap(values.begin(), values.end());
|
||||||
if (currentTop != values.front())
|
// if (currentTop != values.front())
|
||||||
fChanged = true;
|
// fChanged = true;
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
fChanged = true;
|
// fChanged = true;
|
||||||
if (pfChanged)
|
//if (pfChanged)
|
||||||
*pfChanged = fChanged;
|
// *pfChanged = fChanged;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +112,11 @@ bool CClaimTrieNode::haveValue(const uint256& txhash, uint32_t nOut) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClaimTrieNode::reorderValues()
|
||||||
|
{
|
||||||
|
std::make_heap(values.begin(), values.end());
|
||||||
|
}
|
||||||
|
|
||||||
uint256 CClaimTrie::getMerkleHash()
|
uint256 CClaimTrie::getMerkleHash()
|
||||||
{
|
{
|
||||||
return root.hash;
|
return root.hash;
|
||||||
|
@ -121,13 +127,8 @@ bool CClaimTrie::empty() const
|
||||||
return root.empty();
|
return root.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::queueEmpty() const
|
bool CClaimTrie::keyTypeEmpty(char key) const
|
||||||
{
|
{
|
||||||
for (valueQueueType::const_iterator itRow = dirtyQueueRows.begin(); itRow != dirtyQueueRows.end(); ++itRow)
|
|
||||||
{
|
|
||||||
if (!itRow->second.empty())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
||||||
pcursor->SeekToFirst();
|
pcursor->SeekToFirst();
|
||||||
|
|
||||||
|
@ -139,7 +140,7 @@ bool CClaimTrie::queueEmpty() const
|
||||||
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||||
char chType;
|
char chType;
|
||||||
ssKey >> chType;
|
ssKey >> chType;
|
||||||
if (chType == 'r')
|
if (chType == key)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -153,6 +154,16 @@ bool CClaimTrie::queueEmpty() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CClaimTrie::queueEmpty() const
|
||||||
|
{
|
||||||
|
for (valueQueueType::const_iterator itRow = dirtyQueueRows.begin(); itRow != dirtyQueueRows.end(); ++itRow)
|
||||||
|
{
|
||||||
|
if (!itRow->second.empty())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return keyTypeEmpty(QUEUE_ROW);
|
||||||
|
}
|
||||||
|
|
||||||
bool CClaimTrie::expirationQueueEmpty() const
|
bool CClaimTrie::expirationQueueEmpty() const
|
||||||
{
|
{
|
||||||
for (valueQueueType::const_iterator itRow = dirtyExpirationQueueRows.begin(); itRow != dirtyExpirationQueueRows.end(); ++itRow)
|
for (valueQueueType::const_iterator itRow = dirtyExpirationQueueRows.begin(); itRow != dirtyExpirationQueueRows.end(); ++itRow)
|
||||||
|
@ -160,29 +171,27 @@ bool CClaimTrie::expirationQueueEmpty() const
|
||||||
if (!itRow->second.empty())
|
if (!itRow->second.empty())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
return keyTypeEmpty(EXP_QUEUE_ROW);
|
||||||
pcursor->SeekToFirst();
|
}
|
||||||
|
|
||||||
while(pcursor->Valid())
|
bool CClaimTrie::supportEmpty() const
|
||||||
{
|
{
|
||||||
try
|
for (supportMapType::const_iterator itNode = dirtySupportNodes.begin(); itNode != dirtySupportNodes.end(); ++itNode)
|
||||||
{
|
|
||||||
leveldb::Slice slKey = pcursor->key();
|
|
||||||
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
|
||||||
char chType;
|
|
||||||
ssKey >> chType;
|
|
||||||
if (chType == 'e')
|
|
||||||
{
|
{
|
||||||
|
if (!itNode->second.empty())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
return keyTypeEmpty(SUPPORT);
|
||||||
catch (const std::exception& e)
|
}
|
||||||
|
|
||||||
|
bool CClaimTrie::supportQueueEmpty() const
|
||||||
|
{
|
||||||
|
for (supportValueQueueType::const_iterator itRow = dirtySupportQueueRows.begin(); itRow != dirtySupportQueueRows.end(); ++itRow)
|
||||||
{
|
{
|
||||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
|
if (!itRow->second.empty())
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
pcursor->Next();
|
return keyTypeEmpty(SUPPORT_QUEUE);
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClaimTrie::setExpirationTime(int t)
|
void CClaimTrie::setExpirationTime(int t)
|
||||||
|
@ -361,7 +370,7 @@ bool CClaimTrie::getQueueRow(int nHeight, std::vector<CValueQueueEntry>& row)
|
||||||
row = itQueueRow->second;
|
row = itQueueRow->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return db.Read(std::make_pair('r', nHeight), row);
|
return db.Read(std::make_pair(QUEUE_ROW, nHeight), row);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::getExpirationQueueRow(int nHeight, std::vector<CValueQueueEntry>& row)
|
bool CClaimTrie::getExpirationQueueRow(int nHeight, std::vector<CValueQueueEntry>& row)
|
||||||
|
@ -372,7 +381,7 @@ bool CClaimTrie::getExpirationQueueRow(int nHeight, std::vector<CValueQueueEntry
|
||||||
row = itQueueRow->second;
|
row = itQueueRow->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return db.Read(std::make_pair('e', nHeight), row);
|
return db.Read(std::make_pair(EXP_QUEUE_ROW, nHeight), row);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClaimTrie::updateQueueRow(int nHeight, std::vector<CValueQueueEntry>& row)
|
void CClaimTrie::updateQueueRow(int nHeight, std::vector<CValueQueueEntry>& row)
|
||||||
|
@ -403,7 +412,57 @@ void CClaimTrie::updateExpirationRow(int nHeight, std::vector<CValueQueueEntry>&
|
||||||
itQueueRow->second.swap(row);
|
itQueueRow->second.swap(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlockIn, valueQueueType& queueCache, valueQueueType& expirationQueueCache, int nNewHeight)
|
void CClaimTrie::updateSupportMap(const std::string& name, supportMapNodeType& node)
|
||||||
|
{
|
||||||
|
supportMapType::iterator itNode = dirtySupportNodes.find(name);
|
||||||
|
if (itNode == dirtySupportNodes.end())
|
||||||
|
{
|
||||||
|
supportMapNodeType newNode;
|
||||||
|
std::pair<supportMapType::iterator, bool> ret;
|
||||||
|
ret = dirtySupportNodes.insert(std::pair<std::string, supportMapNodeType>(name, newNode));
|
||||||
|
assert(ret.second);
|
||||||
|
itNode = ret.first;
|
||||||
|
}
|
||||||
|
itNode->second.swap(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClaimTrie::updateSupportQueue(int nHeight, std::vector<CSupportValueQueueEntry>& row)
|
||||||
|
{
|
||||||
|
supportValueQueueType::iterator itQueueRow = dirtySupportQueueRows.find(nHeight);
|
||||||
|
if (itQueueRow == dirtySupportQueueRows.end())
|
||||||
|
{
|
||||||
|
std::vector<CSupportValueQueueEntry> newRow;
|
||||||
|
std::pair<supportValueQueueType::iterator, bool> ret;
|
||||||
|
ret = dirtySupportQueueRows.insert(std::pair<int, std::vector<CSupportValueQueueEntry> >(nHeight, newRow));
|
||||||
|
assert(ret.second);
|
||||||
|
itQueueRow = ret.first;
|
||||||
|
}
|
||||||
|
itQueueRow->second.swap(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrie::getSupportNode(std::string name, supportMapNodeType& node)
|
||||||
|
{
|
||||||
|
supportMapType::iterator itNode = dirtySupportNodes.find(name);
|
||||||
|
if (itNode != dirtySupportNodes.end())
|
||||||
|
{
|
||||||
|
node = itNode->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return db.Read(std::make_pair(SUPPORT, name), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrie::getSupportQueueRow(int nHeight, std::vector<CSupportValueQueueEntry>& row)
|
||||||
|
{
|
||||||
|
supportValueQueueType::iterator itQueueRow = dirtySupportQueueRows.find(nHeight);
|
||||||
|
if (itQueueRow != dirtySupportQueueRows.end())
|
||||||
|
{
|
||||||
|
row = itQueueRow->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return db.Read(std::make_pair(SUPPORT_QUEUE, nHeight), row);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlockIn, valueQueueType& queueCache, valueQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportValueQueueType& supportQueueCache)
|
||||||
{
|
{
|
||||||
// General strategy: the cache is ordered by length, ensuring child
|
// General strategy: the cache is ordered by length, ensuring child
|
||||||
// nodes are always inserted after their parents. Insert each node
|
// nodes are always inserted after their parents. Insert each node
|
||||||
|
@ -445,6 +504,14 @@ bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, const uint256
|
||||||
{
|
{
|
||||||
updateExpirationRow(itExpirationRow->first, itExpirationRow->second);
|
updateExpirationRow(itExpirationRow->first, itExpirationRow->second);
|
||||||
}
|
}
|
||||||
|
for (supportMapType::iterator itSupportCache = supportCache.begin(); itSupportCache != supportCache.end(); ++itSupportCache)
|
||||||
|
{
|
||||||
|
updateSupportMap(itSupportCache->first, itSupportCache->second);
|
||||||
|
}
|
||||||
|
for (supportValueQueueType::iterator itSupportQueue = supportQueueCache.begin(); itSupportQueue != supportQueueCache.end(); ++itSupportQueue)
|
||||||
|
{
|
||||||
|
updateSupportQueue(itSupportQueue->first, itSupportQueue->second);
|
||||||
|
}
|
||||||
hashBlock = hashBlockIn;
|
hashBlock = hashBlockIn;
|
||||||
nCurrentHeight = nNewHeight;
|
nCurrentHeight = nNewHeight;
|
||||||
return true;
|
return true;
|
||||||
|
@ -540,9 +607,9 @@ void CClaimTrie::BatchWriteNode(CLevelDBBatch& batch, const std::string& name, c
|
||||||
{
|
{
|
||||||
LogPrintf("%s: Writing %s to disk with %d values\n", __func__, name, pNode->values.size());
|
LogPrintf("%s: Writing %s to disk with %d values\n", __func__, name, pNode->values.size());
|
||||||
if (pNode)
|
if (pNode)
|
||||||
batch.Write(std::make_pair('n', name), *pNode);
|
batch.Write(std::make_pair(TRIE_NODE, name), *pNode);
|
||||||
else
|
else
|
||||||
batch.Erase(std::make_pair('n', name));
|
batch.Erase(std::make_pair(TRIE_NODE, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClaimTrie::BatchWriteQueueRows(CLevelDBBatch& batch)
|
void CClaimTrie::BatchWriteQueueRows(CLevelDBBatch& batch)
|
||||||
|
@ -551,11 +618,11 @@ void CClaimTrie::BatchWriteQueueRows(CLevelDBBatch& batch)
|
||||||
{
|
{
|
||||||
if (itQueue->second.empty())
|
if (itQueue->second.empty())
|
||||||
{
|
{
|
||||||
batch.Erase(std::make_pair('r', itQueue->first));
|
batch.Erase(std::make_pair(QUEUE_ROW, itQueue->first));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
batch.Write(std::make_pair('r', itQueue->first), itQueue->second);
|
batch.Write(std::make_pair(QUEUE_ROW, itQueue->first), itQueue->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,11 +633,41 @@ void CClaimTrie::BatchWriteExpirationQueueRows(CLevelDBBatch& batch)
|
||||||
{
|
{
|
||||||
if (itQueue->second.empty())
|
if (itQueue->second.empty())
|
||||||
{
|
{
|
||||||
batch.Erase(std::make_pair('e', itQueue->first));
|
batch.Erase(std::make_pair(EXP_QUEUE_ROW, itQueue->first));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
batch.Write(std::make_pair('e', itQueue->first), itQueue->second);
|
batch.Write(std::make_pair(EXP_QUEUE_ROW, itQueue->first), itQueue->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClaimTrie::BatchWriteSupportNodes(CLevelDBBatch& batch)
|
||||||
|
{
|
||||||
|
for (supportMapType::iterator itSupport = dirtySupportNodes.begin(); itSupport != dirtySupportNodes.end(); ++itSupport)
|
||||||
|
{
|
||||||
|
if (itSupport->second.empty())
|
||||||
|
{
|
||||||
|
batch.Erase(std::make_pair(SUPPORT, itSupport->first));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
batch.Write(std::make_pair(SUPPORT, itSupport->first), itSupport->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClaimTrie::BatchWriteSupportQueueRows(CLevelDBBatch& batch)
|
||||||
|
{
|
||||||
|
for (supportValueQueueType::iterator itQueue = dirtySupportQueueRows.begin(); itQueue != dirtySupportQueueRows.end(); ++itQueue)
|
||||||
|
{
|
||||||
|
if (itQueue->second.empty())
|
||||||
|
{
|
||||||
|
batch.Erase(std::make_pair(SUPPORT_QUEUE, itQueue->first));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
batch.Write(std::make_pair(SUPPORT_QUEUE, itQueue->first), itQueue->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -585,8 +682,12 @@ bool CClaimTrie::WriteToDisk()
|
||||||
dirtyQueueRows.clear();
|
dirtyQueueRows.clear();
|
||||||
BatchWriteExpirationQueueRows(batch);
|
BatchWriteExpirationQueueRows(batch);
|
||||||
dirtyExpirationQueueRows.clear();
|
dirtyExpirationQueueRows.clear();
|
||||||
batch.Write('h', hashBlock);
|
BatchWriteSupportNodes(batch);
|
||||||
batch.Write('t', nCurrentHeight);
|
dirtySupportNodes.clear();
|
||||||
|
BatchWriteSupportQueueRows(batch);
|
||||||
|
dirtySupportQueueRows.clear();
|
||||||
|
batch.Write(HASH_BLOCK, hashBlock);
|
||||||
|
batch.Write(CURRENT_HEIGHT, nCurrentHeight);
|
||||||
return db.WriteBatch(batch);
|
return db.WriteBatch(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,9 +712,9 @@ bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node)
|
||||||
|
|
||||||
bool CClaimTrie::ReadFromDisk(bool check)
|
bool CClaimTrie::ReadFromDisk(bool check)
|
||||||
{
|
{
|
||||||
if (!db.Read('h', hashBlock))
|
if (!db.Read(HASH_BLOCK, hashBlock))
|
||||||
LogPrintf("%s: Couldn't read the best block's hash\n", __func__);
|
LogPrintf("%s: Couldn't read the best block's hash\n", __func__);
|
||||||
if (!db.Read('t', nCurrentHeight))
|
if (!db.Read(CURRENT_HEIGHT, nCurrentHeight))
|
||||||
LogPrintf("%s: Couldn't read the current height\n", __func__);
|
LogPrintf("%s: Couldn't read the current height\n", __func__);
|
||||||
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
||||||
pcursor->SeekToFirst();
|
pcursor->SeekToFirst();
|
||||||
|
@ -626,7 +727,7 @@ bool CClaimTrie::ReadFromDisk(bool check)
|
||||||
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||||
char chType;
|
char chType;
|
||||||
ssKey >> chType;
|
ssKey >> chType;
|
||||||
if (chType == 'n')
|
if (chType == TRIE_NODE)
|
||||||
{
|
{
|
||||||
leveldb::Slice slValue = pcursor->value();
|
leveldb::Slice slValue = pcursor->value();
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -810,7 +911,19 @@ bool CClaimTrieCache::insertClaimIntoTrie(const std::string name, CNodeValue val
|
||||||
cache[name] = currentNode;
|
cache[name] = currentNode;
|
||||||
}
|
}
|
||||||
bool fChanged = false;
|
bool fChanged = false;
|
||||||
currentNode->insertValue(val, &fChanged);
|
if (currentNode->values.empty())
|
||||||
|
{
|
||||||
|
fChanged = true;
|
||||||
|
currentNode->insertValue(val);//, &fChanged);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CNodeValue currentTop = currentNode->values.front();
|
||||||
|
currentNode->insertValue(val);
|
||||||
|
currentNode->reorderValues();
|
||||||
|
if (currentTop != currentNode->values.front())
|
||||||
|
fChanged = true;
|
||||||
|
}
|
||||||
if (fChanged)
|
if (fChanged)
|
||||||
{
|
{
|
||||||
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur)
|
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur)
|
||||||
|
@ -864,7 +977,26 @@ bool CClaimTrieCache::removeClaimFromTrie(const std::string name, uint256 txhash
|
||||||
bool fChanged = false;
|
bool fChanged = false;
|
||||||
assert(currentNode != NULL);
|
assert(currentNode != NULL);
|
||||||
CNodeValue val;
|
CNodeValue val;
|
||||||
bool success = currentNode->removeValue(txhash, nOut, val, &fChanged);
|
bool success = false;
|
||||||
|
|
||||||
|
if (currentNode->values.empty())
|
||||||
|
{
|
||||||
|
LogPrintf("%s: Asked to remove value from node without values\n", __func__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CNodeValue currentTop = currentNode->values.front();
|
||||||
|
|
||||||
|
success = currentNode->removeValue(txhash, nOut, val);//, &fChanged);
|
||||||
|
|
||||||
|
if (!currentNode->values.empty())
|
||||||
|
{
|
||||||
|
currentNode->reorderValues();
|
||||||
|
if (currentTop != currentNode->values.front())
|
||||||
|
fChanged = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fChanged = true;
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
LogPrintf("%s: Removing a value was unsuccessful. name = %s, txhash = %s, nOut = %d", __func__, name.c_str(), txhash.GetHex(), nOut);
|
LogPrintf("%s: Removing a value was unsuccessful. name = %s, txhash = %s, nOut = %d", __func__, name.c_str(), txhash.GetHex(), nOut);
|
||||||
|
@ -1013,14 +1145,13 @@ bool CClaimTrieCache::undoSpendClaim(const std::string name, uint256 txhash, uin
|
||||||
{
|
{
|
||||||
CNodeValue val(txhash, nOut, nAmount, nHeight, nValidAtHeight);
|
CNodeValue val(txhash, nOut, nAmount, nHeight, nValidAtHeight);
|
||||||
CValueQueueEntry entry(name, val);
|
CValueQueueEntry entry(name, val);
|
||||||
insertClaimIntoTrie(name, CNodeValue(txhash, nOut, nAmount, nHeight, nValidAtHeight));
|
|
||||||
addToExpirationQueue(entry);
|
addToExpirationQueue(entry);
|
||||||
|
return insertClaimIntoTrie(name, val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addClaimToQueues(name, txhash, nOut, nAmount, nHeight, nValidAtHeight);
|
return addClaimToQueues(name, txhash, nOut, nAmount, nHeight, nValidAtHeight);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCache::addClaimToQueues(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) const
|
bool CClaimTrieCache::addClaimToQueues(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) const
|
||||||
|
@ -1081,8 +1212,8 @@ bool CClaimTrieCache::removeClaim(const std::string name, uint256 txhash, uint32
|
||||||
else if (removeClaimFromQueue(name, txhash, nOut, nHeight, nValidAtHeight))
|
else if (removeClaimFromQueue(name, txhash, nOut, nHeight, nValidAtHeight))
|
||||||
removed = true;
|
removed = true;
|
||||||
}
|
}
|
||||||
if (removed == false && removeClaimFromQueue(name, txhash, nOut, nHeight, nCurrentHeight))
|
//if (removed == false && removeClaimFromQueue(name, txhash, nOut, nHeight, nCurrentHeight))
|
||||||
removed = true;
|
// removed = true;
|
||||||
if (removed == false && removeClaimFromTrie(name, txhash, nOut, nValidAtHeight))
|
if (removed == false && removeClaimFromTrie(name, txhash, nOut, nValidAtHeight))
|
||||||
removed = true;
|
removed = true;
|
||||||
if (removed == true)
|
if (removed == true)
|
||||||
|
@ -1138,7 +1269,228 @@ valueQueueType::iterator CClaimTrieCache::getExpirationQueueCacheRow(int nHeight
|
||||||
return itQueueRow;
|
return itQueueRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCache::incrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo) const
|
bool CClaimTrieCache::reorderTrieNode(const std::string name) const
|
||||||
|
{
|
||||||
|
assert(base);
|
||||||
|
nodeCacheType::iterator cachedNode;
|
||||||
|
cachedNode = cache.find("name");
|
||||||
|
if (cachedNode == cache.end())
|
||||||
|
{
|
||||||
|
CClaimTrieNode* currentNode = &(base->root);
|
||||||
|
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur)
|
||||||
|
{
|
||||||
|
std::string sCurrentSubstring(name.begin(), itCur);
|
||||||
|
std::string sNextSubstring(name.begin(), itCur + 1);
|
||||||
|
|
||||||
|
cachedNode = cache.find(sNextSubstring);
|
||||||
|
if (cachedNode != cache.end())
|
||||||
|
{
|
||||||
|
currentNode = cachedNode->second;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nodeMapType::iterator childNode = currentNode->children.find(*itCur);
|
||||||
|
if (childNode != currentNode->children.end())
|
||||||
|
{
|
||||||
|
currentNode = childNode->second;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// The node doesn't exist, so it can't be reordered.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
currentNode = new CClaimTrieNode(*currentNode);
|
||||||
|
std::pair<nodeCacheType::iterator, bool> ret;
|
||||||
|
ret = cache.insert(std::pair<std::string, CClaimTrieNode*>(name, currentNode));
|
||||||
|
assert(ret.second);
|
||||||
|
cachedNode = ret.first;
|
||||||
|
}
|
||||||
|
bool fChanged = false;
|
||||||
|
if (cachedNode->second->values.empty())
|
||||||
|
{
|
||||||
|
// Nothing in there to reorder
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CNodeValue currentTop = cachedNode->second->values.front();
|
||||||
|
cachedNode->second->reorderValues();
|
||||||
|
if (currentTop != cachedNode->second->values.front())
|
||||||
|
fChanged = true;
|
||||||
|
}
|
||||||
|
if (fChanged)
|
||||||
|
{
|
||||||
|
for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur)
|
||||||
|
{
|
||||||
|
std::string sub(name.begin(), itCur);
|
||||||
|
dirtyHashes.insert(sub);
|
||||||
|
}
|
||||||
|
dirtyHashes.insert(name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::insertSupportIntoMap(const std::string name, CSupportNodeValue val) const
|
||||||
|
{
|
||||||
|
supportMapType::iterator cachedNode;
|
||||||
|
// If this node is already in the cache, use that
|
||||||
|
cachedNode = supportCache.find(name);
|
||||||
|
// If not, copy the one from base if it exists, and use that
|
||||||
|
if (cachedNode == supportCache.end())
|
||||||
|
{
|
||||||
|
supportMapNodeType node;
|
||||||
|
base->getSupportNode(name, node);
|
||||||
|
std::pair<supportMapType::iterator, bool> ret;
|
||||||
|
ret = supportCache.insert(std::pair<std::string, supportMapNodeType>(name, node));
|
||||||
|
assert(ret.second);
|
||||||
|
cachedNode = ret.first;
|
||||||
|
}
|
||||||
|
cachedNode->second.push_back(val);
|
||||||
|
// See if this changed the biggest bid
|
||||||
|
return reorderTrieNode(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::removeSupportFromMap(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight, int& nValidAtHeight) const
|
||||||
|
{
|
||||||
|
supportMapType::iterator cachedNode;
|
||||||
|
cachedNode = supportCache.find(name);
|
||||||
|
if (cachedNode == supportCache.end())
|
||||||
|
{
|
||||||
|
supportMapNodeType node;
|
||||||
|
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, supportMapNodeType>(name, node));
|
||||||
|
assert(ret.second);
|
||||||
|
cachedNode = ret.first;
|
||||||
|
}
|
||||||
|
for (supportMapNodeType::iterator itSupport = cachedNode->second.begin(); itSupport != cachedNode->second.end(); ++itSupport)
|
||||||
|
{
|
||||||
|
if (itSupport->txhash == txhash && itSupport->nOut == nOut && itSupport->supportTxhash == supportedTxhash && itSupport->supportnOut == supportednOut && itSupport->nHeight == nHeight)
|
||||||
|
{
|
||||||
|
nValidAtHeight = itSupport->nValidAtHeight;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
supportValueQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const
|
||||||
|
{
|
||||||
|
supportValueQueueType::iterator itQueueRow = supportQueueCache.find(nHeight);
|
||||||
|
if (itQueueRow == supportQueueCache.end())
|
||||||
|
{
|
||||||
|
std::vector<CSupportValueQueueEntry> queueRow;
|
||||||
|
bool exists = base->getSupportQueueRow(nHeight, queueRow);
|
||||||
|
if (!exists)
|
||||||
|
if (!createIfNotExists)
|
||||||
|
return itQueueRow;
|
||||||
|
// Stick the new row in the cache
|
||||||
|
std::pair<supportValueQueueType::iterator, bool> ret;
|
||||||
|
ret = supportQueueCache.insert(std::pair<int, std::vector<CSupportValueQueueEntry> >(nHeight, queueRow));
|
||||||
|
assert(ret.second);
|
||||||
|
itQueueRow = ret.first;
|
||||||
|
}
|
||||||
|
return itQueueRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::addSupportToQueue(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, uint256 supportedTxhash, int supportednOut, int nHeight, int nValidAtHeight) const
|
||||||
|
{
|
||||||
|
LogPrintf("%s: nValidAtHeight: %d\n", __func__, nValidAtHeight);
|
||||||
|
CSupportNodeValue val(txhash, nOut, supportedTxhash, supportednOut, nAmount, nHeight, nValidAtHeight);
|
||||||
|
CSupportValueQueueEntry entry(name, val);
|
||||||
|
supportValueQueueType::iterator itQueueRow = getSupportQueueCacheRow(nValidAtHeight, true);
|
||||||
|
itQueueRow->second.push_back(entry);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::removeSupportFromQueue(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeightToCheck, int& nValidAtHeight) const
|
||||||
|
{
|
||||||
|
supportValueQueueType::iterator itQueueRow = getSupportQueueCacheRow(nHeightToCheck, false);
|
||||||
|
if (itQueueRow == supportQueueCache.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::vector<CSupportValueQueueEntry>::iterator itQueue;
|
||||||
|
for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue)
|
||||||
|
{
|
||||||
|
CSupportNodeValue& val = itQueue->val;
|
||||||
|
if (name == itQueue->name && val.txhash == txhash && val.nOut == nOut && val.supportTxhash == supportedTxhash && val.supportnOut == supportednOut)
|
||||||
|
{
|
||||||
|
nValidAtHeight = val.nValidAtHeight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itQueue != itQueueRow->second.end())
|
||||||
|
{
|
||||||
|
itQueueRow->second.erase(itQueue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::addSupport(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, uint256 supportedTxhash, int supportednOut, int nHeight) const
|
||||||
|
{
|
||||||
|
std::cout << "just adding some support" << std::endl;
|
||||||
|
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, supportedTxhash.GetHex(), supportednOut, nHeight);
|
||||||
|
assert(nHeight == nCurrentHeight);
|
||||||
|
CNodeValue val;
|
||||||
|
if (base->getInfoForName(name, val))
|
||||||
|
{
|
||||||
|
if (val.txhash == supportedTxhash && val.nOut == supportednOut)
|
||||||
|
{
|
||||||
|
LogPrintf("%s: This is a support to a best claim.\n", __func__);
|
||||||
|
return addSupportToQueue(name, txhash, nOut, nAmount, supportedTxhash, supportednOut, nHeight, nHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addSupportToQueue(name, txhash, nOut, nAmount, supportedTxhash, supportednOut, nHeight, nHeight + DEFAULT_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::undoSpendSupport(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, uint256 supportedTxhash, int supportednOut, int nHeight, int nValidAtHeight) const
|
||||||
|
{
|
||||||
|
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, nAmount, supportedTxhash.GetHex(), supportednOut, nHeight);
|
||||||
|
if (nValidAtHeight < nCurrentHeight)
|
||||||
|
{
|
||||||
|
CSupportNodeValue val(txhash, nOut, supportedTxhash, supportednOut, nAmount, nHeight, nValidAtHeight);
|
||||||
|
CSupportValueQueueEntry entry(name, val);
|
||||||
|
return insertSupportIntoMap(name, val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return addSupportToQueue(name, txhash, nOut, nAmount, supportedTxhash, supportednOut, nHeight, nValidAtHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::removeSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight, int& nValidAtHeight) const
|
||||||
|
{
|
||||||
|
bool removed = false;
|
||||||
|
if (nHeight + DEFAULT_DELAY >= nCurrentHeight)
|
||||||
|
{
|
||||||
|
if (removeSupportFromQueue(name, txhash, nOut, supportedTxhash, supportednOut, nHeight + DEFAULT_DELAY, nValidAtHeight))
|
||||||
|
removed = true;
|
||||||
|
else if (removeSupportFromQueue(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, nValidAtHeight))
|
||||||
|
removed = true;
|
||||||
|
}
|
||||||
|
if (removed == false && removeSupportFromMap(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, nValidAtHeight))
|
||||||
|
removed = true;
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::undoAddSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight) const
|
||||||
|
{
|
||||||
|
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, supportedTxhash.GetHex(), supportednOut, nHeight);
|
||||||
|
int throwaway;
|
||||||
|
return removeSupport(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, throwaway);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::spendSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight, int& nValidAtHeight) const
|
||||||
|
{
|
||||||
|
LogPrintf("%s: name: %s, txhash: %s, nOut: %d, supportedTxhash: %s, supportednOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, txhash.GetHex(), nOut, supportedTxhash.GetHex(), supportednOut, nHeight);
|
||||||
|
return removeSupport(name, txhash, nOut, supportedTxhash, supportednOut, nHeight, nValidAtHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClaimTrieCache::incrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo, CSupportValueQueueUndo& insertSupportUndo) const
|
||||||
{
|
{
|
||||||
LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight);
|
LogPrintf("%s: nCurrentHeight (before increment): %d\n", __func__, nCurrentHeight);
|
||||||
valueQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false);
|
valueQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false);
|
||||||
|
@ -1163,11 +1515,21 @@ bool CClaimTrieCache::incrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrie
|
||||||
}
|
}
|
||||||
itExpirationRow->second.clear();
|
itExpirationRow->second.clear();
|
||||||
}
|
}
|
||||||
|
supportValueQueueType::iterator itSupportRow = getSupportQueueCacheRow(nCurrentHeight, false);
|
||||||
|
if (itSupportRow != supportQueueCache.end())
|
||||||
|
{
|
||||||
|
for (std::vector<CSupportValueQueueEntry>::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport)
|
||||||
|
{
|
||||||
|
insertSupportIntoMap(itSupport->name, itSupport->val);
|
||||||
|
insertSupportUndo.push_back(*itSupport);
|
||||||
|
}
|
||||||
|
itSupportRow->second.clear();
|
||||||
|
}
|
||||||
nCurrentHeight++;
|
nCurrentHeight++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CClaimTrieCache::decrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo) const
|
bool CClaimTrieCache::decrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo, CSupportValueQueueUndo& insertSupportUndo) const
|
||||||
{
|
{
|
||||||
LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight);
|
LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight);
|
||||||
nCurrentHeight--;
|
nCurrentHeight--;
|
||||||
|
@ -1191,6 +1553,17 @@ bool CClaimTrieCache::decrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrie
|
||||||
itExpireRow->second.push_back(*itExpireUndo);
|
itExpireRow->second.push_back(*itExpireUndo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (insertSupportUndo.begin() != insertSupportUndo.end())
|
||||||
|
{
|
||||||
|
supportValueQueueType::iterator itSupportRow = getSupportQueueCacheRow(nCurrentHeight, true);
|
||||||
|
for (CSupportValueQueueUndo::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo)
|
||||||
|
{
|
||||||
|
int nValidHeightInMap;
|
||||||
|
assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->val.txhash, itSupportUndo->val.nOut, itSupportUndo->val.supportTxhash, itSupportUndo->val.supportnOut, itSupportUndo->val.nHeight, nValidHeightInMap));
|
||||||
|
assert(nValidHeightInMap == itSupportUndo->val.nValidAtHeight);
|
||||||
|
itSupportRow->second.push_back(*itSupportUndo);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,6 +1590,9 @@ bool CClaimTrieCache::clear() const
|
||||||
dirtyHashes.clear();
|
dirtyHashes.clear();
|
||||||
cacheHashes.clear();
|
cacheHashes.clear();
|
||||||
valueQueueCache.clear();
|
valueQueueCache.clear();
|
||||||
|
expirationQueueCache.clear();
|
||||||
|
supportCache.clear();
|
||||||
|
supportQueueCache.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1224,7 +1600,7 @@ bool CClaimTrieCache::flush()
|
||||||
{
|
{
|
||||||
if (dirty())
|
if (dirty())
|
||||||
getMerkleHash();
|
getMerkleHash();
|
||||||
bool success = base->update(cache, cacheHashes, getBestBlock(), valueQueueCache, expirationQueueCache, nCurrentHeight);
|
bool success = base->update(cache, cacheHashes, getBestBlock(), valueQueueCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
success = clear();
|
success = clear();
|
||||||
|
|
108
src/claimtrie.h
108
src/claimtrie.h
|
@ -16,6 +16,15 @@
|
||||||
|
|
||||||
#define DEFAULT_DELAY 100
|
#define DEFAULT_DELAY 100
|
||||||
|
|
||||||
|
// leveldb keys
|
||||||
|
#define HASH_BLOCK 'h'
|
||||||
|
#define CURRENT_HEIGHT 't'
|
||||||
|
#define TRIE_NODE 'n'
|
||||||
|
#define QUEUE_ROW 'r'
|
||||||
|
#define EXP_QUEUE_ROW 'e'
|
||||||
|
#define SUPPORT 's'
|
||||||
|
#define SUPPORT_QUEUE 'u'
|
||||||
|
|
||||||
class CNodeValue
|
class CNodeValue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -67,6 +76,41 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CSupportNodeValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint256 txhash;
|
||||||
|
uint32_t nOut;
|
||||||
|
uint256 supportTxhash;
|
||||||
|
int supportnOut;
|
||||||
|
CAmount nAmount;
|
||||||
|
int nHeight;
|
||||||
|
int nValidAtHeight;
|
||||||
|
CSupportNodeValue() {};
|
||||||
|
CSupportNodeValue(uint256 txhash, uint32_t nOut, uint256 supportTxhash, uint32_t supportnOut, CAmount nAmount, int nHeight, int nValidAtHeight) : txhash(txhash), nOut(nOut), supportTxhash(supportTxhash), supportnOut(supportnOut), nAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) {}
|
||||||
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
template <typename Stream, typename Operation>
|
||||||
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||||
|
READWRITE(txhash);
|
||||||
|
READWRITE(nOut);
|
||||||
|
READWRITE(supportTxhash);
|
||||||
|
READWRITE(supportnOut);
|
||||||
|
READWRITE(nAmount);
|
||||||
|
READWRITE(nHeight);
|
||||||
|
READWRITE(nValidAtHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const CSupportNodeValue& other) const
|
||||||
|
{
|
||||||
|
return txhash == other.txhash && nOut == other.nOut && supportTxhash == other.supportTxhash && supportnOut == other.supportnOut && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight;
|
||||||
|
}
|
||||||
|
bool operator!=(const CSupportNodeValue& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class CClaimTrieNode;
|
class CClaimTrieNode;
|
||||||
class CClaimTrie;
|
class CClaimTrie;
|
||||||
|
|
||||||
|
@ -80,14 +124,14 @@ public:
|
||||||
CClaimTrieNode() {}
|
CClaimTrieNode() {}
|
||||||
CClaimTrieNode(uint256 hash) : hash(hash) {}
|
CClaimTrieNode(uint256 hash) : hash(hash) {}
|
||||||
uint256 hash;
|
uint256 hash;
|
||||||
uint256 bestBlock;
|
|
||||||
nodeMapType children;
|
nodeMapType children;
|
||||||
std::vector<CNodeValue> values;
|
std::vector<CNodeValue> values;
|
||||||
bool insertValue(CNodeValue val, bool * fChanged = NULL);
|
bool insertValue(CNodeValue val);//, bool * fChanged = NULL);
|
||||||
bool removeValue(uint256& txhash, uint32_t nOut, CNodeValue& val, bool * fChanged = NULL);
|
bool removeValue(uint256& txhash, uint32_t nOut, CNodeValue& val);//, bool * fChanged = NULL);
|
||||||
bool getBestValue(CNodeValue& val) const;
|
bool getBestValue(CNodeValue& val) const;
|
||||||
bool empty() const {return children.empty() && values.empty();}
|
bool empty() const {return children.empty() && values.empty();}
|
||||||
bool haveValue(const uint256& txhash, uint32_t nOut) const;
|
bool haveValue(const uint256& txhash, uint32_t nOut) const;
|
||||||
|
void reorderValues();
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
template <typename Stream, typename Operation>
|
||||||
|
@ -105,8 +149,6 @@ public:
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
bool getValue(uint256& txhash, uint32_t nOut, CNodeValue& val) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nodenamecompare
|
struct nodenamecompare
|
||||||
|
@ -121,7 +163,7 @@ struct nodenamecompare
|
||||||
|
|
||||||
class CValueQueueEntry
|
class CValueQueueEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CValueQueueEntry() {}
|
CValueQueueEntry() {}
|
||||||
CValueQueueEntry(std::string name, CNodeValue val) : name(name), val(val) {}
|
CValueQueueEntry(std::string name, CNodeValue val) : name(name), val(val) {}
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -136,9 +178,32 @@ class CValueQueueEntry
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CSupportValueQueueEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSupportValueQueueEntry() {}
|
||||||
|
CSupportValueQueueEntry(std::string name, CSupportNodeValue val) : name(name), val(val) {}
|
||||||
|
std::string name;
|
||||||
|
CSupportNodeValue val;
|
||||||
|
|
||||||
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
template <typename Stream, typename Operation>
|
||||||
|
inline void SerializationOp(Stream &s, Operation ser_action, int nType, int nVersion) {
|
||||||
|
READWRITE(name);
|
||||||
|
READWRITE(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<CSupportNodeValue> supportMapNodeType;
|
||||||
|
typedef std::map<std::string, supportMapNodeType> supportMapType;
|
||||||
|
|
||||||
typedef std::map<int, std::vector<CValueQueueEntry> > valueQueueType;
|
typedef std::map<int, std::vector<CValueQueueEntry> > valueQueueType;
|
||||||
typedef std::vector<CValueQueueEntry> CClaimTrieQueueUndo;
|
typedef std::vector<CValueQueueEntry> CClaimTrieQueueUndo;
|
||||||
|
|
||||||
|
typedef std::map<int, std::vector<CSupportValueQueueEntry> > supportValueQueueType;
|
||||||
|
typedef std::vector<CSupportValueQueueEntry> CSupportValueQueueUndo;
|
||||||
|
|
||||||
typedef std::map<std::string, CClaimTrieNode*, nodenamecompare> nodeCacheType;
|
typedef std::map<std::string, CClaimTrieNode*, nodenamecompare> nodeCacheType;
|
||||||
|
|
||||||
typedef std::map<std::string, uint256> hashMapType;
|
typedef std::map<std::string, uint256> hashMapType;
|
||||||
|
@ -160,10 +225,14 @@ public:
|
||||||
bool getInfoForName(const std::string& name, CNodeValue& val) const;
|
bool getInfoForName(const std::string& name, CNodeValue& val) const;
|
||||||
int nCurrentHeight;
|
int nCurrentHeight;
|
||||||
bool queueEmpty() const;
|
bool queueEmpty() const;
|
||||||
|
bool supportEmpty() const;
|
||||||
|
bool supportQueueEmpty() const;
|
||||||
bool expirationQueueEmpty() const;
|
bool expirationQueueEmpty() const;
|
||||||
void setExpirationTime(int t);
|
void setExpirationTime(int t);
|
||||||
bool getQueueRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
bool getQueueRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
||||||
bool getExpirationQueueRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
bool getExpirationQueueRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
||||||
|
bool getSupportNode(std::string name, supportMapNodeType& node);
|
||||||
|
bool getSupportQueueRow(int nHeight, std::vector<CSupportValueQueueEntry>& row);
|
||||||
bool haveClaim(const std::string& name, const uint256& txhash, uint32_t nOut) const;
|
bool haveClaim(const std::string& name, const uint256& txhash, uint32_t nOut) const;
|
||||||
unsigned int getTotalNamesInTrie() const;
|
unsigned int getTotalNamesInTrie() const;
|
||||||
unsigned int getTotalClaimsInTrie() const;
|
unsigned int getTotalClaimsInTrie() const;
|
||||||
|
@ -172,7 +241,7 @@ public:
|
||||||
int nExpirationTime;
|
int nExpirationTime;
|
||||||
private:
|
private:
|
||||||
void clear(CClaimTrieNode* current);
|
void clear(CClaimTrieNode* current);
|
||||||
bool update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlock, valueQueueType& queueCache, valueQueueType& expirationQueueCache, int nNewHeight);
|
bool update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlock, valueQueueType& queueCache, valueQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportValueQueueType& supportQueueCache);
|
||||||
bool updateName(const std::string& name, CClaimTrieNode* updatedNode);
|
bool updateName(const std::string& name, CClaimTrieNode* updatedNode);
|
||||||
bool updateHash(const std::string& name, uint256& hash);
|
bool updateHash(const std::string& name, uint256& hash);
|
||||||
bool recursiveNullify(CClaimTrieNode* node, std::string& name);
|
bool recursiveNullify(CClaimTrieNode* node, std::string& name);
|
||||||
|
@ -183,18 +252,26 @@ private:
|
||||||
CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const;
|
CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const;
|
||||||
bool recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const;
|
bool recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const;
|
||||||
CClaimTrieNode root;
|
CClaimTrieNode root;
|
||||||
|
//supportMapType support;
|
||||||
uint256 hashBlock;
|
uint256 hashBlock;
|
||||||
valueQueueType dirtyQueueRows;
|
valueQueueType dirtyQueueRows;
|
||||||
valueQueueType dirtyExpirationQueueRows;
|
valueQueueType dirtyExpirationQueueRows;
|
||||||
|
supportValueQueueType dirtySupportQueueRows;
|
||||||
|
|
||||||
nodeCacheType dirtyNodes;
|
nodeCacheType dirtyNodes;
|
||||||
|
supportMapType dirtySupportNodes;
|
||||||
void markNodeDirty(const std::string& name, CClaimTrieNode* node);
|
void markNodeDirty(const std::string& name, CClaimTrieNode* node);
|
||||||
void updateQueueRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
void updateQueueRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
||||||
void updateExpirationRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
void updateExpirationRow(int nHeight, std::vector<CValueQueueEntry>& row);
|
||||||
|
void updateSupportMap(const std::string& name, supportMapNodeType& node);
|
||||||
|
void updateSupportQueue(int nHeight, std::vector<CSupportValueQueueEntry>& row);
|
||||||
void BatchWriteNode(CLevelDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const;
|
void BatchWriteNode(CLevelDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const;
|
||||||
void BatchEraseNode(CLevelDBBatch& batch, const std::string& nome) const;
|
void BatchEraseNode(CLevelDBBatch& batch, const std::string& nome) const;
|
||||||
void BatchWriteQueueRows(CLevelDBBatch& batch);
|
void BatchWriteQueueRows(CLevelDBBatch& batch);
|
||||||
void BatchWriteExpirationQueueRows(CLevelDBBatch& batch);
|
void BatchWriteExpirationQueueRows(CLevelDBBatch& batch);
|
||||||
|
void BatchWriteSupportNodes(CLevelDBBatch& batch);
|
||||||
|
void BatchWriteSupportQueueRows(CLevelDBBatch& batch);
|
||||||
|
bool keyTypeEmpty(char key) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CClaimTrieCache
|
class CClaimTrieCache
|
||||||
|
@ -210,10 +287,14 @@ public:
|
||||||
bool undoAddClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight) const;
|
bool undoAddClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight) const;
|
||||||
bool spendClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight, int& nValidAtHeight) const;
|
bool spendClaim(const std::string name, uint256 txhash, uint32_t nOut, int nHeight, int& nValidAtHeight) const;
|
||||||
bool undoSpendClaim(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) const;
|
bool undoSpendClaim(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) const;
|
||||||
|
bool addSupport(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, uint256 supportedTxhash, int supportednOut, int nHeight) const;
|
||||||
|
bool undoAddSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight) const;
|
||||||
|
bool spendSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight, int& nValidAtHeight) const;
|
||||||
|
bool undoSpendSupport(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, uint256 supportedTxhash, int supportednOut, int nHeight, int nValidAtHeight) const;
|
||||||
uint256 getBestBlock();
|
uint256 getBestBlock();
|
||||||
void setBestBlock(const uint256& hashBlock);
|
void setBestBlock(const uint256& hashBlock);
|
||||||
bool incrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo) const;
|
bool incrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo, CSupportValueQueueUndo& insertSupportUndo) const;
|
||||||
bool decrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo) const;
|
bool decrementBlock(CClaimTrieQueueUndo& insertUndo, CClaimTrieQueueUndo& expireUndo, CSupportValueQueueUndo& insertSupportUndo) const;
|
||||||
~CClaimTrieCache() { clear(); }
|
~CClaimTrieCache() { clear(); }
|
||||||
bool insertClaimIntoTrie(const std::string name, CNodeValue val) const;
|
bool insertClaimIntoTrie(const std::string name, CNodeValue val) const;
|
||||||
bool removeClaimFromTrie(const std::string name, uint256 txhash, uint32_t nOut, int& nValidAtHeight) const;
|
bool removeClaimFromTrie(const std::string name, uint256 txhash, uint32_t nOut, int& nValidAtHeight) const;
|
||||||
|
@ -224,9 +305,12 @@ private:
|
||||||
mutable hashMapType cacheHashes;
|
mutable hashMapType cacheHashes;
|
||||||
mutable valueQueueType valueQueueCache;
|
mutable valueQueueType valueQueueCache;
|
||||||
mutable valueQueueType expirationQueueCache;
|
mutable valueQueueType expirationQueueCache;
|
||||||
|
mutable supportMapType supportCache;
|
||||||
|
mutable supportValueQueueType supportQueueCache;
|
||||||
mutable int nCurrentHeight; // Height of the block that is being worked on, which is
|
mutable int nCurrentHeight; // Height of the block that is being worked on, which is
|
||||||
// one greater than the height of the chain's tip
|
// one greater than the height of the chain's tip
|
||||||
uint256 computeHash() const;
|
uint256 computeHash() const;
|
||||||
|
bool reorderTrieNode(const std::string name) const;
|
||||||
bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std::string sPos) const;
|
bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std::string sPos) const;
|
||||||
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified = NULL) const;
|
bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified = NULL) const;
|
||||||
bool clear() const;
|
bool clear() const;
|
||||||
|
@ -237,6 +321,12 @@ private:
|
||||||
void removeFromExpirationQueue(const std::string name, uint256 txhash, uint32_t nOut, int nHeight) const;
|
void removeFromExpirationQueue(const std::string name, uint256 txhash, uint32_t nOut, int nHeight) const;
|
||||||
valueQueueType::iterator getQueueCacheRow(int nHeight, bool createIfNotExists) const;
|
valueQueueType::iterator getQueueCacheRow(int nHeight, bool createIfNotExists) const;
|
||||||
valueQueueType::iterator getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const;
|
valueQueueType::iterator getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const;
|
||||||
|
bool removeSupport(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight, int& nValidAtHeight) const;
|
||||||
|
bool removeSupportFromMap(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeight, int& nValidAtHeight) const;
|
||||||
|
bool insertSupportIntoMap(const std::string name, CSupportNodeValue val) const;
|
||||||
|
supportValueQueueType::iterator getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const;
|
||||||
|
bool addSupportToQueue(const std::string name, uint256 txhash, uint32_t nOut, CAmount nAmount, uint256 supportedTxhash, int supportednOut, int nHeight, int nValidAtHeight) const;
|
||||||
|
bool removeSupportFromQueue(const std::string name, uint256 txhash, uint32_t nOut, uint256 supportedTxhash, int supportednOut, int nHeightToCheck, int& nValidAtHeight) const;
|
||||||
uint256 hashBlock;
|
uint256 hashBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
80
src/main.cpp
80
src/main.cpp
|
@ -1622,15 +1622,41 @@ static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, CClaimTr
|
||||||
int op;
|
int op;
|
||||||
std::vector<std::vector<unsigned char> > vvchParams;
|
std::vector<std::vector<unsigned char> > vvchParams;
|
||||||
if (DecodeClaimScript(undo.txout.scriptPubKey, op, vvchParams))
|
if (DecodeClaimScript(undo.txout.scriptPubKey, op, vvchParams))
|
||||||
|
{
|
||||||
|
if (op == OP_CLAIM_NAME)
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
LogPrintf("%s: Restoring %s to the claim trie due to a block being disconnected\n", __func__, name.c_str());
|
|
||||||
int nValidHeight = undo.nClaimValidHeight;
|
int nValidHeight = undo.nClaimValidHeight;
|
||||||
if (nValidHeight > 0 && nValidHeight >= coins->nHeight)
|
if (nValidHeight > 0 && nValidHeight >= coins->nHeight)
|
||||||
{
|
{
|
||||||
|
LogPrintf("%s: (txid: %s, nOut: %d) Restoring %s to the claim trie due to a block being disconnected\n", __func__, out.hash.ToString(), out.n, name.c_str());
|
||||||
if (!trieCache.undoSpendClaim(name, out.hash, out.n, undo.txout.nValue, coins->nHeight, nValidHeight))
|
if (!trieCache.undoSpendClaim(name, out.hash, out.n, undo.txout.nValue, coins->nHeight, nValidHeight))
|
||||||
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
LogPrintf("%s: Something went wrong inserting the claim\n", __func__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrintf("%s: (txid: %s, nOut: %d) Not restoring %s to the claim trie because it expired before it was spent\n", __func__, out.hash.ToString(), out.n, name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
assert(vvchParams.size() == 3);
|
||||||
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
uint256 supportedTxid(vvchParams[1]);
|
||||||
|
CScriptNum snOut(vvchParams[2], true);
|
||||||
|
int supportednOut = snOut.getint();
|
||||||
|
int nValidHeight = undo.nClaimValidHeight;
|
||||||
|
if (nValidHeight > 0 && nValidHeight >= coins->nHeight)
|
||||||
|
{
|
||||||
|
LogPrintf("%s: (txid: %s, nOut: %d) Restoring support for %s in txid %s nOut %d due to a block being disconnected\n", __func__, out.hash.ToString(), out.n, name, supportedTxid.ToString(), supportednOut);
|
||||||
|
if (!trieCache.undoSpendSupport(name, out.hash, out.n, undo.txout.nValue, supportedTxid, supportednOut, coins->nHeight, nValidHeight))
|
||||||
|
LogPrintf("%s: Something went wrong inserting support for the claim\n", __func__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrintf("%s: (txid: %s, nOut: %d) Not restoring support for %s in txid %s nOut %d because the support expired before it was spent\n", __func__, out.hash.ToString(), out.n, name, supportedTxid.ToString(), supportednOut);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1659,7 +1685,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
|
if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
|
||||||
return error("DisconnectBlock(): block and undo data inconsistent");
|
return error("DisconnectBlock(): block and undo data inconsistent");
|
||||||
|
|
||||||
assert(trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo));
|
assert(trieCache.decrementBlock(blockUndo.insertUndo, blockUndo.expireUndo, blockUndo.insertSupportUndo));
|
||||||
|
|
||||||
// undo transactions in reverse order
|
// undo transactions in reverse order
|
||||||
for (int i = block.vtx.size() - 1; i >= 0; i--) {
|
for (int i = block.vtx.size() - 1; i >= 0; i--) {
|
||||||
|
@ -1689,13 +1715,27 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
int op;
|
int op;
|
||||||
std::vector<std::vector<unsigned char> > vvchParams;
|
std::vector<std::vector<unsigned char> > vvchParams;
|
||||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||||
|
{
|
||||||
|
if (op == OP_CLAIM_NAME)
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
LogPrintf("%s: Removing %s from the claim trie due to its block being disconnected\n", __func__, name.c_str());
|
LogPrintf("%s: (txid: %s, nOut: %d) Removing %s from the claim trie due to its block being disconnected\n", __func__, hash.ToString(), i, name.c_str());
|
||||||
if (!trieCache.undoAddClaim(name, hash, i, pindex->nHeight))
|
if (!trieCache.undoAddClaim(name, hash, i, pindex->nHeight))
|
||||||
LogPrintf("%s: Something went wrong removing the name %s in hash %s\n", __func__, name.c_str(), hash.GetHex());
|
LogPrintf("%s: Something went wrong removing the name %s in hash %s\n", __func__, name.c_str(), hash.GetHex());
|
||||||
}
|
}
|
||||||
|
else if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
assert(vvchParams.size() == 3);
|
||||||
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
uint256 supportedTxid(vvchParams[1]);
|
||||||
|
CScriptNum snOut(vvchParams[2], true);
|
||||||
|
int supportednOut = snOut.getint();
|
||||||
|
LogPrintf("%s: (txid: %s, nOut: %d) Removing support for %s from txid %s nOut %d due to its block being disconnected\n", __func__, hash.ToString(), i, supportedTxid.ToString(), supportednOut, name.c_str());
|
||||||
|
if (!trieCache.undoAddSupport(name, hash, i, supportedTxid, supportednOut, pindex->nHeight))
|
||||||
|
LogPrintf("%s: Something went wrong removing support for name %s in hash %s\n", __func__, name.c_str(), hash.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove outputs
|
// remove outputs
|
||||||
|
@ -1968,6 +2008,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
int op;
|
int op;
|
||||||
std::vector<std::vector<unsigned char> > vvchParams;
|
std::vector<std::vector<unsigned char> > vvchParams;
|
||||||
if (DecodeClaimScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
|
if (DecodeClaimScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
|
||||||
|
{
|
||||||
|
if (op == OP_CLAIM_NAME)
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
@ -1981,6 +2023,21 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
spentClaims.insert(entry);
|
spentClaims.insert(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
assert(vvchParams.size() == 3);
|
||||||
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
uint256 supportedTxid(vvchParams[1]);
|
||||||
|
CScriptNum snOut(vvchParams[2], true);
|
||||||
|
int supportednOut = snOut.getint();
|
||||||
|
int nValidAtHeight;
|
||||||
|
LogPrintf("%s: Removing support for %s in txid %s nOut %d. Tx: %s, nOut: %d\n", __func__, name, supportedTxid.ToString(), supportednOut, txin.prevout.hash.ToString(), txin.prevout.n);
|
||||||
|
if (trieCache.spendSupport(name, txin.prevout.hash, txin.prevout.n, supportedTxid, supportednOut, coins->nHeight, nValidAtHeight))
|
||||||
|
{
|
||||||
|
mClaimUndoHeights[0] = nValidAtHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < tx.vout.size(); ++i)
|
for (unsigned int i = 0; i < tx.vout.size(); ++i)
|
||||||
|
@ -1990,6 +2047,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
int op;
|
int op;
|
||||||
std::vector<std::vector<unsigned char> > vvchParams;
|
std::vector<std::vector<unsigned char> > vvchParams;
|
||||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||||
|
{
|
||||||
|
if (op == OP_CLAIM_NAME)
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
@ -2007,6 +2066,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
if (!success)
|
if (!success)
|
||||||
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||||
}
|
}
|
||||||
|
else if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
assert(vvchParams.size() == 3);
|
||||||
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
uint256 supportedTxid(vvchParams[1]);
|
||||||
|
CScriptNum snOut(vvchParams[2], true);
|
||||||
|
int supportednOut = snOut.getint();
|
||||||
|
if (!trieCache.addSupport(name, tx.GetHash(), i, txout.nValue, supportedTxid, supportednOut, pindex->nHeight))
|
||||||
|
LogPrintf("%s: Something went wrong inserting the support\n", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2034,7 +2104,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
|
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo));
|
assert(trieCache.incrementBlock(blockundo.insertUndo, blockundo.expireUndo, blockundo.insertSupportUndo));
|
||||||
|
|
||||||
if (trieCache.getMerkleHash() != block.hashClaimTrie)
|
if (trieCache.getMerkleHash() != block.hashClaimTrie)
|
||||||
return state.DoS(100,
|
return state.DoS(100,
|
||||||
|
|
|
@ -309,6 +309,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
int op;
|
int op;
|
||||||
|
|
||||||
if (DecodeClaimScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
|
if (DecodeClaimScript(coins->vout[txin.prevout.n].scriptPubKey, op, vvchParams))
|
||||||
|
{
|
||||||
|
if (op == OP_CLAIM_NAME)
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
@ -319,6 +321,18 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
std::pair<std::string, std::pair<uint256, unsigned int> >entry(name, val);
|
std::pair<std::string, std::pair<uint256, unsigned int> >entry(name, val);
|
||||||
spentClaims.insert(entry);
|
spentClaims.insert(entry);
|
||||||
}
|
}
|
||||||
|
else if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
assert(vvchParams.size() == 3);
|
||||||
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
uint256 supportedTxid(vvchParams[1]);
|
||||||
|
CScriptNum snOut(vvchParams[2], true);
|
||||||
|
int supportednOut = snOut.getint();
|
||||||
|
int throwaway;
|
||||||
|
if (!trieCache.spendSupport(name, txin.prevout.hash, txin.prevout.n, supportedTxid, supportednOut, coins->nHeight, throwaway))
|
||||||
|
LogPrintf("%s: Something went wrong removing the support\n", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateCoins(tx, state, view, nHeight);
|
UpdateCoins(tx, state, view, nHeight);
|
||||||
|
@ -330,6 +344,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
std::vector<std::vector<unsigned char> > vvchParams;
|
std::vector<std::vector<unsigned char> > vvchParams;
|
||||||
int op;
|
int op;
|
||||||
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
if (DecodeClaimScript(txout.scriptPubKey, op, vvchParams))
|
||||||
|
{
|
||||||
|
if (op == OP_CLAIM_NAME)
|
||||||
{
|
{
|
||||||
assert(vvchParams.size() == 2);
|
assert(vvchParams.size() == 2);
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
@ -345,6 +361,19 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
if (!success)
|
if (!success)
|
||||||
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||||
}
|
}
|
||||||
|
else if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
assert(vvchParams.size() == 3);
|
||||||
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
uint256 supportedTxid(vvchParams[1]);
|
||||||
|
CScriptNum snOut(vvchParams[2], true);
|
||||||
|
int supportednOut = snOut.getint();
|
||||||
|
if (!trieCache.addSupport(name, tx.GetHash(), i, txout.nValue, supportedTxid, supportednOut, nHeight))
|
||||||
|
{
|
||||||
|
LogPrintf("%s: Something went wrong inserting the name\n", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Added
|
// Added
|
||||||
|
@ -398,7 +427,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
|
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
|
||||||
CClaimTrieQueueUndo dummyInsertUndo;
|
CClaimTrieQueueUndo dummyInsertUndo;
|
||||||
CClaimTrieQueueUndo dummyExpireUndo;
|
CClaimTrieQueueUndo dummyExpireUndo;
|
||||||
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo);
|
CSupportValueQueueUndo dummyInsertSupportUndo;
|
||||||
|
trieCache.incrementBlock(dummyInsertUndo, dummyExpireUndo, dummyInsertSupportUndo);
|
||||||
pblock->hashClaimTrie = trieCache.getMerkleHash();
|
pblock->hashClaimTrie = trieCache.getMerkleHash();
|
||||||
|
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
|
|
|
@ -14,39 +14,53 @@ bool DecodeClaimScript(const CScript& scriptIn, int& op, std::vector<std::vector
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (opcode != OP_CLAIM_NAME)
|
|
||||||
|
if (opcode != OP_CLAIM_NAME && opcode != OP_SUPPORT_CLAIM)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
op = opcode;
|
op = opcode;
|
||||||
|
|
||||||
std::vector<unsigned char> vchName;
|
std::vector<unsigned char> vchParam1;
|
||||||
std::vector<unsigned char> vchValue;
|
std::vector<unsigned char> vchParam2;
|
||||||
|
std::vector<unsigned char> vchParam3;
|
||||||
// The correct format is:
|
// Valid formats:
|
||||||
// OP_CLAIM_NAME vchName vchValue OP_DROP2 OP_DROP pubkeyscript
|
// OP_CLAIM_NAME vchName vchValue OP_2DROP OP_DROP pubkeyscript
|
||||||
|
// OP_SUPPORT_CLAIM vchName vchClaimHash vchClaimIndex OP_2DROP OP_2DROP pubkeyscript
|
||||||
// All others are invalid.
|
// All others are invalid.
|
||||||
|
|
||||||
if (!scriptIn.GetOp(pc, opcode, vchName) || opcode < 0 || opcode > OP_PUSHDATA4)
|
|
||||||
|
if (!scriptIn.GetOp(pc, opcode, vchParam1) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!scriptIn.GetOp(pc, opcode, vchValue) || opcode < 0 || opcode > OP_PUSHDATA4)
|
if (!scriptIn.GetOp(pc, opcode, vchParam2) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
if (!scriptIn.GetOp(pc, opcode) || opcode < 0 || opcode > OP_PUSHDATA4)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!scriptIn.GetOp(pc, opcode) || opcode != OP_2DROP)
|
if (!scriptIn.GetOp(pc, opcode) || opcode != OP_2DROP)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!scriptIn.GetOp(pc, opcode) || opcode != OP_DROP)
|
if (!scriptIn.GetOp(pc, opcode) || (op == OP_CLAIM_NAME && opcode != OP_DROP) || (op == OP_SUPPORT_CLAIM && opcode != OP_2DROP))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vvchParams.push_back(vchName);
|
vvchParams.push_back(vchParam1);
|
||||||
vvchParams.push_back(vchValue);
|
vvchParams.push_back(vchParam2);
|
||||||
|
if (op == OP_SUPPORT_CLAIM)
|
||||||
|
{
|
||||||
|
vvchParams.push_back(vchParam3);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,57 @@ const unsigned int expire_nonces[] = {
|
||||||
4359, 35786, 24830, 102413, 17399, 48845, 22866, 8417, 24049, 50162,
|
4359, 35786, 24830, 102413, 17399, 48845, 22866, 8417, 24049, 50162,
|
||||||
36921, 162891, 38509, 121018, 54548, 158171, 54355, 12742, 6174,
|
36921, 162891, 38509, 121018, 54548, 158171, 54355, 12742, 6174,
|
||||||
};
|
};
|
||||||
const unsigned int support_nonces[] = {};
|
const unsigned int support_nonces[] = {
|
||||||
|
6685, 83337, 74116, 50981, 51352, 158110, 132142, 161310, 95702, 32959,
|
||||||
|
5785, 229298, 59738, 71206, 24625, 6, 141161, 43901, 35697, 98865,
|
||||||
|
41764, 104919, 89611, 813, 54564, 13614, 24774, 39079, 67709, 94367,
|
||||||
|
24006, 137451, 87265, 4096, 17540, 93657, 64419, 178853, 45385, 18571,
|
||||||
|
49357, 67111, 92635, 73880, 7810, 15338, 56201, 1419, 92096, 121328,
|
||||||
|
60987, 32796, 63605, 2178, 25415, 19115, 62190, 76200, 155888, 208604,
|
||||||
|
43921, 623, 63809, 129207, 59080, 111270, 58799, 47014, 26935, 140745,
|
||||||
|
15982, 22417, 54877, 64708, 3508, 63688, 117163, 93037, 27595, 49051,
|
||||||
|
109801, 54794, 38790, 192113, 14920, 2056, 419624, 20495, 86719, 27455,
|
||||||
|
94870, 5539, 12871, 24142, 103201, 12358, 60226, 11163, 57429, 49086,
|
||||||
|
115051, 39940, 68936, 392, 23999, 23185, 37265, 793, 196124, 133047,
|
||||||
|
95771, 4927, 2410, 191047, 8416, 36182, 126426, 101492, 268543, 66462,
|
||||||
|
132688, 9709, 25766, 10781, 56169, 17484, 191643, 46857, 180718, 129600,
|
||||||
|
76319, 275342, 113429, 52200, 8584, 205931, 60264, 99367, 71513, 10931,
|
||||||
|
2470, 146435, 35660, 30357, 53621, 126053, 198310, 7340, 23329, 56232,
|
||||||
|
43152, 1290, 178803, 58294, 28730, 135307, 26024, 33903, 23202, 69984,
|
||||||
|
91861, 4406, 21564, 12088, 5307, 17517, 177507, 3629, 81666, 196118,
|
||||||
|
37329, 42816, 1766, 5227, 98516, 62284, 1449, 10331, 4915, 1086,
|
||||||
|
257130, 125081, 63069, 34059, 51482, 15396, 25319, 208595, 45717, 145038,
|
||||||
|
51317, 34896, 60597, 8930, 150489, 15827, 94634, 19809, 90784, 102628,
|
||||||
|
26279, 36205, 239377, 98432, 1949, 167692, 123222, 36572, 5435, 239413,
|
||||||
|
85529, 124924, 17443, 10391, 21356, 109441, 711, 27883, 15410, 172902,
|
||||||
|
9155, 6372, 93226, 31199, 47383, 77311, 107243, 1248, 3968, 88072,
|
||||||
|
50741, 175826, 9475, 19473, 78911, 59587, 172626, 54698, 127135, 4356,
|
||||||
|
70568, 9206, 41708, 162673, 82436, 8787, 12851, 17524, 27151, 34992,
|
||||||
|
19003, 17118, 1353, 173957, 62721, 10956, 28301, 38722, 35000, 51572,
|
||||||
|
122622, 26131, 219537, 24299, 8306, 22556, 117394, 5874, 1658, 4299,
|
||||||
|
85895, 59207, 17620, 65379, 53730, 66114, 31973, 80054, 39898, 88576,
|
||||||
|
35918, 54740, 43218, 310351, 18849, 65424, 18941, 49216, 21837, 1044,
|
||||||
|
36089, 89042, 1064, 57622, 18277, 30812, 392721, 68449, 21958, 59353,
|
||||||
|
230626, 192876, 152661, 83303, 12403, 48000, 322, 36098, 216060, 261073,
|
||||||
|
10127, 40078, 13820, 37595, 2465, 67578, 8074, 17069, 23001, 75590,
|
||||||
|
59540, 38500, 81671, 83017, 21630, 42072, 87988, 34685, 54463, 73723,
|
||||||
|
64583, 11708, 27819, 60914, 44671, 73532, 481251, 50437, 51482, 140164,
|
||||||
|
17802, 52420, 18605, 39313, 5815, 130397, 47241, 41700, 73784, 38254,
|
||||||
|
31816, 81033, 63873, 61180, 73597, 31012, 46596, 34360, 16076, 3553,
|
||||||
|
19667, 70678, 76463, 14007, 6695, 34346, 177277, 82740, 10695, 195656,
|
||||||
|
199473, 19061, 12235, 118857, 5890, 158834, 14991, 9908, 40669, 76476,
|
||||||
|
5798, 56010, 12434, 136848, 44171, 33686, 38022, 85052, 88529, 96055,
|
||||||
|
77808, 14052, 26881, 183273, 110552, 14780, 62505, 29327, 16832, 146503,
|
||||||
|
4492, 3210, 60633, 117771, 14125, 30949, 20800, 35101, 72610, 3023,
|
||||||
|
39933, 7829, 21639, 14090, 59951, 46100, 26005, 57832, 3410, 58340,
|
||||||
|
83407, 189530, 1991, 46036, 39758, 26344, 36726, 13556, 54091, 52219,
|
||||||
|
10445, 23350, 62863, 41887, 39607, 47051, 170358, 62714, 54450, 44956,
|
||||||
|
90394, 89040, 82532, 10732, 30853, 69521, 27096, 129159, 25700, 56643,
|
||||||
|
4510, 61375, 45066, 84264, 47513, 27524, 25215, 95656, 73959, 20581,
|
||||||
|
101988, 14797, 76360, 120161, 17567, 3903, 126413, 64154, 317038, 33995,
|
||||||
|
25108, 8165, 132499, 174571, 4312, 63941, 109366, 12461, 81720, 36019,
|
||||||
|
57768, 30058, 64038, 60147, 5536, 87586, 10954, 84112, 42404, 109189,
|
||||||
|
};
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(claimtrie_tests, TestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(claimtrie_tests, TestingSetup)
|
||||||
|
|
||||||
|
@ -1248,34 +1298,181 @@ BOOST_AUTO_TEST_CASE(claimtrie_supporting_claims)
|
||||||
tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE;
|
tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE;
|
||||||
|
|
||||||
CMutableTransaction tx2 = BuildTransaction(coinbases[1]);
|
CMutableTransaction tx2 = BuildTransaction(coinbases[1]);
|
||||||
tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE;
|
tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE;
|
||||||
|
|
||||||
CMutableTransaction tx3 = BuildTransaction(coinbases[2]);
|
CMutableTransaction tx3 = BuildTransaction(coinbases[2]);
|
||||||
std::string sTx1Hash = tx1.GetHash().ToString();
|
std::string sTx1Hash = tx1.GetHash().ToString();
|
||||||
std::vector<unsigned char> vchTx1Hash(sTx1Hash.begin(), sTx1Hash.end());
|
std::vector<unsigned char> vchTx1Hash(sTx1Hash.begin(), sTx1Hash.end());
|
||||||
tx1.vout[0].scriptPubKey = CScript() << OP_SUPPORT_CLAIM << vchTx1Hash << 0 << OP_2DROP << OP_DROP << OP_TRUE;
|
tx3.vout[0].scriptPubKey = CScript() << OP_SUPPORT_CLAIM << vchName << vchTx1Hash << CScriptNum(0) << OP_2DROP << OP_2DROP << OP_TRUE;
|
||||||
|
|
||||||
|
CNodeValue val;
|
||||||
std::vector<uint256> blocks_to_invalidate;
|
std::vector<uint256> blocks_to_invalidate;
|
||||||
|
|
||||||
// Test 1: create 1 LBC claim (A), create 5 LBC support (A), create 5 LBC claim (B)
|
// Test 1: create 1 LBC claim (tx1), create 5 LBC support (tx3), create 5 LBC claim (tx2)
|
||||||
// Verify that A retains control throughout
|
// Verify that tx1 retains control throughout
|
||||||
|
// spend tx3, verify that tx2 gains control
|
||||||
|
// roll back to before tx3 is valid
|
||||||
|
// advance until tx3 and tx2 are valid, verify tx1 retains control
|
||||||
|
// spend tx3, verify tx2 gains control
|
||||||
|
// roll back to before tx3 is spent, verify tx1 gains control
|
||||||
|
// roll back to before tx2 is valid, spend tx3
|
||||||
|
// advance to tx2 valid, verify tx2 gains control
|
||||||
|
// roll back to before tx3 is valid, spend tx3
|
||||||
|
// advance to tx2 valid, verify tx2 gains control
|
||||||
|
// roll back to insertion of tx3, and don't insert it
|
||||||
|
// insert tx2, advance until it is valid, verify tx2 gains control
|
||||||
|
|
||||||
// Test 2: create 1 LBC claim (A), create 5 LBC claim (B), create 5 LBC support (A)
|
// Put tx1 in the blockchain
|
||||||
// Verify that A loses control when B becomes valid, and then A gains control when support becomes valid
|
|
||||||
|
|
||||||
// Test 3: create 1 LBC claim (A), create 5 LBC support (A), create 5 LBC claim(B), spend (A) support
|
AddToMempool(tx1);
|
||||||
// Verify that A retains control until support is spent
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
BOOST_CHECK(pblocktemplate->block.vtx.size() == 2);
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
// Test 4: create 1 LBC claim (A), wait till valid, create 5 LBC claim (B), create 5 LBC support (A)
|
BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash()));
|
||||||
// Verify that A retains control throughout
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->queueEmpty());
|
||||||
|
BOOST_CHECK(pclaimTrie->supportEmpty());
|
||||||
|
BOOST_CHECK(pclaimTrie->supportQueueEmpty());
|
||||||
|
|
||||||
// Test 5: create 5 LBC claim (A), wait till valid, create 1 LBC claim (B), create 5 LBC support (B)
|
// advance 20 blocks
|
||||||
// Verify that A retains control until support becomes valid
|
|
||||||
|
|
||||||
// Test 6: create 1 LBC claim (A), wait till valid, create 5 LBC claim (B), create 5 LBC support (A), spend A
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
// Verify that A retains control until it is spent
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
for (unsigned int i = 1; i < 20; ++i)
|
||||||
|
{
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
}
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
// Test 7: create 1 LBC claim (A), wait till valid, create 5 LBC support (A), spend A
|
// Put tx3 into the blockchain
|
||||||
|
|
||||||
|
AddToMempool(tx3);
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
BOOST_CHECK(pblocktemplate->block.vtx.size() == 2);
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
blocks_to_invalidate.push_back(pblocktemplate->block.hashPrevBlock);
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(pcoinsTip->HaveCoins(tx3.GetHash()));
|
||||||
|
BOOST_CHECK(pclaimTrie->supportEmpty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->supportQueueEmpty());
|
||||||
|
|
||||||
|
// advance 20 blocks
|
||||||
|
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
for (unsigned int i = 21; i < 40; ++i)
|
||||||
|
{
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
}
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
// Put tx2 into the blockchain
|
||||||
|
|
||||||
|
AddToMempool(tx2);
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
BOOST_CHECK(pblocktemplate->block.vtx.size() == 2);
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash()));
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->queueEmpty());
|
||||||
|
|
||||||
|
// advance until tx1 is valid
|
||||||
|
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
for (unsigned int i = 41; i < 100; ++i)
|
||||||
|
{
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
}
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->queueEmpty());
|
||||||
|
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->queueEmpty());
|
||||||
|
BOOST_CHECK(pclaimTrie->supportEmpty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->supportQueueEmpty());
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK(val.txhash == tx1.GetHash());
|
||||||
|
|
||||||
|
// advance until tx3 is valid
|
||||||
|
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
for (unsigned int i = 101; i < 120; ++i)
|
||||||
|
{
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
}
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->supportEmpty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->supportQueueEmpty());
|
||||||
|
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->supportEmpty());
|
||||||
|
BOOST_CHECK(pclaimTrie->supportQueueEmpty());
|
||||||
|
|
||||||
|
// advance until tx2 is valid
|
||||||
|
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
for (unsigned int i = 121; i < 140; ++i)
|
||||||
|
{
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
}
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!pclaimTrie->queueEmpty());
|
||||||
|
|
||||||
|
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||||
|
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate, pnp, support_nonces[block_counter++]));
|
||||||
|
delete pblocktemplate;
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(pclaimTrie->queueEmpty());
|
||||||
|
BOOST_CHECK(pclaimTrie->getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK(val.txhash == tx1.GetHash());
|
||||||
|
|
||||||
|
// Test 2: create 1 LBC claim (tx1), create 5 LBC claim (tx2), create 5 LBC support (tx3)
|
||||||
|
// Verify that tx1 loses control when tx2 becomes valid, and then tx1 gains control when tx3 becomes valid
|
||||||
|
|
||||||
|
// Test 3: create 1 LBC claim (tx1), create 5 LBC support (tx3), create 5 LBC claim(tx2), spend tx3
|
||||||
|
// Verify that tx1 retains control until tx3 is spent
|
||||||
|
|
||||||
|
// Test 4: create 1 LBC claim (tx1), wait till valid, create 5 LBC claim (tx2), create 5 LBC support (tx3)
|
||||||
|
// Verify that tx1 retains control throughout
|
||||||
|
|
||||||
|
// Test 5: create 5 LBC claim (tx2), wait till valid, create 1 LBC claim (tx1), create 5 LBC support (tx3)
|
||||||
|
// Verify that tx2 retains control until support becomes valid
|
||||||
|
|
||||||
|
// Test 6: create 1 LBC claim (tx1), wait till valid, create 5 LBC claim (tx2), create 5 LBC support (tx3), spend tx1
|
||||||
|
// Verify that tx1 retains control until it is spent
|
||||||
|
|
||||||
|
// Test 7: create 1 LBC claim (tx1), wait till valid, create 5 LBC support (tx3), spend tx1
|
||||||
|
// Verify name trie is empty
|
||||||
|
|
||||||
|
// Test 8: create 1 LBC claim (tx1), create 5 LBC support (tx3), wait till tx1 valid, spend tx1, wait till tx3 valid
|
||||||
// Verify name trie is empty
|
// Verify name trie is empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
std::vector<CTxUndo> vtxundo; // for all but the coinbase
|
std::vector<CTxUndo> vtxundo; // for all but the coinbase
|
||||||
CClaimTrieQueueUndo insertUndo; // any claims that went from the queue to the trie
|
CClaimTrieQueueUndo insertUndo; // any claims that went from the queue to the trie
|
||||||
CClaimTrieQueueUndo expireUndo; // any claims that expired
|
CClaimTrieQueueUndo expireUndo; // any claims that expired
|
||||||
|
CSupportValueQueueUndo insertSupportUndo; // any claims that went from the support queue to the support map
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
@ -90,6 +91,7 @@ public:
|
||||||
READWRITE(vtxundo);
|
READWRITE(vtxundo);
|
||||||
READWRITE(insertUndo);
|
READWRITE(insertUndo);
|
||||||
READWRITE(expireUndo);
|
READWRITE(expireUndo);
|
||||||
|
READWRITE(insertSupportUndo);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue