Skip to content

refactor!: complete ed25519_dalek to iroh-base public API migration#102

Merged
dignifiedquire merged 1 commit into
n0-computer:mainfrom
cbenhagen:refactor/iroh-base-public-api
May 27, 2026
Merged

refactor!: complete ed25519_dalek to iroh-base public API migration#102
dignifiedquire merged 1 commit into
n0-computer:mainfrom
cbenhagen:refactor/iroh-base-public-api

Conversation

@cbenhagen
Copy link
Copy Markdown
Contributor

@cbenhagen cbenhagen commented May 26, 2026

Description

Finishes the migration n0-computer/iroh#3529 started. iroh-docs is one of the last iroh crates still leaking ed25519_dalek::{SigningKey, VerifyingKey, SignatureError} through its public surface.

  • SigningKey becomes iroh::SecretKey (transparent serde; on-disk format byte-identical, locked by test_postcard_format_stable).
  • VerifyingKey becomes iroh::PublicKey inside AuthorPublicKey / NamespacePublicKey (API-only; iroh-docs never serializes these).
  • SignatureError becomes iroh::SignatureError for verification failures.
  • Key-parsing failures now return iroh::KeyParsingError instead of reusing SignatureError.
  • SignedEntry::verify returns a new SignedEntryVerifyError enum that separates key-parsing from signature-mismatch failures.

Breaking Changes

All breakage is in error-return positions; no method names, parameters, or semantic behavior change.

Return types changed from Result<_, SignatureError> to Result<_, KeyParsingError> on:

  • AuthorPublicKey::from_bytes, NamespacePublicKey::from_bytes
  • AuthorId::public_key, AuthorId::into_public_key
  • NamespaceId::public_key, NamespaceId::into_public_key
  • PublicKeyStore::public_key, PublicKeyStore::namespace_key, PublicKeyStore::author_key
  • TryFrom<AuthorId> for AuthorPublicKey, TryFrom<NamespaceId> for NamespacePublicKey

Other changes:

  • SignedEntry::verify now returns Result<(), SignedEntryVerifyError>.
  • From<ed25519_dalek::SigningKey> impls on Author / NamespaceSecret become From<iroh::SecretKey>.

Migration: callers using ? or anyhow are unaffected. Callers pattern-matching on SignatureError should switch to KeyParsingError for parse failures or to the new SignedEntryVerifyError variants for verify failures. Custom PublicKeyStore impls need to update their return types.

Notes & open questions

Targets 0.100.0. Stacked on #101 (the 0.99.1 wire-compat fix lands first)

Change checklist

  • Self-review.
  • Documentation updates following the style guide, if relevant.
  • Tests if relevant.
  • All breaking changes documented.

@n0bot n0bot Bot added this to iroh May 26, 2026
@github-project-automation github-project-automation Bot moved this to 🚑 Needs Triage in iroh May 26, 2026
@matheus23 matheus23 self-requested a review May 26, 2026 07:25
@cbenhagen cbenhagen force-pushed the refactor/iroh-base-public-api branch 2 times, most recently from 3a489ce to 4bea133 Compare May 26, 2026 08:29
Copy link
Copy Markdown
Member

@matheus23 matheus23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just... a couple comments too many for my taste perhaps?

Comment thread src/keys.rs Outdated
Comment thread src/sync.rs Outdated
@github-project-automation github-project-automation Bot moved this from 🚑 Needs Triage to 🏗 In progress in iroh May 26, 2026
The previous commit moved `EntrySignature` to `iroh::Signature` for wire
stability, but `iroh_docs::keys` still leaked `ed25519_dalek::{SigningKey,
VerifyingKey, SignatureError}` through `Author`, `NamespaceSecret`,
`AuthorPublicKey`, `NamespacePublicKey`, `PublicKeyStore`, and friends.
iroh-base PR #3529 ("feat(iroh-base)!: reduce external types in the
iroh-base API for keys") established the pattern for this migration -
see iroh-relay's matching `SignatureError` -> `KeyParsingError` rename
in that PR - and iroh-docs is one of the last iroh crates still leaking
these types through its public surface. This commit finishes that
migration so the iroh-docs public API no longer pins callers to a
specific upstream `ed25519_dalek`.

Concretely:

- `SigningKey` -> `iroh::SecretKey` (a transparent wrapper around dalek's
  `SigningKey` - serde passes straight through, so the on-disk format
  of `Author` / `NamespaceSecret` is byte-identical to before). The
  postcard snapshot tests in the previous commit
  (`test_author_postcard_snapshot`, `test_namespace_secret_postcard_snapshot`)
  lock that format so any future upstream `SigningKey::serialize` drift
  is caught before shipping.
- `VerifyingKey` -> `iroh::PublicKey` inside the `AuthorPublicKey` /
  `NamespacePublicKey` newtypes. `iroh::PublicKey`'s serde format
  differs from dalek's `VerifyingKey` (raw 32 bytes vs varint-length-
  prefixed 32 bytes), but iroh-docs itself never serializes these
  types - the redb store uses raw `&[u8; 32]` and the wire uses the
  raw bytes inside `RecordIdentifier` - so this is an API-only change.
- `ed25519_dalek::SignatureError` -> `iroh::SignatureError` for everything
  that's truly a signature-verification failure (`Author::verify`,
  `EntrySignature::verify`, etc.).
- Key-parsing failures (`AuthorPublicKey::from_bytes`,
  `PublicKeyStore::public_key`, the `TryFrom<AuthorId>` /
  `TryFrom<NamespaceId>` impls) now return `iroh::KeyParsingError`,
  which carries the actual reason (`InvalidKeyData`, `InvalidLength`,
  etc.) instead of opaquely reusing `SignatureError`.
- `SignedEntry::verify` now returns a small `SignedEntryVerifyError`
  enum that separates the two failure modes (key parsing vs signature
  mismatch) instead of conflating them.

`Author::new` / `NamespaceSecret::new` consume 32 bytes via
`rng.fill_bytes`, matching `ed25519_dalek::SigningKey::generate`'s
byte-consumption pattern exactly, so seeded-RNG tests
(`test_replica_queries_*`, etc.) stay deterministic across the
migration.

BREAKING CHANGE: Multiple public API return types and error types
change. Affected items include `AuthorPublicKey::from_bytes`,
`NamespacePublicKey::from_bytes`, `AuthorId::{public_key, into_public_key}`,
`NamespaceId::{public_key, into_public_key}`,
`PublicKeyStore::{public_key, namespace_key, author_key}`, the
`TryFrom<AuthorId>` / `TryFrom<NamespaceId>` impls, and
`SignedEntry::verify` (now returns `SignedEntryVerifyError`). The
`From<SigningKey>` impls on `Author` / `NamespaceSecret` become
`From<SecretKey>`.
@cbenhagen cbenhagen force-pushed the refactor/iroh-base-public-api branch from 4bea133 to b42d497 Compare May 26, 2026 08:50
@cbenhagen cbenhagen requested a review from matheus23 May 26, 2026 08:50
Copy link
Copy Markdown
Member

@matheus23 matheus23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this!

We should hold off on merging this for now - as we might want to keep main in its current state for publishing a 0.99.1. (We're still somewhat undecided about doing that. In theory we should be releasing 0.100 tomorrow anyways, but we're not 100% sure if that's the right way to do this)

Anyways - just to give some context on why I'm not yet giving it a formal ✅

@matheus23 matheus23 dismissed their stale review May 26, 2026 10:28

Changes incorporated

@dignifiedquire dignifiedquire enabled auto-merge (squash) May 26, 2026 19:59
@dignifiedquire dignifiedquire disabled auto-merge May 27, 2026 08:38
@dignifiedquire dignifiedquire enabled auto-merge (squash) May 27, 2026 08:38
@dignifiedquire dignifiedquire merged commit 14ab6a6 into n0-computer:main May 27, 2026
25 checks passed
@github-project-automation github-project-automation Bot moved this from 🏗 In progress to ✅ Done in iroh May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

3 participants