Skip to main content

celestia_types/
fraud_proof.rs

1//! Fraud proof related types and traits.
2//!
3//! A fraud proof is a proof of the detected malicious action done to the network.
4
5use std::fmt;
6
7use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
8use tendermint_proto::Protobuf;
9
10pub use crate::byzantine::BadEncodingFraudProof;
11use crate::hash::Hash;
12use crate::{Error, ExtendedHeader, Result};
13
14/// A proof of the malicious actions done to the network.
15pub trait FraudProof {
16    /// Name of the proof type.
17    const TYPE: &'static str;
18
19    /// HeaderHash returns the block hash.
20    fn header_hash(&self) -> Hash;
21
22    /// Height returns the block height corresponding to the Proof.
23    fn height(&self) -> u64;
24
25    /// Checks the validity of the fraud proof.
26    ///
27    /// # Errors
28    ///
29    /// Returns an error if some conditions don't pass and thus fraud proof is not valid.
30    fn validate(&self, header: &ExtendedHeader) -> Result<()>;
31}
32
33/// Raw representation of the generic fraud proof.
34///
35/// Consists of the name of the proof type and the protobuf serialized payload
36/// holding the proof itself.
37#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
38pub struct RawFraudProof {
39    proof_type: String,
40    #[serde(with = "tendermint_proto::serializers::bytes::base64string")]
41    data: Vec<u8>,
42}
43
44/// Aggregation of all the supported fraud proofs.
45#[derive(Clone, Debug, PartialEq, Deserialize)]
46#[serde(try_from = "RawFraudProof", into = "RawFraudProof")]
47#[non_exhaustive]
48pub enum Proof {
49    /// A proof that a block producer incorrectly encoded [`ExtendedDataSquare`].
50    ///
51    /// [`ExtendedDataSquare`]: crate::eds::ExtendedDataSquare
52    BadEncoding(BadEncodingFraudProof),
53}
54
55impl Proof {
56    /// Returns proof type.
57    pub fn proof_type(&self) -> ProofType {
58        match self {
59            Proof::BadEncoding(_) => ProofType::BadEncoding,
60        }
61    }
62}
63
64/// Proof type
65#[derive(Clone, Copy, Debug)]
66pub enum ProofType {
67    /// Bad encoding fraud proof.
68    BadEncoding,
69}
70
71impl ProofType {
72    /// Returns the string representation.
73    pub fn to_str(&self) -> &'static str {
74        match self {
75            ProofType::BadEncoding => BadEncodingFraudProof::TYPE,
76        }
77    }
78}
79
80impl Serialize for ProofType {
81    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82    where
83        S: Serializer,
84    {
85        self.to_str().serialize(serializer)
86    }
87}
88
89impl<'de> Deserialize<'de> for ProofType {
90    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91    where
92        D: Deserializer<'de>,
93    {
94        struct ProofTypeVisitor;
95
96        impl<'de> de::Visitor<'de> for ProofTypeVisitor {
97            type Value = ProofType;
98
99            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
100                formatter.write_str("a string representing proof type: 'badencoding'")
101            }
102
103            fn visit_str<E>(self, value: &str) -> Result<ProofType, E>
104            where
105                E: de::Error,
106            {
107                match value {
108                    BadEncodingFraudProof::TYPE => Ok(ProofType::BadEncoding),
109                    _ => Err(E::invalid_value(de::Unexpected::Str(value), &self)),
110                }
111            }
112        }
113
114        deserializer.deserialize_str(ProofTypeVisitor)
115    }
116}
117
118impl TryFrom<RawFraudProof> for Proof {
119    type Error = Error;
120
121    fn try_from(value: RawFraudProof) -> Result<Self, Self::Error> {
122        match value.proof_type.as_str() {
123            BadEncodingFraudProof::TYPE => {
124                let befp = BadEncodingFraudProof::decode_vec(&value.data)?;
125                Ok(Proof::BadEncoding(befp))
126            }
127            _ => Err(Error::UnsupportedFraudProofType(value.proof_type)),
128        }
129    }
130}
131
132impl From<&Proof> for RawFraudProof {
133    fn from(value: &Proof) -> Self {
134        match value {
135            Proof::BadEncoding(befp) => RawFraudProof {
136                proof_type: BadEncodingFraudProof::TYPE.to_owned(),
137                data: befp.clone().encode_vec(),
138            },
139        }
140    }
141}
142
143impl Serialize for Proof {
144    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
145    where
146        S: Serializer,
147    {
148        let raw: RawFraudProof = self.into();
149        raw.serialize(serializer)
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use crate::consts::appconsts::AppVersion;
156    use crate::test_utils::{ExtendedHeaderGenerator, corrupt_eds, generate_dummy_eds};
157
158    use super::*;
159
160    #[test]
161    fn befp_serde() {
162        let mut generator = ExtendedHeaderGenerator::new();
163        let mut eds = generate_dummy_eds(8, AppVersion::V2);
164        let (_, proof) = corrupt_eds(&mut generator, &mut eds);
165
166        let proof = Proof::BadEncoding(proof);
167
168        let serialized = serde_json::to_string(&proof).unwrap();
169        let deserialized: Proof = serde_json::from_str(&serialized).unwrap();
170
171        assert_eq!(deserialized, proof);
172    }
173}