mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 07:21:32 +02:00
fix(lws): treat an existing account as registered, not as a node outage
register_account called add_account unconditionally when provisioning was off, which is production's default. monero-lws answers a duplicate with account_exists as an HTTP 500, the backend maps that to a node error, and the user is told NODE_UNAVAILABLE. A routine re-registration was therefore indistinguishable from the node being down. Reported 2026-09-08: a tip failed with an upstream error while both LWS instances were active and had logged no warnings in 24 hours. Nothing was wrong with the node or the account. The provisioning path already checked existence first and documented why. That check now guards both paths, so registration is idempotent and the two branches cannot drift apart again.
This commit is contained in:
+18
-13
@@ -226,22 +226,27 @@ impl LwsClient {
|
||||
view_key: &str,
|
||||
provision_minors: u32,
|
||||
) -> Result<(), AppError> {
|
||||
if provision_minors == 0 {
|
||||
// Provisioning off (the dark default): exactly the call this made
|
||||
// before, including monero-lws answering a duplicate `add_account`
|
||||
// with `account_exists` (an HTTP 500 it maps to a node error).
|
||||
return self.admin_add_account(address, view_key).await;
|
||||
}
|
||||
// Provisioning on: an account that ALREADY exists must still be brought
|
||||
// up to the required ceiling. monero-lws fails a duplicate `add_account`
|
||||
// (`db::storage::do_add_account` returns `lws::error::account_exists`,
|
||||
// served as a 500), so calling it unconditionally would abort before the
|
||||
// provisioning below and make the account permanently unprovisionable
|
||||
// through this path. Existence is checked first instead; nothing about
|
||||
// the account's scan state is touched.
|
||||
// Registration is idempotent. An account that is already scanning is
|
||||
// success, not a failure.
|
||||
//
|
||||
// This used to call `add_account` unconditionally when provisioning was
|
||||
// off, so re-registering an existing account got `account_exists` back as
|
||||
// an HTTP 500, which maps to a node error and reaches the user as
|
||||
// NODE_UNAVAILABLE. A routine re-registration was indistinguishable from
|
||||
// the node being down: reported 2026-09-08 by a user whose tip failed
|
||||
// with an upstream error while both LWS instances were healthy and had
|
||||
// logged nothing at all.
|
||||
//
|
||||
// The existence check now guards both paths rather than only the
|
||||
// provisioning one, so the two cannot drift apart again.
|
||||
if self.account_scan_height(address).await?.is_none() {
|
||||
self.admin_add_account(address, view_key).await?;
|
||||
}
|
||||
if provision_minors == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
// Provisioning on: an account that already exists must still be brought up
|
||||
// to the required ceiling, so this runs whether or not the add just ran.
|
||||
self.provision_account0_covering(address, view_key, provision_minors)
|
||||
.await?;
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user