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
|
||||
.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 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 {
|
||||
new_digest = Some(d);
|
||||
break;
|
||||
@@ -644,10 +645,19 @@ async fn run_rotation(
|
||||
});
|
||||
|
||||
// 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));
|
||||
let (pubkey_after, census_after) = wait_for_serving(deadline).await.with_context(|| {
|
||||
format!("verifying the node after rotation — old material is in {backup}")
|
||||
})?;
|
||||
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}")
|
||||
})?;
|
||||
with_progress(|p| p.channels_after = Some(census_after.channels_open));
|
||||
if pubkey_after != pubkey_before {
|
||||
with_progress(|p| p.set("verify", StepState::Failed, None));
|
||||
|
||||
Reference in New Issue
Block a user