From 1af6117155f0b887ae2b4350a2bfe38300272ae6 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sun, 30 Oct 2022 04:27:15 -0400 Subject: [PATCH] Move TendermintMachine from start_num, time to last_num, time Provides an explicitly clear API clearer to program around. Also adds additional time code to handle an edge case. --- substrate/tendermint/client/src/tendermint.rs | 10 ++--- substrate/tendermint/machine/src/lib.rs | 45 ++++++++++++------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/substrate/tendermint/client/src/tendermint.rs b/substrate/tendermint/client/src/tendermint.rs index f70e3c9a..7b8051c4 100644 --- a/substrate/tendermint/client/src/tendermint.rs +++ b/substrate/tendermint/client/src/tendermint.rs @@ -61,11 +61,11 @@ impl TendermintAuthority { let info = self.0.client.info(); // Header::Number: TryInto doesn't implement Debug and can't be unwrapped - let start_number = match TryInto::::try_into(info.best_number) { - Ok(best) => BlockNumber(best + 1), + let last_number = match info.best_number.try_into() { + Ok(best) => BlockNumber(best), Err(_) => panic!("BlockNumber exceeded u64"), }; - let start_time = Commit::>::decode( + let last_time = Commit::>::decode( &mut self .0 .client @@ -76,7 +76,7 @@ impl TendermintAuthority { .as_ref(), ) .map(|commit| commit.end_time) - // TODO: Genesis start time + // TODO: Genesis start time + BLOCK_TIME .unwrap_or_else(|_| SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()); let proposal = self @@ -88,7 +88,7 @@ impl TendermintAuthority { self.0.clone(), // TODO 0, // ValidatorId - (start_number, start_time), + (last_number, last_time), proposal, )); } diff --git a/substrate/tendermint/machine/src/lib.rs b/substrate/tendermint/machine/src/lib.rs index 7fb02bf6..cb73bcf0 100644 --- a/substrate/tendermint/machine/src/lib.rs +++ b/substrate/tendermint/machine/src/lib.rs @@ -242,24 +242,32 @@ impl TendermintMachine { pub fn new( network: N, proposer: N::ValidatorId, - start: (BlockNumber, u64), + last: (BlockNumber, u64), proposal: N::Block, ) -> TendermintHandle { - // Convert the start time to an instant - // This is imprecise yet should be precise enough - let start_time = { - let instant_now = Instant::now(); - let sys_now = SystemTime::now(); - instant_now - - sys_now - .duration_since(UNIX_EPOCH + Duration::from_secs(start.1)) - .unwrap_or(Duration::ZERO) - }; - let (msg_send, mut msg_recv) = mpsc::channel(100); // Backlog to accept. Currently arbitrary TendermintHandle { messages: msg_send, handle: tokio::spawn(async move { + let last_end = UNIX_EPOCH + Duration::from_secs(last.1); + + // If the last block hasn't ended yet, sleep until it has + { + let now = SystemTime::now(); + if last_end > now { + sleep(last_end.duration_since(now).unwrap_or(Duration::ZERO)).await; + } + } + + // Convert the last time to an instant + // This is imprecise yet should be precise enough, given this library only has + // second accuracy + let last_time = { + let instant_now = Instant::now(); + let sys_now = SystemTime::now(); + instant_now - sys_now.duration_since(last_end).unwrap_or(Duration::ZERO) + }; + let signer = network.signature_scheme(); let weights = network.weights(); let network = Arc::new(RwLock::new(network)); @@ -270,9 +278,16 @@ impl TendermintMachine { weights: weights.clone(), proposer, - number: start.0, - canonical_start_time: start.1, - start_time, + number: BlockNumber(last.0.0 + 1), + canonical_start_time: last.1, + // The end time of the last block is the start time for this one + // The Commit explicitly contains the end time, so loading the last commit will provide + // this. The only exception is for the genesis block, which doesn't have a commit + // Using the genesis time in place will cause this block to be created immediately after + // it, without the standard amount of separation (so their times will be equivalent or + // minimally offset) + // For callers wishing to avoid this, they should pass (0, GENESIS + BLOCK_TIME) + start_time: last_time, personal_proposal: proposal, queue: vec![],