solana_zk_sdk/
transcript.rs1use {
2 crate::{errors::TranscriptError, TRANSCRIPT_DOMAIN},
3 curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar, traits::IsIdentity},
4 merlin::Transcript,
5};
6
7pub trait TranscriptProtocol {
8 fn new_zk_elgamal_transcript(label: &'static [u8]) -> Transcript;
10
11 fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar);
13
14 fn append_point(&mut self, label: &'static [u8], point: &CompressedRistretto);
16
17 fn validate_and_append_point(
20 &mut self,
21 label: &'static [u8],
22 point: &CompressedRistretto,
23 ) -> Result<(), TranscriptError>;
24
25 fn range_proof_domain_separator(&mut self, n: u64);
27
28 fn inner_product_proof_domain_separator(&mut self, n: u64);
30
31 fn ciphertext_ciphertext_equality_proof_domain_separator(&mut self);
33
34 fn ciphertext_commitment_equality_proof_domain_separator(&mut self);
36
37 fn zero_ciphertext_proof_domain_separator(&mut self);
39
40 fn grouped_ciphertext_validity_proof_domain_separator(&mut self, handles: u64);
42
43 fn batched_grouped_ciphertext_validity_proof_domain_separator(&mut self, handles: u64);
45
46 fn percentage_with_cap_proof_domain_separator(&mut self);
48
49 fn pubkey_proof_domain_separator(&mut self);
51
52 fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar;
54}
55
56impl TranscriptProtocol for Transcript {
57 fn new_zk_elgamal_transcript(label: &'static [u8]) -> Transcript {
58 let mut transcript = Transcript::new(TRANSCRIPT_DOMAIN);
59 transcript.append_message(b"dom-sep", label);
60 transcript
61 }
62
63 fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
64 self.append_message(label, scalar.as_bytes());
65 }
66
67 fn append_point(&mut self, label: &'static [u8], point: &CompressedRistretto) {
68 self.append_message(label, point.as_bytes());
69 }
70
71 fn validate_and_append_point(
72 &mut self,
73 label: &'static [u8],
74 point: &CompressedRistretto,
75 ) -> Result<(), TranscriptError> {
76 if point.is_identity() {
77 Err(TranscriptError::ValidationError)
78 } else {
79 self.append_message(label, point.as_bytes());
80 Ok(())
81 }
82 }
83
84 fn range_proof_domain_separator(&mut self, n: u64) {
85 self.append_message(b"dom-sep", b"range-proof");
86 self.append_u64(b"n", n);
87 }
88
89 fn inner_product_proof_domain_separator(&mut self, n: u64) {
90 self.append_message(b"dom-sep", b"inner-product");
91 self.append_u64(b"n", n);
92 }
93
94 fn ciphertext_ciphertext_equality_proof_domain_separator(&mut self) {
95 self.append_message(b"dom-sep", b"ciphertext-ciphertext-equality-proof")
96 }
97
98 fn ciphertext_commitment_equality_proof_domain_separator(&mut self) {
99 self.append_message(b"dom-sep", b"ciphertext-commitment-equality-proof")
100 }
101
102 fn zero_ciphertext_proof_domain_separator(&mut self) {
103 self.append_message(b"dom-sep", b"zero-ciphertext-proof")
104 }
105
106 fn grouped_ciphertext_validity_proof_domain_separator(&mut self, handles: u64) {
107 self.append_message(b"dom-sep", b"validity-proof");
108 self.append_u64(b"handles", handles);
109 }
110
111 fn batched_grouped_ciphertext_validity_proof_domain_separator(&mut self, handles: u64) {
112 self.append_message(b"dom-sep", b"batched-validity-proof");
113 self.append_u64(b"handles", handles);
114 }
115
116 fn percentage_with_cap_proof_domain_separator(&mut self) {
117 self.append_message(b"dom-sep", b"percentage-with-cap-proof")
118 }
119
120 fn pubkey_proof_domain_separator(&mut self) {
121 self.append_message(b"dom-sep", b"pubkey-proof")
122 }
123
124 fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar {
125 let mut buf = [0u8; 64];
126 self.challenge_bytes(label, &mut buf);
127
128 Scalar::from_bytes_mod_order_wide(&buf)
129 }
130}