Ver código fonte

zk/vm: Add BaseAdd and BaseMul from the arithmetic chip.

parazyd 4 anos atrás
pai
commit
4e774c9710
4 arquivos alterados com 71 adições e 0 exclusões
  1. 1 0
      contrib/zk.lua
  2. 40 0
      src/zk/vm.rs
  3. 10 0
      src/zkas/opcode.rs
  4. 20 0
      src/zkas/parser.rs

+ 1 - 0
contrib/zk.lua

@@ -32,6 +32,7 @@ local type = token(l.TYPE, word_match{
 local instruction = token('instruction', word_match{
   'ec_add', 'ec_mul', 'ec_mul_base', 'ec_mul_short',
   'ec_get_x', 'ec_get_y',
+  'base_add', 'base_mul',
   'poseidon_hash', 'calculate_merkle_root',
   'constrain_instance',
 })

+ 40 - 0
src/zk/vm.rs

@@ -22,6 +22,8 @@ use halo2_proofs::{
 use log::debug;
 use pasta_curves::{group::Curve, pallas, Fp};
 
+use super::arith_chip::{ArithmeticChip, ArithmeticChipConfig};
+
 pub use super::vm_stack::{StackVar, Witness};
 use crate::{
     crypto::constants::{
@@ -42,6 +44,7 @@ pub struct VmConfig {
     sinsemilla_cfg1: SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
     _sinsemilla_cfg2: SinsemillaConfig<OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases>,
     poseidon_config: PoseidonConfig<pallas::Base, 3, 2>,
+    arith_config: ArithmeticChipConfig,
 }
 
 impl VmConfig {
@@ -78,6 +81,10 @@ impl VmConfig {
     fn poseidon_chip(&self) -> PoseidonChip<pallas::Base, 3, 2> {
         PoseidonChip::construct(self.poseidon_config.clone())
     }
+
+    fn arithmetic_chip(&self) -> ArithmeticChip {
+        ArithmeticChip::construct(self.arith_config.clone())
+    }
 }
 
 #[derive(Clone, Default)]
@@ -180,6 +187,9 @@ impl Circuit<pallas::Base> for ZkCircuit {
             rc_b,
         );
 
+        // Configuration for the Arithmetic chip
+        let arith_config = ArithmeticChip::configure(meta);
+
         // Configuration for a Sinsemilla hash instantiation and a
         // Merkle hash instantiation using this Sinsemilla instance.
         // Since the Sinsemilla config uses only 5 advice columns,
@@ -219,6 +229,7 @@ impl Circuit<pallas::Base> for ZkCircuit {
             sinsemilla_cfg1,
             _sinsemilla_cfg2,
             poseidon_config,
+            arith_config,
         }
     }
 
@@ -241,6 +252,9 @@ impl Circuit<pallas::Base> for ZkCircuit {
         // Construct the ECC chip.
         let ecc_chip = config.ecc_chip();
 
+        // Construct the Arithmetic chip.
+        let arith_chip = config.arithmetic_chip();
+
         // This constant one is used for short multiplication
         let one = self.load_private(
             layouter.namespace(|| "Load constant one"),
@@ -495,6 +509,32 @@ impl Circuit<pallas::Base> for ZkCircuit {
                     stack.push(StackVar::Base(root));
                 }
 
+                Opcode::BaseAdd => {
+                    debug!("Executing `BaseAdd{:?}` opcode", opcode.1);
+                    let args = &opcode.1;
+
+                    let lhs = stack[args[0]].clone().into();
+                    let rhs = stack[args[1]].clone().into();
+
+                    let sum = arith_chip.add(layouter.namespace(|| "BaseAdd()"), lhs, rhs)?;
+
+                    debug!("Pushing sum to stack index {}", stack.len());
+                    stack.push(StackVar::Base(sum));
+                }
+
+                Opcode::BaseMul => {
+                    debug!("Executing `BaseMul{:?}` opcode", opcode.1);
+                    let args = &opcode.1;
+
+                    let lhs = stack[args[0]].clone().into();
+                    let rhs = stack[args[1]].clone().into();
+
+                    let product = arith_chip.mul(layouter.namespace(|| "BaseMul()"), lhs, rhs)?;
+
+                    debug!("Pushing product to stack index {}", stack.len());
+                    stack.push(StackVar::Base(product));
+                }
+
                 Opcode::ConstrainInstance => {
                     debug!("Executing `ConstrainInstance{:?}` opcode", opcode.1);
                     let args = &opcode.1;

+ 10 - 0
src/zkas/opcode.rs

@@ -28,6 +28,12 @@ pub enum Opcode {
     /// Calculate merkle root given given a position, Merkle path, and an element
     CalculateMerkleRoot = 0x20,
 
+    /// Base field element addition
+    BaseAdd = 0x30,
+
+    /// Base field element multiplication
+    BaseMul = 0x31,
+
     /// Constrain a Base field element to a circuit's public input
     ConstrainInstance = 0xf0,
 
@@ -51,6 +57,8 @@ impl Opcode {
             Opcode::CalculateMerkleRoot => {
                 (vec![Type::Base], vec![Type::Uint32, Type::MerklePath, Type::Base])
             }
+            Opcode::BaseAdd => (vec![Type::Base], vec![Type::Base, Type::Base]),
+            Opcode::BaseMul => (vec![Type::Base], vec![Type::Base, Type::Base]),
             Opcode::ConstrainInstance => (vec![], vec![Type::Base]),
             Opcode::Noop => (vec![], vec![]),
         }
@@ -66,6 +74,8 @@ impl Opcode {
             0x09 => Self::EcGetY,
             0x10 => Self::PoseidonHash,
             0x20 => Self::CalculateMerkleRoot,
+            0x30 => Self::BaseAdd,
+            0x31 => Self::BaseMul,
             0xf0 => Self::ConstrainInstance,
             _ => unimplemented!(),
         }

+ 20 - 0
src/zkas/parser.rs

@@ -638,6 +638,26 @@ impl Parser {
                         continue
                     }
 
+                    "base_add" => {
+                        stmt.args = self.parse_function_call(token, &mut iter);
+                        stmt.opcode = Opcode::BaseAdd;
+                        stmt.line = token.line;
+                        stmts.push(stmt.clone());
+
+                        parsing = false;
+                        continue
+                    }
+
+                    "base_mul" => {
+                        stmt.args = self.parse_function_call(token, &mut iter);
+                        stmt.opcode = Opcode::BaseMul;
+                        stmt.line = token.line;
+                        stmts.push(stmt.clone());
+
+                        parsing = false;
+                        continue
+                    }
+
                     x => {
                         self.error.emit(
                             format!("Unimplemented function call `{}`", x),