penumbra_sdk_transaction/
witness_data.rs

1use std::collections::BTreeMap;
2
3use penumbra_sdk_proto::{core::transaction::v1 as pb, DomainType};
4use penumbra_sdk_shielded_pool::note;
5use penumbra_sdk_tct as tct;
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Serialize, Deserialize)]
9#[serde(try_from = "pb::WitnessData", into = "pb::WitnessData")]
10pub struct WitnessData {
11    pub anchor: tct::Root,
12    pub state_commitment_proofs: BTreeMap<note::StateCommitment, tct::Proof>,
13}
14
15impl WitnessData {
16    /// Add proof to the existing witness data
17    pub fn add_proof(&mut self, nc: note::StateCommitment, proof: tct::Proof) {
18        self.state_commitment_proofs.insert(nc, proof);
19    }
20}
21
22impl DomainType for WitnessData {
23    type Proto = pb::WitnessData;
24}
25
26impl From<WitnessData> for pb::WitnessData {
27    fn from(msg: WitnessData) -> Self {
28        Self {
29            anchor: Some(msg.anchor.into()),
30            state_commitment_proofs: msg
31                .state_commitment_proofs
32                .into_values()
33                .map(|v| v.into())
34                .collect(),
35        }
36    }
37}
38
39impl TryFrom<pb::WitnessData> for WitnessData {
40    type Error = anyhow::Error;
41
42    fn try_from(msg: pb::WitnessData) -> Result<Self, Self::Error> {
43        let mut state_commitment_proofs = BTreeMap::new();
44        for proof in msg.state_commitment_proofs {
45            let tct_proof: tct::Proof = proof.try_into()?;
46            state_commitment_proofs.insert(tct_proof.commitment(), tct_proof);
47        }
48        Ok(Self {
49            anchor: msg
50                .anchor
51                .ok_or_else(|| anyhow::anyhow!("missing anchor"))?
52                .try_into()?,
53            state_commitment_proofs,
54        })
55    }
56}