Skip to content

feat(merkle): implement Merkle-proof allowlist verification module - #439

Merged
Lakes41 merged 1 commit into
Adamantine-guild:mainfrom
benzy018:feat/404-merkle-allowlist
Jul 29, 2026
Merged

feat(merkle): implement Merkle-proof allowlist verification module#439
Lakes41 merged 1 commit into
Adamantine-guild:mainfrom
benzy018:feat/404-merkle-allowlist

Conversation

@benzy018

Copy link
Copy Markdown
Contributor

Summary

Implements a Merkle-proof allowlist verification module for gasless off-chain access checks.

Changes

New @guildpass/sdk/merkle subpath

  • buildAllowlistTree(addresses[]) — constructs a Merkle tree from validated, checksum-normalised, deduplicated addresses
  • getProof(tree, address) — O(log n) Merkle proof generation from a pre-built tree
  • verifyProof(root, address, proof[]) — deterministic, side-effect-free proof verification suitable for client-side pre-checks
  • verifyProofFromLeaf(root, leaf, proof[]) — verify from a pre-computed leaf hash

Key design decisions

  • Leaf hashing: keccak256 of the 20 raw address bytes, matching OpenZeppelin's keccak256(abi.encodePacked(address))
  • Internal nodes: Sorted-pair hashing keccak256(a || b) where a ≤ b
  • Odd-leaf-count handling: Level promotion (not duplication), avoiding the well-known vulnerability of duplication schemes
  • Zero new runtime dependencies — reuses js-sha3 already in the dependency tree
  • hexToBytes helper reused from src/crypto/secp256k1.ts (no duplication)

Tests

  • 31 comprehensive tests covering:
    • Single-leaf, two-leaf, three-leaf, five-leaf, and seven-leaf trees
    • Odd-count trees with multi-level promotion
    • Address deduplication (identical and case-different)
    • Negative tests: tampered proof, wrong address, proof from different tree, truncated/extra-long proofs, invalid addresses
    • Performance at scale (5,000 addresses — build, lookup, and verify)
    • OpenZeppelin compatibility and determinism

Documentation

  • docs/merkle-allowlists.md — full workflow (build → publish root → distribute proofs → verify client-side / server-side) with explicit security note that client-side proof verification is a UX optimisation, not an authoritative access decision

Files changed

File Change
src/merkle/allowlistTree.ts New — core implementation
src/merkle/index.ts New — barrel export
tests/merkle.test.ts New — 31 tests
docs/merkle-allowlists.md New — documentation
package.json Added ./merkle subpath export
tsup.config.ts Added merkle entry point
CHANGELOG.md Added entry for #404

Closes #404

Implement a dependency-free (js-sha3 only) Merkle-proof allowlist
verification module for gasless off-chain access checks.

New @guildpass/sdk/merkle subpath exports:
- buildAllowlistTree(addresses[]) — constructs tree from validated,
  checksum-normalised, deduplicated addresses
- getProof(tree, address) — O(log n) proof generation
- verifyProof(root, address, proof[]) — deterministic client-side
  verification
- verifyProofFromLeaf(root, leaf, proof[]) — verify from pre-computed leaf

Key design decisions:
- Leaf hashing: keccak256 of 20 raw address bytes, matching
  OpenZeppelin's keccak256(abi.encodePacked(address))
- Internal nodes: sorted-pair hashing keccak256(a || b) where a ≤ b
- Odd-leaf-count handling: level promotion (not duplication),
  avoiding known vulnerability of duplication schemes
- Zero new runtime dependencies — reuses js-sha3 (already in tree)
- Hex-to-bytes helper reused from src/crypto/secp256k1.ts

Includes:
- 31 comprehensive tests covering correctness, odd counts, negative
  cases, and performance at scale (5000 addresses)
- docs/merkle-allowlists.md with full workflow documentation and
  explicit security note about client-side verification
- CHANGELOG entry

Closes Adamantine-guild#404
@Lakes41
Lakes41 merged commit 17e524a into Adamantine-guild:main Jul 29, 2026
4 checks passed
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.

Implement a Merkle-proof allowlist verification module for gasless off-chain access checks

2 participants