round_time.rs
Overview
This file implements a time calculation mechanism for rounds in a block-based system. It defines a RoundTime structure that manages multiple "buckets" of round durations, allowing the calculation of a current round number and the remaining time within that round based on an elapsed duration from the parent block. The design accommodates varying round durations and iteration counts using configurable buckets, enabling flexible round time modeling that can adapt to different system requirements.
Structures and Core Components
RoundBucket
Purpose: Represents a configuration unit for rounds consisting of:
round_duration: The duration of a single round in this bucket.max_number_of_loops: The maximum allowed iterations (loops) in this bucket.
Fields:
round_duration: Duration— Duration of each round within the bucket.max_number_of_loops: u32— Maximum number of loops allowed in this bucket.
Traits:
Derives
Clonefor duplicating instances.
RoundTime
Purpose: Holds a sequence of
RoundBuckets and a default bucket to calculate the round and remaining round time given elapsed durations.Fields:
buckets: Vec<RoundBucket>— A vector of configured round buckets.default_bucket: Duration— Duration used for rounds not covered by any bucket.
Builder Pattern:
Uses the TypedBuilder crate for an ergonomic builder pattern.
Custom mutator method
add_bucketvalidates and appends buckets dynamically.Buckets are added in order of increasing round duration.
default_bucketis required and used as a fallback.
Key Methods:
RoundTime::linearCreates a
RoundTimeinstance with linearly increasing round durations frommin_round_durationtomax_round_durationin steps ofstep.Each bucket has a single loop (
max_number_of_loops = 1).Parameters:
min_round_duration: Duration— Minimum round duration to start from.step: Duration— Increment of round duration per bucket.max_round_duration: Duration— Maximum round duration to stop at.
Returns: A constructed
RoundTimewith buckets representing linear increments.Usage Example:
let round_time = RoundTime::linear( Duration::from_secs(1), Duration::from_secs(1), Duration::from_secs(10), );
RoundTime::calculate_roundCalculates the current round number and remaining time within that round based on the elapsed duration since the parent block and the block's backing set size.
Parameters:
duration_from_parent_block: Duration— The elapsed duration from the parent block.block_bk_set_size: u16— Number of blocks in the backing set, affects loop calculations.
Returns:
CalculateRoundResultcontaining:round: BlockRound— The calculated round number.round_remaining_time: Duration— Remaining time in the current round.
Algorithm:
Iterates over buckets in order:
Computes total duration per bucket as
round_duration * block_bk_set_size * max_number_of_loops.If remaining duration exceeds this, adds corresponding rounds and decrements remaining duration.
Else, uses helper division function to determine how many loops and rounds fit in remaining time.
If no buckets apply, falls back to the
default_bucket.
Usage Example:
let result = round_time.calculate_round(Duration::from_secs(120), 10); println!("Round: {}, Remaining: {:?}", result.round, result.round_remaining_time);
CalculateRoundResult
Purpose: Return type for
RoundTime::calculate_round.Fields:
round: BlockRound— The computed round number.round_remaining_time: Duration— Remaining duration in the current round.
Helper Function: div_with_reminder
Purpose: Divides one
Durationby another and returns the quotient as au32and the remainder as aDuration.Implementation Details:
Uses floating-point division (
div_duration_f64) for precision.Applies floor to quotient and safely converts it to
u32.Calculates remainder by subtracting the multiplied divisor from the dividend.
Parameters:
duration: Duration— Dividend duration.divider: Duration— Divisor duration.
Returns: Tuple
(u32, Duration)representing quotient and remainder.
Implementation Details and Algorithms
The main calculation logic in
calculate_roundhandles multiple buckets, each with a distinct round duration and loop count.The calculation accumulates rounds by fully consuming buckets where the remaining time exceeds their maximum duration.
For partial consumption of a bucket, it calculates how many full loops fit in the remaining time, then how many rounds fit in the leftover time.
The use of floating-point division in
div_with_reminderensures handling of large durations without overflow or precision loss.The
RoundTime::linearmethod provides a utility for generating buckets with increasing round durations, useful for common linear scaling scenarios.
Interaction with Other Parts of the Application
The file depends on external types:
BlockRoundfromcrate::typesrepresents the round number type.
The calculated rounds and times are likely used in scheduling, timing, or consensus modules that require precise round-based timing.
The builder pattern facilitates integration with configuration or initialization code that sets up round timing parameters.
Tests
The
testsmodule verifies:Basic round calculation correctness with a simple default bucket.
Proper ordering and effect of multiple buckets with different durations and loop counts.
Mermaid Diagram: Structure of round_time.rs
classDiagram
class RoundBucket {
- round_duration: Duration
- max_number_of_loops: u32
}
class RoundTime {
- buckets: Vec<RoundBucket>
- default_bucket: Duration
+ linear(min_round_duration: Duration, step: Duration, max_round_duration: Duration) RoundTime
+ calculate_round(duration_from_parent_block: Duration, block_bk_set_size: u16) CalculateRoundResult
}
class CalculateRoundResult {
+ round: BlockRound
+ round_remaining_time: Duration
}
RoundTime --> "0..*" RoundBucket
RoundTime ..> CalculateRoundResult
This diagram shows the relationships between the core data structures and their key methods in this file.