fix(lnd): give the rotation's verify step its own deadline
The mint wait and the post-rotation verify shared one 15-minute budget. A rotation that legitimately spent 14 of those minutes waiting for LND to mint a fresh macaroon — normal on a loaded node, where opening channel.db/graph.db/ wallet.db alone has been measured at 2m38s — then had 60 seconds to confirm the node identity and channel census came back, and would report FAILURE on a wallet that was completely healthy. That is the most alarming possible way to be wrong about someone's Lightning node: it names a backup directory and tells them to investigate before retrying, at the exact moment nothing is actually broken. Each wait now gets its own budget. Waiting longer costs nothing here — the failure this step exists to catch (changed identity, missing channels) is not time-sensitive. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
45c2925bdd
commit
a9cefb8326
@@ -616,10 +616,11 @@ async fn run_rotation(
|
|||||||
.await
|
.await
|
||||||
.with_context(|| format!("unlocking the wallet — old material is in {backup}"))?;
|
.with_context(|| format!("unlocking the wallet — old material is in {backup}"))?;
|
||||||
|
|
||||||
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(MACAROON_WAIT_SECS);
|
let mint_deadline =
|
||||||
|
std::time::Instant::now() + std::time::Duration::from_secs(MACAROON_WAIT_SECS);
|
||||||
let admin_path = format!("{LND_MAINNET_DIR}/admin.macaroon");
|
let admin_path = format!("{LND_MAINNET_DIR}/admin.macaroon");
|
||||||
let mut new_digest = None;
|
let mut new_digest = None;
|
||||||
while std::time::Instant::now() < deadline {
|
while std::time::Instant::now() < mint_deadline {
|
||||||
if let Some(d) = digest_as_root(&admin_path).await {
|
if let Some(d) = digest_as_root(&admin_path).await {
|
||||||
new_digest = Some(d);
|
new_digest = Some(d);
|
||||||
break;
|
break;
|
||||||
@@ -644,8 +645,17 @@ async fn run_rotation(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 6. Verify the things that must NOT have changed.
|
// 6. Verify the things that must NOT have changed.
|
||||||
|
//
|
||||||
|
// Its own budget, deliberately not the mint deadline. Sharing one would mean
|
||||||
|
// a rotation that legitimately spent 14 of its 15 minutes waiting for LND to
|
||||||
|
// mint gets 1 minute to prove the channels came back, and then reports
|
||||||
|
// FAILURE on a node that is perfectly healthy — the most alarming possible
|
||||||
|
// way to be wrong about someone's Lightning wallet.
|
||||||
with_progress(|p| p.set("verify", StepState::Running, None));
|
with_progress(|p| p.set("verify", StepState::Running, None));
|
||||||
let (pubkey_after, census_after) = wait_for_serving(deadline).await.with_context(|| {
|
let verify_deadline =
|
||||||
|
std::time::Instant::now() + std::time::Duration::from_secs(MACAROON_WAIT_SECS);
|
||||||
|
let (pubkey_after, census_after) =
|
||||||
|
wait_for_serving(verify_deadline).await.with_context(|| {
|
||||||
format!("verifying the node after rotation — old material is in {backup}")
|
format!("verifying the node after rotation — old material is in {backup}")
|
||||||
})?;
|
})?;
|
||||||
with_progress(|p| p.channels_after = Some(census_after.channels_open));
|
with_progress(|p| p.channels_after = Some(census_after.channels_open));
|
||||||
|
|||||||
Reference in New Issue
Block a user