tendermint_machine/
ext.rs1use core::{hash::Hash, fmt::Debug};
2use std::{sync::Arc, collections::HashSet};
3
4use async_trait::async_trait;
5use thiserror::Error;
6
7use parity_scale_codec::{Encode, Decode};
8
9use crate::{SignedMessageFor, commit_msg};
10
11pub trait ValidatorId:
14 Send + Sync + Clone + Copy + PartialEq + Eq + Hash + Debug + Encode + Decode
15{
16}
17impl<V: Send + Sync + Clone + Copy + PartialEq + Eq + Hash + Debug + Encode + Decode> ValidatorId
18 for V
19{
20}
21
22pub trait Signature: Send + Sync + Clone + PartialEq + Debug + Encode + Decode {}
25impl<S: Send + Sync + Clone + PartialEq + Debug + Encode + Decode> Signature for S {}
26
27#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode)]
31pub struct BlockNumber(pub u64);
32#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encode, Decode)]
34pub struct RoundNumber(pub u32);
35
36#[async_trait]
38pub trait Signer: Send + Sync {
39 type ValidatorId: ValidatorId;
41 type Signature: Signature;
43
44 async fn validator_id(&self) -> Option<Self::ValidatorId>;
46 async fn sign(&self, msg: &[u8]) -> Self::Signature;
48}
49
50#[async_trait]
51impl<S: Signer> Signer for Arc<S> {
52 type ValidatorId = S::ValidatorId;
53 type Signature = S::Signature;
54
55 async fn validator_id(&self) -> Option<Self::ValidatorId> {
56 self.as_ref().validator_id().await
57 }
58
59 async fn sign(&self, msg: &[u8]) -> Self::Signature {
60 self.as_ref().sign(msg).await
61 }
62}
63
64pub trait SignatureScheme: Send + Sync {
66 type ValidatorId: ValidatorId;
68 type Signature: Signature;
70 type AggregateSignature: Signature;
75
76 type Signer: Signer<ValidatorId = Self::ValidatorId, Signature = Self::Signature>;
78
79 #[must_use]
81 fn verify(&self, validator: Self::ValidatorId, msg: &[u8], sig: &Self::Signature) -> bool;
82
83 fn aggregate(sigs: &[Self::Signature]) -> Self::AggregateSignature;
85 #[must_use]
87 fn verify_aggregate(
88 &self,
89 signers: &[Self::ValidatorId],
90 msg: &[u8],
91 sig: &Self::AggregateSignature,
92 ) -> bool;
93}
94
95impl<S: SignatureScheme> SignatureScheme for Arc<S> {
96 type ValidatorId = S::ValidatorId;
97 type Signature = S::Signature;
98 type AggregateSignature = S::AggregateSignature;
99 type Signer = S::Signer;
100
101 fn verify(&self, validator: Self::ValidatorId, msg: &[u8], sig: &Self::Signature) -> bool {
102 self.as_ref().verify(validator, msg, sig)
103 }
104
105 fn aggregate(sigs: &[Self::Signature]) -> Self::AggregateSignature {
106 S::aggregate(sigs)
107 }
108
109 #[must_use]
110 fn verify_aggregate(
111 &self,
112 signers: &[Self::ValidatorId],
113 msg: &[u8],
114 sig: &Self::AggregateSignature,
115 ) -> bool {
116 self.as_ref().verify_aggregate(signers, msg, sig)
117 }
118}
119
120#[derive(Clone, PartialEq, Debug, Encode, Decode)]
123pub struct Commit<S: SignatureScheme> {
124 pub end_time: u64,
126 pub validators: Vec<S::ValidatorId>,
128 pub signature: S::AggregateSignature,
130}
131
132pub trait Weights: Send + Sync {
134 type ValidatorId: ValidatorId;
135
136 fn total_weight(&self) -> u64;
138 fn weight(&self, validator: Self::ValidatorId) -> u64;
140 fn threshold(&self) -> u64 {
142 ((self.total_weight() * 2) / 3) + 1
143 }
144 fn fault_thresold(&self) -> u64 {
146 (self.total_weight() - self.threshold()) + 1
147 }
148
149 fn proposer(&self, block: BlockNumber, round: RoundNumber) -> Self::ValidatorId;
151}
152
153impl<W: Weights> Weights for Arc<W> {
154 type ValidatorId = W::ValidatorId;
155
156 fn total_weight(&self) -> u64 {
157 self.as_ref().total_weight()
158 }
159
160 fn weight(&self, validator: Self::ValidatorId) -> u64 {
161 self.as_ref().weight(validator)
162 }
163
164 fn proposer(&self, block: BlockNumber, round: RoundNumber) -> Self::ValidatorId {
165 self.as_ref().proposer(block, round)
166 }
167}
168
169#[derive(Clone, Copy, PartialEq, Eq, Debug, Error, Encode, Decode)]
171pub enum BlockError {
172 #[error("invalid block")]
174 Fatal,
175 #[error("invalid block under local view")]
178 Temporal,
179}
180
181pub trait Block: Send + Sync + Clone + PartialEq + Debug + Encode + Decode {
183 type Id: Send + Sync + Copy + Clone + PartialEq + AsRef<[u8]> + Debug + Encode + Decode;
185
186 fn id(&self) -> Self::Id;
188}
189
190#[cfg(feature = "substrate")]
191impl<B: sp_runtime::traits::Block> Block for B {
192 type Id = B::Hash;
193 fn id(&self) -> B::Hash {
194 self.hash()
195 }
196}
197
198#[async_trait]
200pub trait Network: Send + Sync {
201 type ValidatorId: ValidatorId;
203 type SignatureScheme: SignatureScheme<ValidatorId = Self::ValidatorId>;
205 type Weights: Weights<ValidatorId = Self::ValidatorId>;
207 type Block: Block;
209
210 const BLOCK_PROCESSING_TIME: u32;
213 const LATENCY_TIME: u32;
215
216 fn block_time() -> u32 {
218 Self::BLOCK_PROCESSING_TIME + (3 * Self::LATENCY_TIME)
219 }
220
221 fn signer(&self) -> <Self::SignatureScheme as SignatureScheme>::Signer;
223 fn signature_scheme(&self) -> Self::SignatureScheme;
225 fn weights(&self) -> Self::Weights;
227
228 #[must_use]
231 fn verify_commit(
232 &self,
233 id: <Self::Block as Block>::Id,
234 commit: &Commit<Self::SignatureScheme>,
235 ) -> bool {
236 if commit.validators.iter().collect::<HashSet<_>>().len() != commit.validators.len() {
237 return false;
238 }
239
240 if !self.signature_scheme().verify_aggregate(
241 &commit.validators,
242 &commit_msg(commit.end_time, id.as_ref()),
243 &commit.signature,
244 ) {
245 return false;
246 }
247
248 let weights = self.weights();
249 commit.validators.iter().map(|v| weights.weight(*v)).sum::<u64>() >= weights.threshold()
250 }
251
252 async fn broadcast(&mut self, msg: SignedMessageFor<Self>);
257
258 async fn slash(&mut self, validator: Self::ValidatorId);
261
262 async fn validate(&mut self, block: &Self::Block) -> Result<(), BlockError>;
264 async fn add_block(
270 &mut self,
271 block: Self::Block,
272 commit: Commit<Self::SignatureScheme>,
273 ) -> Self::Block;
274}