sapling_crypto/pczt/
prover.rs1use core::fmt;
2
3use rand::{CryptoRng, RngCore};
4
5use crate::{
6 prover::{OutputProver, SpendProver},
7 Note, Rseed,
8};
9
10impl super::Bundle {
11 pub fn create_proofs<S, O, R: RngCore + CryptoRng>(
13 &mut self,
14 spend_prover: &S,
15 output_prover: &O,
16 mut rng: R,
17 ) -> Result<(), ProverError>
18 where
19 S: SpendProver,
20 O: OutputProver,
21 {
22 for spend in &mut self.spends {
23 let proof_generation_key = spend
24 .proof_generation_key
25 .clone()
26 .ok_or(ProverError::MissingProofGenerationKey)?;
27
28 let note = Note::from_parts(
29 spend.recipient.ok_or(ProverError::MissingRecipient)?,
30 spend.value.ok_or(ProverError::MissingValue)?,
31 spend.rseed.ok_or(ProverError::MissingRandomSeed)?,
32 );
33
34 let alpha = spend.alpha.ok_or(ProverError::MissingSpendAuthRandomizer)?;
35
36 let rcv = spend
37 .rcv
38 .clone()
39 .ok_or(ProverError::MissingValueCommitTrapdoor)?;
40
41 let merkle_path = spend.witness.clone().ok_or(ProverError::MissingWitness)?;
42
43 let circuit = S::prepare_circuit(
44 proof_generation_key,
45 *note.recipient().diversifier(),
46 *note.rseed(),
47 note.value(),
48 alpha,
49 rcv,
50 self.anchor.inner(),
51 merkle_path,
52 )
53 .ok_or(ProverError::InvalidDiversifier)?;
54
55 let proof = spend_prover.create_proof(circuit, &mut rng);
56 spend.zkproof = Some(S::encode_proof(proof));
57 }
58
59 for output in &mut self.outputs {
60 let recipient = output.recipient.ok_or(ProverError::MissingRecipient)?;
61 let value = output.value.ok_or(ProverError::MissingValue)?;
62
63 let note = Note::from_parts(
64 recipient,
65 value,
66 output
67 .rseed
68 .map(Rseed::AfterZip212)
69 .ok_or(ProverError::MissingRandomSeed)?,
70 );
71
72 let esk = note.generate_or_derive_esk(&mut rng);
73 let rcm = note.rcm();
74
75 let rcv = output
76 .rcv
77 .clone()
78 .ok_or(ProverError::MissingValueCommitTrapdoor)?;
79
80 let circuit = O::prepare_circuit(&esk, recipient, rcm, value, rcv);
81 let proof = output_prover.create_proof(circuit, &mut rng);
82 output.zkproof = Some(O::encode_proof(proof));
83 }
84
85 Ok(())
86 }
87}
88
89#[derive(Debug)]
91#[non_exhaustive]
92pub enum ProverError {
93 InvalidDiversifier,
100 MissingProofGenerationKey,
102 MissingRandomSeed,
104 MissingRecipient,
106 MissingSpendAuthRandomizer,
108 MissingValue,
110 MissingValueCommitTrapdoor,
112 MissingWitness,
114}
115
116impl fmt::Display for ProverError {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 match self {
119 ProverError::InvalidDiversifier => {
120 write!(f, "`recipient` has invalid diversifier")
121 }
122 ProverError::MissingProofGenerationKey => {
123 write!(f, "`proof_generation_key` must be set for the Prover role")
124 }
125 ProverError::MissingRandomSeed => {
126 write!(f, "`rseed` fields must be set for the Prover role")
127 }
128 ProverError::MissingRecipient => {
129 write!(f, "`recipient` fields must be set for the Prover role")
130 }
131 ProverError::MissingSpendAuthRandomizer => {
132 write!(f, "`alpha` must be set for the Prover role")
133 }
134 ProverError::MissingValue => {
135 write!(f, "`value` fields must be set for the Prover role")
136 }
137 ProverError::MissingValueCommitTrapdoor => {
138 write!(f, "`rcv` must be set for the Prover role")
139 }
140 ProverError::MissingWitness => write!(f, "`witness` must be set for the Prover role"),
141 }
142 }
143}
144
145#[cfg(feature = "std")]
146impl std::error::Error for ProverError {}