sigma_proof_compiler/
transcript.rs1use curve25519_dalek::{
2 ristretto::{CompressedRistretto, RistrettoPoint},
3 scalar::Scalar,
4};
5use std::io::{Read, Write};
6
7pub(crate) struct ProofTranscript {
8 state: merlin::Transcript,
9 proof: std::io::Cursor<Vec<u8>>,
10 is_prover: bool,
11}
12
13impl ProofTranscript {
14 pub(crate) fn new_prover(label: &'static [u8]) -> Self {
15 Self {
16 state: merlin::Transcript::new(label),
17 proof: std::io::Cursor::new(Vec::new()),
18 is_prover: true,
19 }
20 }
21
22 pub(crate) fn new_verifier(label: &'static [u8], proof: &[u8]) -> Self {
23 Self {
24 state: merlin::Transcript::new(label),
25 proof: std::io::Cursor::new(proof.to_vec()),
26 is_prover: false,
27 }
28 }
29
30 pub(crate) fn common_absorb_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
31 self.state.append_message(label, scalar.as_bytes());
32 }
33
34 pub(crate) fn common_absorb_point(&mut self, label: &'static [u8], point: &RistrettoPoint) {
35 self.state
36 .append_message(label, point.compress().as_bytes());
37 }
38
39 pub(crate) fn prover_absorb_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
40 assert!(self.is_prover);
41 self.common_absorb_scalar(label, scalar);
42 self.proof.write_all(scalar.as_bytes()).unwrap();
43 }
44
45 pub(crate) fn verifier_receives_all_scalars(
46 &mut self,
47 label: &'static [u8],
48 ) -> Option<Vec<Scalar>> {
49 assert!(!self.is_prover);
50 let mut scalars = Vec::new();
51 loop {
52 let mut buf = [0u8; 32];
53 match self.proof.read_exact(&mut buf) {
54 Ok(()) => {
55 let scalar = Scalar::from_canonical_bytes(buf).into_option()?;
56 self.common_absorb_scalar(label, &scalar);
57 scalars.push(scalar);
58 }
59 Err(_) => break,
60 }
61 }
62 Some(scalars)
63 }
64
65 pub(crate) fn prover_absorb_point(&mut self, label: &'static [u8], point: &RistrettoPoint) {
66 assert!(self.is_prover);
67 self.common_absorb_point(label, &point);
68 self.proof.write_all(point.compress().as_bytes()).unwrap();
69 }
70
71 pub(crate) fn verifier_receive_points(
72 &mut self,
73 label: &'static [u8],
74 count: usize,
75 ) -> Option<Vec<RistrettoPoint>> {
76 assert!(!self.is_prover);
77 let mut points = Vec::with_capacity(count);
78 for _ in 0..count {
79 let mut buf = [0u8; 32];
80 if self.proof.read_exact(&mut buf).is_err() {
81 return None;
82 }
83 let point = CompressedRistretto(buf).decompress()?;
84 self.common_absorb_point(label, &point); points.push(point);
86 }
87 Some(points)
88 }
89
90 pub(crate) fn challenge(&mut self, label: &'static [u8]) -> Scalar {
91 let mut buf = [0u8; 64];
92 self.state.challenge_bytes(label, &mut buf);
93 Scalar::from_bytes_mod_order_wide(&buf)
94 }
95
96 pub(crate) fn finalize(self) -> Vec<u8> {
97 self.proof.into_inner()
98 }
99}