1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
//! Runtime tables are tables (or arrays) that can be produced during proof creation.
//! The setup has to prepare for their presence using [`RuntimeTableCfg`].
//! At proving time, the prover can use [`RuntimeTable`] to specify the actual tables.
// TODO: write cargo specifications
use crate::circuits::{berkeley_columns::Column, expr::prologue::*, gate::CurrOrNext};
use ark_ff::Field;
use serde::{Deserialize, Serialize};
/// The specification of a runtime table.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeTableSpec {
/// The table ID.
pub id: i32,
/// The number of entries contained in the runtime table.
pub len: usize,
}
/// Use this type at setup time, to list all the runtime tables.
///
/// Note: care must be taken as table IDs can collide with IDs of other types of lookup tables.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeTableCfg<F> {
/// The table ID.
pub id: i32,
/// The content of the first column of the runtime table.
pub first_column: Vec<F>,
}
impl<F> RuntimeTableCfg<F> {
/// Returns the ID of the runtime table.
pub fn id(&self) -> i32 {
self.id
}
/// Returns the length of the runtime table.
pub fn len(&self) -> usize {
self.first_column.len()
}
/// Returns `true` if the runtime table is empty.
pub fn is_empty(&self) -> bool {
self.first_column.is_empty()
}
}
impl<F> From<RuntimeTableCfg<F>> for RuntimeTableSpec {
fn from(rt_cfg: RuntimeTableCfg<F>) -> Self {
Self {
id: rt_cfg.id,
len: rt_cfg.first_column.len(),
}
}
}
/// A runtime table. Runtime tables must match the configuration
/// that was specified in [`RuntimeTableCfg`].
#[derive(Debug, Clone)]
pub struct RuntimeTable<F> {
/// The table id.
pub id: i32,
/// A single column.
pub data: Vec<F>,
}
/// Returns the constraints related to the runtime tables.
pub fn constraints<F>() -> Vec<E<F>>
where
F: Field,
{
// This constrains that runtime_table takes values
// when selector_RT is 0, and doesn't when selector_RT is 1:
//
// runtime_table * selector_RT = 0
//
let var = |x| E::cell(x, CurrOrNext::Curr);
let rt_check = var(Column::LookupRuntimeTable) * var(Column::LookupRuntimeSelector);
vec![rt_check]
}
#[cfg(feature = "ocaml_types")]
pub mod caml {
use super::{RuntimeTable, RuntimeTableCfg, RuntimeTableSpec};
use ark_ff::PrimeField;
//
// CamlRuntimeTable<CamlF>
//
#[derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
pub struct CamlRuntimeTable<CamlF> {
pub id: i32,
pub data: Vec<CamlF>,
}
// CamlRuntimeTable<CamlF> <---> RuntimeTable<F>
impl<F, CamlF> From<RuntimeTable<F>> for CamlRuntimeTable<CamlF>
where
F: PrimeField,
CamlF: From<F>,
{
fn from(rt: RuntimeTable<F>) -> Self {
Self {
id: rt.id,
data: rt.data.into_iter().map(Into::into).collect(),
}
}
}
impl<F, CamlF> From<CamlRuntimeTable<CamlF>> for RuntimeTable<F>
where
F: PrimeField,
CamlF: Into<F>,
{
fn from(caml_rt: CamlRuntimeTable<CamlF>) -> Self {
Self {
id: caml_rt.id,
data: caml_rt.data.into_iter().map(Into::into).collect(),
}
}
}
#[derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
pub struct CamlRuntimeTableSpec {
pub id: i32,
pub len: usize,
}
impl From<RuntimeTableSpec> for CamlRuntimeTableSpec {
fn from(rt_spec: RuntimeTableSpec) -> Self {
Self {
id: rt_spec.id,
len: rt_spec.len,
}
}
}
impl From<CamlRuntimeTableSpec> for RuntimeTableSpec {
fn from(caml_rt_spec: CamlRuntimeTableSpec) -> Self {
Self {
id: caml_rt_spec.id,
len: caml_rt_spec.len,
}
}
}
// CamlRuntimetableCfg
#[derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
pub struct CamlRuntimeTableCfg<CamlF> {
pub id: i32,
pub first_column: Vec<CamlF>,
}
// CamlRuntimeTableCfg <--> RuntimeTableCfg
impl<F, CamlF> From<RuntimeTableCfg<F>> for CamlRuntimeTableCfg<CamlF>
where
F: PrimeField,
CamlF: From<F>,
{
fn from(rt_cfg: RuntimeTableCfg<F>) -> Self {
Self {
id: rt_cfg.id,
first_column: rt_cfg.first_column.into_iter().map(Into::into).collect(),
}
}
}
impl<F, CamlF> From<CamlRuntimeTableCfg<CamlF>> for RuntimeTableCfg<F>
where
F: PrimeField,
CamlF: Into<F>,
{
fn from(caml_rt_cfg: CamlRuntimeTableCfg<CamlF>) -> Self {
Self {
id: caml_rt_cfg.id,
first_column: caml_rt_cfg
.first_column
.into_iter()
.map(Into::into)
.collect(),
}
}
}
}