Serialize effective amount #231
3 changed files with 416 additions and 1 deletions
109
src/ncctrie.cpp
109
src/ncctrie.cpp
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
uint256 CNodeValue::GetHash() const
|
||||
uint256 getOutPointHash(uint256 txhash, uint32_t nOut)
|
||||
{
|
||||
CHash256 valTxHasher;
|
||||
valTxHasher.Write(txhash.begin(), txhash.size());
|
||||
|
@ -28,6 +28,11 @@ uint256 CNodeValue::GetHash() const
|
|||
return valHash;
|
||||
}
|
||||
|
||||
uint256 CNodeValue::GetHash() const
|
||||
{
|
||||
return getOutPointHash(txhash, nOut);
|
||||
}
|
||||
|
||||
bool CNCCTrieNode::insertValue(CNodeValue val, bool * pfChanged)
|
||||
{
|
||||
LogPrintf("%s: Inserting %s:%d (amount: %d) into the ncc trie\n", __func__, val.txhash.ToString(), val.nOut, val.nAmount);
|
||||
|
@ -1267,3 +1272,105 @@ bool CNCCTrieCache::flush()
|
|||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
std::pair<std::string, CNCCTrieProofLeafNode> CNCCTrieCache::getLeafNodeForProof(const std::string& currentPosition, unsigned char nodeChar, const CNCCTrieNode* currentNode) const
|
||||
{
|
||||
std::stringstream leafPosition;
|
||||
leafPosition << currentPosition << nodeChar;
|
||||
hashMapType::iterator cachedHash = cacheHashes.find(leafPosition.str());
|
||||
if (cachedHash != cacheHashes.end())
|
||||
{
|
||||
return std::make_pair(leafPosition.str(), CNCCTrieProofLeafNode(cachedHash->second));
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_pair(leafPosition.str(), CNCCTrieProofLeafNode(currentNode->hash));
|
||||
}
|
||||
}
|
||||
|
||||
CNCCTrieProof CNCCTrieCache::getProofForName(const std::string& name) const
|
||||
{
|
||||
if (dirty())
|
||||
getMerkleHash();
|
||||
std::map<std::string, CNCCTrieProofNode> nodes;
|
||||
std::map<std::string, CNCCTrieProofLeafNode> leafNodes;
|
||||
CNCCTrieNode* current = &(base->root);
|
||||
nodeCacheType::const_iterator cachedNode;
|
||||
CNodeValue nameVal;
|
||||
bool fNameHasValue;
|
||||
uint256 txhash;
|
||||
uint32_t nOut;
|
||||
for (std::string::const_iterator itName = name.begin(); itName != name.end(); ++itName)
|
||||
{
|
||||
std::string currentPosition(name.begin(), itName);
|
||||
cachedNode = cache.find(currentPosition);
|
||||
if (cachedNode != cache.end())
|
||||
current = cachedNode->second;
|
||||
hashMapType::const_iterator cachedHash = cacheHashes.find(currentPosition);
|
||||
uint256 nodeHash;
|
||||
if (cachedHash != cacheHashes.end())
|
||||
nodeHash = cachedHash->second;
|
||||
else
|
||||
nodeHash = current->hash;
|
||||
CNodeValue val;
|
||||
bool fNodeHasValue = current->getBestValue(val);
|
||||
uint256 valHash;
|
||||
if (fNodeHasValue)
|
||||
valHash = val.GetHash();
|
||||
std::vector<unsigned char> child_chars;
|
||||
CNCCTrieNode* nextCurrent = NULL;
|
||||
for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren)
|
||||
{
|
||||
child_chars.push_back(itChildren->first);
|
||||
if (itChildren->first != *itName) // Leaf node
|
||||
{
|
||||
std::pair<std::string, CNCCTrieProofLeafNode> leaf = getLeafNodeForProof(currentPosition, itChildren->first, itChildren->second);
|
||||
leafNodes[leaf.first] = leaf.second;
|
||||
}
|
||||
else // Full node
|
||||
{
|
||||
nextCurrent = itChildren->second;
|
||||
}
|
||||
}
|
||||
nodes[currentPosition] = CNCCTrieProofNode(child_chars, fNodeHasValue, valHash, nodeHash);
|
||||
current = nextCurrent;
|
||||
if (current == NULL)
|
||||
break;
|
||||
}
|
||||
if (current != NULL)
|
||||
{
|
||||
cachedNode = cache.find(name);
|
||||
if (cachedNode != cache.end())
|
||||
current = cachedNode->second;
|
||||
hashMapType::const_iterator cachedHash = cacheHashes.find(name);
|
||||
uint256 nodeHash;
|
||||
if (cachedHash != cacheHashes.end())
|
||||
nodeHash = cachedHash->second;
|
||||
else
|
||||
nodeHash = current->hash;
|
||||
fNameHasValue = current->getBestValue(nameVal);
|
||||
uint256 valHash;
|
||||
if (fNameHasValue)
|
||||
{
|
||||
txhash = nameVal.txhash;
|
||||
nOut = nameVal.nOut;
|
||||
valHash = nameVal.GetHash();
|
||||
}
|
||||
else
|
||||
nOut = 0;
|
||||
std::vector<unsigned char> child_chars;
|
||||
for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren)
|
||||
{
|
||||
child_chars.push_back(itChildren->first);
|
||||
std::pair<std::string, CNCCTrieProofLeafNode> leaf = getLeafNodeForProof(name, itChildren->first, itChildren->second);
|
||||
leafNodes[leaf.first] = leaf.second;
|
||||
}
|
||||
nodes[name] = CNCCTrieProofNode(child_chars, fNameHasValue, valHash, nodeHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
fNameHasValue = false;
|
||||
nOut = 0;
|
||||
}
|
||||
return CNCCTrieProof(nodes, leafNodes, fNameHasValue, txhash, nOut);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#define DEFAULT_DELAY 100
|
||||
|
||||
uint256 getOutPointHash(uint256 txhash, uint32_t nOut);
|
||||
|
||||
class CNodeValue
|
||||
{
|
||||
public:
|
||||
|
@ -199,6 +201,37 @@ private:
|
|||
void BatchWriteExpirationQueueRows(CLevelDBBatch& batch);
|
||||
};
|
||||
|
||||
class CNCCTrieProofNode
|
||||
{
|
||||
public:
|
||||
CNCCTrieProofNode() {};
|
||||
CNCCTrieProofNode(std::vector<unsigned char> children, bool hasValue, uint256 valHash, uint256 nodeHash) : children(children), hasValue(hasValue), valHash(valHash), nodeHash(nodeHash) {};
|
||||
std::vector<unsigned char> children;
|
||||
bool hasValue;
|
||||
uint256 valHash;
|
||||
uint256 nodeHash;
|
||||
};
|
||||
|
||||
class CNCCTrieProofLeafNode
|
||||
{
|
||||
public:
|
||||
CNCCTrieProofLeafNode() {};
|
||||
CNCCTrieProofLeafNode(uint256 nodeHash) : nodeHash(nodeHash) {};
|
||||
uint256 nodeHash;
|
||||
};
|
||||
|
||||
class CNCCTrieProof
|
||||
{
|
||||
public:
|
||||
CNCCTrieProof() {};
|
||||
CNCCTrieProof(std::map<std::string, CNCCTrieProofNode> nodes, std::map<std::string, CNCCTrieProofLeafNode> leafNodes, bool hasValue, uint256 txhash, uint32_t nOut) : nodes(nodes), leafNodes(leafNodes), hasValue(hasValue), txhash(txhash), nOut(nOut) {}
|
||||
std::map<std::string, CNCCTrieProofNode> nodes;
|
||||
std::map<std::string, CNCCTrieProofLeafNode> leafNodes;
|
||||
bool hasValue;
|
||||
uint256 txhash;
|
||||
uint32_t nOut;
|
||||
};
|
||||
|
||||
class CNCCTrieCache
|
||||
{
|
||||
public:
|
||||
|
@ -219,6 +252,7 @@ public:
|
|||
~CNCCTrieCache() { clear(); }
|
||||
bool insertClaimIntoTrie(const std::string name, CNodeValue val) const;
|
||||
bool removeClaimFromTrie(const std::string name, uint256 txhash, uint32_t nOut, int& nValidAtHeight) const;
|
||||
CNCCTrieProof getProofForName(const std::string& name) const;
|
||||
private:
|
||||
CNCCTrie* base;
|
||||
mutable nodeCacheType cache;
|
||||
|
@ -239,6 +273,7 @@ private:
|
|||
void removeFromExpirationQueue(const std::string name, uint256 txhash, uint32_t nOut, int nHeight) const;
|
||||
valueQueueType::iterator getQueueCacheRow(int nHeight, bool createIfNotExists) const;
|
||||
valueQueueType::iterator getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const;
|
||||
std::pair<std::string, CNCCTrieProofLeafNode> getLeafNodeForProof(const std::string& currentPosition, unsigned char nodeChar, const CNCCTrieNode* currentNode) const;
|
||||
uint256 hashBlock;
|
||||
};
|
||||
|
||||
|
|
|
@ -163,6 +163,30 @@ const unsigned int expire_nonces[] = {
|
|||
120057, 8823, 5430, 44579, 61385, 84720, 64857, 70478, 116285, 8904,
|
||||
63423};
|
||||
|
||||
const unsigned int proof_nonces[] = {
|
||||
54804, 229797, 119107, 77644, 9782, 104842, 72332, 47116, 363729, 170598,
|
||||
434, 48775, 15164, 51638, 63813, 21028, 31896, 117216, 26019, 7458,
|
||||
101082, 48571, 84174, 56983, 4607, 176131, 60681, 11348, 42867, 152045,
|
||||
162526, 48222, 9115, 162702, 7084, 49303, 34393, 67035, 72372, 81712,
|
||||
58846, 123668, 37484, 69474, 77333, 104992, 71743, 9675, 12363, 39457,
|
||||
29256, 190978, 55083, 171352, 82498, 94184, 110307, 25965, 53432, 193885,
|
||||
3633, 74876, 15957, 252915, 119231, 32149, 84494, 139388, 141968, 9092,
|
||||
216682, 4336, 62779, 24742, 46920, 249663, 223300, 64403, 128849, 56433,
|
||||
30665, 174236, 77179, 18440, 217216, 45037, 35402, 135703, 15338, 126459,
|
||||
14097, 21840, 1175, 37591, 82927, 37893, 121151, 54253, 15384, 2192,
|
||||
12708, 74849, 39787, 15685, 37774, 13139, 34776, 159887, 6814, 3021,
|
||||
53901, 24286, 110415, 72451, 130820, 111543, 1300, 98281, 48336, 220704,
|
||||
51457, 91510, 148670, 41904, 16121, 41743, 63992, 27520, 15825, 108299,
|
||||
107508, 49504, 31499, 132824, 96172, 71483, 26828, 2545, 29227, 7846,
|
||||
114426, 221520, 9779, 594, 284222, 40381, 19645, 38653, 41721, 55469,
|
||||
16191, 7360, 42980, 36694, 13660, 72041, 1305, 83146, 92665, 15203,
|
||||
25428, 45068, 281892, 168851, 27104, 42352, 4321, 65234, 32459, 4261,
|
||||
101678, 29995, 34940, 34278, 169292, 24555, 20685, 44997, 42753, 21555,
|
||||
5974, 30, 59247, 17323, 10938, 78807, 17244, 68852, 17954, 26818,
|
||||
131893, 87813, 31242, 86553, 119319, 20972, 142663, 73972, 35525, 4782,
|
||||
20213, 13208, 35272, 229212, 203438,
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(ncctrie_tests, TestingSetup)
|
||||
|
||||
CMutableTransaction BuildTransaction(const uint256& prevhash)
|
||||
|
@ -1394,4 +1418,253 @@ BOOST_AUTO_TEST_CASE(ncctrienode_serialize_unserialize)
|
|||
BOOST_CHECK(n1 == n2);
|
||||
}
|
||||
|
||||
bool verify_proof(CNCCTrieProof proof, uint256 rootHash, const std::string& name)
|
||||
{
|
||||
for (std::string::const_iterator itName = name.begin(); itName != name.end(); ++itName)
|
||||
{
|
||||
std::string currentPosition(name.begin(), itName);
|
||||
std::map<std::string, CNCCTrieProofNode>::const_iterator itNode = proof.nodes.find(currentPosition);
|
||||
if (itNode == proof.nodes.end())
|
||||
{
|
||||
return currentPosition != "" && !proof.hasValue;
|
||||
}
|
||||
std::vector<unsigned char> vchToHash;
|
||||
for (std::vector<unsigned char>::const_iterator itChildren = itNode->second.children.begin(); itChildren != itNode->second.children.end(); ++itChildren)
|
||||
{
|
||||
vchToHash.push_back(*itChildren);
|
||||
std::stringstream nextPosition;
|
||||
nextPosition << currentPosition << *itChildren;
|
||||
if (*itChildren == *itName)
|
||||
{
|
||||
std::map<std::string, CNCCTrieProofNode>::const_iterator itChildNode = proof.nodes.find(nextPosition.str());
|
||||
if (itChildNode == proof.nodes.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vchToHash.insert(vchToHash.end(), itChildNode->second.nodeHash.begin(), itChildNode->second.nodeHash.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<std::string, CNCCTrieProofLeafNode>::const_iterator itChildNode = proof.leafNodes.find(nextPosition.str());
|
||||
if (itChildNode == proof.leafNodes.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vchToHash.insert(vchToHash.end(), itChildNode->second.nodeHash.begin(), itChildNode->second.nodeHash.end());
|
||||
}
|
||||
}
|
||||
if (itNode->second.hasValue)
|
||||
{
|
||||
vchToHash.insert(vchToHash.end(), itNode->second.valHash.begin(), itNode->second.valHash.end());
|
||||
}
|
||||
CHash256 hasher;
|
||||
std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE);
|
||||
hasher.Write(vchToHash.data(), vchToHash.size());
|
||||
hasher.Finalize(&(vchHash[0]));
|
||||
uint256 calculatedHash(vchHash);
|
||||
if (calculatedHash != itNode->second.nodeHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (currentPosition == "" && calculatedHash != rootHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
std::map<std::string, CNCCTrieProofNode>::const_iterator itNode = proof.nodes.find(name);
|
||||
if (itNode == proof.nodes.end())
|
||||
{
|
||||
return name != "" && !proof.hasValue;
|
||||
}
|
||||
std::vector<unsigned char> vchToHash;
|
||||
for (std::vector<unsigned char>::const_iterator itChildren = itNode->second.children.begin(); itChildren != itNode->second.children.end(); ++itChildren)
|
||||
{
|
||||
vchToHash.push_back(*itChildren);
|
||||
std::stringstream nextPosition;
|
||||
nextPosition << name << *itChildren;
|
||||
std::map<std::string, CNCCTrieProofLeafNode>::const_iterator itChildNode = proof.leafNodes.find(nextPosition.str());
|
||||
if (itChildNode == proof.leafNodes.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vchToHash.insert(vchToHash.end(), itChildNode->second.nodeHash.begin(), itChildNode->second.nodeHash.end());
|
||||
}
|
||||
if (itNode->second.hasValue != proof.hasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (itNode->second.hasValue)
|
||||
{
|
||||
uint256 valHash = getOutPointHash(proof.txhash, proof.nOut);
|
||||
if (valHash != itNode->second.valHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vchToHash.insert(vchToHash.end(), valHash.begin(), valHash.end());
|
||||
}
|
||||
CHash256 hasher;
|
||||
std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE);
|
||||
hasher.Write(vchToHash.data(), vchToHash.size());
|
||||
hasher.Finalize(&(vchHash[0]));
|
||||
uint256 calculatedHash(vchHash);
|
||||
if (calculatedHash != itNode->second.nodeHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (name == "" && calculatedHash != rootHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ncctrievalue_proof)
|
||||
{
|
||||
int block_counter = 0;
|
||||
bool find_nonces = false;
|
||||
BOOST_CHECK(pnccTrie->nCurrentHeight == chainActive.Height() + 1);
|
||||
|
||||
CBlockTemplate *pblocktemplate;
|
||||
LOCK(cs_main);
|
||||
|
||||
CScript scriptPubKey = CScript() << OP_TRUE;
|
||||
|
||||
std::string sName1("a");
|
||||
std::string sValue1("testa");
|
||||
|
||||
std::string sName2("abc");
|
||||
std::string sValue2("testabc");
|
||||
|
||||
std::string sName3("abd");
|
||||
std::string sValue3("testabd");
|
||||
|
||||
std::string sName4("zyx");
|
||||
std::string sValue4("testzyx");
|
||||
|
||||
std::string sName5("zyxa");
|
||||
std::string sName6("omg");
|
||||
std::string sName7("");
|
||||
|
||||
std::vector<unsigned char> vchName1(sName1.begin(), sName1.end());
|
||||
std::vector<unsigned char> vchValue1(sValue1.begin(), sValue1.end());
|
||||
|
||||
std::vector<unsigned char> vchName2(sName2.begin(), sName2.end());
|
||||
std::vector<unsigned char> vchValue2(sValue2.begin(), sValue2.end());
|
||||
|
||||
std::vector<unsigned char> vchName3(sName3.begin(), sName3.end());
|
||||
std::vector<unsigned char> vchValue3(sValue3.begin(), sValue3.end());
|
||||
|
||||
std::vector<unsigned char> vchName4(sName4.begin(), sName4.end());
|
||||
std::vector<unsigned char> vchValue4(sValue4.begin(), sValue4.end());
|
||||
|
||||
CNodeValue val;
|
||||
|
||||
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||
std::vector<CTransaction> coinbases;
|
||||
for (unsigned int i = 0; i < 104; ++i)
|
||||
{
|
||||
BOOST_CHECK(CreateBlock(pblocktemplate, find_nonces, proof_nonces[block_counter++]));
|
||||
if (coinbases.size() < 4)
|
||||
coinbases.push_back(CTransaction(pblocktemplate->block.vtx[0]));
|
||||
}
|
||||
|
||||
delete pblocktemplate;
|
||||
|
||||
CMutableTransaction tx1 = BuildTransaction(coinbases[0]);
|
||||
tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName1 << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
CMutableTransaction tx2 = BuildTransaction(coinbases[1]);
|
||||
tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName2 << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
CMutableTransaction tx3 = BuildTransaction(coinbases[2]);
|
||||
tx3.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName3 << vchValue3 << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
CMutableTransaction tx4 = BuildTransaction(coinbases[3]);
|
||||
tx4.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName4 << vchValue4 << OP_2DROP << OP_DROP << OP_TRUE;
|
||||
|
||||
std::vector<uint256> blocks_to_invalidate;
|
||||
|
||||
// create a claim. verify the expiration event has been scheduled.
|
||||
|
||||
AddToMempool(tx1);
|
||||
AddToMempool(tx2);
|
||||
AddToMempool(tx3);
|
||||
AddToMempool(tx4);
|
||||
|
||||
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||
BOOST_CHECK(pblocktemplate->block.vtx.size() == 5);
|
||||
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||
BOOST_CHECK(CreateBlock(pblocktemplate, find_nonces, proof_nonces[block_counter++]));
|
||||
blocks_to_invalidate.push_back(pblocktemplate->block.hashPrevBlock);
|
||||
delete pblocktemplate;
|
||||
|
||||
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||
for (unsigned int i = 1; i < 100; ++i)
|
||||
{
|
||||
BOOST_CHECK(CreateBlock(pblocktemplate, find_nonces, proof_nonces[block_counter++]));
|
||||
}
|
||||
delete pblocktemplate;
|
||||
|
||||
BOOST_CHECK(pnccTrie->empty());
|
||||
BOOST_CHECK(!pnccTrie->queueEmpty());
|
||||
|
||||
BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
|
||||
pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||
BOOST_CHECK(CreateBlock(pblocktemplate, find_nonces, proof_nonces[block_counter++]));
|
||||
delete pblocktemplate;
|
||||
|
||||
BOOST_CHECK(!pnccTrie->empty());
|
||||
BOOST_CHECK(pnccTrie->queueEmpty());
|
||||
BOOST_CHECK(pnccTrie->getInfoForName(sName1, val));
|
||||
BOOST_CHECK(val.txhash == tx1.GetHash());
|
||||
BOOST_CHECK(pnccTrie->getInfoForName(sName2, val));
|
||||
BOOST_CHECK(val.txhash == tx2.GetHash());
|
||||
BOOST_CHECK(pnccTrie->getInfoForName(sName3, val));
|
||||
BOOST_CHECK(val.txhash == tx3.GetHash());
|
||||
BOOST_CHECK(pnccTrie->getInfoForName(sName4, val));
|
||||
BOOST_CHECK(val.txhash == tx4.GetHash());
|
||||
|
||||
CNCCTrieCache cache(pnccTrie);
|
||||
|
||||
CNCCTrieProof proof;
|
||||
|
||||
proof = cache.getProofForName(sName1);
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashNCCTrie, sName1));
|
||||
BOOST_CHECK(proof.txhash == tx1.GetHash());
|
||||
BOOST_CHECK(proof.nOut == 0);
|
||||
|
||||
proof = cache.getProofForName(sName2);
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashNCCTrie, sName2));
|
||||
BOOST_CHECK(proof.txhash == tx2.GetHash());
|
||||
BOOST_CHECK(proof.nOut == 0);
|
||||
|
||||
proof = cache.getProofForName(sName3);
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashNCCTrie, sName3));
|
||||
BOOST_CHECK(proof.txhash == tx3.GetHash());
|
||||
BOOST_CHECK(proof.nOut == 0);
|
||||
|
||||
proof = cache.getProofForName(sName4);
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashNCCTrie, sName4));
|
||||
BOOST_CHECK(proof.txhash == tx4.GetHash());
|
||||
BOOST_CHECK(proof.nOut == 0);
|
||||
|
||||
proof = cache.getProofForName(sName5);
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashNCCTrie, sName5));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
proof = cache.getProofForName(sName6);
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashNCCTrie, sName6));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
proof = cache.getProofForName(sName7);
|
||||
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashNCCTrie, sName7));
|
||||
BOOST_CHECK(proof.hasValue == false);
|
||||
|
||||
BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back()));
|
||||
blocks_to_invalidate.pop_back();
|
||||
BOOST_CHECK(pnccTrie->empty());
|
||||
BOOST_CHECK(pnccTrie->queueEmpty());
|
||||
BOOST_CHECK(blocks_to_invalidate.empty());
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Reference in a new issue