Skip to main content
Every module’s version is committed by a single Merkle root. The layout is RFC 6962 over lexicographically sorted leaves:
Two decisions, each closing something the paper leaves open:
  • Sorting makes the root a pure function of the set of blocks, so two parties that assembled the same knowledge in different orders agree.
  • RFC 6962 avoids the duplicate-leaf ambiguity a naive tree admits (CVE-2012-2459), by hashing leaves and internal nodes under different prefixes.
Internal nodes are derived, not stored. A module with no blocks still has a well-defined root.

Computing a root

Inclusion proofs

Membership is provable in O(log n), without holding the rest of the module.
A proof binds a block to one composition, not to any composition: verifying it against a different root fails. That is what makes a root a version identifier rather than a checksum.

Swapping the layout

MerkleLayout is a protocol, so a deployment can commit to a different tree — but both sides must agree, which is why the layout name travels in every ModuleRef.
Two implementations can only compare roots if they agree on the layout. A ModuleRef records layout for exactly that reason — a root computed under another layout is not a smaller or larger number, it is a different question’s answer.

Diffing two versions

What a consumer must fetch to move between versions falls out of the composition, with no server-side computation:
This is the mechanism behind an incremental update: the layers whose root did not change are reused by digest rather than transferred again.