mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-21 14:20:56 +00:00
`belowHelper` built each stack entry's `SHAMapNodeID` from `branch`, the branch used to reach the subtree root, rather than `childBranch`, the branch it had just descended. The resulting IDs carried a correct depth but named a different subtree, and nothing rejected them: such an ID has a legal depth and a legal mask, so only comparing it against an actual leaf key exposes the mismatch. The affected stacks feed read-only traversals whose consumers use only the depth, so no ledger state, hash, or peer message was affected, but any future consumer of `getNodeID()` would have silently received the wrong position. Rather than fix the one call, make the mistake unrepresentable. `NodePathStack` replaces the bare `std::stack` and refuses to accept an ID at all: every push takes the branch being descended and derives the ID itself, so a node and its ID cannot disagree. `isPrefixOf` assertions on each push catch a wrong branch at the point it happens rather than wherever the ID is later read. Leaf entries now keep the depth they were reached at instead of a normalized `kLeafDepth`, which is what lets those assertions hold: `addGiveItem` splits a leaf from the depth it actually sits at. The new traversal tests fail on the previous code: reverting the branch derivation trips the leaf-key assertion on the first iteration. Also adds a `deepFanOutKeysAtLeafDepth` helper and mirrors them against it, since the existing `deepFanOutKeys`'s fan-out at the 6th nibble keeps its tree only about 6 levels deep and never exercised the depth-63/64 code these tests are meant to protect, plus a case that collapses the entire depth-63 chain of single-child inner nodes into a leaf on the final delete, which the every-other-key deletion pattern the other new tests use never triggers.