Separate the block processing time from the latency

This commit is contained in:
Luke Parker
2022-11-11 05:42:13 -05:00
parent 2411660bd8
commit fffb7a6914
7 changed files with 46 additions and 31 deletions

View File

@@ -130,8 +130,9 @@ impl<T: TendermintValidator> TendermintAuthority<T> {
.propose(
self.import.inherent_data(parent).await,
Digest::default(),
// TODO: Production time, size limit
Duration::from_secs(1),
// Assumes a block cannot take longer to download than it'll take to process
Duration::from_secs((T::BLOCK_PROCESSING_TIME_IN_SECONDS / 2).into()),
// TODO: Size limit
None,
)
.await
@@ -253,7 +254,8 @@ impl<T: TendermintValidator> Network for TendermintAuthority<T> {
type Weights = TendermintValidators<T>;
type Block = T::Block;
const BLOCK_TIME: u32 = T::BLOCK_TIME_IN_SECONDS;
const BLOCK_PROCESSING_TIME: u32 = T::BLOCK_PROCESSING_TIME_IN_SECONDS;
const LATENCY_TIME: u32 = T::LATENCY_TIME_IN_SECONDS;
fn signer(&self) -> TendermintSigner<T> {
self.active.as_ref().unwrap().signer.clone()

View File

@@ -53,7 +53,8 @@ pub fn set_config(protocol: ProtocolName) -> NonDefaultSetConfig {
/// Trait consolidating all generics required by sc_tendermint for processing.
pub trait TendermintClient: Send + Sync + 'static {
const BLOCK_TIME_IN_SECONDS: u32;
const BLOCK_PROCESSING_TIME_IN_SECONDS: u32;
const LATENCY_TIME_IN_SECONDS: u32;
type Block: Block;
type Backend: Backend<Self::Block> + 'static;
@@ -81,7 +82,8 @@ pub trait TendermintClient: Send + Sync + 'static {
/// Trait implementable on firm types to automatically provide a full TendermintClient impl.
pub trait TendermintClientMinimal: Send + Sync + 'static {
const BLOCK_TIME_IN_SECONDS: u32;
const BLOCK_PROCESSING_TIME_IN_SECONDS: u32;
const LATENCY_TIME_IN_SECONDS: u32;
type Block: Block;
type Backend: Backend<Self::Block> + 'static;
@@ -102,7 +104,8 @@ where
BlockBuilderApi<T::Block> + TendermintApi<T::Block>,
TransactionFor<T::Client, T::Block>: Send + Sync + 'static,
{
const BLOCK_TIME_IN_SECONDS: u32 = T::BLOCK_TIME_IN_SECONDS;
const BLOCK_PROCESSING_TIME_IN_SECONDS: u32 = T::BLOCK_PROCESSING_TIME_IN_SECONDS;
const LATENCY_TIME_IN_SECONDS: u32 = T::LATENCY_TIME_IN_SECONDS;
type Block = T::Block;
type Backend = T::Backend;

View File

@@ -207,8 +207,16 @@ pub trait Network: Send + Sync {
/// Type used for ordered blocks of information.
type Block: Block;
// Block time in seconds
const BLOCK_TIME: u32;
/// Maximum block processing time in seconds. This should include both the actual processing time
/// and the time to download the block.
const BLOCK_PROCESSING_TIME: u32;
/// Network latency time in seconds.
const LATENCY_TIME: u32;
/// The block time is defined as the processing time plus three times the latency.
fn block_time() -> u32 {
Self::BLOCK_PROCESSING_TIME + (3 * Self::LATENCY_TIME)
}
/// Return a handle on the signer in use, usable for the entire lifetime of the machine.
fn signer(&self) -> <Self::SignatureScheme as SignatureScheme>::Signer;

View File

@@ -155,23 +155,22 @@ impl<N: Network + 'static> TendermintMachine<N> {
fn canonical_end_time(&self, round: Round) -> u64 {
let mut time = self.canonical_start_time;
for r in 0 .. u64::from(round.0 + 1) {
time += (r + 1) * u64::from(N::BLOCK_TIME);
time += (r + 1) * u64::from(N::block_time());
}
time
}
fn timeout(&self, step: Step) -> Instant {
let mut round_time = Duration::from_secs(N::BLOCK_TIME.into());
round_time *= self.round.0 + 1;
// TODO: Non-uniform timeouts. Proposal has to validate the block which will take much longer
// than any other step
let step_time = round_time / 3;
let offset = match step {
Step::Propose => step_time,
Step::Prevote => step_time * 2,
Step::Precommit => step_time * 3,
};
let adjusted_block = N::BLOCK_PROCESSING_TIME * (self.round.0 + 1);
let adjusted_latency = N::LATENCY_TIME * (self.round.0 + 1);
let offset = Duration::from_secs(
(match step {
Step::Propose => adjusted_block + adjusted_latency,
Step::Prevote => adjusted_block + (2 * adjusted_latency),
Step::Precommit => adjusted_block + (3 * adjusted_latency),
})
.into(),
);
self.start_time + offset
}
@@ -301,7 +300,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
// 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)
// For callers wishing to avoid this, they should pass (0, GENESIS + N::block_time())
start_time: last_time,
personal_proposal: proposal,

View File

@@ -103,7 +103,8 @@ impl Network for TestNetwork {
type Weights = TestWeights;
type Block = TestBlock;
const BLOCK_TIME: u32 = 1;
const BLOCK_PROCESSING_TIME: u32 = 2;
const LATENCY_TIME: u32 = 1;
fn signer(&self) -> TestSigner {
TestSigner(self.0)
@@ -168,7 +169,5 @@ impl TestNetwork {
#[tokio::test]
async fn test() {
TestNetwork::new(4).await;
for _ in 0 .. 10 {
sleep(Duration::from_secs(1)).await;
}
sleep(Duration::from_secs(30)).await;
}