Skip to content

Commit c963ba9

Browse files
committed
Merge branch 'main' into devnet5
2 parents 98bdb66 + 9a56f54 commit c963ba9

2 files changed

Lines changed: 62 additions & 2 deletions

File tree

crates/blockchain/src/key_manager.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use std::collections::HashMap;
2+
use std::time::Instant;
23

34
use ethlambda_types::{
45
attestation::{AttestationData, XmssSignature},
56
primitives::{H256, HashTreeRoot as _},
67
signature::{ValidatorSecretKey, ValidatorSignature},
78
};
8-
use tracing::info;
9+
use tracing::{info, warn};
910

1011
use crate::metrics;
1112

@@ -48,6 +49,14 @@ impl KeyManager {
4849
self.keys.keys().copied().collect()
4950
}
5051

52+
/// Advances every validator's XMSS preparation windows to cover slot
53+
pub fn advance_keys_to(&mut self, slot: u32) {
54+
for (validator_id, key_pair) in self.keys.iter_mut() {
55+
advance_key(*validator_id, &mut key_pair.attestation_key, slot);
56+
advance_key(*validator_id, &mut key_pair.proposal_key, slot);
57+
}
58+
}
59+
5160
/// Signs an attestation using the validator's attestation key.
5261
pub fn sign_attestation(
5362
&mut self,
@@ -85,6 +94,7 @@ impl KeyManager {
8594
// Multiple advances may be needed if the node was offline for an extended period.
8695
if !key_pair.attestation_key.is_prepared_for(slot) {
8796
info!(validator_id, slot, "Advancing XMSS key preparation window");
97+
let start = Instant::now();
8898
while !key_pair.attestation_key.is_prepared_for(slot) {
8999
let before = key_pair.attestation_key.get_prepared_interval();
90100
key_pair.attestation_key.advance_preparation();
@@ -95,6 +105,12 @@ impl KeyManager {
95105
)));
96106
}
97107
}
108+
info!(
109+
validator_id,
110+
slot,
111+
elapsed_ms = start.elapsed().as_millis() as u64,
112+
"Advanced XMSS key preparation window"
113+
);
98114
}
99115

100116
let signature: ValidatorSignature = {
@@ -130,6 +146,7 @@ impl KeyManager {
130146
validator_id,
131147
slot, "Advancing XMSS proposal key preparation window"
132148
);
149+
let start = Instant::now();
133150
while !key_pair.proposal_key.is_prepared_for(slot) {
134151
let before = key_pair.proposal_key.get_prepared_interval();
135152
key_pair.proposal_key.advance_preparation();
@@ -140,6 +157,12 @@ impl KeyManager {
140157
)));
141158
}
142159
}
160+
info!(
161+
validator_id,
162+
slot,
163+
elapsed_ms = start.elapsed().as_millis() as u64,
164+
"Advanced XMSS proposal key preparation window"
165+
);
143166
}
144167

145168
let signature: ValidatorSignature = key_pair
@@ -153,6 +176,28 @@ impl KeyManager {
153176
}
154177
}
155178

179+
fn advance_key(validator_id: u64, key: &mut ValidatorSecretKey, slot: u32) {
180+
if key.is_prepared_for(slot) {
181+
return;
182+
}
183+
info!(validator_id, slot, "Advancing XMSS key preparation window");
184+
let start = Instant::now();
185+
while !key.is_prepared_for(slot) {
186+
let before = key.get_prepared_interval();
187+
key.advance_preparation();
188+
if key.get_prepared_interval() == before {
189+
warn!(validator_id, slot, "XMSS key activation interval exhausted");
190+
break;
191+
}
192+
}
193+
info!(
194+
validator_id,
195+
slot,
196+
elapsed_ms = start.elapsed().as_millis() as u64,
197+
"Advanced XMSS key preparation window"
198+
);
199+
}
200+
156201
#[cfg(test)]
157202
mod tests {
158203
use super::*;

crates/blockchain/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,19 @@ impl BlockChain {
6262
metrics::set_is_aggregator(aggregator.is_enabled());
6363
metrics::set_node_sync_status(metrics::SyncStatus::Idle);
6464
let genesis_time = store.config().genesis_time;
65-
let key_manager = key_manager::KeyManager::new(validator_keys);
65+
let mut key_manager = key_manager::KeyManager::new(validator_keys);
66+
67+
// Catch XMSS keys up to the current slot before the first tick
68+
// store.time() doesn't work here: after an offline gap it lags wall-clock by
69+
// exactly the gap we need to catch up through
70+
let now_ms = SystemTime::UNIX_EPOCH
71+
.elapsed()
72+
.expect("already past the unix epoch")
73+
.as_millis() as u64;
74+
let current_slot =
75+
(now_ms.saturating_sub(genesis_time * 1000) / MILLISECONDS_PER_SLOT) as u32;
76+
key_manager.advance_keys_to(current_slot);
77+
6678
let handle = BlockChainServer {
6779
store,
6880
p2p: None,
@@ -193,6 +205,9 @@ impl BlockChainServer {
193205
metrics::update_safe_target_slot(self.store.safe_target_slot());
194206
// Update head slot metric (head may change when attestations are promoted at intervals 0/4)
195207
metrics::update_head_slot(self.store.head_slot());
208+
209+
// Advance XMSS keys for next slot so the signing paths don't have to
210+
self.key_manager.advance_keys_to((slot + 1) as u32);
196211
}
197212

198213
/// Kick off a committee-signature aggregation session:

0 commit comments

Comments
 (0)