Claim name returned is strange #172

Closed
mirgee wants to merge 286 commits from issue-119 into master
5 changed files with 62 additions and 64 deletions
Showing only changes of commit c9785bb21f - Show all commits

View file

@ -1046,7 +1046,7 @@ bool AppInit2(boost::thread_group& threadGroup)
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
pcoinsTip = new CCoinsViewCache(pcoinscatcher);
pnccTrie = new CNCCTrie();
pnccTrie = new CNCCTrie(false, fReindex);
if (fReindex)
pblocktree->WriteReindexing(true);

View file

@ -2081,6 +2081,8 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
}
}
// Finally flush the chainstate (which may refer to block index entries).
if (!pnccTrie->WriteToDisk())
return state.Abort("Failed to write to ncc trie database");
if (!pcoinsTip->Flush())
return state.Abort("Failed to write to coin database");
// Update best block in wallet (so we can detect restored wallets).

View file

@ -40,7 +40,6 @@ bool CNCCTrieNode::removeValue(uint256& txhash, uint32_t nOut, CNodeValue& val,
CNodeValue currentTop = values.front();
//std::vector<CNodeValue>::iterator position = std::find(values.begin(), values.end(), val);
std::vector<CNodeValue>::iterator position;
for (position = values.begin(); position != values.end(); ++position)
{
@ -214,11 +213,13 @@ bool CNCCTrie::recursiveCheckConsistency(CNCCTrieNode* node)
return calculatedHash == node->hash;
}
valueQueueType::iterator CNCCTrie::getQueueRow(int nHeight)
valueQueueType::iterator CNCCTrie::getQueueRow(int nHeight, bool createIfNotExists)
{
valueQueueType::iterator itQueueRow = valueQueue.find(nHeight);
if (itQueueRow == valueQueue.end())
{
if (!createIfNotExists)
return itQueueRow;
std::vector<CValueQueueEntry> queueRow;
std::pair<valueQueueType::iterator, bool> ret;
ret = valueQueue.insert(std::pair<int, std::vector<CValueQueueEntry> >(nHeight, queueRow));
@ -250,56 +251,54 @@ bool CNCCTrie::update(nodeCacheType& cache, hashMapType& hashes, const uint256&
// This can probably be optimized by checking each substring against
// the caches each time, but that will come after this is shown to
// work correctly.
// As far as saving to disk goes, the idea is to use the list of
// hashes to construct a list of (pointers to) nodes that have been
// altered in the update, and to construct a list of names of nodes
// that have been deleted, and to use a leveldb batch to write them
// all to disk. As of right now, txundo stuff will be handled by
// appending extra data to the normal txundo, which will call the
// normal insert/remove names, but obviously the opposite and in
// reverse order (though the order shouldn't ever matter).
// Disk strategy: keep a map of <string: dirty node>, where
// any nodes that are changed get put into the map, and any nodes
// to be deleted will simply be empty (no value, no children). Nodes
// whose hashes change will also be inserted into the map.
// As far as the queue goes, just keep a list of dirty queue entries.
// When the time comes, send all of that to disk in one batch, and
// empty the map/list.
bool success = true;
std::vector<std::string> deletedNames;
nodeCacheType changedNodes;
for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache)
{
CNCCTrieNode* pNode;
success = updateName(itcache->first, itcache->second, deletedNames, &pNode);
success = updateName(itcache->first, itcache->second);
if (!success)
return false;
changedNodes[itcache->first] = pNode;
}
for (hashMapType::iterator ithash = hashes.begin(); ithash != hashes.end(); ++ithash)
{
CNCCTrieNode* pNode;
success = updateHash(ithash->first, ithash->second, &pNode);
success = updateHash(ithash->first, ithash->second);
if (!success)
return false;
changedNodes[ithash->first] = pNode;
}
std::vector<int> vChangedQueueRows;
std::vector<int> vDeletedQueueRows;
for (valueQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow)
{
if (itQueueCacheRow->second.empty())
{
vDeletedQueueRows.push_back(itQueueCacheRow->first);
deleteQueueRow(itQueueCacheRow->first);
}
else
{
vChangedQueueRows.push_back(itQueueCacheRow->first);
valueQueueType::iterator itQueueRow = getQueueRow(itQueueCacheRow->first);
valueQueueType::iterator itQueueRow = getQueueRow(itQueueCacheRow->first, true);
itQueueRow->second.swap(itQueueCacheRow->second);
}
vDirtyQueueRows.push_back(itQueueCacheRow->first);
}
BatchWrite(changedNodes, deletedNames, hashBlockIn, vChangedQueueRows, vDeletedQueueRows, nNewHeight);
hashBlock = hashBlockIn;
nCurrentHeight = nNewHeight;
return true;
}
bool CNCCTrie::updateName(const std::string &name, CNCCTrieNode* updatedNode, std::vector<std::string>& deletedNames, CNCCTrieNode** pNodeRet)
void CNCCTrie::markNodeDirty(const std::string &name, CNCCTrieNode* node)
{
std::pair<nodeCacheType::iterator, bool> ret;
ret = dirtyNodes.insert(std::pair<std::string, CNCCTrieNode*>(name, node));
if (ret.second == false)
ret.first->second = node;
}
bool CNCCTrie::updateName(const std::string &name, CNCCTrieNode* updatedNode)
{
CNCCTrieNode* current = &root;
for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname)
@ -323,7 +322,7 @@ bool CNCCTrie::updateName(const std::string &name, CNCCTrieNode* updatedNode, st
}
assert(current != NULL);
current->values.swap(updatedNode->values);
*pNodeRet = current;
markNodeDirty(name, current);
for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();)
{
nodeMapType::iterator itupdatechild = updatedNode->children.find(itchild->first);
@ -334,7 +333,7 @@ bool CNCCTrie::updateName(const std::string &name, CNCCTrieNode* updatedNode, st
std::stringstream ss;
ss << name << itchild->first;
std::string newName = ss.str();
if (!recursiveNullify(itchild->second, newName, deletedNames))
if (!recursiveNullify(itchild->second, newName))
return false;
current->children.erase(itchild++);
}
@ -344,7 +343,7 @@ bool CNCCTrie::updateName(const std::string &name, CNCCTrieNode* updatedNode, st
return true;
}
bool CNCCTrie::recursiveNullify(CNCCTrieNode* node, std::string& name, std::vector<std::string>& deletedNames)
bool CNCCTrie::recursiveNullify(CNCCTrieNode* node, std::string& name)
{
assert(node != NULL);
for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild)
@ -352,16 +351,16 @@ bool CNCCTrie::recursiveNullify(CNCCTrieNode* node, std::string& name, std::vect
std::stringstream ss;
ss << name << itchild->first;
std::string newName = ss.str();
if (!recursiveNullify(itchild->second, newName, deletedNames))
if (!recursiveNullify(itchild->second, newName))
return false;
}
node->children.clear();
markNodeDirty(name, NULL);
delete node;
deletedNames.push_back(name);
return true;
}
bool CNCCTrie::updateHash(const std::string& name, uint256& hash, CNCCTrieNode** pNodeRet)
bool CNCCTrie::updateHash(const std::string& name, uint256& hash)
{
CNCCTrieNode* current = &root;
for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname)
@ -373,45 +372,39 @@ bool CNCCTrie::updateHash(const std::string& name, uint256& hash, CNCCTrieNode**
}
assert(current != NULL);
current->hash = hash;
*pNodeRet = current;
markNodeDirty(name, current);
return true;
}
void CNCCTrie::BatchWriteNode(CLevelDBBatch& batch, const std::string& name, const CNCCTrieNode* pNode) const
{
LogPrintf("%s: Writing %s to disk with %d values\n", __func__, name, pNode->values.size());
batch.Write(std::make_pair('n', name), *pNode);
}
void CNCCTrie::BatchEraseNode(CLevelDBBatch& batch, const std::string& name) const
{
batch.Erase(std::make_pair('n', name));
if (pNode)
batch.Write(std::make_pair('n', name), *pNode);
else
batch.Erase(std::make_pair('n', name));
}
void CNCCTrie::BatchWriteQueueRow(CLevelDBBatch& batch, int nRowNum)
{
valueQueueType::iterator itQueueRow = getQueueRow(nRowNum);
batch.Write(std::make_pair('r', nRowNum), itQueueRow->second);
valueQueueType::iterator itQueueRow = getQueueRow(nRowNum, false);
if (itQueueRow != valueQueue.end())
batch.Write(std::make_pair('r', nRowNum), itQueueRow->second);
else
batch.Erase(std::make_pair('r', nRowNum));
}
void CNCCTrie::BatchEraseQueueRow(CLevelDBBatch& batch, int nRowNum)
{
batch.Erase(std::make_pair('r', nRowNum));
}
bool CNCCTrie::BatchWrite(nodeCacheType& changedNodes, std::vector<std::string>& deletedNames, const uint256& hashBlockIn, std::vector<int> vChangedQueueRows, std::vector<int> vDeletedQueueRows, int nNewHeight)
bool CNCCTrie::WriteToDisk()
{
CLevelDBBatch batch;
for (nodeCacheType::iterator itcache = changedNodes.begin(); itcache != changedNodes.end(); ++itcache)
for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache)
BatchWriteNode(batch, itcache->first, itcache->second);
for (std::vector<std::string>::iterator itname = deletedNames.begin(); itname != deletedNames.end(); ++itname)
BatchEraseNode(batch, *itname);
for (std::vector<int>::iterator itRowNum = vChangedQueueRows.begin(); itRowNum != vChangedQueueRows.end(); ++itRowNum)
dirtyNodes.clear();
for (std::vector<int>::iterator itRowNum = vDirtyQueueRows.begin(); itRowNum != vDirtyQueueRows.end(); ++itRowNum)
BatchWriteQueueRow(batch, *itRowNum);
for (std::vector<int>::iterator itRowNum = vDeletedQueueRows.begin(); itRowNum != vDeletedQueueRows.end(); ++itRowNum)
BatchEraseQueueRow(batch, *itRowNum);
batch.Write('h', hashBlockIn);
batch.Write('t', nNewHeight);
vDirtyQueueRows.clear();
batch.Write('h', hashBlock);
batch.Write('t', nCurrentHeight);
return db.WriteBatch(batch);
}
@ -468,7 +461,7 @@ bool CNCCTrie::ReadFromDisk(bool check)
int nHeight;
ssKey >> nHeight;
CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
valueQueueType::iterator itQueueRow = getQueueRow(nHeight);
valueQueueType::iterator itQueueRow = getQueueRow(nHeight, true);
ssValue >> itQueueRow->second;
}
pcursor->Next();

View file

@ -26,7 +26,6 @@ public:
int nHeight;
int nValidAtHeight;
CNodeValue() {};
//CNodeValue(uint256 txhash, uint32_t nOut) : txhash(txhash), nOut(nOut), nAmount(0), nHeight(0), nValidAtHeight(0) {}
CNodeValue(uint256 txhash, uint32_t nOut, CAmount nAmount, int nHeight, int nValidAtHeight) : txhash(txhash), nOut(nOut), nAmount(nAmount), nHeight(nHeight), nValidAtHeight(nValidAtHeight) {}
std::string ToString();
@ -149,11 +148,12 @@ class CNCCTrieCache;
class CNCCTrie
{
public:
CNCCTrie() : db(GetDataDir() / "ncctrie", 100, false, false), nCurrentHeight(1), root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) {}
CNCCTrie(bool fMemory = false, bool fWipe = false) : db(GetDataDir() / "ncctrie", 100, fMemory, fWipe), nCurrentHeight(1), root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) {}
uint256 getMerkleHash();
CLevelDBWrapper db;
bool empty() const;
bool checkConsistency();
bool WriteToDisk();
bool ReadFromDisk(bool check = false);
json_spirit::Array dumpToJSON() const;
bool getInfoForName(const std::string& name, CNodeValue& val) const;
@ -163,17 +163,20 @@ public:
friend class CNCCTrieCache;
private:
bool update(nodeCacheType& cache, hashMapType& hashes, const uint256& hashBlock, valueQueueType& queueCache, int nNewHeight);
bool updateName(const std::string& name, CNCCTrieNode* updatedNode, std::vector<std::string>& deletedNames, CNCCTrieNode** pNodeRet);
bool updateHash(const std::string& name, uint256& hash, CNCCTrieNode** pNodeRet);
bool recursiveNullify(CNCCTrieNode* node, std::string& name, std::vector<std::string>& deletedNames);
bool updateName(const std::string& name, CNCCTrieNode* updatedNode);
bool updateHash(const std::string& name, uint256& hash);
bool recursiveNullify(CNCCTrieNode* node, std::string& name);
bool recursiveCheckConsistency(CNCCTrieNode* node);
bool BatchWrite(nodeCacheType& changedNodes, std::vector<std::string>& deletedNames, const uint256& hashBlock, std::vector<int> vChangedQueueRows, std::vector<int> vDeletedQueueRows, int nNewHeight);
bool InsertFromDisk(const std::string& name, CNCCTrieNode* node);
bool recursiveDumpToJSON(const std::string& name, const CNCCTrieNode* current, json_spirit::Array& ret) const;
CNCCTrieNode root;
uint256 hashBlock;
valueQueueType valueQueue;
valueQueueType::iterator getQueueRow(int nHeight);
valueQueueType::iterator getQueueRow(int nHeight, bool deleteIfNotExists);
nodeCacheType dirtyNodes;
std::vector<int> vDirtyQueueRows;
void markNodeDirty(const std::string& name, CNCCTrieNode* node);
void deleteQueueRow(int nHeight);
void BatchWriteNode(CLevelDBBatch& batch, const std::string& name, const CNCCTrieNode* pNode) const;
void BatchEraseNode(CLevelDBBatch& batch, const std::string& nome) const;

View file

@ -42,7 +42,7 @@ struct TestingSetup {
pblocktree = new CBlockTreeDB(1 << 20, true);
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
pnccTrie = new CNCCTrie();
pnccTrie = new CNCCTrie(true);
InitBlockIndex();
#ifdef ENABLE_WALLET
bool fFirstRun;