proof_of_sql/sql/evm_proof_plan/
proof_plan.rs

1use super::{error::Error, plans::Plan};
2use crate::{
3    base::{
4        database::{ColumnField, ColumnRef, OwnedTable, Table, TableEvaluation, TableRef},
5        map::{IndexMap, IndexSet},
6        proof::ProofError,
7        scalar::Scalar,
8    },
9    sql::{
10        proof::{
11            FinalRoundBuilder, FirstRoundBuilder, ProofPlan, ProverEvaluate, VerificationBuilder,
12        },
13        proof_plans::DynProofPlan,
14    },
15};
16use alloc::{
17    string::{String, ToString},
18    vec::Vec,
19};
20use bumpalo::Bump;
21use itertools::Itertools;
22use serde::{Serialize, Serializer};
23
24#[derive(Debug)]
25/// An implementation of `ProofPlan` that allows for EVM compatible serialization.
26/// Serialization should be done using bincode with fixint, big-endian encoding in order to be compatible with EVM.
27///
28/// This is simply a wrapper around a `DynProofPlan`.
29pub struct EVMProofPlan {
30    inner: DynProofPlan,
31}
32
33impl EVMProofPlan {
34    /// Create a new `EVMProofPlan` from a `DynProofPlan`.
35    #[must_use]
36    pub fn new(plan: DynProofPlan) -> Self {
37        Self { inner: plan }
38    }
39    /// Get the inner `DynProofPlan`.
40    #[must_use]
41    pub fn into_inner(self) -> DynProofPlan {
42        self.inner
43    }
44    /// Get a reference to the inner `DynProofPlan`.
45    #[must_use]
46    pub fn inner(&self) -> &DynProofPlan {
47        &self.inner
48    }
49}
50
51impl Serialize for EVMProofPlan {
52    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
53        #[derive(Serialize)]
54        struct CompactPlan {
55            tables: Vec<String>,
56            columns: Vec<(usize, String)>,
57            plan: Plan,
58        }
59
60        let table_refs = self.get_table_references();
61        let column_refs = self.get_column_references();
62
63        let plan = Plan::try_from_proof_plan(self.inner(), &table_refs, &column_refs)
64            .map_err(serde::ser::Error::custom)?;
65        let columns = column_refs
66            .into_iter()
67            .map(|column_ref| {
68                let table_index = table_refs
69                    .get_index_of(&column_ref.table_ref())
70                    .ok_or(Error::TableNotFound)?;
71                Ok((table_index, column_ref.column_id().to_string()))
72            })
73            .try_collect()
74            .map_err(serde::ser::Error::custom::<Error>)?;
75        let tables = table_refs.iter().map(ToString::to_string).collect();
76
77        CompactPlan {
78            tables,
79            columns,
80            plan,
81        }
82        .serialize(serializer)
83    }
84}
85
86impl ProofPlan for EVMProofPlan {
87    fn verifier_evaluate<S: Scalar>(
88        &self,
89        builder: &mut impl VerificationBuilder<S>,
90        accessor: &IndexMap<ColumnRef, S>,
91        result: Option<&OwnedTable<S>>,
92        chi_eval_map: &IndexMap<TableRef, S>,
93    ) -> Result<TableEvaluation<S>, ProofError> {
94        self.inner()
95            .verifier_evaluate(builder, accessor, result, chi_eval_map)
96    }
97    fn get_column_result_fields(&self) -> Vec<ColumnField> {
98        self.inner().get_column_result_fields()
99    }
100    fn get_column_references(&self) -> IndexSet<ColumnRef> {
101        self.inner().get_column_references()
102    }
103    fn get_table_references(&self) -> IndexSet<TableRef> {
104        self.inner().get_table_references()
105    }
106}
107impl ProverEvaluate for EVMProofPlan {
108    fn first_round_evaluate<'a, S: Scalar>(
109        &self,
110        builder: &mut FirstRoundBuilder<'a, S>,
111        alloc: &'a Bump,
112        table_map: &IndexMap<TableRef, Table<'a, S>>,
113    ) -> Table<'a, S> {
114        self.inner().first_round_evaluate(builder, alloc, table_map)
115    }
116    fn final_round_evaluate<'a, S: Scalar>(
117        &self,
118        builder: &mut FinalRoundBuilder<'a, S>,
119        alloc: &'a Bump,
120        table_map: &IndexMap<TableRef, Table<'a, S>>,
121    ) -> Table<'a, S> {
122        self.inner().final_round_evaluate(builder, alloc, table_map)
123    }
124}