Skip to content

feat: Directory Client: Attested Anchor#6948

Open
jstuczyn wants to merge 6 commits into
feat/directory-client-validator-verificationfrom
feat/directory-client-attested-anchor
Open

feat: Directory Client: Attested Anchor#6948
jstuczyn wants to merge 6 commits into
feat/directory-client-validator-verificationfrom
feat/directory-client-attested-anchor

Conversation

@jstuczyn

@jstuczyn jstuczyn commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Why

The trust model has a gap: the checkpoint / root-key layer (LightClientAnchor's prerequisite) is blocked on a root key that doesn't exist yet. A second, independent authority is available today - the curated Tier-1 nym-api identity keys - so a quorum of them signing a snapshot gives a deployable trust root now, strictly stronger than trusting a single RPC and strictly weaker than the light client.

What Changed

New anchor (common/nym-directory-client/src/anchor/attested.rs)

  • AttestedTrustAnchor<S>: constructed with trusted signer keys, a quorum threshold K, chain-id, and contract address, or via with_default_anchor(...) using a compiled-in default.
  • DigestSnapshot / SignedDigestSnapshot: the attestation carries {height, app_hash, accumulator, node_identities_hash} - the directory digest AND a hash over the current NodeId -> ed25519 identity mapping, both signed together so a quorum-verified snapshot proves authorship bindings too, with no chain query needed.
  • AttestationSource trait (identity(), latest_snapshot(), snapshot_at(height)) - transport-agnostic; concrete HTTP transport is a follow-up.
  • refresh() seeds a height from one source's latest_snapshot() (shuffled, untrusted hint), then confirms it against every other source's snapshot_at(H), avoiding cadence-boundary splits from comparing independently-reported "latest" heights.
  • reach_quorum groups candidates by exact attested value, counts distinct signers, accepts the first group to reach K.
  • AttestedTrustAnchor::majority_quorum(n) derives the default quorum as a simple majority of however many signers are configured, rather than a separately hardcoded threshold - so growing the default signer set later doesn't need a second change to keep a quorum number in sync.

Default anchor (common/network-defaults/src/{mainnet,network}.rs)

  • DIRECTORY_ATTESTATION_SOURCES: mainnet's known nym-api identity keys + URLs, following the same pattern as the existing UPGRADE_MODE_ATTESTER_ED25519_BS58_PUBKEY. Only 2 of 3 Nym SA nym-apis are included - the third has no way to expose its identity key yet (see Follow-ups).
  • default_directory_attestation_sources(): env-var overridable (DIRECTORY_ATTESTATION_SOURCES JSON), mirroring NYM_APIS/NYM_VPN_APIS; falls back to the compiled mainnet list otherwise. Wired into setup_env()'s existing backfill so real binaries loading a static .env file pick up the default with no extra config.

Data-source-agnostic verification (common/nym-directory-client/src/verify.rs, client.rs)

  • verify_directory(...): extracted from DirectoryClient::verified_directory's body - digest recompute, optional node-identities-hash recompute, per-entry authorship attribution - takes pre-fetched data, no CosmWasmClient involved at all.
  • verify_directory_offline(...): same core, but requires a node-identities hash (NodeIdentitiesHashUnavailable if none given) instead of silently skipping authorship verification - the entry point for callers with no chain RPC connection at all.
  • DirectoryClient::verified_directory is now a thin wrapper: fetch via self.client as before, then call verify_directory(.., None) - unchanged behavior for ProvenTrustAnchor / LightClientAnchor.

Known gaps / explicitly deferred

  • Default anchor key material is real but incomplete: only 2 of Nym SA's 3 mainnet nym-apis are included, since the third isn't a coconut-dkg dealer and has no other way to expose its identity key today.
  • nym-api producer endpoint (signs snapshots) and concrete HTTP AttestationSource: both explicitly out of scope, follow-up changes; this change fixes the wire format they must emit/consume.
  • nym-api identity-key exposure + possession-proof: named as its own nym-api-side prerequisite for the override path (a caller substituting their own nym-api) to be broadly usable - today, an identity key is only discoverable via DKG dealer registration.
  • Generalized canonical-subset attestation (per-label slices, deriving the live Tier-1 signer set from chain state instead of hand-maintaining it): explored at length, deliberately parked - see design.md's "Future direction".

This change is Reviewable

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nym-explorer-v2 Ready Ready Preview, Comment Jul 9, 2026 12:49pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs-nextra Ignored Ignored Preview Jul 9, 2026 12:49pm
nym-node-status Ignored Ignored Preview Jul 9, 2026 12:49pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 692089a6-12d8-474e-ab6d-0ba3b4919298

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/directory-client-attested-anchor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jstuczyn
jstuczyn force-pushed the feat/directory-client-validator-verification branch from f07b05f to b5c054b Compare July 9, 2026 09:03
@jstuczyn
jstuczyn force-pushed the feat/directory-client-attested-anchor branch from 82aa39f to 8710237 Compare July 9, 2026 09:03
@jstuczyn
jstuczyn force-pushed the feat/directory-client-validator-verification branch from b5c054b to bc25634 Compare July 9, 2026 12:46
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