penumbra_sdk_tct/
proof.rs

1use poseidon377::Fq;
2
3use crate::prelude::*;
4
5/// A proof of the inclusion of some [`Commitment`] in a [`Tree`] with a particular [`Root`].
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Proof(
8    pub(super)  crate::internal::proof::Proof<
9        frontier::Top<frontier::Tier<frontier::Tier<frontier::Item>>>,
10    >,
11);
12
13impl Proof {
14    /// Construct a new [`Proof`] of inclusion for a given [`Commitment`], index, and authentication
15    /// path from root to leaf.
16    pub fn new(
17        commitment: StateCommitment,
18        position: Position,
19        auth_path: [[Hash; 3]; 24],
20    ) -> Self {
21        use crate::internal::path::{Leaf, Node};
22
23        let position = position.into();
24
25        let [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x] = auth_path;
26        let child = Leaf;
27        let child = Node { siblings: x, child };
28        let child = Node { siblings: w, child };
29        let child = Node { siblings: v, child };
30        let child = Node { siblings: u, child };
31        let child = Node { siblings: t, child };
32        let child = Node { siblings: s, child };
33        let child = Node { siblings: r, child };
34        let child = Node { siblings: q, child };
35        let child = Node { siblings: p, child };
36        let child = Node { siblings: o, child };
37        let child = Node { siblings: n, child };
38        let child = Node { siblings: m, child };
39        let child = Node { siblings: l, child };
40        let child = Node { siblings: k, child };
41        let child = Node { siblings: j, child };
42        let child = Node { siblings: i, child };
43        let child = Node { siblings: h, child };
44        let child = Node { siblings: g, child };
45        let child = Node { siblings: f, child };
46        let child = Node { siblings: e, child };
47        let child = Node { siblings: d, child };
48        let child = Node { siblings: c, child };
49        let child = Node { siblings: b, child };
50        let child = Node { siblings: a, child };
51        Self(crate::internal::proof::Proof {
52            leaf: commitment,
53            position,
54            auth_path: child,
55        })
56    }
57
58    /// Generate a dummy [`Proof`] for a given commitment.
59    pub fn dummy<R: Rng + rand::CryptoRng>(rng: &mut R, commitment: StateCommitment) -> Self {
60        let dummy_position = 0u64.into();
61        let dummy_auth_path: [[Hash; 3]; 24] = [[Hash::new(Fq::rand(rng)); 3]; 24];
62        Self::new(commitment, dummy_position, dummy_auth_path)
63    }
64
65    /// Verify a [`Proof`] of inclusion against the [`Root`] of a [`Tree`].
66    ///
67    /// # Errors
68    ///
69    /// Returns [`VerifyError`] if the proof is invalid for that [`Root`].
70    pub fn verify(&self, root: Root) -> Result<(), VerifyError> {
71        self.0.verify(root.0)
72    }
73
74    /// Get the commitment whose inclusion is witnessed by the proof.
75    pub fn commitment(&self) -> StateCommitment {
76        self.0.leaf
77    }
78
79    /// Get the position of the witnessed commitment.
80    pub fn position(&self) -> crate::Position {
81        self.0.index().into()
82    }
83
84    /// Get the root of the tree from which the proof was generated.
85    pub fn root(&self) -> Root {
86        Root(self.0.root())
87    }
88
89    /// Get the authentication path for this proof, order from root to leaf.
90    pub fn auth_path(&self) -> [&[Hash; 3]; 24] {
91        use crate::internal::path::{Leaf, Node};
92        let child = self.0.auth_path();
93        let Node { siblings: a, child } = child;
94        let Node { siblings: b, child } = child;
95        let Node { siblings: c, child } = child;
96        let Node { siblings: d, child } = child;
97        let Node { siblings: e, child } = child;
98        let Node { siblings: f, child } = child;
99        let Node { siblings: g, child } = child;
100        let Node { siblings: h, child } = child;
101        let Node { siblings: i, child } = child;
102        let Node { siblings: j, child } = child;
103        let Node { siblings: k, child } = child;
104        let Node { siblings: l, child } = child;
105        let Node { siblings: m, child } = child;
106        let Node { siblings: n, child } = child;
107        let Node { siblings: o, child } = child;
108        let Node { siblings: p, child } = child;
109        let Node { siblings: q, child } = child;
110        let Node { siblings: r, child } = child;
111        let Node { siblings: s, child } = child;
112        let Node { siblings: t, child } = child;
113        let Node { siblings: u, child } = child;
114        let Node { siblings: v, child } = child;
115        let Node { siblings: w, child } = child;
116        let Node { siblings: x, child } = child;
117        let Leaf = child;
118        [
119            a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
120        ]
121    }
122}
123
124use penumbra_sdk_proto::penumbra::crypto::tct::v1 as pb;
125use rand::Rng;
126
127impl From<Proof> for pb::StateCommitmentProof {
128    fn from(proof: Proof) -> Self {
129        proof.0.into()
130    }
131}
132
133impl TryFrom<pb::StateCommitmentProof> for Proof {
134    type Error = crate::error::proof::DecodeError;
135
136    fn try_from(value: pb::StateCommitmentProof) -> Result<Self, Self::Error> {
137        Ok(Proof(crate::internal::proof::Proof::try_from(value)?))
138    }
139}
140
141impl penumbra_sdk_proto::DomainType for Proof {
142    type Proto = pb::StateCommitmentProof;
143}