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.
This commit is contained in:
Luke Parker 2022-10-30 04:27:15 -04:00
parent edb2e00db7
commit 1af6117155
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
2 changed files with 35 additions and 20 deletions

View file

@ -61,11 +61,11 @@ impl<T: TendermintValidator> TendermintAuthority<T> {
let info = self.0.client.info(); let info = self.0.client.info();
// Header::Number: TryInto<u64> doesn't implement Debug and can't be unwrapped // Header::Number: TryInto<u64> doesn't implement Debug and can't be unwrapped
let start_number = match TryInto::<u64>::try_into(info.best_number) { let last_number = match info.best_number.try_into() {
Ok(best) => BlockNumber(best + 1), Ok(best) => BlockNumber(best),
Err(_) => panic!("BlockNumber exceeded u64"), Err(_) => panic!("BlockNumber exceeded u64"),
}; };
let start_time = Commit::<TendermintValidators<T>>::decode( let last_time = Commit::<TendermintValidators<T>>::decode(
&mut self &mut self
.0 .0
.client .client
@ -76,7 +76,7 @@ impl<T: TendermintValidator> TendermintAuthority<T> {
.as_ref(), .as_ref(),
) )
.map(|commit| commit.end_time) .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()); .unwrap_or_else(|_| SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs());
let proposal = self let proposal = self
@ -88,7 +88,7 @@ impl<T: TendermintValidator> TendermintAuthority<T> {
self.0.clone(), self.0.clone(),
// TODO // TODO
0, // ValidatorId 0, // ValidatorId
(start_number, start_time), (last_number, last_time),
proposal, proposal,
)); ));
} }

View file

@ -242,24 +242,32 @@ impl<N: Network + 'static> TendermintMachine<N> {
pub fn new( pub fn new(
network: N, network: N,
proposer: N::ValidatorId, proposer: N::ValidatorId,
start: (BlockNumber, u64), last: (BlockNumber, u64),
proposal: N::Block, proposal: N::Block,
) -> TendermintHandle<N> { ) -> TendermintHandle<N> {
// 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 let (msg_send, mut msg_recv) = mpsc::channel(100); // Backlog to accept. Currently arbitrary
TendermintHandle { TendermintHandle {
messages: msg_send, messages: msg_send,
handle: tokio::spawn(async move { 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 signer = network.signature_scheme();
let weights = network.weights(); let weights = network.weights();
let network = Arc::new(RwLock::new(network)); let network = Arc::new(RwLock::new(network));
@ -270,9 +278,16 @@ impl<N: Network + 'static> TendermintMachine<N> {
weights: weights.clone(), weights: weights.clone(),
proposer, proposer,
number: start.0, number: BlockNumber(last.0.0 + 1),
canonical_start_time: start.1, canonical_start_time: last.1,
start_time, // 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, personal_proposal: proposal,
queue: vec![], queue: vec![],