Skip to content

refactor: Unify upperBound and lowerBound into boundHelper - #7943

Draft
bthomee wants to merge 1 commit into
bthomee/shamap-stack-05-derive-traversal-node-idsfrom
bthomee/shamap-stack-06-unify-upper-lower-bound
Draft

refactor: Unify upperBound and lowerBound into boundHelper#7943
bthomee wants to merge 1 commit into
bthomee/shamap-stack-05-derive-traversal-node-idsfrom
bthomee/shamap-stack-06-unify-upper-lower-bound

Conversation

@bthomee

@bthomee bthomee commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Part 6/8 of a stack. Base: part 5 (bthomee/shamap-stack-05-derive-traversal-node-ids).

The two functions were near duplicates: walk to the key, then look for the
nearest leaf on one side. Only the scan direction, the comparison deciding a
leaf qualifies, and whether to take the first or last leaf below the subtree
differed, exactly the distinction BelowDirection already draws for
belowHelper, so the pair collapse into one parameterised walk. Also drops
the stale // TODO: what to return here? above lowerBound's return end():
no predecessor is the correct answer for the smallest key, and the tests pin
it.

Existing coverage only exercised boundHelper's inner-node branch, every test
map had at least three items, so the root was always an inner node and the
leaf branch at the top of the function was never reached with a real answer to
give. Adds coverage for a single-item map, where the leaf branch alone decides
the outcome, and an empty map, where the scan must find nothing on every
branch before falling through to end().

Fixes the single-item test's own comment, which claimed root_ becomes a
leaf, when in fact root_ stays the inner node it was constructed with for
any map built via addItem; only a single-item map synced from a peer
(addRootNode) ever replaces root_ with a leaf directly.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors SHAMap bound traversal logic by consolidating the duplicated upperBound/lowerBound implementations into a single parameterized helper, and expands traversal test coverage to include empty and single-item maps.

Changes:

  • Introduces SHAMap::boundHelper(id, direction) to unify predecessor/successor search behavior.
  • Re-implements upperBound and lowerBound as thin wrappers over boundHelper.
  • Adds traversal tests covering empty-map and single-item-map bound behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/libxrpl/shamap/SHAMap.cpp Collapses duplicated bound-walk logic into boundHelper and delegates upperBound/lowerBound to it.
include/xrpl/shamap/SHAMap.h Declares the new private boundHelper used by bound queries.
src/tests/libxrpl/shamap/SHAMap.cpp Adds empty/single-item bound tests to cover previously unexercised traversal branches.
Suppressed comments (1)

src/tests/libxrpl/shamap/SHAMap.cpp:451

  • This comment claims boundHelper’s leaf branch decides the outcome “before root_'s own inner-node scan would ever run”, but for probes equal to the single key the leaf comparison fails and boundHelper pops the leaf then scans the root (which then falls through to end()). This matters for understanding why upperBound(key)/lowerBound(key) return end().
    // it was constructed with, with the single leaf one level below it. So here the stack holds
    // that inner root plus the leaf, and boundHelper's leaf branch, examined first, decides the
    // outcome before root_'s own inner-node scan would ever run.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +428 to +430
// The root is a childless inner node, so boundHelper's inner-node branch must scan all 16
// branches, find every one empty, and fall through to end() rather than dereference a child.
EXPECT_EQ(map.upperBound(uint256{}), map.end());
@bthomee
bthomee force-pushed the bthomee/shamap-stack-05-derive-traversal-node-ids branch from 199fe0d to 651f082 Compare August 3, 2026 23:25
@bthomee
bthomee force-pushed the bthomee/shamap-stack-06-unify-upper-lower-bound branch from cfd2adf to c208afa Compare August 3, 2026 23:25
@bthomee
bthomee force-pushed the bthomee/shamap-stack-05-derive-traversal-node-ids branch from 651f082 to fcbd9fe Compare August 4, 2026 00:12
@bthomee
bthomee force-pushed the bthomee/shamap-stack-06-unify-upper-lower-bound branch from c208afa to dc9f746 Compare August 4, 2026 00:12
The two functions were near duplicates: walk to the key, then look for the
nearest leaf on one side. Only the scan direction, the comparison deciding a
leaf qualifies, and whether to take the first or last leaf below the subtree
differed, exactly the distinction `BelowDirection` already draws for
`belowHelper`, so the pair collapse into one parameterised walk. Also drops
the stale `// TODO: what to return here?` above `lowerBound`'s `return end()`:
no predecessor is the correct answer for the smallest key, and the tests pin
it.

Existing coverage only exercised `boundHelper`'s inner-node branch, every test
map had at least three items, so the root was always an inner node and the
leaf branch at the top of the function was never reached with a real answer to
give. Adds coverage for a single-item map, where the leaf branch alone decides
the outcome, and an empty map, where the scan must find nothing on every
branch before falling through to `end()`.

Fixes the single-item test's own comment, which claimed `root_` becomes a
leaf, when in fact `root_` stays the inner node it was constructed with for
any map built via `addItem`; only a single-item map synced from a peer
(`addRootNode`) ever replaces `root_` with a leaf directly.
@bthomee
bthomee force-pushed the bthomee/shamap-stack-05-derive-traversal-node-ids branch from fcbd9fe to 6318ca4 Compare August 4, 2026 00:49
@bthomee
bthomee force-pushed the bthomee/shamap-stack-06-unify-upper-lower-bound branch from dc9f746 to 8022ede Compare August 4, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants