hacktober fest #214
4 changed files with 138 additions and 160 deletions
|
@ -1273,18 +1273,18 @@ bool CNCCTrieCache::flush()
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::string, CNCCTrieProofLeafNode> CNCCTrieCache::getLeafNodeForProof(const std::string& currentPosition, unsigned char nodeChar, const CNCCTrieNode* currentNode) const
|
uint256 CNCCTrieCache::getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, const CNCCTrieNode* currentNode) const
|
||||||
{
|
{
|
||||||
std::stringstream leafPosition;
|
std::stringstream leafPosition;
|
||||||
leafPosition << currentPosition << nodeChar;
|
leafPosition << currentPosition << nodeChar;
|
||||||
hashMapType::iterator cachedHash = cacheHashes.find(leafPosition.str());
|
hashMapType::iterator cachedHash = cacheHashes.find(leafPosition.str());
|
||||||
if (cachedHash != cacheHashes.end())
|
if (cachedHash != cacheHashes.end())
|
||||||
{
|
{
|
||||||
return std::make_pair(leafPosition.str(), CNCCTrieProofLeafNode(cachedHash->second));
|
return cachedHash->second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return std::make_pair(leafPosition.str(), CNCCTrieProofLeafNode(currentNode->hash));
|
return currentNode->hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,75 +1292,52 @@ CNCCTrieProof CNCCTrieCache::getProofForName(const std::string& name) const
|
||||||
{
|
{
|
||||||
if (dirty())
|
if (dirty())
|
||||||
getMerkleHash();
|
getMerkleHash();
|
||||||
std::map<std::string, CNCCTrieProofNode> nodes;
|
std::vector<CNCCTrieProofNode> nodes;
|
||||||
std::map<std::string, CNCCTrieProofLeafNode> leafNodes;
|
|
||||||
CNCCTrieNode* current = &(base->root);
|
CNCCTrieNode* current = &(base->root);
|
||||||
nodeCacheType::const_iterator cachedNode;
|
nodeCacheType::const_iterator cachedNode;
|
||||||
CNodeValue nameVal;
|
bool fNameHasValue = false;
|
||||||
bool fNameHasValue;
|
|
||||||
uint256 txhash;
|
uint256 txhash;
|
||||||
uint32_t nOut;
|
uint32_t nOut = 0;
|
||||||
for (std::string::const_iterator itName = name.begin(); itName != name.end(); ++itName)
|
for (std::string::const_iterator itName = name.begin(); current; ++itName)
|
||||||
{
|
{
|
||||||
std::string currentPosition(name.begin(), itName);
|
std::string currentPosition(name.begin(), itName);
|
||||||
cachedNode = cache.find(currentPosition);
|
cachedNode = cache.find(currentPosition);
|
||||||
if (cachedNode != cache.end())
|
if (cachedNode != cache.end())
|
||||||
current = cachedNode->second;
|
current = cachedNode->second;
|
||||||
hashMapType::const_iterator cachedHash = cacheHashes.find(currentPosition);
|
|
||||||
CNodeValue val;
|
CNodeValue val;
|
||||||
bool fNodeHasValue = current->getBestValue(val);
|
bool fNodeHasValue = current->getBestValue(val);
|
||||||
uint256 valHash;
|
uint256 valHash;
|
||||||
if (fNodeHasValue)
|
if (fNodeHasValue)
|
||||||
valHash = val.GetHash();
|
valHash = val.GetHash();
|
||||||
std::vector<unsigned char> child_chars;
|
std::vector<std::pair<unsigned char, uint256> > children;
|
||||||
CNCCTrieNode* nextCurrent = NULL;
|
CNCCTrieNode* nextCurrent = NULL;
|
||||||
for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren)
|
for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren)
|
||||||
{
|
{
|
||||||
child_chars.push_back(itChildren->first);
|
if (itName == name.end() || itChildren->first != *itName) // Leaf node
|
||||||
if (itChildren->first != *itName) // Leaf node
|
|
||||||
{
|
{
|
||||||
std::pair<std::string, CNCCTrieProofLeafNode> leaf = getLeafNodeForProof(currentPosition, itChildren->first, itChildren->second);
|
uint256 childHash = getLeafHashForProof(currentPosition, itChildren->first, itChildren->second);
|
||||||
leafNodes[leaf.first] = leaf.second;
|
children.push_back(std::make_pair(itChildren->first, childHash));
|
||||||
}
|
}
|
||||||
else // Full node
|
else // Full node
|
||||||
{
|
{
|
||||||
nextCurrent = itChildren->second;
|
nextCurrent = itChildren->second;
|
||||||
|
uint256 childHash;
|
||||||
|
children.push_back(std::make_pair(itChildren->first, childHash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodes[currentPosition] = CNCCTrieProofNode(child_chars, fNodeHasValue, valHash);
|
if (currentPosition == name)
|
||||||
current = nextCurrent;
|
|
||||||
if (current == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (current != NULL)
|
|
||||||
{
|
{
|
||||||
cachedNode = cache.find(name);
|
fNameHasValue = fNodeHasValue;
|
||||||
if (cachedNode != cache.end())
|
|
||||||
current = cachedNode->second;
|
|
||||||
hashMapType::const_iterator cachedHash = cacheHashes.find(name);
|
|
||||||
fNameHasValue = current->getBestValue(nameVal);
|
|
||||||
uint256 valHash;
|
|
||||||
if (fNameHasValue)
|
if (fNameHasValue)
|
||||||
{
|
{
|
||||||
txhash = nameVal.txhash;
|
txhash = val.txhash;
|
||||||
nOut = nameVal.nOut;
|
nOut = val.nOut;
|
||||||
valHash = nameVal.GetHash();
|
|
||||||
}
|
}
|
||||||
else
|
valHash.SetNull();
|
||||||
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);
|
CNCCTrieProofNode node(children, fNodeHasValue, valHash);
|
||||||
|
nodes.push_back(node);
|
||||||
|
current = nextCurrent;
|
||||||
}
|
}
|
||||||
else
|
return CNCCTrieProof(nodes, fNameHasValue, txhash, nOut);
|
||||||
{
|
|
||||||
fNameHasValue = false;
|
|
||||||
nOut = 0;
|
|
||||||
}
|
|
||||||
return CNCCTrieProof(nodes, leafNodes, fNameHasValue, txhash, nOut);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,27 +205,18 @@ class CNCCTrieProofNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CNCCTrieProofNode() {};
|
CNCCTrieProofNode() {};
|
||||||
CNCCTrieProofNode(std::vector<unsigned char> children, bool hasValue, uint256 valHash) : children(children), hasValue(hasValue), valHash(valHash) {};
|
CNCCTrieProofNode(std::vector<std::pair<unsigned char, uint256> > children, bool hasValue, uint256 valHash) : children(children), hasValue(hasValue), valHash(valHash) {};
|
||||||
std::vector<unsigned char> children;
|
std::vector<std::pair<unsigned char, uint256> > children;
|
||||||
bool hasValue;
|
bool hasValue;
|
||||||
uint256 valHash;
|
uint256 valHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CNCCTrieProofLeafNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CNCCTrieProofLeafNode() {};
|
|
||||||
CNCCTrieProofLeafNode(uint256 nodeHash) : nodeHash(nodeHash) {};
|
|
||||||
uint256 nodeHash;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CNCCTrieProof
|
class CNCCTrieProof
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CNCCTrieProof() {};
|
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) {}
|
CNCCTrieProof(std::vector<CNCCTrieProofNode> nodes, bool hasValue, uint256 txhash, uint32_t nOut) : nodes(nodes), hasValue(hasValue), txhash(txhash), nOut(nOut) {}
|
||||||
std::map<std::string, CNCCTrieProofNode> nodes;
|
std::vector<CNCCTrieProofNode> nodes;
|
||||||
std::map<std::string, CNCCTrieProofLeafNode> leafNodes;
|
|
||||||
bool hasValue;
|
bool hasValue;
|
||||||
uint256 txhash;
|
uint256 txhash;
|
||||||
uint32_t nOut;
|
uint32_t nOut;
|
||||||
|
@ -272,7 +263,7 @@ 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;
|
||||||
std::pair<std::string, CNCCTrieProofLeafNode> getLeafNodeForProof(const std::string& currentPosition, unsigned char nodeChar, const CNCCTrieNode* currentNode) const;
|
uint256 getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, const CNCCTrieNode* currentNode) const;
|
||||||
uint256 hashBlock;
|
uint256 hashBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -274,32 +274,28 @@ UniValue proofToJSON(const CNCCTrieProof& proof)
|
||||||
{
|
{
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
UniValue nodes(UniValue::VARR);
|
UniValue nodes(UniValue::VARR);
|
||||||
for (std::map<std::string, CNCCTrieProofNode>::const_iterator itNode = proof.nodes.begin(); itNode != proof.nodes.end(); ++itNode)
|
for (std::vector<CNCCTrieProofNode>::const_iterator itNode = proof.nodes.begin(); itNode != proof.nodes.end(); ++itNode)
|
||||||
{
|
{
|
||||||
UniValue node(UniValue::VOBJ);
|
UniValue node(UniValue::VOBJ);
|
||||||
node.push_back(Pair("name", itNode->first));
|
|
||||||
UniValue children(UniValue::VARR);
|
UniValue children(UniValue::VARR);
|
||||||
for (std::vector<unsigned char>::const_iterator itChildren = itNode->second.children.begin(); itChildren != itNode->second.children.end(); ++itChildren)
|
for (std::vector<std::pair<unsigned char, uint256> >::const_iterator itChildren = itNode->children.begin(); itChildren != itNode->children.end(); ++itChildren)
|
||||||
{
|
{
|
||||||
children.push_back(*itChildren);
|
UniValue child(UniValue::VOBJ);
|
||||||
|
child.push_back(Pair("character", itChildren->first));
|
||||||
|
if (!itChildren->second.IsNull())
|
||||||
|
{
|
||||||
|
child.push_back(Pair("nodeHash", itChildren->second.GetHex()));
|
||||||
|
}
|
||||||
|
children.push_back(child);
|
||||||
}
|
}
|
||||||
node.push_back(Pair("children", children));
|
node.push_back(Pair("children", children));
|
||||||
if (itNode->second.hasValue)
|
if (itNode->hasValue && !itNode->valHash.IsNull())
|
||||||
{
|
{
|
||||||
node.push_back(Pair("valueHash", itNode->second.valHash.GetHex()));
|
node.push_back(Pair("valueHash", itNode->valHash.GetHex()));
|
||||||
}
|
}
|
||||||
nodes.push_back(node);
|
nodes.push_back(node);
|
||||||
}
|
}
|
||||||
result.push_back(Pair("nodes", nodes));
|
result.push_back(Pair("nodes", nodes));
|
||||||
UniValue leafNodes(UniValue::VARR);
|
|
||||||
for (std::map<std::string, CNCCTrieProofLeafNode>::const_iterator itLeafNode = proof.leafNodes.begin(); itLeafNode != proof.leafNodes.end(); ++itLeafNode)
|
|
||||||
{
|
|
||||||
UniValue leafNode(UniValue::VOBJ);
|
|
||||||
leafNode.push_back(Pair("name", itLeafNode->first));
|
|
||||||
leafNode.push_back(Pair("nodeHash", itLeafNode->second.nodeHash.GetHex()));
|
|
||||||
leafNodes.push_back(leafNode);
|
|
||||||
}
|
|
||||||
result.push_back(Pair("leafNodes", leafNodes));
|
|
||||||
if (proof.hasValue)
|
if (proof.hasValue)
|
||||||
{
|
{
|
||||||
result.push_back(Pair("txhash", proof.txhash.GetHex()));
|
result.push_back(Pair("txhash", proof.txhash.GetHex()));
|
||||||
|
@ -328,25 +324,28 @@ UniValue getnameproof(const UniValue& params, bool fHelp)
|
||||||
" \"nodes\" : [ (array of object) full nodes (i.e.\n"
|
" \"nodes\" : [ (array of object) full nodes (i.e.\n"
|
||||||
" those which lead to\n"
|
" those which lead to\n"
|
||||||
" the requested name)\n"
|
" the requested name)\n"
|
||||||
" \"name\" : \"node name\" (string) The name of the node\n"
|
" \"children\" : [ (array of object) the children of\n"
|
||||||
" \"children\" : [ (array of numeric) the characters\n"
|
|
||||||
" corresponding to\n"
|
|
||||||
" the children of\n"
|
|
||||||
" this node\n"
|
" this node\n"
|
||||||
" \"child\" (numeric) a 0-255 number referring to\n"
|
" \"child\" : { (object) a child node, either leaf or\n"
|
||||||
" a child node of this node\n"
|
" reference to a full node\n"
|
||||||
|
" \"character\" : \"char\" (string) the character which\n"
|
||||||
|
" leads from the parent\n"
|
||||||
|
" to this child node\n"
|
||||||
|
" \"nodeHash\" : \"hash\" (string, if exists) the hash of\n"
|
||||||
|
" the node if\n"
|
||||||
|
" this is a \n"
|
||||||
|
" leaf node\n"
|
||||||
|
" }\n"
|
||||||
" ]\n"
|
" ]\n"
|
||||||
" \"valueHash\" (string, if exists) the hash of this\n"
|
" \"valueHash\" (string, if exists) the hash of this\n"
|
||||||
" node's value, if\n"
|
" node's value, if\n"
|
||||||
" it has one\n"
|
" it has one. If \n"
|
||||||
" ]\n"
|
" this is the\n"
|
||||||
" \"leaf_nodes\" : [ (array of object) leaf nodes (i.e.\n"
|
" requested name\n"
|
||||||
" those which do not\n"
|
" this will not\n"
|
||||||
" lead to the requested\n"
|
" exist whether\n"
|
||||||
" name but nonetheless\n"
|
" the node has a\n"
|
||||||
" contribute to the proof\n"
|
" value or not\n"
|
||||||
" \"name\" : \"node name\" (string) the name of the node\n"
|
|
||||||
" \"nodeHash\" : \"hash\" (string) the hash of the node\n"
|
|
||||||
" ]\n"
|
" ]\n"
|
||||||
" \"txhash\" : \"hash\" (string, if exists) the txid of the\n"
|
" \"txhash\" : \"hash\" (string, if exists) the txid of the\n"
|
||||||
" claim which controls\n"
|
" claim which controls\n"
|
||||||
|
@ -378,7 +377,7 @@ UniValue getnameproof(const UniValue& params, bool fHelp)
|
||||||
if (!chainActive.Contains(pblockIndex))
|
if (!chainActive.Contains(pblockIndex))
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not in main chain");
|
||||||
|
|
||||||
if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + 10))
|
if (chainActive.Tip()->nHeight > (pblockIndex->nHeight + 20))
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to generate proof");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block too deep to generate proof");
|
||||||
|
|
||||||
CNCCTrieProof proof;
|
CNCCTrieProof proof;
|
||||||
|
|
|
@ -1418,84 +1418,95 @@ BOOST_AUTO_TEST_CASE(ncctrienode_serialize_unserialize)
|
||||||
BOOST_CHECK(n1 == n2);
|
BOOST_CHECK(n1 == n2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_node_hash(const std::string& name, const std::string& currentPosition, const std::string::const_iterator itName, CNCCTrieProof& proof, uint256& nodeHash)
|
bool verify_proof(const CNCCTrieProof proof, uint256 rootHash, const std::string& name)
|
||||||
{
|
{
|
||||||
std::map<std::string, CNCCTrieProofNode>::const_iterator itNode = proof.nodes.find(currentPosition);
|
uint256 previousComputedHash;
|
||||||
if (itNode == proof.nodes.end())
|
std::string computedReverseName;
|
||||||
|
bool verifiedValue = false;
|
||||||
|
|
||||||
|
for (std::vector<CNCCTrieProofNode>::const_reverse_iterator itNodes = proof.nodes.rbegin(); itNodes != proof.nodes.rend(); ++itNodes)
|
||||||
{
|
{
|
||||||
return false;
|
bool foundChildInChain = false;
|
||||||
}
|
|
||||||
if (name == currentPosition && itName != name.end())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::vector<unsigned char> vchToHash;
|
std::vector<unsigned char> vchToHash;
|
||||||
bool haveNextNode = false;
|
for (std::vector<std::pair<unsigned char, uint256> >::const_iterator itChildren = itNodes->children.begin(); itChildren != itNodes->children.end(); ++itChildren)
|
||||||
for (std::vector<unsigned char>::const_iterator itChildren = itNode->second.children.begin(); itChildren != itNode->second.children.end(); ++itChildren)
|
|
||||||
{
|
{
|
||||||
vchToHash.push_back(*itChildren);
|
vchToHash.push_back(itChildren->first);
|
||||||
std::stringstream nextPosition;
|
uint256 childHash;
|
||||||
nextPosition << currentPosition << *itChildren;
|
if (itChildren->second.IsNull())
|
||||||
if (name != currentPosition && *itChildren == *itName)
|
|
||||||
{
|
{
|
||||||
uint256 childNodeHash;
|
if (previousComputedHash.IsNull())
|
||||||
if (!get_node_hash(name, nextPosition.str(), itName + 1, proof, childNodeHash))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
haveNextNode = true;
|
if (foundChildInChain)
|
||||||
vchToHash.insert(vchToHash.end(), childNodeHash.begin(), childNodeHash.end());
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foundChildInChain = true;
|
||||||
|
computedReverseName += itChildren->first;
|
||||||
|
childHash = previousComputedHash;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::map<std::string, CNCCTrieProofLeafNode>::const_iterator itChildNode = proof.leafNodes.find(nextPosition.str());
|
childHash = itChildren->second;
|
||||||
if (itChildNode == proof.leafNodes.end())
|
}
|
||||||
|
vchToHash.insert(vchToHash.end(), childHash.begin(), childHash.end());
|
||||||
|
}
|
||||||
|
if (itNodes != proof.nodes.rbegin() && !foundChildInChain)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
vchToHash.insert(vchToHash.end(), itChildNode->second.nodeHash.begin(), itChildNode->second.nodeHash.end());
|
if (itNodes->hasValue)
|
||||||
}
|
|
||||||
}
|
|
||||||
if (name != currentPosition)
|
|
||||||
{
|
{
|
||||||
if (!haveNextNode && proof.hasValue)
|
uint256 valHash;
|
||||||
|
if (itNodes->valHash.IsNull())
|
||||||
|
{
|
||||||
|
if (itNodes != proof.nodes.rbegin())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (itNode->second.hasValue)
|
if (!proof.hasValue)
|
||||||
{
|
{
|
||||||
vchToHash.insert(vchToHash.end(), itNode->second.valHash.begin(), itNode->second.valHash.end());
|
return false;
|
||||||
}
|
}
|
||||||
|
valHash = getOutPointHash(proof.txhash, proof.nOut);
|
||||||
|
verifiedValue = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (proof.hasValue != itNode->second.hasValue)
|
valHash = itNodes->valHash;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (proof.hasValue)
|
|
||||||
{
|
|
||||||
uint256 valHash = getOutPointHash(proof.txhash, proof.nOut);
|
|
||||||
if (valHash != itNode->second.valHash)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
vchToHash.insert(vchToHash.end(), valHash.begin(), valHash.end());
|
vchToHash.insert(vchToHash.end(), valHash.begin(), valHash.end());
|
||||||
}
|
}
|
||||||
|
else if (proof.hasValue && itNodes == proof.nodes.rbegin())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
CHash256 hasher;
|
CHash256 hasher;
|
||||||
std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE);
|
std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE);
|
||||||
hasher.Write(vchToHash.data(), vchToHash.size());
|
hasher.Write(vchToHash.data(), vchToHash.size());
|
||||||
hasher.Finalize(&(vchHash[0]));
|
hasher.Finalize(&(vchHash[0]));
|
||||||
uint256 calculatedHash(vchHash);
|
uint256 calculatedHash(vchHash);
|
||||||
nodeHash = calculatedHash;
|
previousComputedHash = calculatedHash;
|
||||||
return true;
|
}
|
||||||
}
|
if (previousComputedHash != rootHash)
|
||||||
|
{
|
||||||
bool verify_proof(CNCCTrieProof proof, uint256 rootHash, const std::string& name)
|
return false;
|
||||||
{
|
}
|
||||||
uint256 computedRootHash;
|
if (proof.hasValue && !verifiedValue)
|
||||||
return get_node_hash(name, "", name.begin(), proof, computedRootHash) && rootHash == computedRootHash;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string::reverse_iterator itComputedName = computedReverseName.rbegin();
|
||||||
|
std::string::const_iterator itName = name.begin();
|
||||||
|
for (; itName != name.end() && itComputedName != computedReverseName.rend(); ++itName, ++itComputedName)
|
||||||
|
{
|
||||||
|
if (*itName != *itComputedName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (!proof.hasValue || itName == name.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(ncctrievalue_proof)
|
BOOST_AUTO_TEST_CASE(ncctrievalue_proof)
|
||||||
|
|
Loading…
Reference in a new issue