ソースを参照

working blake2s hash function!

narodnik 5 年 前
コミット
2bda684163
5 ファイル変更93 行追加19 行削除
  1. 4 0
      proofs/simple.aux
  2. 5 1
      proofs/simple.pism
  3. 16 1
      scripts/codegen.py
  4. 35 15
      scripts/pism.py
  5. 33 2
      src/simple.rs

+ 4 - 0
proofs/simple.aux

@@ -3,6 +3,10 @@
         "G_SPEND": {
             "maps_to": "SPENDING_KEY_GENERATOR",
             "module_includes": "zcash_proofs::constants"
+        },
+        "CRH_IVK": {
+            "maps_to": "CRH_IVK_PERSONALIZATION",
+            "module_includes": "zcash_primitives::constants"
         }
     }
 }

+ 5 - 1
proofs/simple.pism

@@ -1,6 +1,7 @@
 # :set syntax=pism
 # :source ../scripts/pism.vim
 constant G_SPEND FixedGenerator
+constant CRH_IVK BlakePersonalization
 
 contract input_spend
     param secret Fr
@@ -17,7 +18,10 @@ start
 
     alloc_binary preimage
     ec_repr repr_ak ak
-    binary_clone repr_ak2 repr_ak
+    #binary_clone repr_ak2 repr_ak
     binary_extend preimage repr_ak
+    static_assert_binary_size preimage 256
+    blake2s ivk preimage CRH_IVK
+    emit_binary ivk
 end
 

+ 16 - 1
scripts/codegen.py

@@ -36,8 +36,23 @@ def alloc_binary(line, out):
     return "let mut %s = vec![];" % out
 
 def binary_clone(line, out, binary):
-    return "let %s = %s.iter().cloned()" % (out, binary)
+    return "let %s = %s.iter().cloned();" % (out, binary)
 
 def binary_extend(line, binary, value):
     return "%s.extend(%s);" % (binary, value)
 
+def static_assert_binary_size(line, binary, size):
+    return "assert_eq!(%s.len(), %s);" % (binary, size)
+
+def blake2s(line, out, input, personalization):
+    return \
+r"""let mut %s = blake2s::blake2s(
+    cs.namespace(|| "%s"),
+    &%s,
+    %s,
+)?;""" % (out, line, input, personalization)
+
+def emit_binary(line, binary):
+    return 'multipack::pack_into_inputs(cs.namespace(|| "%s"), &%s)?;' % (
+        line, binary)
+

+ 35 - 15
scripts/pism.py

@@ -9,17 +9,6 @@ symbol_table = {
     "param": 2,
     "start": 0,
     "end": 0,
-
-    "witness": 2,
-    "assert_not_small_order": 1,
-    "fr_as_binary_le": 2,
-    "ec_mul_const": 3,
-    "ec_add": 3,
-    "ec_repr": 2,
-    "emit_ec": 1,
-    "alloc_binary": 1,
-    "binary_clone": 2,
-    "binary_extend": 2,
 }
 
 types_map = {
@@ -70,6 +59,18 @@ command_desc = {
         ("Vec<Boolean>",    False),
         ("Vec<Boolean>",    False),
     ),
+    "static_assert_binary_size": (
+        ("Vec<Boolean>",    False),
+        ("INTEGER",         False),
+    ),
+    "blake2s": (
+        ("Vec<Boolean>",    True),
+        ("Vec<Boolean>",    False),
+        ("BlakePersonalization", False),
+    ),
+    "emit_binary": (
+        ("Vec<Boolean>",    False),
+    ),
 }
 
 def eprint(*args):
@@ -163,8 +164,19 @@ def extract(segment):
 
     for line in segment:
         command, args = line.command(), line.args()
-        if symbol_table[command] != len(args):
-            eprint("error: wrong number of args for command '%s'" % command)
+
+        if command in symbol_table:
+            if symbol_table[command] != len(args):
+                eprint("error: wrong number of args for command '%s'" % command)
+                eprint(line)
+                return None
+        elif command in command_desc:
+            if len(command_desc[command]) != len(args):
+                eprint("error: wrong number of args for command '%s'" % command)
+                eprint(line)
+                return None
+        else:
+            eprint("error: missing symbol for command '%s'" % command)
             eprint(line)
             return None
 
@@ -217,6 +229,7 @@ r"""use bellman::{
         boolean,
         boolean::{AllocatedBit, Boolean},
         multipack,
+        blake2s,
     },
     groth16, Circuit, ConstraintSystem, SynthesisError,
 };
@@ -275,6 +288,9 @@ use zcash_proofs::circuit::ecc;
             if new_val:
                 continue
 
+            if expected_type == "INTEGER":
+                continue
+
             if is_param:
                 actual_type = self.params[argname]
             elif argname in self.constants:
@@ -296,7 +312,7 @@ use zcash_proofs::circuit::ecc;
         type_list = command_desc[command]
         assert len(type_list) == len(args)
 
-        for (_, is_new_val), (arg, is_param) in zip(type_list, args):
+        for (expected_type, is_new_val), (arg, is_param) in zip(type_list, args):
             if is_param:
                 continue
             if is_new_val:
@@ -306,6 +322,9 @@ use zcash_proofs::circuit::ecc;
             if arg in self.constants:
                 continue
 
+            if expected_type == "INTEGER":
+                continue
+
             eprint("error: cannot find '%s' in the stack" % arg)
             eprint(line)
             return False
@@ -405,7 +424,8 @@ def process(contents, aux):
 
     codes = []
     for segment in segments:
-        contract = extract(segment)
+        if (contract := extract(segment)) is None:
+            return False
         if (code := contract.compile(constants, aux)) is None:
             return False
         codes.append(code)

+ 33 - 2
src/simple.rs

@@ -1,7 +1,10 @@
 use bellman::groth16;
+use bellman::gadgets::multipack;
 use bls12_381::Bls12;
 use ff::Field;
-use group::{Curve, Group};
+use group::{Curve, Group, GroupEncoding};
+use blake2s_simd::Params as Blake2sParams;
+
 mod simple_circuit;
 use simple_circuit::InputSpend;
 
@@ -29,7 +32,7 @@ fn main() {
 
     let proof = groth16::create_random_proof(c, &params, &mut OsRng).unwrap();
 
-    let mut public_input = [bls12_381::Scalar::zero(); 2];
+    let mut public_input = [bls12_381::Scalar::zero(); 4];
     {
         let result = jubjub::ExtendedPoint::from(public);
         let affine = result.to_affine();
@@ -40,5 +43,33 @@ fn main() {
         public_input[1] = v;
     }
 
+    {
+        const CRH_IVK_PERSONALIZATION: &[u8; 8] = b"Zcashivk";
+        let preimage = [42; 80];
+        let hash_result = {
+            let mut hash = [0; 32];
+            hash.copy_from_slice(
+                Blake2sParams::new()
+                .hash_length(32)
+                .personal(CRH_IVK_PERSONALIZATION)
+                .to_state()
+                .update(&ak.to_bytes())
+                .finalize()
+                .as_bytes()
+            );
+            hash
+        };
+
+        // Pack the hash as inputs for proof verification.
+        let hash = multipack::bytes_to_bits_le(&hash_result);
+        let hash = multipack::compute_multipacking(&hash);
+
+        // There are 2 chunks for a blake hash
+        assert_eq!(hash.len(), 2);
+
+        public_input[2] = hash[0];
+        public_input[3] = hash[1];
+    }
+
     assert!(groth16::verify_proof(&pvk, &proof, &public_input).is_ok());
 }