fix(chat): session-guard the fast-scan callback (stale-wallet ingest)
Review of 30bd0d9 found the 0-conf fast-scan MainCb was the one async chat
callback missing the chat_session_generation_ guard the broadcast + identity-fetch
callbacks use. worker_ survives a wallet switch/lock, so a fast-scan posted under
wallet A could drain after resetChatSession() and ingest A's metadata (or toast)
against wallet B's freshly-provisioned store.
- Capture scanGen at post time and drop the result if it changed by drain time.
- Clear chat_fast_scan_in_flight_ in resetChatSession() so a switch immediately
re-enables the fast path; the stale callback returns WITHOUT clearing the flag so
it can't clobber the new session's own in-flight scan (generation is bumped only
in resetChatSession, which already reset the flag).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2765,6 +2765,7 @@ void App::resetChatSession()
|
||||
chat_db_.lock();
|
||||
chat_identity_provisioned_ = false;
|
||||
chat_identity_fetch_in_flight_ = false;
|
||||
chat_fast_scan_in_flight_ = false; // a stale in-flight fast-scan is dropped by its session guard
|
||||
chat_identity_unavailable_ = false;
|
||||
// Invalidate any in-flight identity fetch that captured the PREVIOUS wallet's secret, so its
|
||||
// completion callback can't provision that secret under the new wallet.
|
||||
@@ -3178,7 +3179,8 @@ void App::fastScanChatMemos()
|
||||
if (addr.empty()) return;
|
||||
|
||||
chat_fast_scan_in_flight_ = true;
|
||||
worker_->post([this, addr]() -> rpc::RPCWorker::MainCb {
|
||||
const int scanGen = chat_session_generation_; // guard: drop the result if the wallet switches/locks
|
||||
worker_->post([this, addr, scanGen]() -> rpc::RPCWorker::MainCb {
|
||||
std::vector<chat::HushChatTransactionMetadata> metadata;
|
||||
try {
|
||||
rpc::RPCClient::TraceScope trace("HushChat / 0-conf fast scan");
|
||||
@@ -3208,7 +3210,11 @@ void App::fastScanChatMemos()
|
||||
}
|
||||
}
|
||||
} catch (const std::exception&) {}
|
||||
return [this, metadata = std::move(metadata)]() mutable {
|
||||
return [this, scanGen, metadata = std::move(metadata)]() mutable {
|
||||
// The wallet was switched/locked between post and now — this metadata belongs to the previous
|
||||
// session. resetChatSession already reset the in-flight flag, so just drop; clearing it here
|
||||
// would clobber a new session's own in-flight scan (mirrors the broadcast/identity guards).
|
||||
if (scanGen != chat_session_generation_) return;
|
||||
chat_fast_scan_in_flight_ = false;
|
||||
if (metadata.empty()) return;
|
||||
// Skip HIDDEN conversations — the mempool fast path deliberately doesn't surface them; they
|
||||
|
||||
Reference in New Issue
Block a user