pub use circuit::{IvcCircuit, IvcInstance, IvcWitness};
pub use error::IvcError;
use midnight_circuits::{
instructions::{BinaryInstructions, EqualityInstructions},
types::{AssignedBit, AssignedNative},
verifier::{BlstrsEmulation, SelfEmulation},
};
use midnight_proofs::{
circuit::{Layouter, Value},
plonk::Error,
};
use midnight_zk_stdlib::{ZkStdLib, ZkStdLibArch};
pub use prover::IvcProver;
pub use setup::setup;
pub use verifier::IvcVerifier;
pub(crate) type S = BlstrsEmulation;
pub(crate) type F = <S as SelfEmulation>::F;
pub(crate) type C = <S as SelfEmulation>::C;
pub(crate) type E = <S as SelfEmulation>::Engine;
pub mod circuit;
pub mod error;
pub mod prover;
pub mod setup;
pub mod verifier;
pub trait IvcContext: Clone {
type Context: Clone + std::fmt::Debug;
fn new(std_lib: ZkStdLib, ctx: &Self::Context) -> Self;
fn write_context<W: std::io::Write>(ctx: &Self::Context, writer: &mut W)
-> std::io::Result<()>;
fn read_context<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self::Context>;
}
pub trait IvcState: IvcContext {
type State: Clone;
type AssignedState: Clone;
fn genesis(ctx: &Self::Context) -> Self::State;
fn decider(ctx: &Self::Context, state: &Self::State) -> bool;
}
pub trait IvcIO: IvcState {
fn assign(
&self,
layouter: &mut impl Layouter<F>,
value: Value<Self::State>,
) -> Result<Self::AssignedState, Error>;
fn constrain_as_public_input(
&self,
layouter: &mut impl Layouter<F>,
state: &Self::AssignedState,
) -> Result<(), Error>;
fn as_public_input(
&self,
layouter: &mut impl Layouter<F>,
state: &Self::AssignedState,
) -> Result<Vec<AssignedNative<F>>, Error>;
fn format_public_input(state: &Self::State) -> Vec<F>;
}
pub trait IvcTransition: IvcState {
type Witness: Clone;
fn arch() -> ZkStdLibArch;
fn transition(ctx: &Self::Context, state: &Self::State, witness: Self::Witness) -> Self::State;
fn circuit_transition(
&self,
layouter: &mut impl Layouter<F>,
state: &Self::AssignedState,
witness: Value<Self::Witness>,
) -> Result<Self::AssignedState, Error>;
}
pub trait Ivc: IvcTransition + IvcIO {
fn is_genesis(ctx: &Self::Context, state: &Self::State) -> bool {
Self::format_public_input(state) == Self::format_public_input(&Self::genesis(ctx))
}
fn circuit_is_genesis(
&self,
std_lib: &ZkStdLib,
layouter: &mut impl Layouter<F>,
ctx: &Self::Context,
state: &Self::AssignedState,
) -> Result<AssignedBit<F>, Error> {
let bits = (self.as_public_input(layouter, state)?.iter())
.zip(Self::format_public_input(&Self::genesis(ctx)))
.map(|(x, c)| std_lib.is_equal_to_fixed(layouter, x, c))
.collect::<Result<Vec<_>, _>>()?;
std_lib.and(layouter, &bits)
}
}
impl<I: IvcTransition + IvcIO> Ivc for I {}