Skip to content

Commit 2de938f

Browse files
committed
Fix advance loop to handle multiple window advances after extended outages
The previous loop returned an error after a single failed advance, but a node that was offline for more than one window (65,536 slots) needs multiple advances. Now detects true key exhaustion by comparing the prepared interval before and after advance_preparation().
1 parent e1e2583 commit 2de938f

2 files changed

Lines changed: 10 additions & 1 deletion

File tree

crates/blockchain/src/key_manager.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,13 @@ impl KeyManager {
105105

106106
// Advance XMSS key preparation window if the slot is outside the current window.
107107
// Each bottom tree covers 65,536 slots; the window holds 2 at a time.
108+
// Multiple advances may be needed if the node was offline for an extended period.
108109
if !secret_key.is_prepared_for(slot) {
109110
info!(validator_id, slot, "Advancing XMSS key preparation window");
110111
while !secret_key.is_prepared_for(slot) {
112+
let before = secret_key.get_prepared_interval();
111113
secret_key.advance_preparation();
112-
if !secret_key.is_prepared_for(slot) {
114+
if secret_key.get_prepared_interval() == before {
113115
return Err(KeyManagerError::SigningError(format!(
114116
"XMSS key exhausted for validator {validator_id}: \
115117
slot {slot} is beyond the key's activation interval"

crates/common/types/src/signature.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::Range;
2+
13
use leansig::{
24
serialization::Serializable,
35
signature::{SignatureScheme, SignatureSchemeSecretKey as _, SigningError},
@@ -106,6 +108,11 @@ impl ValidatorSecretKey {
106108
self.inner.get_prepared_interval().contains(&(slot as u64))
107109
}
108110

111+
/// Returns the slot range currently covered by the prepared window.
112+
pub fn get_prepared_interval(&self) -> Range<u64> {
113+
self.inner.get_prepared_interval()
114+
}
115+
109116
/// Advance the prepared window forward by one bottom tree.
110117
///
111118
/// Each call slides the window by sqrt(LIFETIME) = 65,536 slots.

0 commit comments

Comments
 (0)