Skip to main content

Keygen with Reconcile Protocol

Overview

keygen (like import and refresh) does not write your active keyshare directly. The freshly generated share is first written to the staged slot of its ReconcileStoreDao; a short reconcile exchange with the cloud then settles it before it becomes the current share.

Why the extra step? When the key-generation session ends, your device has produced a share — but the SDK cannot be certain the cloud peer persisted its matching share. A dropped connection or a crash at that moment can leave the two sides disagreeing. Reconcile is the commit protocol that gets both parties onto the same key, and the two-slot (current / staged) record is what makes it crash-safe: whatever happens, one slot always holds a usable value, and an interrupted keygen can be finished later without repeating the expensive MPC computation.

Your StorageClient is the source of truth throughout: the SDK reads the record back before and after the exchange and drives every slot transition through your write.

Reconcile runs automatically as the final step of keygen, refresh, and import — you normally never call it yourself. DuoSession exposes reconcile(keyId:) async -> Result<Data, Error> only as a manual retry: if a prior operation crashed mid-reconcile, call it with the affected keyId to complete the protocol. The diagram below shows what the SDK does internally.

Outcomes

For a fresh keygen, reconcile settles into one of two results:

  • Complete — the staged share landed; the SDK promotes it to current and clears staged.
  • Already applied — a prior interrupted attempt had already committed; the SDK confirms storage matches and moves on.

A first keygen has no earlier share to fall back to, so it never rolls back. refresh — which replaces an existing share — additionally has a rollback path.

Key Components

ComponentDescriptionInterface
StorageClientManages keyshare transactions/states and storage operationsStorageClientInterface app supposed to implement
Mobile SDKSilentShard SDK-
CloudCloud node-
Current KeyshareKeyshare went through reconcile protocol successfully-
Staged KeyshareKeyshare which will be subjected to reconcile protocol and could potentially become current keyshare if it goes through reconcile successfully-
Loading Diagram...

Retrying after a crash

keygen, import, and refresh reconcile internally, so you normally never call reconcile yourself. The exception is recovery after a crash: if the app is killed mid-reconcile, the new share stays in the staged slot and was never promoted. Calling reconcile(keyId:) on next launch resumes from that staged share — it does not re-run keygen.

A robust integration reconciles on startup: enumerate every stored keyId and call reconcile on each, so any key left mid-transition is settled before the user signs.

// Run once on app launch.
func reconcileOnStartup(duoSession: DuoSession, storedKeyIds: [String]) async {
for keyId in storedKeyIds {
if case .failure(let error) = await duoSession.reconcile(keyId: keyId) {
Swift.print("reconcile failed for \(keyId): \(error)")
}
}
}