mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
zkas: Implement EcNiPoint type and EcMulVarBase opcode.
This commit is contained in:
@@ -32,14 +32,13 @@ local constant = token(l.CONSTANT, word_match{
|
||||
-- Types.
|
||||
local type = token(l.TYPE, word_match{
|
||||
'EcPoint', 'EcFixedPoint', 'EcFixedPointBase', 'EcFixedPointShort',
|
||||
'Base', 'BaseArray', 'Scalar', 'ScalarArray',
|
||||
'MerklePath',
|
||||
'Uint32', 'Uint64',
|
||||
'EcNiPoint', 'Base', 'BaseArray', 'Scalar', 'ScalarArray',
|
||||
'MerklePath', 'Uint32', 'Uint64',
|
||||
})
|
||||
|
||||
-- Instructions.
|
||||
local instruction = token('instruction', word_match{
|
||||
'ec_add', 'ec_mul', 'ec_mul_base', 'ec_mul_short',
|
||||
'ec_add', 'ec_mul', 'ec_mul_base', 'ec_mul_short', 'ec_mul_var_base',
|
||||
'ec_get_x', 'ec_get_y',
|
||||
'base_add', 'base_mul', 'base_sub',
|
||||
'poseidon_hash', 'merkle_root',
|
||||
|
||||
@@ -13,13 +13,12 @@ syn keyword zkasKeyword
|
||||
\ circuit
|
||||
|
||||
syn keyword zkasType
|
||||
\ EcPoint EcFixedPoint EcFixedPointBase EcFixedPointShort
|
||||
\ EcPoint EcFixedPoint EcFixedPointBase EcFixedPointShort EcNiPoint
|
||||
\ Base BaseArray Scalar ScalarArray
|
||||
\ MerklePath
|
||||
\ Uint32 Uint64
|
||||
\ MerklePath Uint32 Uint64
|
||||
|
||||
syn keyword zkasInstruction
|
||||
\ ec_add ec_mul ec_mul_base ec_mul_short
|
||||
\ ec_add ec_mul ec_mul_base ec_mul_short ec_mul_var_base
|
||||
\ ec_get_x ec_get_y
|
||||
\ base_add base_mul base_sub
|
||||
\ poseidon_hash merkle_root
|
||||
|
||||
@@ -15,6 +15,9 @@ contract "Opcodes" {
|
||||
|
||||
Base secret,
|
||||
|
||||
EcNiPoint pubkey,
|
||||
Base ephem_secret,
|
||||
|
||||
Uint32 leaf_pos,
|
||||
MerklePath path,
|
||||
}
|
||||
@@ -56,4 +59,8 @@ circuit "Opcodes" {
|
||||
constrain_instance(ec_get_y(public));
|
||||
|
||||
bool_check(one);
|
||||
|
||||
ephem_public = ec_mul_var_base(ephem_secret, pubkey);
|
||||
constrain_instance(ec_get_x(ephem_public));
|
||||
constrain_instance(ec_get_y(ephem_public));
|
||||
}
|
||||
|
||||
35
src/zk/vm.rs
35
src/zk/vm.rs
@@ -24,7 +24,8 @@ use darkfi_sdk::crypto::constants::{
|
||||
use halo2_gadgets::{
|
||||
ecc::{
|
||||
chip::{EccChip, EccConfig},
|
||||
FixedPoint, FixedPointBaseField, FixedPointShort, Point, ScalarFixed, ScalarFixedShort,
|
||||
FixedPoint, FixedPointBaseField, FixedPointShort, NonIdentityPoint, Point, ScalarFixed,
|
||||
ScalarFixedShort, ScalarVar,
|
||||
},
|
||||
poseidon::{
|
||||
primitives as poseidon, Hash as PoseidonHash, Pow5Chip as PoseidonChip,
|
||||
@@ -414,6 +415,18 @@ impl Circuit<pallas::Base> for ZkCircuit {
|
||||
stack.push(StackVar::EcPoint(point));
|
||||
}
|
||||
|
||||
Witness::EcNiPoint(w) => {
|
||||
trace!(target: L_TGT, "Witnessing EcNiPoint into circuit");
|
||||
let point = NonIdentityPoint::new(
|
||||
ecc_chip.clone(),
|
||||
layouter.namespace(|| "Witness EcNiPoint"),
|
||||
w.as_ref().map(|cm| cm.to_affine()),
|
||||
)?;
|
||||
|
||||
trace!(target: L_TGT, "Pushing EcNiPoint to stack index {}", stack.len());
|
||||
stack.push(StackVar::EcNiPoint(point));
|
||||
}
|
||||
|
||||
Witness::EcFixedPoint(_) => {
|
||||
error!(target: L_TGT, "Unable to witness EcFixedPoint, this is unimplemented.");
|
||||
return Err(plonk::Error::Synthesis)
|
||||
@@ -501,6 +514,26 @@ impl Circuit<pallas::Base> for ZkCircuit {
|
||||
stack.push(StackVar::EcPoint(ret));
|
||||
}
|
||||
|
||||
Opcode::EcMulVarBase => {
|
||||
trace!(target: L_TGT, "Executing `EcMulVarBase{:?}` opcode", opcode.1);
|
||||
let args = &opcode.1;
|
||||
|
||||
let lhs: NonIdentityPoint<pallas::Affine, EccChip<OrchardFixedBases>> =
|
||||
stack[args[1].1].clone().into();
|
||||
|
||||
let rhs: AssignedCell<Fp, Fp> = stack[args[0].1].clone().into();
|
||||
let rhs = ScalarVar::from_base(
|
||||
ecc_chip.clone(),
|
||||
layouter.namespace(|| "EcMulVarBase::from_base()"),
|
||||
&rhs,
|
||||
)?;
|
||||
|
||||
let (ret, _) = lhs.mul(layouter.namespace(|| "EcMulVarBase()"), rhs)?;
|
||||
|
||||
trace!(target: L_TGT, "Pushing result to stack index {}", stack.len());
|
||||
stack.push(StackVar::EcPoint(ret));
|
||||
}
|
||||
|
||||
Opcode::EcMulBase => {
|
||||
trace!(target: L_TGT, "Executing `EcMulBase{:?}` opcode", opcode.1);
|
||||
let args = &opcode.1;
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
//! VM stack type abstractions
|
||||
use darkfi_sdk::crypto::{constants::OrchardFixedBases, MerkleNode};
|
||||
use halo2_gadgets::ecc::{chip::EccChip, FixedPoint, FixedPointBaseField, FixedPointShort, Point};
|
||||
use halo2_gadgets::ecc::{
|
||||
chip::EccChip, FixedPoint, FixedPointBaseField, FixedPointShort, NonIdentityPoint, Point,
|
||||
};
|
||||
use halo2_proofs::{
|
||||
circuit::{AssignedCell, Value},
|
||||
pasta::pallas,
|
||||
@@ -31,6 +33,7 @@ use crate::zkas::{decoder::ZkBinary, types::VarType};
|
||||
#[derive(Clone)]
|
||||
pub enum Witness {
|
||||
EcPoint(Value<pallas::Point>),
|
||||
EcNiPoint(Value<pallas::Point>),
|
||||
EcFixedPoint(Value<pallas::Point>),
|
||||
Base(Value<pallas::Base>),
|
||||
Scalar(Value<pallas::Scalar>),
|
||||
@@ -51,6 +54,7 @@ pub fn empty_witnesses(zkbin: &ZkBinary) -> Vec<Witness> {
|
||||
for witness in &zkbin.witnesses {
|
||||
match witness {
|
||||
VarType::EcPoint => ret.push(Witness::EcPoint(Value::unknown())),
|
||||
VarType::EcNiPoint => ret.push(Witness::EcNiPoint(Value::unknown())),
|
||||
VarType::EcFixedPoint => ret.push(Witness::EcFixedPoint(Value::unknown())),
|
||||
VarType::Base => ret.push(Witness::Base(Value::unknown())),
|
||||
VarType::Scalar => ret.push(Witness::Scalar(Value::unknown())),
|
||||
@@ -66,9 +70,10 @@ pub fn empty_witnesses(zkbin: &ZkBinary) -> Vec<Witness> {
|
||||
|
||||
/// These represent the witness types inside the circuit
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum StackVar {
|
||||
EcPoint(Point<pallas::Affine, EccChip<OrchardFixedBases>>),
|
||||
EcNiPoint(NonIdentityPoint<pallas::Affine, EccChip<OrchardFixedBases>>),
|
||||
EcFixedPoint(FixedPoint<pallas::Affine, EccChip<OrchardFixedBases>>),
|
||||
EcFixedPointShort(FixedPointShort<pallas::Affine, EccChip<OrchardFixedBases>>),
|
||||
EcFixedPointBase(FixedPointBaseField<pallas::Affine, EccChip<OrchardFixedBases>>),
|
||||
@@ -94,6 +99,7 @@ macro_rules! impl_from {
|
||||
}
|
||||
|
||||
impl_from!(EcPoint, Point<pallas::Affine, EccChip<OrchardFixedBases>>);
|
||||
impl_from!(EcNiPoint, NonIdentityPoint<pallas::Affine, EccChip<OrchardFixedBases>>);
|
||||
impl_from!(EcFixedPoint, FixedPoint<pallas::Affine, EccChip<OrchardFixedBases>>);
|
||||
impl_from!(EcFixedPointShort, FixedPointShort<pallas::Affine, EccChip<OrchardFixedBases>>);
|
||||
impl_from!(EcFixedPointBase, FixedPointBaseField<pallas::Affine, EccChip<OrchardFixedBases>>);
|
||||
|
||||
@@ -28,7 +28,7 @@ pub enum Opcode {
|
||||
/// Elliptic curve addition
|
||||
EcAdd = 0x01,
|
||||
|
||||
// Elliptic curve multiplication
|
||||
/// Elliptic curve multiplication
|
||||
EcMul = 0x02,
|
||||
|
||||
/// Elliptic curve multiplication with a Base field element
|
||||
@@ -37,6 +37,9 @@ pub enum Opcode {
|
||||
/// Elliptic curve multiplication with a Base field element of 64bit width
|
||||
EcMulShort = 0x04,
|
||||
|
||||
/// Variable Elliptic curve multiplication with a Base field element
|
||||
EcMulVarBase = 0x05,
|
||||
|
||||
/// Get the x coordinate of an elliptic curve point
|
||||
EcGetX = 0x08,
|
||||
|
||||
@@ -95,6 +98,7 @@ impl Opcode {
|
||||
"ec_mul" => Some(Self::EcMul),
|
||||
"ec_mul_base" => Some(Self::EcMulBase),
|
||||
"ec_mul_short" => Some(Self::EcMulShort),
|
||||
"ec_mul_var_base" => Some(Self::EcMulVarBase),
|
||||
"ec_get_x" => Some(Self::EcGetX),
|
||||
"ec_get_y" => Some(Self::EcGetY),
|
||||
"poseidon_hash" => Some(Self::PoseidonHash),
|
||||
@@ -121,6 +125,7 @@ impl Opcode {
|
||||
0x02 => Some(Self::EcMul),
|
||||
0x03 => Some(Self::EcMulBase),
|
||||
0x04 => Some(Self::EcMulShort),
|
||||
0x05 => Some(Self::EcMulVarBase),
|
||||
0x08 => Some(Self::EcGetX),
|
||||
0x09 => Some(Self::EcGetY),
|
||||
0x10 => Some(Self::PoseidonHash),
|
||||
@@ -159,6 +164,10 @@ impl Opcode {
|
||||
(vec![VarType::EcPoint], vec![VarType::Base, VarType::EcFixedPointShort])
|
||||
}
|
||||
|
||||
Opcode::EcMulVarBase => {
|
||||
(vec![VarType::EcPoint], vec![VarType::Base, VarType::EcNiPoint])
|
||||
}
|
||||
|
||||
Opcode::EcGetX => (vec![VarType::Base], vec![VarType::EcPoint]),
|
||||
|
||||
Opcode::EcGetY => (vec![VarType::Base], vec![VarType::EcPoint]),
|
||||
|
||||
@@ -509,6 +509,24 @@ impl Parser {
|
||||
|
||||
// Valid witness types
|
||||
match v.1.token.as_str() {
|
||||
"EcPoint" => {
|
||||
ret.push(Witness {
|
||||
name: k.to_string(),
|
||||
typ: VarType::EcPoint,
|
||||
line: v.0.line,
|
||||
column: v.0.column,
|
||||
});
|
||||
}
|
||||
|
||||
"EcNiPoint" => {
|
||||
ret.push(Witness {
|
||||
name: k.to_string(),
|
||||
typ: VarType::EcNiPoint,
|
||||
line: v.0.line,
|
||||
column: v.0.column,
|
||||
});
|
||||
}
|
||||
|
||||
"Base" => {
|
||||
ret.push(Witness {
|
||||
name: k.to_string(),
|
||||
|
||||
@@ -53,6 +53,9 @@ pub enum VarType {
|
||||
/// Elliptic curve fixed point in base field
|
||||
EcFixedPointBase = 0x04,
|
||||
|
||||
/// Elliptic curve nonidentity point
|
||||
EcNiPoint = 0x05,
|
||||
|
||||
/// Base field element
|
||||
Base = 0x10,
|
||||
|
||||
@@ -82,6 +85,7 @@ impl VarType {
|
||||
0x02 => Some(Self::EcFixedPoint),
|
||||
0x03 => Some(Self::EcFixedPointShort),
|
||||
0x04 => Some(Self::EcFixedPointBase),
|
||||
0x05 => Some(Self::EcNiPoint),
|
||||
0x10 => Some(Self::Base),
|
||||
0x11 => Some(Self::BaseArray),
|
||||
0x12 => Some(Self::Scalar),
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
use darkfi_sdk::{
|
||||
crypto::{pedersen::pedersen_commitment_u64, MerkleNode, PublicKey, SecretKey},
|
||||
crypto::{pedersen::pedersen_commitment_u64, util::mod_r_p, MerkleNode, PublicKey, SecretKey},
|
||||
incrementalmerkletree::{bridgetree::BridgeTree, Tree},
|
||||
};
|
||||
use halo2_gadgets::poseidon::{
|
||||
@@ -80,6 +80,10 @@ fn zkvm_opcodes() -> Result<()> {
|
||||
let merkle_path = tree.authentication_path(leaf_pos, &root).unwrap();
|
||||
let leaf_pos: u64 = leaf_pos.into();
|
||||
|
||||
let ephem_secret = SecretKey::random(&mut OsRng);
|
||||
let pubkey = PublicKey::from_secret(ephem_secret).inner();
|
||||
let (ephem_x, ephem_y) = PublicKey::from(pubkey * mod_r_p(ephem_secret.inner())).xy();
|
||||
|
||||
let prover_witnesses = vec![
|
||||
Witness::Base(Value::known(pallas::Base::from(value))),
|
||||
Witness::Scalar(Value::known(value_blind)),
|
||||
@@ -87,6 +91,8 @@ fn zkvm_opcodes() -> Result<()> {
|
||||
Witness::Base(Value::known(a)),
|
||||
Witness::Base(Value::known(b)),
|
||||
Witness::Base(Value::known(secret)),
|
||||
Witness::EcNiPoint(Value::known(pubkey)),
|
||||
Witness::Base(Value::known(ephem_secret.inner())),
|
||||
Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())),
|
||||
Witness::MerklePath(Value::known(merkle_path.try_into().unwrap())),
|
||||
];
|
||||
@@ -100,8 +106,17 @@ fn zkvm_opcodes() -> Result<()> {
|
||||
let public = PublicKey::from_secret(SecretKey::from(secret));
|
||||
let (pub_x, pub_y) = public.xy();
|
||||
|
||||
let public_inputs =
|
||||
vec![*value_coords.x(), *value_coords.y(), c2, d, root.inner(), pub_x, pub_y];
|
||||
let public_inputs = vec![
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
c2,
|
||||
d,
|
||||
root.inner(),
|
||||
pub_x,
|
||||
pub_y,
|
||||
ephem_x,
|
||||
ephem_y,
|
||||
];
|
||||
|
||||
let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
|
||||
let proving_key = ProvingKey::build(13, &circuit);
|
||||
|
||||
Reference in New Issue
Block a user