use super::{
Accumulator, BinaryInstructions, Circuit, ComposableChip, ConstraintSystem, E, Error,
EvaluationDomain, F, K, KZGCommitmentScheme, Layouter, PublicInputInstructions, S,
SimpleFloorPlanner, Value, VerifyingKey,
config::{IvcConfig, configure_ivc_circuit},
gadget::IvcGadget,
state::{Global, State, Witness},
};
#[derive(Clone, Debug)]
pub struct IvcCircuit {
pub global: Value<Global>,
pub state: Value<State>,
pub witness: Value<Witness>,
pub cert_proof: Value<Vec<u8>>,
pub self_proof: Value<Vec<u8>>,
pub acc: Value<Accumulator<S>>,
pub cert_domain_cs: (EvaluationDomain<F>, ConstraintSystem<F>),
pub self_domain_cs: (EvaluationDomain<F>, ConstraintSystem<F>),
}
impl IvcCircuit {
#[allow(clippy::too_many_arguments)]
pub fn new(
global: Global,
state: State,
witness: Witness,
cert_proof: Vec<u8>,
self_proof: Vec<u8>,
acc: Accumulator<S>,
cert_vk: &VerifyingKey<F, KZGCommitmentScheme<E>>,
self_vk: &VerifyingKey<F, KZGCommitmentScheme<E>>,
) -> Self {
IvcCircuit {
global: Value::known(global),
state: Value::known(state),
witness: Value::known(witness),
cert_proof: Value::known(cert_proof),
self_proof: Value::known(self_proof),
acc: Value::known(acc),
cert_domain_cs: (cert_vk.get_domain().clone(), cert_vk.cs().clone()),
self_domain_cs: (self_vk.get_domain().clone(), self_vk.cs().clone()),
}
}
pub fn unknown(cert_vk: &VerifyingKey<F, KZGCommitmentScheme<E>>) -> Self {
let mut self_cs = ConstraintSystem::default();
configure_ivc_circuit(&mut self_cs);
let self_domain = EvaluationDomain::new(self_cs.degree() as u32, K);
IvcCircuit {
global: Value::unknown(),
state: Value::unknown(),
witness: Value::unknown(),
cert_proof: Value::unknown(),
self_proof: Value::unknown(),
acc: Value::unknown(),
cert_domain_cs: (cert_vk.get_domain().clone(), cert_vk.cs().clone()),
self_domain_cs: (self_domain, self_cs),
}
}
}
impl Circuit<F> for IvcCircuit {
type Config = IvcConfig;
type FloorPlanner = SimpleFloorPlanner;
type Params = ();
fn without_witnesses(&self) -> Self {
unreachable!()
}
fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
configure_ivc_circuit(meta)
}
fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<F>,
) -> Result<(), Error> {
let ivc_gadget = IvcGadget::new(&config);
let global = ivc_gadget.assign_global_as_public_input(
&mut layouter,
&self.global,
&self.cert_domain_cs,
&self.self_domain_cs,
)?;
let state = ivc_gadget.assign_state(&mut layouter, &self.state)?;
let witness = ivc_gadget.assign_witness(&mut layouter, &self.witness)?;
let is_genesis = ivc_gadget.is_genesis(&mut layouter, &state)?;
let is_not_genesis = ivc_gadget.native_gadget.not(&mut layouter, &is_genesis)?;
ivc_gadget.assert_genesis(&mut layouter, &is_not_genesis, &global, &witness)?;
let next_state = ivc_gadget.transition(
&mut layouter,
&is_genesis,
&is_not_genesis,
&global,
&state,
&witness,
)?;
ivc_gadget.constrain_state_as_public_input(&mut layouter, &next_state)?;
let next_acc = ivc_gadget.verify_prepare(
&mut layouter,
&global,
&is_not_genesis,
&state,
&witness,
&self.cert_proof,
&self.self_proof,
&self.acc,
)?;
ivc_gadget
.verifier_gadget
.constrain_as_public_input(&mut layouter, &next_acc)?;
ivc_gadget.core_decomp_chip.load(&mut layouter)?;
ivc_gadget.sha2_256_chip.load(&mut layouter)
}
}