Skip to main content

lilium_transcript/
transcript_builder.rs

1use crate::{
2    messages::PointRound,
3    params::{ParamResolver, ParamStack},
4    protocols::{Protocol, Reduction},
5    Message, Transcript,
6};
7use ark_ff::Field;
8use sponge::sponge::{Duplex, SpongeBuilder};
9use std::any::{Any, TypeId};
10
11pub struct TranscriptBuilder {
12    rounds: Vec<(TypeId, usize)>,
13    //TODO: can likely be handled through params
14    vars: usize,
15    sponge_builder: SpongeBuilder,
16    params: ParamStack,
17}
18
19impl TranscriptBuilder {
20    pub fn with_params<F>(mut self, params: ParamResolver, f: F) -> Self
21    where
22        F: Fn(Self) -> Self,
23    {
24        self.params.push(params);
25        let mut builder = f(self);
26        builder.params.pop();
27        builder
28    }
29
30    pub fn add_protocol_patter<F: Field, S: Protocol<F>>(self, key: &S::Key) -> Self {
31        S::transcript_pattern(key, self)
32    }
33
34    pub fn add_reduction_patter<F: Field, S: Reduction<F>>(self, key: &S::Key) -> Self {
35        S::transcript_pattern(key, self)
36    }
37
38    pub fn new(vars: usize, params: ParamResolver) -> Self {
39        let sponge_builder = SpongeBuilder::new();
40        Self {
41            rounds: vec![],
42            vars,
43            sponge_builder,
44            params: ParamStack::new(vec![params]),
45        }
46    }
47
48    pub fn round<F: Field, T: Any + Message<F>, const N: usize>(self) -> Self {
49        let Self {
50            mut rounds,
51            sponge_builder,
52            vars,
53            params,
54        } = self;
55        let id = TypeId::of::<T>();
56        rounds.push((id, N));
57
58        let resolver = params.top();
59        let sponge_builder = sponge_builder
60            .absorb(T::len(vars, resolver).try_into().unwrap())
61            .squeeze(N.try_into().unwrap());
62
63        Self {
64            rounds,
65            sponge_builder,
66            params,
67            ..self
68        }
69    }
70
71    pub fn point(self) -> Self {
72        let Self {
73            mut rounds,
74            vars,
75            sponge_builder,
76            ..
77        } = self;
78        let round = (TypeId::of::<PointRound>(), vars);
79        rounds.push(round);
80        let sponge_builder = sponge_builder.squeeze(vars.try_into().unwrap());
81        Self {
82            rounds,
83            vars,
84            sponge_builder,
85            ..self
86        }
87    }
88
89    fn fold_round_rec<F: Field, T: Any + Message<F>, const N: usize>(self, left: usize) -> Self {
90        if left == 0 {
91            self
92        } else {
93            let builder = self.round::<F, T, N>();
94            builder.fold_round_rec::<F, T, N>(left - 1)
95        }
96    }
97
98    /// Adds V rounds for the V variables in the transcript for split and fold
99    /// protocols which send one message per variable.
100    pub fn fold_rounds<F: Field, T: Any + Message<F>, const N: usize>(self) -> Self {
101        let vars = self.vars;
102        self.fold_round_rec::<F, T, N>(vars)
103    }
104
105    pub fn finish<F: Field, S: Duplex<F>>(self) -> TranscriptDescriptor<F, S> {
106        let Self {
107            rounds,
108            sponge_builder,
109            vars,
110            ..
111        } = self;
112        let sponge = S::from_builder(sponge_builder);
113        TranscriptDescriptor {
114            sponge,
115            rounds,
116            vars,
117        }
118    }
119
120    pub fn repeat<const N: usize, M: Fn(Self, usize) -> Self>(self, f: M) -> Self {
121        (0..N).fold(self, f)
122    }
123}
124
125pub struct TranscriptDescriptor<F: Field, S: Duplex<F>> {
126    sponge: S::Initializer,
127    rounds: Vec<(TypeId, usize)>,
128    vars: usize,
129}
130
131impl<F: Field, S: Duplex<F>> TranscriptDescriptor<F, S> {
132    pub fn instanciate(&self) -> Transcript<F, S> {
133        let sponge = S::instanciate(&self.sponge);
134        let rounds = self.rounds.clone().into_iter();
135        Transcript::new(sponge, rounds, self.vars)
136    }
137}