-
Notifications
You must be signed in to change notification settings - Fork 13
fix(wallet): stop a duplicate identity index from making a wallet unloadable #951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v1.0-dev
Are you sure you want to change the base?
Changes from all commits
dfcb906
72de5ae
dc547a1
4c1013a
ff26767
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ use dash_sdk::dpp::identity::accessors::IdentityGettersV0; | |
| use dash_sdk::platform::Identifier; | ||
|
|
||
| impl AppContext { | ||
| pub(super) fn remove_identity( | ||
| pub(super) async fn remove_identity( | ||
| &self, | ||
| identity_id: Identifier, | ||
| ) -> Result<BackendTaskSuccessResult, TaskError> { | ||
|
|
@@ -16,11 +16,13 @@ impl AppContext { | |
| .map(|(voter_identity, _)| voter_identity.id()) | ||
| }); | ||
|
|
||
| self.release_identity_index(&identity_id).await; | ||
| self.delete_local_qualified_identity(&identity_id)?; | ||
|
|
||
| let mut removed_identity_ids = vec![identity_id]; | ||
| let mut associated_cleanup_failed = false; | ||
| if let Some(voter_id) = associated_voter_identity_id.filter(|id| *id != identity_id) { | ||
| self.release_identity_index(&voter_id).await; | ||
| match self.delete_local_qualified_identity(&voter_id) { | ||
| Ok(()) => removed_identity_ids.push(voter_id), | ||
| Err(error) => { | ||
|
|
@@ -39,4 +41,27 @@ impl AppContext { | |
| associated_cleanup_failed, | ||
| }) | ||
| } | ||
|
|
||
| /// Release the identity index this identity holds in the wallet backend. | ||
| /// | ||
| /// DET's own records are not the only ones holding it: an entry left behind | ||
| /// upstream keeps the index occupied by an identity the user believes is | ||
| /// gone, which blocks re-adding one there and lets a later registration | ||
| /// collide into the damaged-saved-data failure. | ||
| /// | ||
| /// Best-effort — a wallet not registered this session has nothing to | ||
| /// release, and the user's removal must complete either way. | ||
| async fn release_identity_index(&self, identity_id: &Identifier) { | ||
| let Ok(backend) = self.wallet_backend() else { | ||
| return; | ||
| }; | ||
| if let Err(error) = backend.forget_identity(identity_id).await { | ||
| tracing::warn!( | ||
| %identity_id, | ||
| %error, | ||
| "Identity index could not be released in the wallet backend; \ | ||
| adding an identity at that index may be refused" | ||
| ); | ||
| } | ||
|
Comment on lines
+54
to
+65
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift Do not report removal success when index release fails.
Return the typed release error before local deletion, or persist a durable retry record before reporting successful removal. As per coding guidelines, backend tasks are the authoritative enforcement layer and must return typed 🤖 Prompt for AI AgentsSource: Coding guidelines
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The finding is valid, but propagating
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
DET must persist a durable tombstone or a durable cleanup-retry record before it deletes the local identity and returns The review finding remains valid with this stronger requirement. 🐇🔍 ✏️ Learnings added
You are interacting with an AI system. |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 Blocking: Keep the local identity until index release is durable
release_identity_indexis best-effort, but the local identity is deleted unconditionally immediately afterward. If backend initialization was deferred,wallet_backend()fails and release becomes a no-op. Even with an initialized backend, the pinned upstreamIdentityManager::remove_identitymutates memory, callspersister.store, logs and swallows any persistence error, and still returns success. A transient failure leaves the tombstone only in the persister buffer, while a terminal failure drops it; exiting before a retained write commits lets the old occupant reappear on restart after DET has deleted the identity and its only cleanup retry anchor. Reusing the apparently free slot can then recreate duplicate persisted identity rows or leave a paid replacement unmanaged. Require an observably durable tombstone, or save a durable cleanup-retry record, before deleting the local identity and reporting removal success.source: ['codex']