Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package org.dashfoundation.example.services

import org.dashfoundation.dashsdk.identity.IdentityKeyPreview
import org.dashfoundation.dashsdk.identity.RegistrationKeySet
import org.dashfoundation.dashsdk.identity.RegistrationKeySlot
import org.dashfoundation.dashsdk.identity.RegistrationKeys

/**
* Registration key provisioning — the derive-set → persist → zero →
* build-rich-rows sequence the create-identity flow runs before it broadcasts.
* App-level analog of Swift's `CreateIdentityView` submit path
* (`prePersistIdentityKeysForRegistration` + `makeDashpayKeyPair`).
* (`prePersistIdentityKeysForRegistration`).
*
* ## Why a dedicated helper rather than reusing `IdentityKeyAdditionFlow`
*
Expand All @@ -22,11 +23,11 @@ import org.dashfoundation.dashsdk.identity.RegistrationKeys
* `previewRegistrationKeySet` pass — the secret-lifecycle mandate is one
* derivation, not N overlapping ones;
* - its policy depends on the existing identity's current key IDs and builds
* an update batch, while registration needs a fixed 0..N role table before
* the identity exists.
* an update batch, while registration needs the Rust-owned creation layout
* before the identity exists.
*
* Forcing registration through it would fork its semantics; this helper reuses
* the shared pieces instead — the SDK's [RegistrationKeys] role table for the
* the shared pieces instead — the Rust layout via [RegistrationKeys] for the
* on-chain rows and [IdentityKeyPersistence] for the store-then-zero secret
* discipline (shared with [IdentityKeyAdditionFlow]).
*/
Expand All @@ -37,8 +38,8 @@ object DashpayKeyProvisioning {
* rich rows the registration wire format carries, tied to the identity HD
* slot that produced them.
*
* [previews] must be exactly `RegistrationKeys.keyCount(includeDashPayKeys)`
* rows in key-ID order — the single [IdentityKeyPreview] derivation pass
* [previews] must be exactly one row per [slots] entry, in key-ID order
* ([slots] is `RegistrationKeys.layout(...)` for the flow's layout) — the single [IdentityKeyPreview] derivation pass
* (`previewRegistrationKeySet`). Every preview's private array is zeroed on
* both the success and every failure path (including the count-mismatch
* rejection); a partial persist failure never leaves a plaintext scalar
Expand All @@ -53,11 +54,11 @@ object DashpayKeyProvisioning {
*/
suspend fun provision(
previews: List<IdentityKeyPreview>,
includeDashPayKeys: Boolean,
slots: List<RegistrationKeySlot>,
walletId: ByteArray,
persister: IdentityKeyPersistence.PrivateKeyPersister,
): RegistrationKeySet {
val expected = RegistrationKeys.keyCount(includeDashPayKeys)
val expected = slots.size
try {
// Inside the try so the catch below scrubs the derived scalars even
// on a count-mismatch rejection (a wire-skew symptom) — no plaintext
Expand Down Expand Up @@ -89,7 +90,7 @@ object DashpayKeyProvisioning {
identityIndex = previews.first().identityIndex,
rows = RegistrationKeys.buildRegistrationRows(
previews.map { it.publicKey },
includeDashPayKeys,
slots,
),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.dashfoundation.dashsdk.identity.IdentityCreationKeyLayout
import org.dashfoundation.dashsdk.identity.RegistrationKeys
import org.dashfoundation.dashsdk.tokens.InvitationPreview
import org.dashfoundation.example.di.LocalAppContainer
Expand Down Expand Up @@ -144,17 +145,18 @@ fun ClaimInvitationSheet(
.filter { it.walletId?.contentEquals(wallet.walletId) == true }
.map { it.identityIndex } + heldByCoordinator,
)
// Full fresh-registration set: base four + the DashPay
// enc/dec pair, pre-persisted before the broadcast.
// Full fresh-registration set (Rust layout, DashPay
// enc/dec pair included), pre-persisted before the broadcast.
val layout = IdentityCreationKeyLayout.NEW_IDENTITY_WITH_DASHPAY_KEYS
val previews = mgr.identityRegistration.previewRegistrationKeySet(
walletHandle = wallet.handle,
mnemonicResolverHandle = mgr.mnemonicResolverHandle,
identityIndex = identityIndex,
count = RegistrationKeys.keyCount(includeDashPayKeys = true),
layout = layout,
)
val keySet = DashpayKeyProvisioning.provision(
previews = previews,
includeDashPayKeys = true,
slots = RegistrationKeys.layout(layout),
walletId = wallet.walletId,
persister = { keyHex, priv, owner ->
container.walletStorage.storePrivateKey(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.dashfoundation.dashsdk.identity.IdentityCreationKeyLayout
import org.dashfoundation.dashsdk.identity.RegistrationKeys
import org.dashfoundation.dashsdk.persistence.entities.InvitationEntity
import org.dashfoundation.dashsdk.wallet.ManagedPlatformWallet
import org.dashfoundation.example.di.LocalAppContainer
Expand Down Expand Up @@ -151,19 +153,19 @@ fun ReclaimInvitationSheet(
walletIdentities.map { it.identityIndex } + heldByCoordinator,
)
// Pre-broadcast local work — BEFORE the marker, so a
// failure here leaves no in-flight marker. Base 4-key
// set: a reclaim sends no contact request (iOS
// authKeyCount = 4).
// failure here leaves no in-flight marker. New-identity
// set without DashPay keys: a reclaim sends no contact
// request.
val layout = IdentityCreationKeyLayout.NEW_IDENTITY
val previews = mgr.identityRegistration.previewRegistrationKeySet(
walletHandle = wallet.handle,
mnemonicResolverHandle = mgr.mnemonicResolverHandle,
identityIndex = identityIndex,
count = org.dashfoundation.dashsdk.identity.RegistrationKeys
.keyCount(includeDashPayKeys = false),
layout = layout,
)
val keySet = DashpayKeyProvisioning.provision(
previews = previews,
includeDashPayKeys = false,
slots = RegistrationKeys.layout(layout),
walletId = wallet.walletId,
persister = { keyHex, priv, owner ->
container.walletStorage.storePrivateKey(
Expand Down
Loading
Loading