solana_zk_token_sdk/
transcript.rs

1use {
2    crate::{errors::TranscriptError, zk_token_elgamal::pod},
3    curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar, traits::IsIdentity},
4    merlin::Transcript,
5};
6
7#[allow(dead_code)]
8pub trait TranscriptProtocol {
9    /// Append a domain separator for an `n`-bit rangeproof for ElGamalKeypair
10    /// ciphertext using a decryption key
11    fn rangeproof_from_key_domain_separator(&mut self, n: u64);
12
13    /// Append a domain separator for an `n`-bit rangeproof for ElGamalKeypair
14    /// ciphertext using an opening
15    fn rangeproof_from_opening_domain_separator(&mut self, n: u64);
16
17    /// Append a domain separator for a length-`n` inner product proof.
18    fn innerproduct_domain_separator(&mut self, n: u64);
19
20    /// Append a domain separator for close account proof.
21    fn close_account_proof_domain_separator(&mut self);
22
23    /// Append a domain separator for withdraw proof.
24    fn withdraw_proof_domain_separator(&mut self);
25
26    /// Append a domain separator for transfer proof.
27    fn transfer_proof_domain_separator(&mut self);
28
29    /// Append a `scalar` with the given `label`.
30    fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar);
31
32    /// Append a `point` with the given `label`.
33    fn append_point(&mut self, label: &'static [u8], point: &CompressedRistretto);
34
35    /// Append an ElGamal pubkey with the given `label`.
36    fn append_pubkey(&mut self, label: &'static [u8], point: &pod::ElGamalPubkey);
37
38    /// Append an ElGamal ciphertext with the given `label`.
39    fn append_ciphertext(&mut self, label: &'static [u8], point: &pod::ElGamalCiphertext);
40
41    /// Append a grouped ElGamal ciphertext with 2 handles with the given `label`.
42    fn append_grouped_ciphertext_2_handles(
43        &mut self,
44        label: &'static [u8],
45        point: &pod::GroupedElGamalCiphertext2Handles,
46    );
47
48    /// Append a grouped ElGamal ciphertext with 3 handles with the given `label`.
49    fn append_grouped_ciphertext_3_handles(
50        &mut self,
51        label: &'static [u8],
52        point: &pod::GroupedElGamalCiphertext3Handles,
53    );
54
55    /// Append a Pedersen commitment with the given `label`.
56    fn append_commitment(&mut self, label: &'static [u8], point: &pod::PedersenCommitment);
57
58    /// Append an ElGamal decryption handle with the given `label`.
59    fn append_handle(&mut self, label: &'static [u8], point: &pod::DecryptHandle);
60
61    /// Append a domain separator for equality proof.
62    fn equality_proof_domain_separator(&mut self);
63
64    /// Append a domain separator for zero-balance proof.
65    fn zero_balance_proof_domain_separator(&mut self);
66
67    /// Append a domain separator for grouped ciphertext validity proof.
68    fn grouped_ciphertext_validity_proof_domain_separator(&mut self);
69
70    /// Append a domain separator for batched grouped ciphertext validity proof.
71    fn batched_grouped_ciphertext_validity_proof_domain_separator(&mut self);
72
73    /// Append a domain separator for fee sigma proof.
74    fn fee_sigma_proof_domain_separator(&mut self);
75
76    /// Append a domain separator for public-key proof.
77    fn pubkey_proof_domain_separator(&mut self);
78
79    /// Check that a point is not the identity, then append it to the
80    /// transcript.  Otherwise, return an error.
81    fn validate_and_append_point(
82        &mut self,
83        label: &'static [u8],
84        point: &CompressedRistretto,
85    ) -> Result<(), TranscriptError>;
86
87    /// Compute a `label`ed challenge variable.
88    fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar;
89}
90
91impl TranscriptProtocol for Transcript {
92    fn rangeproof_from_key_domain_separator(&mut self, n: u64) {
93        self.append_message(b"dom-sep", b"rangeproof from opening v1");
94        self.append_u64(b"n", n);
95    }
96
97    fn rangeproof_from_opening_domain_separator(&mut self, n: u64) {
98        self.append_message(b"dom-sep", b"rangeproof from opening v1");
99        self.append_u64(b"n", n);
100    }
101
102    fn innerproduct_domain_separator(&mut self, n: u64) {
103        self.append_message(b"dom-sep", b"ipp v1");
104        self.append_u64(b"n", n);
105    }
106
107    fn close_account_proof_domain_separator(&mut self) {
108        self.append_message(b"dom-sep", b"CloseAccountProof");
109    }
110
111    fn withdraw_proof_domain_separator(&mut self) {
112        self.append_message(b"dom-sep", b"WithdrawProof");
113    }
114
115    fn transfer_proof_domain_separator(&mut self) {
116        self.append_message(b"dom-sep", b"TransferProof");
117    }
118
119    fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
120        self.append_message(label, scalar.as_bytes());
121    }
122
123    fn append_point(&mut self, label: &'static [u8], point: &CompressedRistretto) {
124        self.append_message(label, point.as_bytes());
125    }
126
127    fn validate_and_append_point(
128        &mut self,
129        label: &'static [u8],
130        point: &CompressedRistretto,
131    ) -> Result<(), TranscriptError> {
132        if point.is_identity() {
133            Err(TranscriptError::ValidationError)
134        } else {
135            self.append_message(label, point.as_bytes());
136            Ok(())
137        }
138    }
139
140    fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar {
141        let mut buf = [0u8; 64];
142        self.challenge_bytes(label, &mut buf);
143
144        Scalar::from_bytes_mod_order_wide(&buf)
145    }
146
147    fn append_pubkey(&mut self, label: &'static [u8], pubkey: &pod::ElGamalPubkey) {
148        self.append_message(label, &pubkey.0);
149    }
150
151    fn append_ciphertext(&mut self, label: &'static [u8], ciphertext: &pod::ElGamalCiphertext) {
152        self.append_message(label, &ciphertext.0);
153    }
154
155    fn append_grouped_ciphertext_2_handles(
156        &mut self,
157        label: &'static [u8],
158        grouped_ciphertext: &pod::GroupedElGamalCiphertext2Handles,
159    ) {
160        self.append_message(label, &grouped_ciphertext.0);
161    }
162
163    fn append_grouped_ciphertext_3_handles(
164        &mut self,
165        label: &'static [u8],
166        grouped_ciphertext: &pod::GroupedElGamalCiphertext3Handles,
167    ) {
168        self.append_message(label, &grouped_ciphertext.0);
169    }
170
171    fn append_commitment(&mut self, label: &'static [u8], commitment: &pod::PedersenCommitment) {
172        self.append_message(label, &commitment.0);
173    }
174
175    fn append_handle(&mut self, label: &'static [u8], handle: &pod::DecryptHandle) {
176        self.append_message(label, &handle.0);
177    }
178
179    fn equality_proof_domain_separator(&mut self) {
180        self.append_message(b"dom-sep", b"equality-proof")
181    }
182
183    fn zero_balance_proof_domain_separator(&mut self) {
184        self.append_message(b"dom-sep", b"zero-balance-proof")
185    }
186
187    fn grouped_ciphertext_validity_proof_domain_separator(&mut self) {
188        self.append_message(b"dom-sep", b"validity-proof")
189    }
190
191    fn batched_grouped_ciphertext_validity_proof_domain_separator(&mut self) {
192        self.append_message(b"dom-sep", b"batched-validity-proof")
193    }
194
195    fn fee_sigma_proof_domain_separator(&mut self) {
196        self.append_message(b"dom-sep", b"fee-sigma-proof")
197    }
198
199    fn pubkey_proof_domain_separator(&mut self) {
200        self.append_message(b"dom-sep", b"pubkey-proof")
201    }
202}