Skip to main content

ValidatorSet

Trait ValidatorSet 

Source
pub trait ValidatorSet {
    type Validator: Validator;

    // Required methods
    fn total_weight(&self) -> NonZero<u16>;
    fn validators(&self) -> impl IntoIterator<Item = &Self::Validator>;
    fn weight(&self, validator: &Self::Validator) -> Option<NonZero<u16>>;
    fn proposer(
        &self,
        block_number: BlockNumber,
        round_number: RoundNumber,
    ) -> Self::Validator;

    // Provided methods
    fn threshold(&self) -> u16 { ... }
    fn fault_threshold(&self) -> u16 { ... }
}
Expand description

The set of validators

Required Associated Types§

Source

type Validator: Validator

The type used to identify validators.

Required Methods§

Source

fn total_weight(&self) -> NonZero<u16>

The total weight of all validators.

If this method is incorrect, the Tendermint process MAY panic or be otherwise incorrect.

Source

fn validators(&self) -> impl IntoIterator<Item = &Self::Validator>

An iterator over every validator.

The validators MUST be consistent for the lifetime of this blockchain. However, the order they’re yielded in DOES NOT have to be stable. Every validator MUST have weight in the consensus process.

If this method is incorrect, the Tendermint process MAY panic or be otherwise incorrect.

Source

fn weight(&self, validator: &Self::Validator) -> Option<NonZero<u16>>

The weight for a specific validator.

This MUST be consistent for the lifetime of this blockchain.

If this method is incorrect, the Tendermint process MAY panic or be otherwise incorrect.

Source

fn proposer( &self, block_number: BlockNumber, round_number: RoundNumber, ) -> Self::Validator

The proposer for this block and round number.

This MUST be deterministic to these two arguments, block_number and round_number, and should presumably be a weighted round robin.

Provided Methods§

Source

fn threshold(&self) -> u16

The threshold of weight needed for consensus.

This MUST return a value equal to ((self.total_weight() * 2) / 3) + 1, as the provided implementation does.

Source

fn fault_threshold(&self) -> u16

The threshold of weight which may be faulty.

This MUST return a value equal to self.total_weight() - self.threshold(), as the provided implementation does.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<V: ?Sized + ValidatorSet> ValidatorSet for &V

Source§

type Validator = <V as ValidatorSet>::Validator

Source§

fn total_weight(&self) -> NonZero<u16>

Source§

fn validators(&self) -> impl IntoIterator<Item = &Self::Validator>

Source§

fn weight(&self, validator: &Self::Validator) -> Option<NonZero<u16>>

Source§

fn proposer( &self, block_number: BlockNumber, round_number: RoundNumber, ) -> Self::Validator

Source§

impl<V: PartialOrd + Ord + Validator, H: BuildHasher> ValidatorSet for HashMap<V, NonZero<u16>, H>

Available on crate feature std only.
Source§

fn total_weight(&self) -> NonZero<u16>

This MAY panic or be incorrect if the values’ sum is zero or is not representable in a u16.

Source§

fn proposer( &self, block_number: BlockNumber, round_number: RoundNumber, ) -> Self::Validator

This implements a weighted round robin with the validators ordered by the ordinality of their IDs. This MAY run in time superlinear to the amount of validators, despite expecting this to be called upon every block proposal. This MAY only make sense for small validator sets accordingly. For large validator sets, the representation of a ValidatorSet SHOULD cache the order of the round robin as to allow executing this function with a lookup.

The round robin is initialized with the block number’s as the starting index, regardless of if prior blocks required multiple rounds to achieve consensus. The round robin is spaced out such that validators with multiple units of weight are not assigned simultaneous slots within a single iteration of the round robin unless they have more weight than all other validators. Each validator’s slots are not guaranteed to be uniformly distributed however and MAY grow in density as the round robin approaches its tail.

To ensure a random distribution, a random coin would be needed, which Tendermint does not require (nor provide). A bespoke ValidatorSet implementation could make use of one however. Lacking one, this attempts to provide a slightly more fair distribution (as detailed above), but this is solely on a best-effort basis.

Source§

type Validator = V

Source§

fn validators(&self) -> impl IntoIterator<Item = &Self::Validator>

Source§

fn weight(&self, validator: &Self::Validator) -> Option<NonZero<u16>>

Source§

impl<V: PartialOrd + Ord + Validator> ValidatorSet for BTreeMap<V, NonZero<u16>>

Available on crate feature alloc only.
Source§

fn total_weight(&self) -> NonZero<u16>

This MAY panic or be incorrect if the values’ sum is zero or is not representable in a u16.

Source§

fn proposer( &self, block_number: BlockNumber, round_number: RoundNumber, ) -> Self::Validator

This implements a weighted round robin with the validators ordered by the ordinality of their IDs. This MAY run in time superlinear to the amount of validators, despite expecting this to be called upon every block proposal. This MAY only make sense for small validator sets accordingly. For large validator sets, the representation of a ValidatorSet SHOULD cache the order of the round robin as to allow executing this function with a lookup.

The round robin is initialized with the block number’s as the starting index, regardless of if prior blocks required multiple rounds to achieve consensus. The round robin is spaced out such that validators with multiple units of weight are not assigned simultaneous slots within a single iteration of the round robin unless they have more weight than all other validators. Each validator’s slots are not guaranteed to be uniformly distributed however and MAY grow in density as the round robin approaches its tail.

To ensure a random distribution, a random coin would be needed, which Tendermint does not require (nor provide). A bespoke ValidatorSet implementation could make use of one however. Lacking one, this attempts to provide a slightly more fair distribution (as detailed above), but this is solely on a best-effort basis.

Source§

type Validator = V

Source§

fn validators(&self) -> impl IntoIterator<Item = &Self::Validator>

Source§

fn weight(&self, validator: &Self::Validator) -> Option<NonZero<u16>>

Implementors§