Skip to content

Conversation

@mkorovkin2
Copy link

@mkorovkin2 mkorovkin2 commented Jan 9, 2026

Addressing TODO item in code: optimize PMMR segments to only include hashes at pruning boundaries; tests updated as segment size dropped from 521 to 281 bytes (7 hashes -> 1 hash)


name: Pull Request
about: Pull Request checklist
title: 'Optimize PMMR segments to only include hashes at pruning boundaries'
labels: ''
assignees: ''


  • This PR addresses the TODO at core/src/core/pmmr/segment.rs:338: "optimize, no need to send every intermediary hash"
  • PROBLEM: During PIBD sync, segments are generated containing leaf data, intermediate hashes, Merkle proofs. Previously, the from_pmmr function included hashes for every position in prunable segments, even when many of these hashes were unnecessary for validation. This resulted in unnecessarily large segment payloads being transmitted over the network
  • SOLUTION: identify "pruning boundaries" (positions where a fully pruned subtree meets a non fully pruned sibling). Only hashes at these boundaries are actually needed during segment validation (when the root() function encounters a (None, Some) or (Some, None) case and must look up the missing child's hash)
  • CHANGE IMPACT: in the ser_round_trip test case, this optimization reduces the number of hashes from 7 to 1, shrinking the segment from 521 bytes to 281 bytes (46%); real-world savings will vary depending on pruning patterns but any segment with partial pruning will see reduced size
  • CONSENUS BREAKING? No. (this change does not affect consensus rules)
  • BREAKING CHANGES: API change: The Segment::from_pmmr() function signature changed:
    • ---> Before: from_pmmr(segment_id, pmmr, prunable: bool)
    • ---> After: from_pmmr(segment_id, pmmr, bitmap: Option<&Bitmap>)
    • Callers update:
    • ---> false to None (for non-prunable segments like kernels, bitmaps)
    • ---> true to Some(&bitmap) (for prunable segments like outputs, rangeproofs)
  • TESTING:
    • Unit tests: All existing segment tests pass cargo test -p grin_core unprunable_mmr / cargo test -p grin_store --test segment / cargo test -p grin_chain --test bitmap_segment
    • All unit test pass and they're pretty reliable here since they generate segments of varied pruning patterns, immediately validate those segments, and cover a number of edge cases
    • The ser_round_trip test assertion was updated to reflect the reduced hash count, serving as verification that the optimization is working as intended
    • Manual build testing: build verification completed with cargo build. no new warnings introduced by this change.
    • Manual testnet sync: manual testnet sync; fully works and passes; ensured that node runs and syncs.
    • Manual local testing across two nodes: synced node (node1) and fresh node (node2)
    • node1 had synced full chain data, node2 connected to node1 and requested segments
    • Flow tested:
      • node1 calls Segmenter::output_segment() / rangeproof_segment() which uses the modified from_pmmr() to generate optimized segments
      • node1 serializes and sends segments
      • node2 deserializes and calls segment.validate() to verify the segemnt
      • node2 successfully reconstructs the chain state
      • ---> can see that optimized segments (with fewer hashes) survive serialization, network transmission, deserialization, and validation by a real node

…t pruning boundaries; tests updated as segment size dropped from 521 to 281 bytes (7 hashes -> 1 hash)
@mkorovkin2
Copy link
Author

mkorovkin2 commented Jan 9, 2026

First PR! (People in the Keybase/Telegram chat suggested to tag John/David)

@mkorovkin2
Copy link
Author

Hey @DavidBurkett - when you get a chance would appreciate your feedback on this PR!

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.

1 participant