Explorar o código

zkas/vm: Add bool_check opcode.

Luther Blissett %!s(int64=3) %!d(string=hai) anos
pai
achega
3f29c4f36d
Modificáronse 5 ficheiros con 32 adicións e 2 borrados
  1. 2 1
      contrib/zk.lua
  2. 1 1
      contrib/zk.vim
  3. 2 0
      proof/opcodes.zk
  4. 20 0
      src/zk/vm.rs
  5. 7 0
      src/zkas/opcode.rs

+ 2 - 1
contrib/zk.lua

@@ -43,7 +43,8 @@ local instruction = token('instruction', word_match{
   'ec_get_x', 'ec_get_y',
   'base_add', 'base_mul', 'base_sub', 'greater_than',
   'poseidon_hash', 'merkle_root', 'constrain_instance',
-  'range_check', 'less_than', 'witness_base',
+  'range_check', 'less_than', 'bool_check',
+  'witness_base',
 })
 
 -- Identifiers.

+ 1 - 1
contrib/zk.vim

@@ -23,7 +23,7 @@ syn keyword zkasInstruction
     \ ec_get_x ec_get_y
     \ base_add base_mul base_sub
     \ poseidon_hash merkle_root constrain_instance
-    \ range_check less_than witness_base
+    \ range_check less_than bool_check witness_base
 
 syn region zkasString start='"' end='"' contained
 

+ 2 - 0
proof/opcodes.zk

@@ -45,4 +45,6 @@ circuit "Opcodes" {
 	public = ec_mul_base(secret, NULLIFIER_K);
 	constrain_instance(ec_get_x(public));
 	constrain_instance(ec_get_y(public));
+
+	bool_check(one);
 }

+ 20 - 0
src/zk/vm.rs

@@ -31,6 +31,7 @@ use super::{
         arithmetic::{ArithChip, ArithConfig, ArithInstruction},
         less_than::{LessThanChip, LessThanConfig},
         native_range_check::{NativeRangeCheckChip, NativeRangeCheckConfig},
+        small_range_check::{SmallRangeCheckChip, SmallRangeCheckConfig},
     },
 };
 use crate::{
@@ -59,6 +60,7 @@ pub struct VmConfig {
     native_64_range_check_config: NativeRangeCheckConfig<3, 64, 22>,
     native_253_range_check_config: NativeRangeCheckConfig<3, 253, 85>,
     lessthan_config: LessThanConfig<3, 253, 85>,
+    boolcheck_config: SmallRangeCheckConfig,
 }
 
 impl VmConfig {
@@ -232,6 +234,10 @@ impl Circuit<pallas::Base> for ZkCircuit {
             k_values_table_253,
         );
 
+        // Configuration for boolean checks, it uses the small_range_check
+        // chip with a range of 2, which enforces one bit, i.e. 0 or 1.
+        let boolcheck_config = SmallRangeCheckChip::configure(meta, advices[9], 2);
+
         VmConfig {
             primary,
             advices,
@@ -245,6 +251,7 @@ impl Circuit<pallas::Base> for ZkCircuit {
             native_64_range_check_config,
             native_253_range_check_config,
             lessthan_config,
+            boolcheck_config,
         }
     }
 
@@ -300,6 +307,9 @@ impl Circuit<pallas::Base> for ZkCircuit {
         // Construct the Arithmetic chip.
         let arith_chip = config.arithmetic_chip();
 
+        // Construct the boolean check chip.
+        let boolcheck_chip = SmallRangeCheckChip::construct(config.boolcheck_config.clone());
+
         // ==========================
         // Constants setup
         // ==========================
@@ -697,6 +707,16 @@ impl Circuit<pallas::Base> for ZkCircuit {
                     )?;
                 }
 
+                Opcode::BoolCheck => {
+                    debug!("Executing `BoolCheck{:?}` opcode", opcode.1);
+                    let args = &opcode.1;
+
+                    let w = stack[args[0].1].clone().into();
+
+                    boolcheck_chip
+                        .small_range_check(layouter.namespace(|| "copy boolean check"), w)?;
+                }
+
                 Opcode::ConstrainInstance => {
                     debug!("Executing `ConstrainInstance{:?}` opcode", opcode.1);
                     let args = &opcode.1;

+ 7 - 0
src/zkas/opcode.rs

@@ -49,6 +49,9 @@ pub enum Opcode {
     /// Compare two Base field elements and see if a is less than b
     LessThan = 0x51,
 
+    /// Check if a field element fits in a boolean (Either 0 or 1)
+    BoolCheck = 0x52,
+
     /// Constrain a Base field element to a circuit's public input
     ConstrainInstance = 0xf0,
 
@@ -73,6 +76,7 @@ impl Opcode {
             "witness_base" => Some(Self::WitnessBase),
             "range_check" => Some(Self::RangeCheck),
             "less_than" => Some(Self::LessThan),
+            "bool_check" => Some(Self::BoolCheck),
             "constrain_instance" => Some(Self::ConstrainInstance),
             "debug" => Some(Self::DebugPrint),
             _ => None,
@@ -95,6 +99,7 @@ impl Opcode {
             0x40 => Some(Self::WitnessBase),
             0x50 => Some(Self::RangeCheck),
             0x51 => Some(Self::LessThan),
+            0x52 => Some(Self::BoolCheck),
             0xf0 => Some(Self::ConstrainInstance),
             0xff => Some(Self::DebugPrint),
             _ => None,
@@ -141,6 +146,8 @@ impl Opcode {
 
             Opcode::LessThan => (vec![], vec![VarType::Base, VarType::Base]),
 
+            Opcode::BoolCheck => (vec![], vec![VarType::Base]),
+
             Opcode::ConstrainInstance => (vec![], vec![VarType::Base]),
 
             Opcode::DebugPrint => (vec![], vec![]),