Skip to content

[FEAT] Add CommitmentRegistry contract#57

Merged
roeezolantz merged 11 commits intomasterfrom
feat/commitment-registry
Apr 9, 2026
Merged

[FEAT] Add CommitmentRegistry contract#57
roeezolantz merged 11 commits intomasterfrom
feat/commitment-registry

Conversation

@roeezolantz
Copy link
Copy Markdown
Contributor

@roeezolantz roeezolantz commented Mar 24, 2026

Summary

UUPS-upgradeable contract for on-chain FHE computation commitments on Arbitrum One. Threshold Network verifies ciphertext integrity before decrypting by looking up committed hashes. Part of the effort to reduce trust between CoFHE components.

Storage: mapping(version => mapping(handle => commitHash)) + bytes32[] handlesByVersion for enumeration. Write-once, version lifecycle enforced.

Design decisions

  • Direct mapping over merkle tree — TN needs instant O(1) lookup (getCommitment). Merkle can be added via UUPS upgrade if costs warrant it (~10-20x cheaper but requires an event indexing service).
  • Explicit version in postCommitments — The version is an opaque bytes32 from the FHE engine: keccak256(publicKey[securityZone], library_id, version, params). Explicit because:
    • Multiple versions can be active simultaneously (different security zones have different keys)
    • No coupling to FHE internals — contract is FHE-library-agnostic
    • Race condition safety — version in calldata preserves poster intent if admin changes active version mid-flight
    • Auditability — every commitment permanently tagged with its version
  • Multi-poster supportmapping(address => bool) posters instead of single address poster, allowing horizontal scaling of poster services. Managed via addPoster() / removePoster() (owner-only). Write-once enforcement still applies across all posters — no poster can overwrite another's commitment.
  • Array-based enumerationhandlesByVersion array enables paginated cursor (getHandles) for migration and iteration. Roughly doubles gas per commitment vs mapping-only.
  • Version state machine — Unset -> Active -> Deprecated/Revoked. No resurrection.
  • ERC-7201 storage — matching ACL pattern for upgrade safety.

Gas (measured, includes mapping + array)

Per commitment (L2 execution):

  • Single post: 102,287 gas (~$0.007/CT)
  • Batch of 10: 51,776 gas/CT (~$0.003/CT)
  • Batch of 50: 47,287 gas/CT (~$0.003/CT)

Poster management:

  • addPoster: 52,365 gas
  • removePoster: 30,738 gas
  • isPoster read: 28,982 gas

At 0.03 gwei effective gas price, ETH ~$2,140.

Monthly at 100K CTs/day: $9K-20K/mo depending on batch efficiency.

Test plan

  • 72 tests covering all code paths
  • Multi-poster concurrent posting, cross-poster write-once enforcement
  • Poster add/remove access control, re-add after removal, isolation between posters
  • Gas benchmarks for poster management operations
  • State preservation after UUPS upgrade (including multi-poster state)
  • Deployed on Arbitrum Sepolia (0x753882Fa0389E600913657B846990beBDC4BBeb6)
  • Measure real mainnet L1+L2 costs
  • Integrate poster service + TN verification

See README in contracts/internal/registry-chain/contracts/commitment-registry/.

@roeezolantz roeezolantz changed the title Add CommitmentRegistry contract [FEAT] Add CommitmentRegistry contract Mar 24, 2026
@roeezolantz roeezolantz marked this pull request as ready for review March 24, 2026 20:19
@roeezolantz roeezolantz requested a review from a team as a code owner March 24, 2026 20:19
@roeezolantz
Copy link
Copy Markdown
Contributor Author

Adding comparison with OZ's EnumerableMap :

EnumerableMap is a general-purpose library: mapping + array + index tracking. Supports insert, update, delete, existence check, and key enumeration. Battle-tested, audited, composable across any contract.

CommitmentRegistry is purpose-built for write-once commitments. It drops deletion, update, and index tracking — features we don't need, which gives us:

  • ~22k less gas per insert (3 SSTOREs vs 4)
  • Half the gas per read (1 SLOAD vs 2)
  • No zero-value ambiguity (banned at write boundary, so 0 = "doesn't exist" is always true)
  • No swap-and-pop logic = less attack surface for feature we don't even need (deletions)
  • Built-in access control, versions lifecycle, ERC-7201 storage, and pagination

I recommend keeping our version, as it's simpler, cheaper, and more secure for our specific use case. OZ solves a broader problem we don't have.
While OZ's audit status carries real weight, forking it would mean stripping out deletion, adding version management, access control, ERC-7201 storage, and zero-value guards, at which point the audited code is buried under enough modifications that a reviewer would need to understand both the original OZ patterns and why we deviated from them, rather than just reading a clean, purpose-built contract.

@roeezolantz roeezolantz force-pushed the feat/commitment-registry branch from a319299 to 13621cc Compare April 9, 2026 10:04
@roeezolantz roeezolantz merged commit 9232380 into master Apr 9, 2026
7 checks passed
@roeezolantz roeezolantz deleted the feat/commitment-registry branch April 9, 2026 10:23
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