mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
SHAMap fixups:
* Change state_ to Invalid if inner node types mismatch * flushDirty before unsharing to ensure modified nodes get written * Remove unnecessary code * Fix updateHash for V2 inner nodes * In descend, call isInconsistentNode only if node is found * getMissingNodes could request duplicates in some cases * An invalid node with the right hash is useful, it proves the map invalid
This commit is contained in:
@@ -84,7 +84,7 @@ private:
|
|||||||
std::uint32_t seq_;
|
std::uint32_t seq_;
|
||||||
std::uint32_t ledgerSeq_ = 0; // sequence number of ledger this is part of
|
std::uint32_t ledgerSeq_ = 0; // sequence number of ledger this is part of
|
||||||
std::shared_ptr<SHAMapAbstractNode> root_;
|
std::shared_ptr<SHAMapAbstractNode> root_;
|
||||||
SHAMapState state_;
|
mutable SHAMapState state_;
|
||||||
SHAMapType type_;
|
SHAMapType type_;
|
||||||
bool backed_ = true; // Map is backed by the database
|
bool backed_ = true; // Map is backed by the database
|
||||||
|
|
||||||
@@ -372,6 +372,7 @@ inline
|
|||||||
bool
|
bool
|
||||||
SHAMap::is_v2() const
|
SHAMap::is_v2() const
|
||||||
{
|
{
|
||||||
|
assert (root_);
|
||||||
return std::dynamic_pointer_cast<SHAMapInnerNodeV2>(root_) != nullptr;
|
return std::dynamic_pointer_cast<SHAMapInnerNodeV2>(root_) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ public:
|
|||||||
bool has_common_prefix(uint256 const& key) const;
|
bool has_common_prefix(uint256 const& key) const;
|
||||||
int get_common_prefix(uint256 const& key) const;
|
int get_common_prefix(uint256 const& key) const;
|
||||||
void set_common(int depth, uint256 const& key);
|
void set_common(int depth, uint256 const& key);
|
||||||
|
bool updateHash () override;
|
||||||
void addRaw(Serializer& s, SHANodeFormat format) const override;
|
void addRaw(Serializer& s, SHANodeFormat format) const override;
|
||||||
uint256 const& key() const override;
|
uint256 const& key() const override;
|
||||||
void setChildren(std::shared_ptr<SHAMapTreeNode> const& child1,
|
void setChildren(std::shared_ptr<SHAMapTreeNode> const& child1,
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ SHAMap::make_v2() const
|
|||||||
t = hotUNKNOWN;
|
t = hotUNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret->unshare();
|
|
||||||
ret->flushDirty(t, ret->seq_);
|
ret->flushDirty(t, ret->seq_);
|
||||||
|
ret->unshare();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +144,8 @@ SHAMap::make_v1() const
|
|||||||
t = hotUNKNOWN;
|
t = hotUNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret->unshare();
|
|
||||||
ret->flushDirty(t, ret->seq_);
|
ret->flushDirty(t, ret->seq_);
|
||||||
|
ret->unshare();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,12 +184,13 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const
|
|||||||
assert(stack == nullptr || stack->empty());
|
assert(stack == nullptr || stack->empty());
|
||||||
auto inNode = root_;
|
auto inNode = root_;
|
||||||
SHAMapNodeID nodeID;
|
SHAMapNodeID nodeID;
|
||||||
if (stack != nullptr)
|
|
||||||
stack->push({inNode, nodeID});
|
|
||||||
auto const isv2 = is_v2();
|
auto const isv2 = is_v2();
|
||||||
|
|
||||||
while (inNode->isInner())
|
while (inNode->isInner())
|
||||||
{
|
{
|
||||||
|
if (stack != nullptr)
|
||||||
|
stack->push({inNode, nodeID});
|
||||||
|
|
||||||
auto const inner = std::static_pointer_cast<SHAMapInnerNode>(std::move(inNode));
|
auto const inner = std::static_pointer_cast<SHAMapInnerNode>(std::move(inNode));
|
||||||
if (isv2)
|
if (isv2)
|
||||||
{
|
{
|
||||||
@@ -208,7 +209,10 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const
|
|||||||
{
|
{
|
||||||
auto n = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(inNode);
|
auto n = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(inNode);
|
||||||
if (n == nullptr)
|
if (n == nullptr)
|
||||||
|
{
|
||||||
|
assert (false);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
nodeID = SHAMapNodeID{n->depth(), n->common()};
|
nodeID = SHAMapNodeID{n->depth(), n->common()};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -220,9 +224,10 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const
|
|||||||
{
|
{
|
||||||
nodeID = nodeID.getChildNodeID (branch);
|
nodeID = nodeID.getChildNodeID (branch);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stack != nullptr)
|
if (stack != nullptr)
|
||||||
stack->push({inNode, nodeID});
|
stack->push({inNode, nodeID});
|
||||||
}
|
|
||||||
return static_cast<SHAMapTreeNode*>(inNode.get());
|
return static_cast<SHAMapTreeNode*>(inNode.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,26 +310,6 @@ SHAMap::checkFilter(SHAMapHash const& hash,
|
|||||||
{
|
{
|
||||||
node = SHAMapAbstractNode::make(
|
node = SHAMapAbstractNode::make(
|
||||||
nodeData, 0, snfPREFIX, hash, true, f_.journal ());
|
nodeData, 0, snfPREFIX, hash, true, f_.journal ());
|
||||||
if (node && node->isInner())
|
|
||||||
{
|
|
||||||
bool isv2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) != nullptr;
|
|
||||||
if (isv2 != is_v2())
|
|
||||||
{
|
|
||||||
auto root = std::dynamic_pointer_cast<SHAMapInnerNode>(root_);
|
|
||||||
assert(root);
|
|
||||||
assert(root->isEmpty());
|
|
||||||
if (isv2)
|
|
||||||
{
|
|
||||||
auto temp = make_v2();
|
|
||||||
swap(temp->root_, const_cast<std::shared_ptr<SHAMapAbstractNode>&>(root_));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto temp = make_v1();
|
|
||||||
swap(temp->root_, const_cast<std::shared_ptr<SHAMapAbstractNode>&>(root_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node)
|
if (node)
|
||||||
{
|
{
|
||||||
filter->gotNode (true, hash,
|
filter->gotNode (true, hash,
|
||||||
@@ -458,14 +443,15 @@ SHAMap::descend (SHAMapInnerNode * parent, SHAMapNodeID const& parentID,
|
|||||||
if (!child)
|
if (!child)
|
||||||
{
|
{
|
||||||
std::shared_ptr<SHAMapAbstractNode> childNode = fetchNodeNT (childHash, filter);
|
std::shared_ptr<SHAMapAbstractNode> childNode = fetchNodeNT (childHash, filter);
|
||||||
if (isInconsistentNode(childNode))
|
|
||||||
childNode = nullptr;
|
|
||||||
|
|
||||||
if (childNode)
|
if (childNode)
|
||||||
{
|
{
|
||||||
childNode = parent->canonicalizeChild (branch, std::move(childNode));
|
childNode = parent->canonicalizeChild (branch, std::move(childNode));
|
||||||
child = childNode.get ();
|
child = childNode.get ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (child && isInconsistentNode(childNode))
|
||||||
|
child = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child && is_v2())
|
if (child && is_v2())
|
||||||
@@ -512,21 +498,12 @@ SHAMap::descendAsync (SHAMapInnerNode* parent, int branch,
|
|||||||
|
|
||||||
ptr = SHAMapAbstractNode::make(obj->getData(), 0, snfPREFIX,
|
ptr = SHAMapAbstractNode::make(obj->getData(), 0, snfPREFIX,
|
||||||
hash, true, f_.journal());
|
hash, true, f_.journal());
|
||||||
|
|
||||||
if (ptr && ptr->isInner())
|
|
||||||
{
|
|
||||||
bool isv2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(ptr) != nullptr;
|
|
||||||
if (isv2 != is_v2())
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ptr && backed_)
|
if (ptr && backed_)
|
||||||
canonicalize (hash, ptr);
|
canonicalize (hash, ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInconsistentNode(ptr))
|
if (ptr && isInconsistentNode(ptr))
|
||||||
ptr = nullptr;
|
ptr = nullptr;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
ptr = parent->canonicalizeChild (branch, std::move(ptr));
|
ptr = parent->canonicalizeChild (branch, std::move(ptr));
|
||||||
@@ -955,7 +932,7 @@ SHAMap::addGiveItem (std::shared_ptr<SHAMapItem const> const& item,
|
|||||||
auto parent_depth = parent->depth();
|
auto parent_depth = parent->depth();
|
||||||
auto depth = inner->get_common_prefix(tag);
|
auto depth = inner->get_common_prefix(tag);
|
||||||
auto new_inner = std::make_shared<SHAMapInnerNodeV2>(seq_);
|
auto new_inner = std::make_shared<SHAMapInnerNodeV2>(seq_);
|
||||||
auto nodeID = SHAMapNodeID{depth, prefix(depth, inner->common())};
|
nodeID = SHAMapNodeID{depth, prefix(depth, inner->common())};
|
||||||
new_inner->setChild(nodeID.selectBranch(inner->common()), inner);
|
new_inner->setChild(nodeID.selectBranch(inner->common()), inner);
|
||||||
nodeID = SHAMapNodeID{depth, prefix(depth, tag)};
|
nodeID = SHAMapNodeID{depth, prefix(depth, tag)};
|
||||||
new_inner->setChild(nodeID.selectBranch(tag),
|
new_inner->setChild(nodeID.selectBranch(tag),
|
||||||
@@ -1394,10 +1371,18 @@ SHAMap::invariants() const
|
|||||||
bool
|
bool
|
||||||
SHAMap::isInconsistentNode(std::shared_ptr<SHAMapAbstractNode> const& node) const
|
SHAMap::isInconsistentNode(std::shared_ptr<SHAMapAbstractNode> const& node) const
|
||||||
{
|
{
|
||||||
|
assert(root_);
|
||||||
|
assert(node);
|
||||||
if (std::dynamic_pointer_cast<SHAMapTreeNode>(node) != nullptr)
|
if (std::dynamic_pointer_cast<SHAMapTreeNode>(node) != nullptr)
|
||||||
return false;
|
return false;
|
||||||
bool is_node_v2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) != nullptr;
|
bool is_node_v2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) != nullptr;
|
||||||
return is_v2() != is_node_v2;
|
assert (! is_node_v2 || (std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node)->depth() != 0));
|
||||||
|
|
||||||
|
if (is_v2() == is_node_v2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
state_ = SHAMapState::Invalid;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ SHAMap::getMissingNodes(std::size_t max, SHAMapSyncFilter* filter)
|
|||||||
{
|
{
|
||||||
if (!pending)
|
if (!pending)
|
||||||
{ // node is not in the database
|
{ // node is not in the database
|
||||||
|
missingHashes.insert (childHash);
|
||||||
ret.emplace_back (
|
ret.emplace_back (
|
||||||
childID,
|
childID,
|
||||||
childHash.as_uint256());
|
childHash.as_uint256());
|
||||||
@@ -254,15 +255,15 @@ SHAMap::getMissingNodes(std::size_t max, SHAMapSyncFilter* filter)
|
|||||||
|
|
||||||
// Process all deferred reads
|
// Process all deferred reads
|
||||||
int hits = 0;
|
int hits = 0;
|
||||||
for (auto const& node : deferredReads)
|
for (auto const& deferredNode : deferredReads)
|
||||||
{
|
{
|
||||||
auto parent = std::get<0>(node);
|
auto parent = std::get<0>(deferredNode);
|
||||||
auto branch = std::get<1>(node);
|
auto branch = std::get<1>(deferredNode);
|
||||||
auto const& nodeID = std::get<2>(node);
|
auto const& deferredNodeID = std::get<2>(deferredNode);
|
||||||
auto const& nodeHash = parent->getChildHash (branch);
|
auto const& nodeHash = parent->getChildHash (branch);
|
||||||
|
|
||||||
auto nodePtr = fetchNodeNT(nodeHash, filter);
|
auto nodePtr = fetchNodeNT(nodeHash, filter);
|
||||||
if (nodePtr && !isInconsistentNode(nodePtr))
|
if (nodePtr)
|
||||||
{
|
{
|
||||||
++hits;
|
++hits;
|
||||||
if (backed_)
|
if (backed_)
|
||||||
@@ -273,7 +274,7 @@ SHAMap::getMissingNodes(std::size_t max, SHAMapSyncFilter* filter)
|
|||||||
{
|
{
|
||||||
ret.push_back (
|
ret.push_back (
|
||||||
std::make_pair (
|
std::make_pair (
|
||||||
nodeID,
|
deferredNodeID,
|
||||||
nodeHash.as_uint256()));
|
nodeHash.as_uint256()));
|
||||||
|
|
||||||
--max;
|
--max;
|
||||||
@@ -401,10 +402,10 @@ bool SHAMap::getNodeFat (SHAMapNodeID wanted,
|
|||||||
else if (childNode->isInner() || fatLeaves)
|
else if (childNode->isInner() || fatLeaves)
|
||||||
{
|
{
|
||||||
// Just include this node
|
// Just include this node
|
||||||
Serializer s;
|
Serializer ns;
|
||||||
childNode->addRaw (s, snfWIRE);
|
childNode->addRaw (ns, snfWIRE);
|
||||||
nodeIDs.push_back (childID);
|
nodeIDs.push_back (childID);
|
||||||
rawNodes.push_back (std::move (s.peekData ()));
|
rawNodes.push_back (std::move (ns.peekData ()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,18 +499,6 @@ SHAMap::addKnownNode (const SHAMapNodeID& node, Blob const& rawNode,
|
|||||||
|
|
||||||
if (iNode == nullptr)
|
if (iNode == nullptr)
|
||||||
{
|
{
|
||||||
if ((std::dynamic_pointer_cast<SHAMapInnerNodeV2>(newNode) && !iNodeID.has_common_prefix(node)) ||
|
|
||||||
(!std::dynamic_pointer_cast<SHAMapInnerNodeV2>(newNode) && iNodeID != node))
|
|
||||||
{
|
|
||||||
// Either this node is broken or we didn't request it (yet)
|
|
||||||
JLOG(journal_.warn()) << "unable to hook node " << node;
|
|
||||||
JLOG(journal_.info()) << " stuck at " << iNodeID;
|
|
||||||
JLOG(journal_.info()) <<
|
|
||||||
"got depth=" << node.getDepth () <<
|
|
||||||
", walked to= " << iNodeID.getDepth ();
|
|
||||||
return SHAMapAddNode::invalid ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newNode || !newNode->isValid() || childHash != newNode->getNodeHash ())
|
if (!newNode || !newNode->isValid() || childHash != newNode->getNodeHash ())
|
||||||
{
|
{
|
||||||
JLOG(journal_.warn()) << "Corrupt node received";
|
JLOG(journal_.warn()) << "Corrupt node received";
|
||||||
@@ -525,16 +514,25 @@ SHAMap::addKnownNode (const SHAMapNodeID& node, Blob const& rawNode,
|
|||||||
|
|
||||||
if (newNode && isInconsistentNode(newNode))
|
if (newNode && isInconsistentNode(newNode))
|
||||||
{
|
{
|
||||||
return SHAMapAddNode::invalid();
|
state_ = SHAMapState::Invalid;
|
||||||
|
return SHAMapAddNode::useful();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((std::dynamic_pointer_cast<SHAMapInnerNodeV2>(newNode) && !iNodeID.has_common_prefix(node)) ||
|
||||||
|
(!std::dynamic_pointer_cast<SHAMapInnerNodeV2>(newNode) && iNodeID != node))
|
||||||
|
{
|
||||||
|
// Either this node is broken or we didn't request it (yet)
|
||||||
|
JLOG(journal_.warn()) << "unable to hook node " << node;
|
||||||
|
JLOG(journal_.info()) << " stuck at " << iNodeID;
|
||||||
|
JLOG(journal_.info()) <<
|
||||||
|
"got depth=" << node.getDepth () <<
|
||||||
|
", walked to= " << iNodeID.getDepth ();
|
||||||
|
return SHAMapAddNode::useful ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backed_)
|
if (backed_)
|
||||||
{
|
|
||||||
auto temp = newNode;
|
|
||||||
canonicalize (childHash, newNode);
|
canonicalize (childHash, newNode);
|
||||||
if (isInconsistentNode(newNode))
|
|
||||||
newNode = temp;
|
|
||||||
}
|
|
||||||
newNode = prevNode->canonicalizeChild (branch, std::move(newNode));
|
newNode = prevNode->canonicalizeChild (branch, std::move(newNode));
|
||||||
|
|
||||||
if (filter)
|
if (filter)
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ SHAMapAbstractNode::make(Blob const& rawNode, std::uint32_t seq, SHANodeFormat f
|
|||||||
}
|
}
|
||||||
else if (type == 5)
|
else if (type == 5)
|
||||||
{
|
{
|
||||||
// full inner
|
// full v2 inner
|
||||||
if (len != 512)
|
if (len != 512)
|
||||||
Throw<std::runtime_error> ("invalid FI node");
|
Throw<std::runtime_error> ("invalid FI node");
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ SHAMapAbstractNode::make(Blob const& rawNode, std::uint32_t seq, SHANodeFormat f
|
|||||||
else if (type == 6)
|
else if (type == 6)
|
||||||
{
|
{
|
||||||
auto ret = std::make_shared<SHAMapInnerNodeV2>(seq);
|
auto ret = std::make_shared<SHAMapInnerNodeV2>(seq);
|
||||||
// compressed inner
|
// compressed v2 inner
|
||||||
for (int i = 0; i < (len / 33); ++i)
|
for (int i = 0; i < (len / 33); ++i)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
@@ -296,7 +296,7 @@ SHAMapAbstractNode::make(Blob const& rawNode, std::uint32_t seq, SHANodeFormat f
|
|||||||
auto len = s.getLength();
|
auto len = s.getLength();
|
||||||
bool isV2 = (prefix == HashPrefix::innerNodeV2);
|
bool isV2 = (prefix == HashPrefix::innerNodeV2);
|
||||||
|
|
||||||
if ((len < 512) || (!isV2 && (len != 512)))
|
if ((len < 512) || (!isV2 && (len != 512)) || (isV2 && (len == 512)))
|
||||||
Throw<std::runtime_error> ("invalid PIN node");
|
Throw<std::runtime_error> ("invalid PIN node");
|
||||||
|
|
||||||
std::shared_ptr<SHAMapInnerNode> ret;
|
std::shared_ptr<SHAMapInnerNode> ret;
|
||||||
@@ -498,6 +498,24 @@ SHAMapInnerNodeV2::addRaw(Serializer& s, SHANodeFormat format) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SHAMapInnerNodeV2::updateHash()
|
||||||
|
{
|
||||||
|
uint256 nh;
|
||||||
|
|
||||||
|
if (mIsBranch != 0)
|
||||||
|
{
|
||||||
|
Serializer s(580);
|
||||||
|
addRaw (s, snfPREFIX);
|
||||||
|
nh = s.getSHA512Half();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nh == mHash.as_uint256())
|
||||||
|
return false;
|
||||||
|
mHash = SHAMapHash{nh};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SHAMapTreeNode::addRaw(Serializer& s, SHANodeFormat format) const
|
SHAMapTreeNode::addRaw(Serializer& s, SHANodeFormat format) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -224,14 +224,14 @@ public:
|
|||||||
std::vector<uint256> hashes(8);
|
std::vector<uint256> hashes(8);
|
||||||
if (is_v2)
|
if (is_v2)
|
||||||
{
|
{
|
||||||
hashes[0].SetHex ("B7387CFEA0465759ADC718E8C42B52D2309D179B326E239EB5075C64B6281F7F");
|
hashes[0].SetHex ("90F77DA53895E34042DC8048518CC98AD24276D0A96CCA2C515A83FDAF9F9FC9");
|
||||||
hashes[1].SetHex ("6A70885D21024F9F4F50E688B365D0E017266F53AE3E77B52AAEF84E167FE942");
|
hashes[1].SetHex ("425A3B6A68FAD9CB43B9981C7D0D39B942FE62110B437201057EE703F5E76390");
|
||||||
hashes[2].SetHex ("BA635322BDF510CCFC0578C194C1F87DA2D97C1A55A469F6E7A463BE963663D7");
|
hashes[2].SetHex ("1B4BE72DD18F90F367D64C0147D2414329149724339F79958D6470E7C99E3F4A");
|
||||||
hashes[3].SetHex ("5F751361AC7A161DED4D6EAAC4B587C7C01E50E1F9EC3DD61207BD6B196E7DB1");
|
hashes[3].SetHex ("CCC18ED9B0C353278F02465E2E2F3A8A07427B458CF74C51D87ABE9C1B2ECAD8");
|
||||||
hashes[4].SetHex ("FC1C57DD4BF15E37961E0B3064C43E60A9DC26EA332D7A6178FE2284901DB49F");
|
hashes[4].SetHex ("24AF98675227F387CE0E4932B71B099FE8BC66E5F07BE2DA70D7E7D98E16C8BC");
|
||||||
hashes[5].SetHex ("4FCDFE944E8E19E35FF60E7BDA7DB21B1CD99670BCF158FEF8F0F8B49BF5C9AD");
|
hashes[5].SetHex ("EAA373271474A9BF18F1CC240B40C7B5C83C7017977F1388771E56D5943F2B9B");
|
||||||
hashes[6].SetHex ("31F6DE8152FBE77EAD59805631FCDDB71F1BC6A5E9BD8FA3948D82D1CE1F93D6");
|
hashes[6].SetHex ("C7968A323A06BD46769B402B2A85A7FE7F37FCE99C0004A6197AD8E5D76F200D");
|
||||||
hashes[7].SetHex ("00895AD3B161D483C4EF7B5469B0D305685222B5102C2C3F614FD84AD50C4B14");
|
hashes[7].SetHex ("0A2412DBB16308706211E5FA5B0160817D54757B4DDC0CB105391A79D06B47BA");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -250,11 +250,11 @@ public:
|
|||||||
map.setUnbacked ();
|
map.setUnbacked ();
|
||||||
|
|
||||||
BEAST_EXPECT(map.getHash() == zero);
|
BEAST_EXPECT(map.getHash() == zero);
|
||||||
for (int i = 0; i < keys.size(); ++i)
|
for (int k = 0; k < keys.size(); ++k)
|
||||||
{
|
{
|
||||||
SHAMapItem item (keys[i], IntToVUC (i));
|
SHAMapItem item (keys[k], IntToVUC (k));
|
||||||
BEAST_EXPECT(map.addItem (std::move(item), true, false));
|
BEAST_EXPECT(map.addItem (std::move(item), true, false));
|
||||||
BEAST_EXPECT(map.getHash().as_uint256() == hashes[i]);
|
BEAST_EXPECT(map.getHash().as_uint256() == hashes[k]);
|
||||||
map.invariants();
|
map.invariants();
|
||||||
}
|
}
|
||||||
if (v == SHAMap::version{1})
|
if (v == SHAMap::version{1})
|
||||||
@@ -264,21 +264,21 @@ public:
|
|||||||
BEAST_EXPECT(map_v2 != nullptr);
|
BEAST_EXPECT(map_v2 != nullptr);
|
||||||
BEAST_EXPECT(map_v2->is_v2());
|
BEAST_EXPECT(map_v2->is_v2());
|
||||||
map_v2->invariants();
|
map_v2->invariants();
|
||||||
auto i1 = map.begin();
|
auto m1 = map.begin();
|
||||||
auto e1 = map.end();
|
auto e1 = map.end();
|
||||||
auto i2 = map_v2->begin();
|
auto m2 = map_v2->begin();
|
||||||
auto e2 = map_v2->end();
|
auto e2 = map_v2->end();
|
||||||
for (; i1 != e1; ++i1, ++i2)
|
for (; m1 != e1; ++m1, ++m2)
|
||||||
{
|
{
|
||||||
BEAST_EXPECT(i2 != e2);
|
BEAST_EXPECT(m2 != e2);
|
||||||
BEAST_EXPECT(*i1 == *i2);
|
BEAST_EXPECT(*m1 == *m2);
|
||||||
}
|
}
|
||||||
BEAST_EXPECT(i2 == e2);
|
BEAST_EXPECT(m2 == e2);
|
||||||
}
|
}
|
||||||
for (int i = keys.size() - 1; i >= 0; --i)
|
for (int k = keys.size() - 1; k >= 0; --k)
|
||||||
{
|
{
|
||||||
BEAST_EXPECT(map.getHash().as_uint256() == hashes[i]);
|
BEAST_EXPECT(map.getHash().as_uint256() == hashes[k]);
|
||||||
BEAST_EXPECT(map.delItem (keys[i]));
|
BEAST_EXPECT(map.delItem (keys[k]));
|
||||||
map.invariants();
|
map.invariants();
|
||||||
}
|
}
|
||||||
BEAST_EXPECT(map.getHash() == zero);
|
BEAST_EXPECT(map.getHash() == zero);
|
||||||
@@ -300,8 +300,8 @@ public:
|
|||||||
keys[6].SetHex ("b91891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8");
|
keys[6].SetHex ("b91891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8");
|
||||||
keys[7].SetHex ("292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8");
|
keys[7].SetHex ("292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8");
|
||||||
|
|
||||||
tests::TestFamily f{beast::Journal{}};
|
tests::TestFamily tf{beast::Journal{}};
|
||||||
SHAMap map{SHAMapType::FREE, f, v};
|
SHAMap map{SHAMapType::FREE, tf, v};
|
||||||
if (! backed)
|
if (! backed)
|
||||||
map.setUnbacked ();
|
map.setUnbacked ();
|
||||||
for (auto const& k : keys)
|
for (auto const& k : keys)
|
||||||
@@ -310,11 +310,11 @@ public:
|
|||||||
map.invariants();
|
map.invariants();
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 7;
|
int h = 7;
|
||||||
for (auto const& k : map)
|
for (auto const& k : map)
|
||||||
{
|
{
|
||||||
BEAST_EXPECT(k.key() == keys[i]);
|
BEAST_EXPECT(k.key() == keys[h]);
|
||||||
--i;
|
--h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,9 +94,9 @@ public:
|
|||||||
void run(SHAMap::version v)
|
void run(SHAMap::version v)
|
||||||
{
|
{
|
||||||
beast::Journal const j; // debug journal
|
beast::Journal const j; // debug journal
|
||||||
TestFamily f(j);
|
TestFamily f(j), f2(j);
|
||||||
SHAMap source (SHAMapType::FREE, f, v);
|
SHAMap source (SHAMapType::FREE, f, v);
|
||||||
SHAMap destination (SHAMapType::FREE, f, v);
|
SHAMap destination (SHAMapType::FREE, f2, v);
|
||||||
|
|
||||||
int items = 10000;
|
int items = 10000;
|
||||||
for (int i = 0; i < items; ++i)
|
for (int i = 0; i < items; ++i)
|
||||||
@@ -133,21 +133,21 @@ public:
|
|||||||
destination.setSynching ();
|
destination.setSynching ();
|
||||||
|
|
||||||
{
|
{
|
||||||
std::vector<SHAMapNodeID> gotNodeIDs;
|
std::vector<SHAMapNodeID> gotNodeIDs_a;
|
||||||
std::vector<Blob> gotNodes;
|
std::vector<Blob> gotNodes_a;
|
||||||
|
|
||||||
BEAST_EXPECT(source.getNodeFat (
|
BEAST_EXPECT(source.getNodeFat (
|
||||||
SHAMapNodeID (),
|
SHAMapNodeID (),
|
||||||
gotNodeIDs,
|
gotNodeIDs_a,
|
||||||
gotNodes,
|
gotNodes_a,
|
||||||
rand_bool(),
|
rand_bool(),
|
||||||
rand_int(2)));
|
rand_int(2)));
|
||||||
|
|
||||||
unexpected (gotNodes.size () < 1, "NodeSize");
|
unexpected (gotNodes_a.size () < 1, "NodeSize");
|
||||||
|
|
||||||
BEAST_EXPECT(destination.addRootNode (
|
BEAST_EXPECT(destination.addRootNode (
|
||||||
source.getHash(),
|
source.getHash(),
|
||||||
*gotNodes.begin (),
|
*gotNodes_a.begin (),
|
||||||
snfWIRE,
|
snfWIRE,
|
||||||
nullptr).isGood());
|
nullptr).isGood());
|
||||||
}
|
}
|
||||||
@@ -163,29 +163,29 @@ public:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// get as many nodes as possible based on this information
|
// get as many nodes as possible based on this information
|
||||||
std::vector<SHAMapNodeID> gotNodeIDs;
|
std::vector<SHAMapNodeID> gotNodeIDs_b;
|
||||||
std::vector<Blob> gotNodes;
|
std::vector<Blob> gotNodes_b;
|
||||||
|
|
||||||
for (auto& it : nodesMissing)
|
for (auto& it : nodesMissing)
|
||||||
{
|
{
|
||||||
BEAST_EXPECT(source.getNodeFat (
|
BEAST_EXPECT(source.getNodeFat (
|
||||||
it.first,
|
it.first,
|
||||||
gotNodeIDs,
|
gotNodeIDs_b,
|
||||||
gotNodes,
|
gotNodes_b,
|
||||||
rand_bool(),
|
rand_bool(),
|
||||||
rand_int(2)));
|
rand_int(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BEAST_EXPECT(gotNodeIDs.size () == gotNodes.size ());
|
BEAST_EXPECT(gotNodeIDs_b.size () == gotNodes_b.size ());
|
||||||
BEAST_EXPECT(!gotNodeIDs.empty ());
|
BEAST_EXPECT(!gotNodeIDs_b.empty ());
|
||||||
|
|
||||||
for (std::size_t i = 0; i < gotNodeIDs.size(); ++i)
|
for (std::size_t i = 0; i < gotNodeIDs_b.size(); ++i)
|
||||||
{
|
{
|
||||||
BEAST_EXPECT(
|
BEAST_EXPECT(
|
||||||
destination.addKnownNode (
|
destination.addKnownNode (
|
||||||
gotNodeIDs[i],
|
gotNodeIDs_b[i],
|
||||||
gotNodes[i],
|
gotNodes_b[i],
|
||||||
nullptr).isGood ());
|
nullptr).isUseful ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (true);
|
while (true);
|
||||||
|
|||||||
Reference in New Issue
Block a user