From a1341581701aa82a99c1ebb8519b073317388970 Mon Sep 17 00:00:00 2001 From: jwinterm Date: Wed, 10 Jun 2026 14:57:09 -0400 Subject: [PATCH] Contracts: store the signed tx after the wallet-state commit save_step wrote the tx file (store_tx) before the atomic batch commit, so a DB failure could leave the stored tx out of sync with wallet state. Move store_tx to after batch.commit() (and after the post-commit signing-context check), matching the core convention in internal::selection. #755 keeps stored txs as files for all flows, so this reorder closes the desync window without diverging from core. Addresses PR #754 review (utils.rs). --- libwallet/src/contract/utils.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libwallet/src/contract/utils.rs b/libwallet/src/contract/utils.rs index 4f724e0..1164f01 100644 --- a/libwallet/src/contract/utils.rs +++ b/libwallet/src/contract/utils.rs @@ -215,9 +215,6 @@ where // Update TxLogEntry if we have signed the contract (we have data about the kernel) if is_signed { update_tx_log_entry(w, keychain_mask, &slate, &context, &mut tx_log_entry)?; - // TODO: It's possible to store the transaction in a file while and the atomic commit below fails - // In this case, we should revert to the previous stored tx to avoid having discrepancy - w.store_tx(&format!("{}", slate.id), slate.tx_or_err()?)?; } // If we added outputs in this step, we have to create OutputData here because 'batch' // takes the mutable ref and we can no longer call calc_commit_for_cache for output @@ -300,6 +297,13 @@ where )); } } + + // Store the signed transaction only after the wallet-state batch has committed (and + // the signing context is confirmed gone), so a DB failure can't leave the stored tx + // out of sync with wallet state. Matches the core convention (internal::selection). + if is_signed { + w.store_tx(&format!("{}", slate.id), slate.tx_or_err()?)?; + } debug!("contract::utils::save_step => Atomic updated done"); Ok(())