From 281aa87faf2366c6ac0f285a9ca776282664d109 Mon Sep 17 00:00:00 2001 From: parazyd Date: Sat, 8 Jul 2023 11:07:07 +0200 Subject: [PATCH] zk/vm: Implement zero_cond opcode. --- contrib/zk.lang | 1 + contrib/zk.lua | 2 +- contrib/zk.vim | 2 +- src/consensus/fees.rs | 3 ++- src/zk/vm.rs | 33 ++++++++++++++++++++++++++++++--- src/zkas/opcode.rs | 7 +++++++ 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/contrib/zk.lang b/contrib/zk.lang index 2d6c9b651..cb686e8a5 100644 --- a/contrib/zk.lang +++ b/contrib/zk.lang @@ -69,6 +69,7 @@ less_than_loose bool_check cond_select + zero_cond witness_base constrain_equal_base constrain_equal_point diff --git a/contrib/zk.lua b/contrib/zk.lua index fe56e610f..c89d71a21 100644 --- a/contrib/zk.lua +++ b/contrib/zk.lua @@ -43,7 +43,7 @@ local instruction = token('instruction', word_match{ 'base_add', 'base_mul', 'base_sub', 'poseidon_hash', 'merkle_root', 'range_check', 'less_than_strict', 'less_than_loose', 'bool_check', - 'cond_select', 'witness_base', + 'cond_select', 'zero_cond', 'witness_base', 'constrain_equal_base', 'constrain_equal_point', 'constrain_instance', 'debug', }) diff --git a/contrib/zk.vim b/contrib/zk.vim index 1bb0f6ea1..9c910453a 100644 --- a/contrib/zk.vim +++ b/contrib/zk.vim @@ -23,7 +23,7 @@ syn keyword zkasInstruction \ base_add base_mul base_sub \ poseidon_hash merkle_root \ range_check less_than_strict less_than_loose bool_check - \ cond_select witness_base + \ cond_select zero_cond witness_base \ constrain_equal_base constrain_equal_point \ constrain_instance debug diff --git a/src/consensus/fees.rs b/src/consensus/fees.rs index 04fce91e5..87be78585 100644 --- a/src/consensus/fees.rs +++ b/src/consensus/fees.rs @@ -72,7 +72,8 @@ pub fn circuit_gas_use(zkbin: &ZkBinary) -> u64 { Opcode::LessThanStrict => 100, Opcode::LessThanLoose => 100, Opcode::BoolCheck => 20, - Opcode::CondSelect => 30, + Opcode::CondSelect => 10, + Opcode::ZeroCondSelect => 10, Opcode::ConstrainEqualBase => 10, Opcode::ConstrainEqualPoint => 20, Opcode::ConstrainInstance => 10, diff --git a/src/zk/vm.rs b/src/zk/vm.rs index 4fce51b13..5bafa46d8 100644 --- a/src/zk/vm.rs +++ b/src/zk/vm.rs @@ -58,6 +58,7 @@ use super::{ less_than::{LessThanChip, LessThanConfig}, native_range_check::{NativeRangeCheckChip, NativeRangeCheckConfig}, small_range_check::{SmallRangeCheckChip, SmallRangeCheckConfig}, + zero_cond::{ZeroCondChip, ZeroCondConfig}, }, }; use crate::zkas::{ @@ -82,6 +83,7 @@ pub struct VmConfig { lessthan_config: LessThanConfig<3, 253, 85>, boolcheck_config: SmallRangeCheckConfig, condselect_config: ConditionalSelectConfig, + zerocond_config: ZeroCondConfig, } impl VmConfig { @@ -112,6 +114,10 @@ impl VmConfig { fn condselect_chip(&self) -> ConditionalSelectChip { ConditionalSelectChip::construct(self.condselect_config.clone(), ()) } + + fn zerocond_chip(&self) -> ZeroCondChip { + ZeroCondChip::construct(self.zerocond_config.clone()) + } } #[derive(Clone)] @@ -271,10 +277,13 @@ impl Circuit for ZkCircuit { // chip with a range of 2, which enforces one bit, i.e. 0 or 1. let boolcheck_config = SmallRangeCheckChip::configure(meta, advices[9], 2); - // Cnfiguration for the conditional selection chip + // Configuration for the conditional selection chip let condselect_config = ConditionalSelectChip::configure(meta, advices[1..5].try_into().unwrap()); + // Configuration for the zero_cond selection chip + let zerocond_config = ZeroCondChip::configure(meta, advices[1..5].try_into().unwrap()); + VmConfig { primary, advices, @@ -290,6 +299,7 @@ impl Circuit for ZkCircuit { lessthan_config, boolcheck_config, condselect_config, + zerocond_config, } } @@ -348,9 +358,12 @@ impl Circuit for ZkCircuit { // Construct the boolean check chip. let boolcheck_chip = SmallRangeCheckChip::construct(config.boolcheck_config.clone()); - // Construct the conditional selectiono chip + // Construct the conditional selection chip let condselect_chip = config.condselect_chip(); + // Construct the zero_cond selection chip + let zerocond_chip = config.zerocond_chip(); + // ========================== // Constants setup // ========================== @@ -850,6 +863,20 @@ impl Circuit for ZkCircuit { heap.push(HeapVar::Base(out)); } + Opcode::ZeroCondSelect => { + trace!(target: "zk::vm", "Executing `ZeroCondSelect{:?}` opcode", opcode.1); + let args = &opcode.1; + + let lhs: AssignedCell = heap[args[0].1].clone().into(); + let rhs: AssignedCell = heap[args[1].1].clone().into(); + + let out: AssignedCell = + zerocond_chip.assign(layouter.namespace(|| "zero_cond"), lhs, rhs)?; + + trace!(target: "zk::vm", "Pushing assignment to heap address {}", heap.len()); + heap.push(HeapVar::Base(out)); + } + Opcode::ConstrainEqualBase => { trace!(target: "zk::vm", "Executing `ConstrainEqualBase{:?}` opcode", opcode.1); let args = &opcode.1; @@ -902,7 +929,7 @@ impl Circuit for ZkCircuit { println!("[ZKVM DEBUG] {:#?}", heap[args[0].1]); } - _ => { + Opcode::Noop => { error!(target: "zk::vm", "Unsupported opcode"); return Err(plonk::Error::Synthesis) } diff --git a/src/zkas/opcode.rs b/src/zkas/opcode.rs index bb08e3876..c68e02b27 100644 --- a/src/zkas/opcode.rs +++ b/src/zkas/opcode.rs @@ -81,6 +81,9 @@ pub enum Opcode { /// Conditionally select between two base field elements given a boolean CondSelect = 0x60, + /// Conditionally select between a and b (return a if a is zero, and b if a is nonzero) + ZeroCondSelect = 0x61, + /// Constrain equality of two Base field elements inside the circuit ConstrainEqualBase = 0xe0, @@ -115,6 +118,7 @@ impl Opcode { "less_than_loose" => Some(Self::LessThanLoose), "bool_check" => Some(Self::BoolCheck), "cond_select" => Some(Self::CondSelect), + "zero_cond" => Some(Self::ZeroCondSelect), "constrain_equal_base" => Some(Self::ConstrainEqualBase), "constrain_equal_point" => Some(Self::ConstrainEqualPoint), "constrain_instance" => Some(Self::ConstrainInstance), @@ -143,6 +147,7 @@ impl Opcode { 0x52 => Some(Self::LessThanLoose), 0x53 => Some(Self::BoolCheck), 0x60 => Some(Self::CondSelect), + 0x61 => Some(Self::ZeroCondSelect), 0xe0 => Some(Self::ConstrainEqualBase), 0xe1 => Some(Self::ConstrainEqualPoint), 0xf0 => Some(Self::ConstrainInstance), @@ -203,6 +208,8 @@ impl Opcode { (vec![VarType::Base], vec![VarType::Base, VarType::Base, VarType::Base]) } + Opcode::ZeroCondSelect => (vec![VarType::Base], vec![VarType::Base, VarType::Base]), + Opcode::ConstrainEqualBase => (vec![], vec![VarType::Base, VarType::Base]), Opcode::ConstrainEqualPoint => (vec![], vec![VarType::EcPoint, VarType::EcPoint]),