Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions include/xrpl/shamap/SHAMapNodeID.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ class SHAMapNodeID : public CountedObject<SHAMapNodeID>
[[nodiscard]] SHAMapNodeID
getChildNodeID(unsigned int branch) const;

/**
* Test whether this node ID lies on the path to the given leaf key
*
* A node at depth d identifies the tree path spelled by the first d
* nibbles of its key, so any leaf beneath it must agree on that prefix.
* A node ID that fails this test names a different subtree than the one
* it was built for.
*
* @param key the key of a leaf below this node
* @return whether this node ID is a prefix of the leaf key
*/
[[nodiscard]] bool
isPrefixOf(uint256 const& key) const;

/**
* Create a SHAMapNodeID of a node with the depth of the node and
* the key of a leaf
Expand Down
11 changes: 8 additions & 3 deletions src/libxrpl/shamap/SHAMapNodeID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ SHAMapNodeID::SHAMapNodeID(unsigned int depth, uint256 const& hash) : id_(hash),
XRPL_ASSERT(
depth <= SHAMap::kLeafDepth, "xrpl::SHAMapNodeID::SHAMapNodeID : maximum depth input");
XRPL_ASSERT(
id_ == (id_ & depthMask(depth)),
"xrpl::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match");
isPrefixOf(id_), "xrpl::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match");
}

std::string
Expand Down Expand Up @@ -79,14 +78,20 @@ SHAMapNodeID::getChildNodeID(unsigned int branch) const
if (depth_ >= SHAMap::kLeafDepth)
Throw<std::logic_error>("Request for child node ID of " + to_string(*this));

if (id_ != (id_ & depthMask(depth_)))
if (!isPrefixOf(id_))
Throw<std::logic_error>("Incorrect mask for " + to_string(*this));

SHAMapNodeID node{depth_ + 1, id_};
node.id_.begin()[depth_ / 2] |= ((depth_ & 1) != 0u) ? branch : (branch << 4);
return node;
}

bool
SHAMapNodeID::isPrefixOf(uint256 const& key) const
{
return (key & depthMask(depth_)) == id_;
}

[[nodiscard]] std::optional<SHAMapNodeID>
deserializeSHAMapNodeID(void const* data, std::size_t size)
{
Expand Down
7 changes: 3 additions & 4 deletions src/libxrpl/shamap/SHAMapSync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,10 +555,9 @@ SHAMap::addKnownNode(
{
XRPL_ASSERT(!nodeID.isRoot(), "xrpl::SHAMap::addKnownNode : valid node");
XRPL_ASSERT(treeNode, "xrpl::SHAMap::addKnownNode : non-null tree node");
XRPL_ASSERT(
!treeNode->isLeaf() ||
SHAMapNodeID::createID(nodeID.getDepth(), leafKey(*treeNode)).getNodeID() ==
nodeID.getNodeID(),
XRPL_ASSERT_IF(
treeNode->isLeaf(),
nodeID.isPrefixOf(leafKey(*treeNode)),
"xrpl::SHAMap::addKnownNode : leaf position consistent with node ID");

if (!isSynching())
Expand Down
5 changes: 2 additions & 3 deletions src/xrpld/app/ledger/detail/LedgerNodeHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,10 @@ getSHAMapNodeID(protocol::TMLedgerNode const& ledgerNode, SHAMapTreeNode const&
if (treeNode.isLeaf())
{
auto const key = leafKey(treeNode);
auto const expectedID = SHAMapNodeID::createID(nodeID->getDepth(), key);
SOMETIMES(
nodeID->getNodeID() != expectedID.getNodeID(),
!nodeID->isPrefixOf(key),
"xrpl::getSHAMapNodeID : legacy leaf ID inconsistent with key");
if (nodeID->getNodeID() != expectedID.getNodeID())
if (!nodeID->isPrefixOf(key))
return std::nullopt;
}

Expand Down
Loading