casper_types/block/
finality_signature.rs

1mod finality_signature_v1;
2mod finality_signature_v2;
3
4pub use finality_signature_v1::FinalitySignatureV1;
5pub use finality_signature_v2::FinalitySignatureV2;
6
7use core::{
8    fmt::{self, Display, Formatter},
9    hash::Hash,
10};
11
12#[cfg(feature = "datasize")]
13use datasize::DataSize;
14#[cfg(any(feature = "testing", test))]
15use rand::Rng;
16#[cfg(feature = "json-schema")]
17use schemars::JsonSchema;
18use serde::{Deserialize, Serialize};
19
20use crate::{crypto, BlockHash, EraId, PublicKey, Signature};
21#[cfg(any(feature = "testing", test))]
22use crate::{testing::TestRng, ChainNameDigest};
23
24/// A validator's signature of a block, confirming it is finalized.
25///
26/// Clients and joining nodes should wait until the signers' combined weight exceeds the fault
27/// tolerance threshold before accepting the block as finalized.
28#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Debug)]
29#[cfg_attr(
30    feature = "json-schema",
31    derive(JsonSchema),
32    schemars(description = "A validator's signature of a block, confirming it is finalized.")
33)]
34#[cfg_attr(feature = "datasize", derive(DataSize))]
35pub enum FinalitySignature {
36    /// Version 1 of the finality signature.
37    V1(FinalitySignatureV1),
38    /// Version 2 of the finality signature.
39    V2(FinalitySignatureV2),
40}
41
42impl FinalitySignature {
43    /// Returns the block hash of the associated block.
44    pub fn block_hash(&self) -> &BlockHash {
45        match self {
46            FinalitySignature::V1(fs) => fs.block_hash(),
47            FinalitySignature::V2(fs) => fs.block_hash(),
48        }
49    }
50
51    /// Returns the era in which the associated block was created.
52    pub fn era_id(&self) -> EraId {
53        match self {
54            FinalitySignature::V1(fs) => fs.era_id(),
55            FinalitySignature::V2(fs) => fs.era_id(),
56        }
57    }
58
59    /// Returns the public key of the signing validator.
60    pub fn public_key(&self) -> &PublicKey {
61        match self {
62            FinalitySignature::V1(fs) => fs.public_key(),
63            FinalitySignature::V2(fs) => fs.public_key(),
64        }
65    }
66
67    /// Returns the signature over the block hash of the associated block.
68    pub fn signature(&self) -> &Signature {
69        match self {
70            FinalitySignature::V1(fs) => fs.signature(),
71            FinalitySignature::V2(fs) => fs.signature(),
72        }
73    }
74
75    /// Returns `Ok` if the signature is cryptographically valid.
76    pub fn is_verified(&self) -> Result<(), crypto::Error> {
77        match self {
78            FinalitySignature::V1(fs) => fs.is_verified(),
79            FinalitySignature::V2(fs) => fs.is_verified(),
80        }
81    }
82
83    /// Returns a random `FinalitySignature`.
84    #[cfg(any(feature = "testing", test))]
85    pub fn random(rng: &mut TestRng) -> Self {
86        let block_hash = BlockHash::random(rng);
87        let block_height = rng.gen();
88        let era_id = EraId::random(rng);
89        let chain_name_hash = ChainNameDigest::random(rng);
90        Self::random_for_block(block_hash, block_height, era_id, chain_name_hash, rng)
91    }
92
93    /// Returns a random `FinalitySignature` for the provided `block_hash` and `era_id`.
94    #[cfg(any(feature = "testing", test))]
95    pub fn random_for_block(
96        block_hash: BlockHash,
97        block_height: u64,
98        era_id: EraId,
99        chain_name_hash: ChainNameDigest,
100        rng: &mut TestRng,
101    ) -> Self {
102        if rng.gen_bool(0.5) {
103            FinalitySignature::V1(FinalitySignatureV1::random_for_block(
104                block_hash, era_id, rng,
105            ))
106        } else {
107            FinalitySignature::V2(FinalitySignatureV2::random_for_block(
108                block_hash,
109                block_height,
110                era_id,
111                chain_name_hash,
112                rng,
113            ))
114        }
115    }
116}
117
118impl From<FinalitySignatureV1> for FinalitySignature {
119    fn from(fs: FinalitySignatureV1) -> Self {
120        FinalitySignature::V1(fs)
121    }
122}
123
124impl From<FinalitySignatureV2> for FinalitySignature {
125    fn from(fs: FinalitySignatureV2) -> Self {
126        FinalitySignature::V2(fs)
127    }
128}
129
130impl Display for FinalitySignature {
131    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
132        match self {
133            FinalitySignature::V1(fs) => write!(f, "{}", fs),
134            FinalitySignature::V2(fs) => write!(f, "{}", fs),
135        }
136    }
137}