Bläddra i källkod

zkrunner: API and style refactoring

freerangedev 3 år sedan
förälder
incheckning
9912167686

+ 1 - 15
bin/zkrunner/README.md

@@ -1,17 +1,3 @@
 # Installation
 
-For now, you'd need to install maturin manually to run this tool.
-
-```
-# New vene and maturin
-python3 -m venv ~/.venv-zkrunner
-source ~/.venv-zkrunner/bin/activate
-pip install maturin
-
-# Install shared module onto Python
-cd $DARKFI/src/sdk-py
-maturin develop
-
-
-# You can run zkrunner.py now!
-```
+Follow the guide in src/sdk/python/README.md to install the Python bindings and virtual environment.

+ 0 - 85
bin/zkrunner/exploratory/prove_verify.py

@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Script for playing around with the Python SDK
-"""
-
-from darkfi_sdk_py import Base
-from darkfi_sdk_py import Scalar
-from darkfi_sdk_py import Point
-from darkfi_sdk_py import Affine
-from darkfi_sdk_py import Proof
-from darkfi_sdk_py import VerifyingKey
-from darkfi_sdk_py import ProvingKey
-from darkfi_sdk_py import Affine
-from darkfi_sdk_py import ZkCircuit
-from darkfi_sdk_py import ZkBinary
-from time import time
-from sys import getsizeof
-
-##### get circuit #####
-
-f = open("simple.zk.bin", "rb")
-bincode = f.read()
-f.close()
-print(f"bincode {bincode}")
-zkbin = ZkBinary.decode(bincode)
-print(f"zkbin {zkbin}")
-
-##### prover #####
-k = 13
-value = 42
-value_blind = Scalar.random()
-
-zkcircuit = ZkCircuit(zkbin)
-zkcircuit.witness_base(Base.from_u128(value))
-zkcircuit.witness_scalar(value_blind)
-zkcircuit = zkcircuit.build(zkbin)
-
-##### proving key #####
-print("making proving key...")
-proving_key = ProvingKey.build(k, zkcircuit)
-
-# pedersen commitment
-comm = Point.mul_short(value)
-comm_r = Point.blinding_point(value_blind)
-valcom = comm.add(comm_r)
-print(f"valcom {valcom}")
-(x, y) = valcom.to_affine().coordinates()
-print(f"x {x}")
-print(f"y {y}")
-print(x)
-print(y)
-publics = [x, y]
-
-start = time()
-print("making proof...")
-proof = Proof.create(proving_key, [zkcircuit], publics)
-print(f"time {time() - start}")
-
-
-#################### VERIFICATION
-
-print("verification starts.....")
-
-start = time()
-zkcircuit_v = zkcircuit.verifier_build(zkbin)
-
-print(f"building verifying key")
-start = time()
-# IMPORTANT QUESTION: can this be uploaded to an eth smart contract
-verifying_key = VerifyingKey.build(k, zkcircuit_v)
-print(f"time {time() - start}")
-
-
-print(f"verifying")
-start = time()
-proof.verify(verifying_key, publics)
-print(f"time {time() - start}")
-
-print(f"size of proof        : {getsizeof(proof)}")
-print(f"size of proving key  : {getsizeof(proving_key)}")
-print(f"size of verifying key: {getsizeof(verifying_key)}")
-
-## SHOULD FAILLLLLL
-proof.verify(verifying_key, [x])

+ 0 - 103
bin/zkrunner/exploratory/zkrunner.py~

@@ -1,103 +0,0 @@
-############################################################
-# Version that supports (de)serializastion
-# Archived for now
-############################################################
-# """
-# Acceptable format:
-# 
-# A witness or public input = [<type>, <value>]
-# 
-# <type> = Base|Scalar|EcPoint
-# 
-# <value> = "NUMBER|HEX_NUMBER" for Base or Scalar
-#         = "HEX_NUMBER" for Point
-# """
-# def serialize_input(input):
-#     input = ['Base', '42']
-#     vartype, varserial = input
-#     if vartype == 'Base':
-#         return Base.from_u64(varserial)
-#     pass
-# 
-# def deserialize_input():
-#     pass
-# 
-# def make_publics(args):
-#     print(f"make_publics: {args}")
-# 
-# def prove(args):
-#     print(f"prove: {args}")
-# 
-# def verify(args):
-#     print(f"verify: {args}")
-#     
-# """
-# TODO:
-# 
-# * Why did EcNiPoint fail to be witnessed (when building the proving key and in vm.rs)?
-#     * This is the last opcode that is not supported by ZkRunner
-# * Why do the witness type and heap var type have different sets of variants?
-#     * Need to confirm the simplications of types, i.e. Rust has more types than Python, do not have gotchas
-# * If we want to send publics around in a file, we need to figure out the serialization format
-# """
-# if __name__ == "__main__":
-#     desc = "ZkRunner helps compute public inputs, and prove and verify Darkfi zero knowledge proofs."
-#     global_parser = ArgumentParser(
-#         prog="ZkRunner",
-#         description=desc
-#     )
-#     subparsers = global_parser.add_subparsers(title="commands")
-# 
-#     # make_publics
-#     m_parser = subparsers.add_parser("make-publics", help="Make public inputs",)
-#     m_parser.add_argument(
-#             "--witnesses",
-#             default="witnesses.json",
-#             help="[default: witnesses.json] Path for where the witnesses are stored"
-#     )
-#     m_parser.add_argument(
-#             "--publics",
-#             default="publics.json",
-#             help="[default: publics.json] Path for where to store the computed public inputs for proving and verifying"
-#     )
-#     m_parser.set_defaults(func=make_publics)
-# 
-# 
-#     # prove
-#     p_parser = subparsers.add_parser("prove", help="Generate proving key and prove")
-#     p_parser.add_argument(
-#             "--witnesses",
-#             default="witnesses.json",
-#             help="[default: witnesses.json] Path for where the witnesses are stored"
-#     )
-#     p_parser.add_argument(
-#             "--publics",
-#             default="publics.json",
-#             help="[default: publics.json] Path for where to store the computed public inputs for proving and verifying"
-#     )
-#     p_parser.add_argument(
-#             "--proof",
-#             default="proof.json",
-#             help="[default: proof.json] Path for where to store the computed proof"
-#     )
-#     p_parser.set_defaults(func=prove)
-# 
-# 
-#     # verify
-#     v_parser = subparsers.add_parser("verify", help="Generate verifying key and verify")
-#     v_parser.add_argument(
-#             "--publics",
-#             default="publics.json",
-#             help="[default: publics.json] Path for where to store the computed public inputs for proving and verifying"
-#     )
-#     v_parser.add_argument(
-#             "--proof",
-#             default="proof.json",
-#             help="[default: proof.json] Path for where to store the computed proof"
-#     )
-#     v_parser.set_defaults(func=verify)
-# 
-# 
-#     args = global_parser.parse_args()
-#     # calls the command
-#     args.func(args)     

+ 56 - 55
bin/zkrunner/zkrunner.py

@@ -3,108 +3,109 @@
 from argparse import ArgumentParser
 from darkfi_sdk_py.affine import Affine
 from darkfi_sdk_py.base import Base
-from darkfi_sdk_py.scalar import Scalar
+from darkfi_sdk_py.point import Point
 from darkfi_sdk_py.proof import Proof
 from darkfi_sdk_py.proving_key import ProvingKey
-from darkfi_sdk_py.point import Point
+from darkfi_sdk_py.scalar import Scalar
 from darkfi_sdk_py.verifying_key import VerifyingKey
-from darkfi_sdk_py.zk_circuit import ZkCircuit
 from darkfi_sdk_py.zk_binary import ZkBinary
-from time import time
+from darkfi_sdk_py.zk_circuit import ZkCircuit
+from pprint import pprint
 from sys import getsizeof
+from time import time
 
-def insert_heap(heap, element):
-    print(f"Heap before: {heap}, element: {element}")
+def heap_add(heap, element):
+    print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> heap")
+    pprint(heap)
+    print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> to add")
+    pprint(element)
     heap.append(element)
 
-def insert_publics(publics, element):
-    print(f"Publics before: {publics}, element: {element}")
-    publics.append(element)
+def pubin_add(pubins, element):
+    print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> pubins")
+    pprint(pubins)
+    print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> to add")
+    pprint(element)
+    pubins.append(element)
    
-def get_publics(statements, witnesses, constant_count, literals):
+def get_pubins(statements, witnesses, constant_count, literals):
     # Python heap for executing zk statements
     heap = [None] * constant_count + witnesses
-    publics = []
+    pubins = []
     for stmt in statements:
-        print('---------------- BEGIN ------------------')
-        print(f"Statement: {stmt}")
+        print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> Statement")
+        print(stmt)
         opcode, args = stmt[0], stmt[1]
         if opcode == 'BaseAdd':
             a = heap[args[0][1]]
             b = heap[args[1][1]]
-            insert_heap(heap, a.add(b))
+            heap_add(heap, a + b)
         elif opcode == 'BaseMul':
             a = heap[args[0][1]]
             b = heap[args[1][1]]
-            insert_heap(heap, a.mul(b))
+            heap_add(heap, a * b)
         elif opcode == 'BaseSub':
             a = heap[args[0][1]]
             b = heap[args[1][1]]
-            insert_heap(heap, a.sub(b))
+            heap_add(heap, a - b)
         elif opcode == 'EcAdd':
             a = heap[args[0][1]]
             b = heap[args[1][1]]
-            insert_heap(heap, a.add(b))
+            heap_add(heap, a + b)
         elif opcode == 'EcMul':
             a = heap[args[0][1]]
-            insert_heap(heap, Point.mul_r_generator(a))
+            heap_add(heap, Point.mul_r_generator(a))
         elif opcode in {'EcMulBase', 'EcMulVarBase'}:
             i = args[0][1]
             base = heap[i]
             product = Point.mul_base(base)
-            insert_heap(heap, product)
+            heap_add(heap, product)
         elif opcode == 'EcMulShort':
             value = heap[args[0][1]]
-            insert_heap(heap, Point.mul_short(value))
+            heap_add(heap, Point.mul_short(value))
         elif opcode == 'EcGetX':
             i = args[0][1]
             point = heap[i] 
             x, _ = point.to_affine().coordinates()
-            insert_heap(heap, x)
+            heap_add(heap, x)
         elif opcode == 'EcGetY':
             i = args[0][1]
             point = heap[i] 
             _, y = point.to_affine().coordinates()
-            insert_heap(heap, y)
+            heap_add(heap, y)
         elif opcode == 'PoseidonHash':
             messages = [heap[m[1]] for m in args]
-            insert_heap(heap, Base.poseidon_hash(messages))
+            heap_add(heap, Base.poseidon_hash(messages))
         elif opcode == 'MerkleRoot':
             i = heap[args[0][1]]
             p = heap[args[1][1]]
             a = heap[args[2][1]]
-            insert_heap(heap, Base.merkle_root(i, p, a))
+            heap_add(heap, Base.merkle_root(i, p, a))
         elif opcode == 'ConstrainInstance':
             i = args[0][1]
             element = heap[i] 
-            insert_publics(publics, element)
+            pubin_add(pubins, element)
         elif opcode == 'WitnessBase':
             type = args[0][0]
             assert type == 'Lit', f"type should LitType instead of {type}"
-            print(args)
             i = args[0][1]
             element = int(literals[i][1]) # (LitType, Lit)
-            base = Base(element)
-            insert_heap(heap, base)        
+            base = Base.from_u64(element)
+            heap_add(heap, base)        
         elif opcode == 'CondSelect':
             cnd = heap[args[0][1]]
             thn = heap[args[1][1]]
             els = heap[args[2][1]]
-            assert cnd.eq(Base(0)) or cnd.eq(Base(1)), "Failed bool check"
-            res = thn if cnd.eq(Base(1)) else els
-            insert_heap(heap, res)
+            assert cnd == Base.from_u64(0) or cnd == Base.from_u64(1), "Failed bool check"
+            res = thn if cnd == Base.from_u64(1) else els
+            heap_add(heap, res)
         elif opcode in IGNORED_OPCODES:
-            print(f"Processed opcode: {opcode}")
+            print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> Ignored opcode")
+            pprint(opcode)
         else:
-            print(f"Missing implementation: {opcode}")
-    
-    print("-------------------- END --------------------")
-
-    print("-----------------------------------")
-    print(f"Publics: {publics}")
-    print("-----------------------------------")
-    
-    return publics
+            print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> Missing implementation for opcode")
+            pprint(opcode)
+    return pubins
 
 def bincode_data(bincode):
     with open(bincode, "rb") as f:
@@ -134,27 +135,27 @@ if __name__ ==  "__main__":
     ##### Script inputs #####
 
     bincode_path = "opcodes.no-nipoint.zk.bin"
-    # bincode_path = "../../example/simple.zk.bin"
+    # bincode_path = "../../example/simple.zk.bin" # You must change the witnesses as well
     bincode_data_ = bincode_data(bincode_path)
     zkbin, statements, constant_count, literals = bincode_data_['zkbin'], bincode_data_['statements'], bincode_data_['constant_count'], bincode_data_['literals']
     witnesses = [
-        Base(3),
-        Scalar(4),
-        Base(5),
-        Base(6),
-        Base(7),
-        Base(8),
+        Base.from_u64(3),
+        Scalar.from_u64(4),
+        Base.from_u64(5),
+        Base.from_u64(6),
+        Base.from_u64(7),
+        Base.from_u64(8),
         10,
-        [Base(42)] * 32,
-        Base(1),
+        [Base.from_u64(42)] * 32,
+        Base.from_u64(1),
     ]
     
     ##### Proving #####
     
-    print("Making public inputs based off witnesses......")
-    publics = get_publics(statements, witnesses, constant_count, literals)
+    print("Making public inputs based off of witnesses......")
+    pubins = get_pubins(statements, witnesses, constant_count, literals)
     
-    print("Witnessing into prover's circuit.....")
+    print("Witnessing each witness into prover's circuit.....")
     zkcircuit = ZkCircuit(zkbin)
     zkcircuit.witness_base(witnesses[0])
     zkcircuit.witness_scalar(witnesses[1])
@@ -174,7 +175,7 @@ if __name__ ==  "__main__":
     
     print("Proving.....")
     start = time()
-    proof = Proof.create(proving_key, [zkcircuit], publics)
+    proof = Proof.create(proving_key, [zkcircuit], pubins)
     print(f"Time for proving: {time() - start}")
     
     
@@ -189,6 +190,6 @@ if __name__ ==  "__main__":
     
     print("Verifying.....")
     start = time()
-    proof.verify(verifying_key, publics)
+    proof.verify(verifying_key, pubins)
     print(f"Time for verifying {time() - start}")