Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions crates/blockchain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ fn ms_until_next_interval(now_ms: u64, genesis_time_ms: u64) -> u64 {
MILLISECONDS_PER_INTERVAL - (ms_since_genesis % MILLISECONDS_PER_INTERVAL)
}

/// Current UNIX timestamp in milliseconds.
fn unix_now_ms() -> u64 {
SystemTime::UNIX_EPOCH
.elapsed()
.expect("already past the unix epoch")
.as_millis() as u64
}

impl BlockChain {
pub fn spawn(
store: Store,
Expand All @@ -81,10 +89,7 @@ impl BlockChain {
// Catch XMSS keys up to the current slot before the first tick
// store.time() doesn't work here: after an offline gap it lags wall-clock by
// exactly the gap we need to catch up through
let now_ms = SystemTime::UNIX_EPOCH
.elapsed()
.expect("already past the unix epoch")
.as_millis() as u64;
let now_ms = unix_now_ms();
let current_slot =
(now_ms.saturating_sub(genesis_time * 1000) / MILLISECONDS_PER_SLOT) as u32;
key_manager.advance_keys_to(current_slot);
Expand Down Expand Up @@ -692,14 +697,22 @@ pub(crate) trait BlockChainProtocol: Send + Sync {
impl BlockChainServer {
#[send_handler]
async fn handle_tick(&mut self, _msg: block_chain_protocol::Tick, ctx: &Context<Self>) {
let timestamp = SystemTime::UNIX_EPOCH
.elapsed()
.expect("already past the unix epoch");
let now_ms = timestamp.as_millis() as u64;
let now_ms = unix_now_ms();
self.on_tick(now_ms, ctx).await;
// Schedule the next tick at the next interval boundary

let genesis_time_ms = self.store.config().genesis_time * 1000;
let ms_to_next_interval = ms_until_next_interval(now_ms, genesis_time_ms);
let remaining_at_entry = ms_until_next_interval(now_ms, genesis_time_ms);
let now_after_tick = unix_now_ms();
let elapsed = now_after_tick.saturating_sub(now_ms);

// If on_tick ran past the next interval boundary, tick again
// immediately so that interval's duty still runs (issue #413).
let ms_to_next_interval = if elapsed >= remaining_at_entry {
0
} else {
// Schedule the next tick at the next interval boundary
ms_until_next_interval(now_after_tick, genesis_time_ms)
};
send_after(
Duration::from_millis(ms_to_next_interval),
ctx.clone(),
Expand Down
Loading