mirror of https://github.com/zcash/halo2.git
Proving and verifying keys, and placeholder proof logic
This commit is contained in:
parent
f62bbbbb95
commit
4c4400cb63
228
src/circuit.rs
228
src/circuit.rs
|
@ -1,4 +1,232 @@
|
|||
use group::Curve;
|
||||
use halo2::{
|
||||
plonk,
|
||||
poly::{EvaluationDomain, LagrangeCoeff, Polynomial, Rotation},
|
||||
transcript::{Blake2bRead, Blake2bWrite},
|
||||
};
|
||||
use pasta_curves::{pallas, vesta};
|
||||
|
||||
use crate::{
|
||||
note::ExtractedNoteCommitment,
|
||||
primitives::redpallas::{SpendAuth, VerificationKey},
|
||||
tree::Anchor,
|
||||
value::ValueCommitment,
|
||||
Nullifier,
|
||||
};
|
||||
|
||||
pub(crate) mod gadget;
|
||||
|
||||
/// Size of the Orchard circuit.
|
||||
const K: u32 = 11;
|
||||
|
||||
/// The Orchard Action circuit.
|
||||
#[derive(Debug)]
|
||||
pub struct Circuit {}
|
||||
|
||||
impl plonk::Circuit<pallas::Base> for Circuit {
|
||||
type Config = ();
|
||||
|
||||
fn configure(meta: &mut plonk::ConstraintSystem<pallas::Base>) -> Self::Config {
|
||||
// Placeholder so the proving key is correctly built.
|
||||
meta.instance_column();
|
||||
|
||||
// Placeholder gate so there is something for the prover to operate on.
|
||||
let advice = meta.advice_column();
|
||||
meta.create_gate("TODO", |meta| meta.query_advice(advice, Rotation::cur()));
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
&self,
|
||||
_cs: &mut impl plonk::Assignment<pallas::Base>,
|
||||
_config: Self::Config,
|
||||
) -> Result<(), plonk::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The verifying key for the Orchard Action circuit.
|
||||
#[derive(Debug)]
|
||||
pub struct VerifyingKey {
|
||||
params: halo2::poly::commitment::Params<vesta::Affine>,
|
||||
vk: plonk::VerifyingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl VerifyingKey {
|
||||
/// Builds the verifying key.
|
||||
pub fn build() -> Self {
|
||||
let params = halo2::poly::commitment::Params::new(K);
|
||||
let circuit = Circuit {}; // TODO
|
||||
|
||||
let vk = plonk::keygen_vk(¶ms, &circuit).unwrap();
|
||||
|
||||
VerifyingKey { params, vk }
|
||||
}
|
||||
}
|
||||
|
||||
/// The proving key for the Orchard Action circuit.
|
||||
#[derive(Debug)]
|
||||
pub struct ProvingKey {
|
||||
params: halo2::poly::commitment::Params<vesta::Affine>,
|
||||
pk: plonk::ProvingKey<vesta::Affine>,
|
||||
}
|
||||
|
||||
impl ProvingKey {
|
||||
/// Builds the proving key.
|
||||
pub fn build() -> Self {
|
||||
let params = halo2::poly::commitment::Params::new(K);
|
||||
let circuit = Circuit {}; // TODO
|
||||
|
||||
let vk = plonk::keygen_vk(¶ms, &circuit).unwrap();
|
||||
let pk = plonk::keygen_pk(¶ms, vk, &circuit).unwrap();
|
||||
|
||||
ProvingKey { params, pk }
|
||||
}
|
||||
}
|
||||
|
||||
/// Public inputs to the Orchard Action circuit.
|
||||
#[derive(Debug)]
|
||||
pub struct Instance {
|
||||
pub(crate) anchor: Anchor,
|
||||
pub(crate) cv_net: ValueCommitment,
|
||||
pub(crate) nf_old: Nullifier,
|
||||
pub(crate) rk: VerificationKey<SpendAuth>,
|
||||
pub(crate) cmx: ExtractedNoteCommitment,
|
||||
pub(crate) enable_spend: bool,
|
||||
pub(crate) enable_output: bool,
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
fn to_halo2_instance(
|
||||
&self,
|
||||
domain: &EvaluationDomain<vesta::Scalar>,
|
||||
) -> [Polynomial<vesta::Scalar, LagrangeCoeff>; 1] {
|
||||
// TODO
|
||||
[domain.empty_lagrange()]
|
||||
}
|
||||
|
||||
fn to_halo2_instance_commitments(&self, vk: &VerifyingKey) -> [vesta::Affine; 1] {
|
||||
[vk.params
|
||||
.commit_lagrange(
|
||||
&self.to_halo2_instance(vk.vk.get_domain())[0],
|
||||
Default::default(),
|
||||
)
|
||||
.to_affine()]
|
||||
}
|
||||
}
|
||||
|
||||
/// A proof of the validity of an Orchard [`Bundle`].
|
||||
///
|
||||
/// [`Bundle`]: crate::bundle::Bundle
|
||||
#[derive(Debug)]
|
||||
pub struct Proof(Vec<u8>);
|
||||
|
||||
impl Proof {
|
||||
/// Creates a proof for the given circuits and instances.
|
||||
pub fn create(
|
||||
pk: &ProvingKey,
|
||||
circuits: &[Circuit],
|
||||
instances: &[Instance],
|
||||
) -> Result<Self, plonk::Error> {
|
||||
let instances: Vec<_> = instances
|
||||
.iter()
|
||||
.map(|i| i.to_halo2_instance(pk.pk.get_vk().get_domain()))
|
||||
.collect();
|
||||
let instances: Vec<_> = instances.iter().map(|i| &i[..]).collect();
|
||||
|
||||
let mut transcript = Blake2bWrite::<_, vesta::Affine>::init(vec![]);
|
||||
plonk::create_proof(&pk.params, &pk.pk, circuits, &instances, &mut transcript)?;
|
||||
Ok(Proof(transcript.finalize()))
|
||||
}
|
||||
|
||||
/// Verifies this proof with the given instances.
|
||||
pub fn verify(&self, vk: &VerifyingKey, instances: &[Instance]) -> Result<(), plonk::Error> {
|
||||
let instances: Vec<_> = instances
|
||||
.iter()
|
||||
.map(|i| i.to_halo2_instance_commitments(vk))
|
||||
.collect();
|
||||
let instances: Vec<_> = instances.iter().map(|i| &i[..]).collect();
|
||||
|
||||
let msm = vk.params.empty_msm();
|
||||
let mut transcript = Blake2bRead::init(&self.0[..]);
|
||||
let guard = plonk::verify_proof(&vk.params, &vk.vk, msm, &instances, &mut transcript)?;
|
||||
let msm = guard.clone().use_challenges();
|
||||
if msm.eval() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(plonk::Error::ConstraintSystemFailure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ff::Field;
|
||||
use halo2::dev::MockProver;
|
||||
use pasta_curves::pallas;
|
||||
use rand::rngs::OsRng;
|
||||
use std::iter;
|
||||
|
||||
use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K};
|
||||
use crate::{
|
||||
keys::SpendValidatingKey,
|
||||
note::Note,
|
||||
tree::Anchor,
|
||||
value::{ValueCommitTrapdoor, ValueCommitment},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
let mut rng = OsRng;
|
||||
|
||||
let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(())
|
||||
.map(|()| {
|
||||
let (fvk, spent_note) = Note::dummy(&mut rng, None);
|
||||
let nf_old = spent_note.nullifier(&fvk);
|
||||
let ak: SpendValidatingKey = fvk.into();
|
||||
let alpha = pallas::Scalar::random(&mut rng);
|
||||
let rk = ak.randomize(&alpha);
|
||||
|
||||
let (_, output_note) = Note::dummy(&mut rng, Some(nf_old.clone()));
|
||||
let cmx = output_note.commitment().into();
|
||||
|
||||
let value = spent_note.value() - output_note.value();
|
||||
let cv_net = ValueCommitment::derive(value.unwrap(), ValueCommitTrapdoor::zero());
|
||||
|
||||
(
|
||||
Circuit {},
|
||||
Instance {
|
||||
anchor: Anchor,
|
||||
cv_net,
|
||||
nf_old,
|
||||
rk,
|
||||
cmx,
|
||||
enable_spend: true,
|
||||
enable_output: true,
|
||||
},
|
||||
)
|
||||
})
|
||||
.unzip();
|
||||
|
||||
let vk = VerifyingKey::build();
|
||||
for (circuit, instance) in circuits.iter().zip(instances.iter()) {
|
||||
assert_eq!(
|
||||
MockProver::run(
|
||||
K,
|
||||
circuit,
|
||||
instance
|
||||
.to_halo2_instance(vk.vk.get_domain())
|
||||
.iter()
|
||||
.map(|p| p.iter().cloned().collect())
|
||||
.collect()
|
||||
)
|
||||
.unwrap()
|
||||
.verify(),
|
||||
Ok(())
|
||||
);
|
||||
}
|
||||
|
||||
let pk = ProvingKey::build();
|
||||
let proof = Proof::create(&pk, &circuits, &instances).unwrap();
|
||||
assert!(proof.verify(&vk, &instances).is_ok());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue