Circuit: Update value_commit_orchard to take into account asset (#50)

In the circuit, we update value_commit_orchard to take into account asset.
Previously, value_commit_orchard returns cv_net = [v_net] ValueCommitV + [rcv] ValueCommitR..
Now, value_commit_orchard returns cv_net = [v_net] asset + [rcv] ValueCommitR.
ValueCommitV and ValueCommitR are constants
v_net is equal to sign * magnitude where sign is in {-1, 1} and magnitude is an unsigned integer on 64 bits.

To evaluate [v_net] asset where v_net = sign * magnitude, we perform the following steps
1. verify that magnitude is on 64 bits
2. evaluate commitment=[magnitude]asset with the variable-base long-scalar multiplication
3. evaluate result=[sign]commitment with the new mul_sign gate
This commit is contained in:
Constance Beguier 2023-04-21 14:34:50 +02:00 committed by GitHub
parent f0b794896d
commit 563b4e5502
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 3896 additions and 4839 deletions

View File

@ -29,8 +29,8 @@ blake2b_simd = "1"
ff = "0.12"
fpe = "0.5"
group = { version = "0.12.1", features = ["wnaf-memuse"] }
halo2_gadgets = "0.2"
halo2_proofs = "0.2"
halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" }
halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1" }
hex = "0.4"
lazy_static = "1"
memuse = { version = "0.2.1", features = ["nonempty"] }
@ -52,7 +52,7 @@ plotters = { version = "0.3.0", optional = true }
[dev-dependencies]
criterion = "0.3"
halo2_gadgets = { version = "0.2", features = ["test-dependencies"] }
halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" , features = ["test-dependencies"] }
hex = "0.4"
proptest = "1.0.0"
zcash_note_encryption = { version = "0.2", features = ["pre-zip-212"] }

View File

@ -46,7 +46,7 @@ use crate::{
use halo2_gadgets::{
ecc::{
chip::{EccChip, EccConfig},
FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarFixedShort, ScalarVar,
FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar,
},
poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig},
sinsemilla::{
@ -62,6 +62,7 @@ use halo2_gadgets::{
mod commit_ivk;
pub mod gadget;
mod note_commit;
mod value_commit_orchard;
/// Size of the Orchard circuit.
const K: u32 = 11;
@ -109,7 +110,6 @@ pub struct Circuit {
pub(crate) psi_old: Value<pallas::Base>,
pub(crate) rcm_old: Value<NoteCommitTrapdoor>,
pub(crate) cm_old: Value<NoteCommitment>,
pub(crate) asset_old: Value<AssetBase>,
pub(crate) alpha: Value<pallas::Scalar>,
pub(crate) ak: Value<SpendValidatingKey>,
pub(crate) nk: Value<NullifierDerivingKey>,
@ -119,8 +119,8 @@ pub struct Circuit {
pub(crate) v_new: Value<NoteValue>,
pub(crate) psi_new: Value<pallas::Base>,
pub(crate) rcm_new: Value<NoteCommitTrapdoor>,
pub(crate) asset_new: Value<AssetBase>,
pub(crate) rcv: Value<ValueCommitTrapdoor>,
pub(crate) asset: Value<AssetBase>,
pub(crate) split_flag: Value<bool>,
}
@ -175,7 +175,6 @@ impl Circuit {
psi_old: Value::known(psi_old),
rcm_old: Value::known(rcm_old),
cm_old: Value::known(spend.note.commitment()),
asset_old: Value::known(spend.note.asset()),
alpha: Value::known(alpha),
ak: Value::known(spend.fvk.clone().into()),
nk: Value::known(*spend.fvk.nk()),
@ -185,8 +184,8 @@ impl Circuit {
v_new: Value::known(output_note.value()),
psi_new: Value::known(psi_new),
rcm_new: Value::known(rcm_new),
asset_new: Value::known(output_note.asset()),
rcv: Value::known(rcv),
asset: Value::known(spend.note.asset()),
split_flag: Value::known(spend.split_flag),
}
}
@ -475,23 +474,6 @@ impl plonk::Circuit<pallas::Base> for Circuit {
(psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new)
};
// Verify that asset_old and asset_new are equals
{
let asset_old = NonIdentityPoint::new(
ecc_chip.clone(),
layouter.namespace(|| "witness asset_old"),
self.asset_old
.map(|asset_old| asset_old.cv_base().to_affine()),
)?;
let asset_new = NonIdentityPoint::new(
ecc_chip.clone(),
layouter.namespace(|| "asset equality"),
self.asset_new
.map(|asset_new| asset_new.cv_base().to_affine()),
)?;
asset_old.constrain_equal(layouter.namespace(|| "asset equality"), &asset_new)?;
}
// Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial).
let root = {
let path = self
@ -549,22 +531,25 @@ impl plonk::Circuit<pallas::Base> for Circuit {
(magnitude, sign)
};
let v_net = ScalarFixedShort::new(
ecc_chip.clone(),
layouter.namespace(|| "v_net"),
v_net_magnitude_sign.clone(),
)?;
let rcv = ScalarFixed::new(
ecc_chip.clone(),
layouter.namespace(|| "rcv"),
self.rcv.as_ref().map(|rcv| rcv.inner()),
)?;
let cv_net = gadget::value_commit_orchard(
layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"),
let asset = NonIdentityPoint::new(
ecc_chip.clone(),
v_net,
layouter.namespace(|| "witness asset"),
self.asset.map(|asset| asset.cv_base().to_affine()),
)?;
let cv_net = gadget::value_commit_orchard(
layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net_magnitude_sign)"),
config.sinsemilla_chip_1(),
ecc_chip.clone(),
v_net_magnitude_sign.clone(),
rcv,
asset,
)?;
// Constrain cv_net to equal public input
@ -1033,7 +1018,6 @@ mod tests {
use rand::{rngs::OsRng, RngCore};
use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K};
use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey};
use crate::note::AssetBase;
use crate::{
keys::SpendValidatingKey,
@ -1074,7 +1058,6 @@ mod tests {
psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())),
rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())),
cm_old: Value::known(spent_note.commitment()),
asset_old: Value::known(spent_note.asset()),
alpha: Value::known(alpha),
ak: Value::known(ak),
nk: Value::known(nk),
@ -1084,8 +1067,8 @@ mod tests {
v_new: Value::known(output_note.value()),
psi_new: Value::known(output_note.rseed().psi(&output_note.rho())),
rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())),
asset_new: Value::known(output_note.asset()),
rcv: Value::known(rcv),
asset: Value::known(spent_note.asset()),
split_flag: Value::known(false),
},
Instance {
@ -1128,8 +1111,8 @@ mod tests {
K as usize,
&circuits[0],
);
assert_eq!(usize::from(circuit_cost.proof_size(1)), 4992);
assert_eq!(usize::from(circuit_cost.proof_size(2)), 7264);
assert_eq!(usize::from(circuit_cost.proof_size(1)), 5024);
assert_eq!(usize::from(circuit_cost.proof_size(2)), 7296);
usize::from(circuit_cost.proof_size(instances.len()))
};
@ -1156,74 +1139,6 @@ mod tests {
assert_eq!(proof.0.len(), expected_proof_size);
}
#[test]
fn test_not_equal_asset_ids() {
use halo2_proofs::dev::{
metadata::Column, metadata::Region, FailureLocation, VerifyFailure,
};
use halo2_proofs::plonk::Any::Advice;
let mut rng = OsRng;
let (mut circuit, instance) = generate_circuit_instance(&mut rng);
// We would like to test that if the asset of the spent note (called asset_old) and the
// asset of the output note (called asset_new) are not equal, the proof is not verified.
// To do that, we attribute a random value to asset_new.
let random_asset_id = {
let sk = SpendingKey::random(&mut rng);
let isk = IssuanceAuthorizingKey::from(&sk);
let ik = IssuanceValidatingKey::from(&isk);
let asset_descr = "zsa_asset";
AssetBase::derive(&ik, asset_descr)
};
circuit.asset_new = Value::known(random_asset_id);
assert_eq!(
MockProver::run(
K,
&circuit,
instance
.to_halo2_instance()
.iter()
.map(|p| p.to_vec())
.collect()
)
.unwrap()
.verify(),
Err(vec![
VerifyFailure::Permutation {
column: Column::from((Advice, 0)),
location: FailureLocation::InRegion {
region: Region::from((9, "witness non-identity point".to_string())),
offset: 0
}
},
VerifyFailure::Permutation {
column: Column::from((Advice, 0)),
location: FailureLocation::InRegion {
region: Region::from((10, "witness non-identity point".to_string())),
offset: 0
}
},
VerifyFailure::Permutation {
column: Column::from((Advice, 1)),
location: FailureLocation::InRegion {
region: Region::from((9, "witness non-identity point".to_string())),
offset: 0
}
},
VerifyFailure::Permutation {
column: Column::from((Advice, 1)),
location: FailureLocation::InRegion {
region: Region::from((10, "witness non-identity point".to_string())),
offset: 0
}
}
])
);
}
#[test]
fn serialized_proof_test_case() {
use std::io::{Read, Write};
@ -1305,7 +1220,7 @@ mod tests {
let test_case_bytes = include_bytes!("circuit_proof_test_case.bin");
read_test_case(&test_case_bytes[..]).expect("proof must be valid")
};
assert_eq!(proof.0.len(), 4992);
assert_eq!(proof.0.len(), 5024);
assert!(proof.verify(&vk, &[instance]).is_ok());
}
@ -1331,7 +1246,6 @@ mod tests {
psi_old: Value::unknown(),
rcm_old: Value::unknown(),
cm_old: Value::unknown(),
asset_old: Value::unknown(),
alpha: Value::unknown(),
ak: Value::unknown(),
nk: Value::unknown(),
@ -1341,8 +1255,8 @@ mod tests {
v_new: Value::unknown(),
psi_new: Value::unknown(),
rcm_new: Value::unknown(),
asset_new: Value::unknown(),
rcv: Value::unknown(),
asset: Value::unknown(),
split_flag: Value::unknown(),
};
halo2_proofs::dev::CircuitLayout::default()

View File

@ -4,15 +4,9 @@ use ff::Field;
use pasta_curves::pallas;
use super::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip};
use crate::constants::{
NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains,
ValueCommitV,
};
use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains};
use halo2_gadgets::{
ecc::{
chip::EccChip, EccInstructions, FixedPoint, FixedPointBaseField, FixedPointShort, Point,
ScalarFixed, ScalarFixedShort, X,
},
ecc::{chip::EccChip, EccInstructions, FixedPointBaseField, Point, X},
poseidon::{
primitives::{self as poseidon, ConstantLength},
Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip,
@ -107,41 +101,6 @@ where
)
}
/// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)].
///
/// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit
pub(in crate::circuit) fn value_commit_orchard<
EccChip: EccInstructions<
pallas::Affine,
FixedPoints = OrchardFixedBases,
Var = AssignedCell<pallas::Base, pallas::Base>,
>,
>(
mut layouter: impl Layouter<pallas::Base>,
ecc_chip: EccChip,
v: ScalarFixedShort<pallas::Affine, EccChip>,
rcv: ScalarFixed<pallas::Affine, EccChip>,
) -> Result<Point<pallas::Affine, EccChip>, plonk::Error> {
// commitment = [v] ValueCommitV
let (commitment, _) = {
let value_commit_v = ValueCommitV;
let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v);
value_commit_v.mul(layouter.namespace(|| "[v] ValueCommitV"), v)?
};
// blind = [rcv] ValueCommitR
let (blind, _rcv) = {
let value_commit_r = OrchardFixedBasesFull::ValueCommitR;
let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r);
// [rcv] ValueCommitR
value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)?
};
// [v] ValueCommitV + [rcv] ValueCommitR
commitment.add(layouter.namespace(|| "cv"), &blind)
}
/// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers].
///
/// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers
@ -202,3 +161,4 @@ pub(in crate::circuit) fn derive_nullifier<
pub(in crate::circuit) use crate::circuit::commit_ivk::gadgets::commit_ivk;
pub(in crate::circuit) use crate::circuit::note_commit::gadgets::note_commit;
pub(in crate::circuit) use crate::circuit::value_commit_orchard::gadgets::value_commit_orchard;

View File

@ -0,0 +1,341 @@
pub(in crate::circuit) mod gadgets {
use pasta_curves::pallas;
use crate::constants::{
OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains,
};
use halo2_gadgets::{
ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar},
sinsemilla::{self, chip::SinsemillaChip},
};
use halo2_proofs::{
circuit::{AssignedCell, Chip, Layouter},
plonk,
};
/// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)].
///
/// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit
pub(in crate::circuit) fn value_commit_orchard(
mut layouter: impl Layouter<pallas::Base>,
sinsemilla_chip: SinsemillaChip<
OrchardHashDomains,
OrchardCommitDomains,
OrchardFixedBases,
>,
ecc_chip: EccChip<OrchardFixedBases>,
v_net_magnitude_sign: (
AssignedCell<pallas::Base, pallas::Base>,
AssignedCell<pallas::Base, pallas::Base>,
),
rcv: ScalarFixed<pallas::Affine, EccChip<OrchardFixedBases>>,
asset: NonIdentityPoint<pallas::Affine, EccChip<OrchardFixedBases>>,
) -> Result<Point<pallas::Affine, EccChip<OrchardFixedBases>>, plonk::Error> {
// Check that magnitude is 64 bits.
{
let lookup_config = sinsemilla_chip.config().lookup_config();
let (magnitude_words, magnitude_extra_bits) = (6, 4);
assert_eq!(
magnitude_words * sinsemilla::primitives::K + magnitude_extra_bits,
64
);
let magnitude_zs = lookup_config.copy_check(
layouter.namespace(|| "magnitude lowest 60 bits"),
v_net_magnitude_sign.0.clone(),
magnitude_words, // 6 windows of 10 bits.
false, // Do not constrain the result here.
)?;
assert_eq!(magnitude_zs.len(), magnitude_words + 1);
lookup_config.copy_short_check(
layouter.namespace(|| "magnitude highest 4 bits"),
magnitude_zs[magnitude_words].clone(),
magnitude_extra_bits, // The 7th window must be a 4 bits value.
)?;
}
// Multiply asset by magnitude, using the long scalar mul.
// TODO: implement a new variable base multiplication which is optimized for 64-bit scalar
// (the long scalar mul is optimized for pallas::Base scalar (~255-bits))
//
// commitment = [magnitude] asset
let commitment = {
let magnitude_scalar = ScalarVar::from_base(
ecc_chip.clone(),
layouter.namespace(|| "magnitude"),
&v_net_magnitude_sign.0,
)?;
let (commitment, _) =
asset.mul(layouter.namespace(|| "[magnitude] asset"), magnitude_scalar)?;
commitment
};
// signed_commitment = [sign] commitment = [v_net_magnitude_sign] asset
let signed_commitment = commitment.mul_sign(
layouter.namespace(|| "[sign] commitment"),
&v_net_magnitude_sign.1,
)?;
// blind = [rcv] ValueCommitR
let (blind, _rcv) = {
let value_commit_r = OrchardFixedBasesFull::ValueCommitR;
let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r);
// [rcv] ValueCommitR
value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)?
};
// [v] ValueCommitV + [rcv] ValueCommitR
signed_commitment.add(layouter.namespace(|| "cv"), &blind)
}
}
#[cfg(test)]
mod tests {
use crate::{
circuit::gadget::{assign_free_advice, value_commit_orchard},
circuit::K,
constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains},
keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey},
note::AssetBase,
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment},
};
use halo2_gadgets::{
ecc::{
chip::{EccChip, EccConfig},
NonIdentityPoint, ScalarFixed,
},
sinsemilla::chip::{SinsemillaChip, SinsemillaConfig},
utilities::lookup_range_check::LookupRangeCheckConfig,
};
use group::Curve;
use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner, Value},
dev::MockProver,
plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance},
};
use pasta_curves::pallas;
use rand::{rngs::OsRng, RngCore};
#[test]
fn test_value_commit_orchard() {
#[derive(Clone, Debug)]
pub struct MyConfig {
primary: Column<Instance>,
advices: [Column<Advice>; 10],
ecc_config: EccConfig<OrchardFixedBases>,
// Sinsemilla config is only used to initialize the table_idx lookup table in the same
// way as in the Orchard circuit
sinsemilla_config:
SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
}
#[derive(Default)]
struct MyCircuit {
v_old: Value<NoteValue>,
v_new: Value<NoteValue>,
rcv: Value<ValueCommitTrapdoor>,
asset: Value<AssetBase>,
split_flag: Value<bool>,
}
impl Circuit<pallas::Base> for MyCircuit {
type Config = MyConfig;
type FloorPlanner = SimpleFloorPlanner;
fn without_witnesses(&self) -> Self {
Self::default()
}
fn configure(meta: &mut ConstraintSystem<pallas::Base>) -> Self::Config {
let advices = [
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
meta.advice_column(),
];
for advice in advices.iter() {
meta.enable_equality(*advice);
}
// Instance column used for public inputs
let primary = meta.instance_column();
meta.enable_equality(primary);
let table_idx = meta.lookup_table_column();
let lookup = (
table_idx,
meta.lookup_table_column(),
meta.lookup_table_column(),
);
let lagrange_coeffs = [
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
meta.fixed_column(),
];
meta.enable_constant(lagrange_coeffs[0]);
let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx);
let sinsemilla_config = SinsemillaChip::configure(
meta,
advices[..5].try_into().unwrap(),
advices[6],
lagrange_coeffs[0],
lookup,
range_check,
);
MyConfig {
primary,
advices,
ecc_config: EccChip::<OrchardFixedBases>::configure(
meta,
advices,
lagrange_coeffs,
range_check,
),
sinsemilla_config,
}
}
fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<pallas::Base>,
) -> Result<(), Error> {
// Load the Sinsemilla generator lookup table.
SinsemillaChip::load(config.sinsemilla_config.clone(), &mut layouter)?;
// Construct an ECC chip
let ecc_chip = EccChip::construct(config.ecc_config);
let sinsemilla_chip = SinsemillaChip::construct(config.sinsemilla_config.clone());
// Witness the magnitude and sign of v_net = v_old - v_new
let v_net_magnitude_sign = {
// v_net is equal to
// (-v_new) if split_flag = true
// v_old - v_new if split_flag = false
let v_net = self.split_flag.and_then(|split_flag| {
if split_flag {
Value::known(crate::value::NoteValue::zero()) - self.v_new
} else {
self.v_old - self.v_new
}
});
let magnitude_sign = v_net.map(|v_net| {
let (magnitude, sign) = v_net.magnitude_sign();
(
// magnitude is guaranteed to be an unsigned 64-bit value.
// Therefore, we can move it into the base field.
pallas::Base::from(magnitude),
match sign {
crate::value::Sign::Positive => pallas::Base::one(),
crate::value::Sign::Negative => -pallas::Base::one(),
},
)
});
let magnitude = assign_free_advice(
layouter.namespace(|| "v_net magnitude"),
config.advices[9],
magnitude_sign.map(|m_s| m_s.0),
)?;
let sign = assign_free_advice(
layouter.namespace(|| "v_net sign"),
config.advices[9],
magnitude_sign.map(|m_s| m_s.1),
)?;
(magnitude, sign)
};
// Witness rcv
let rcv = ScalarFixed::new(
ecc_chip.clone(),
layouter.namespace(|| "rcv"),
self.rcv.as_ref().map(|rcv| rcv.inner()),
)?;
// Witness asset
let asset = NonIdentityPoint::new(
ecc_chip.clone(),
layouter.namespace(|| "witness asset"),
self.asset.map(|asset| asset.cv_base().to_affine()),
)?;
// Evaluate cv_net with value_commit_orchard
let cv_net = value_commit_orchard(
layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"),
sinsemilla_chip,
ecc_chip,
v_net_magnitude_sign,
rcv,
asset,
)?;
// Constrain cv_net to equal public input
layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, 0)?;
layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, 1)
}
}
// Test different circuits
let mut rng = OsRng;
let mut circuits = vec![];
let mut instances = vec![];
let native_asset = AssetBase::native();
let random_asset = {
let sk = SpendingKey::random(&mut rng);
let isk = IssuanceAuthorizingKey::from(&sk);
let ik = IssuanceValidatingKey::from(&isk);
let asset_descr = "zsa_asset";
AssetBase::derive(&ik, asset_descr)
};
for split_flag in [false, true] {
for asset in [native_asset, random_asset] {
let v_old = NoteValue::from_raw(rng.next_u64());
let v_new = NoteValue::from_raw(rng.next_u64());
let rcv = ValueCommitTrapdoor::random(&mut rng);
let v_net = if split_flag {
NoteValue::zero() - v_new
} else {
v_old - v_new
};
circuits.push(MyCircuit {
v_old: Value::known(v_old),
v_new: Value::known(v_new),
rcv: Value::known(rcv),
asset: Value::known(asset),
split_flag: Value::known(split_flag),
});
let expected_cv_net = ValueCommitment::derive(v_net, rcv, asset);
instances.push([[expected_cv_net.x(), expected_cv_net.y()]]);
}
}
for (circuit, instance) in circuits.iter().zip(instances.iter()) {
let prover = MockProver::<pallas::Base>::run(
K,
circuit,
instance.iter().map(|p| p.to_vec()).collect(),
)
.unwrap();
assert_eq!(prover.verify(), Ok(()));
}
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.