nizks question

Jun 30, 2015 at 7:03 PM
hello,
I am doing my masters I would really love to use Pinocchio in it. I tried the basic functions and it worked nicely but when I tried the nizk example I got some errors.
What I did:
generated circuits from c:
  python $PINOCCHIO/ccompiler/src/vercomp.py nizk-test.c --arith nizk-test.c.arith --ignore-overflow False --progress True
it created circuit:
total 13
input 0                                  # input
input 1                                  # one-input
nizkinput 2                              # input
nizkinput 3                              # input (unused)
nizkinput 4                              # input
nizkinput 5                              # input (unused)
const-mul-0 in 1 <1> out 1 <6>           # zero
add in 2 <0 2> out 1 <7>                 # ArithBusReq.AddReq(DFG.Input,DFG.NIZKInput)
const-mul-0 in 1 <1> out 1 <8>           # constant 0
add in 2 <0 4> out 1 <9>                 # ArithBusReq.AddReq(DFG.Input,DFG.NIZKInput)
mul in 2 <1 7> out 1 <10>                # output-cast
output 10                                #
mul in 2 <1 8> out 1 <11>                # output-cast
output 11                                #
mul in 2 <1 9> out 1 <12>                # output-cast
output 12                                #
then I tried to genkeys, dowork and verify but it failed with segfault at dowork
commands I used:
$PINOCCHIO/pinocchio-v0.5.2.exe --qap --pv --nizk --file test-nizk.c.arith --mem 4 --input test-nizk.input.txt --output test-nizk.output.txt --keys test-nizk-key --genkeys
$PINOCCHIO/pinocchio-v0.5.2.exe --qap --pv --nizk --file test-nizk.c.arith --mem 4 --input test-nizk.input.txt --output test-nizk.output.txt --keys test-nizk-key --dowork
the input file is:
0 5
1 1
2 1
3 2
4 3
5 4
and the output I got:
------------------------
gen keys
------------------------
Warning: Could not open config file: config.txt.  Continuing based on command line only.

Using the NEW crypto protocol!
Using circuit from file build/nizk-test.c.arith
V + W + Y: 3360 Bytes
TargetRoots ~= 96 bytes
Building a QAP with size 9 and degree 3
Built the QAP. Cleaning up construction debris.
1 of 10 polynomials (10.00%) are non-zero at both V and W

Public verification
Chose h=v=7 for preallocation optimization
Size of precomputed table = 7 x 128 = 896 {L,R}EncodedElts = 0.2 MB

Done!
------------------------
do work
------------------------
Warning: Could not open config file: config.txt.  Continuing based on command line only.

Using the NEW crypto protocol!
Using circuit from file build/nizk-test.c.arith
Reading wire values from file: nizk-test.input.txt
V + W + Y: 3360 Bytes
TargetRoots ~= 96 bytes
Building a QAP with size 9 and degree 3
Built the QAP. Cleaning up construction debris.
Segmantation fault
I tried the same without the --nizk parameter, it worked but the verification failed.

How can I make it work?

Thanks!
Coordinator
Jul 2, 2015 at 5:35 PM
Hi,

It looks like there was a bug in the way the verification-only mode handled the inputs. I've fixed it and pushed an updated version to Codeplex. In general, if you only need performance measurements, I'd suggest running the one-pass version, i.e., something like:
$PINOCCHIO/pinocchio-v0.5.3.exe --qap --pv --nizk --file test-nizk.c.arith --mem 4 --input test-nizk.input.txt --output test-nizk.output.txt
That will read in the circuit, generate keys, compute the proof, and verify it all at the same time. That mode has been more thoroughly tested than the various standalone modes (i.e., the --genkeys, --dowork, and --verify modes).

Good luck with your masters work.

-Bryan
Jul 2, 2015 at 11:40 PM
Hi Bryan,

thanks a lot, it works really nice now!

I rather want to use Pinocchio as a framework for proving in ZK statements such as "I know x s.t SHA(x) = h" where h is public and x is private as a part of bigger protocol. Also I will need to perform some other steps in between genkeys, dowork and verify so I need them seperate.

Once more thank you, Pinocchio is great,
-Wac
Coordinator
Jul 3, 2015 at 4:46 AM
Great, glad to hear it's working for you! FWIW, when running with complex circuits like that for SHA, you may want to try using the --pcache option if QAP generation takes too long.

Cheers,
-Bryan
Jul 6, 2015 at 4:09 PM
OK, thanks, I'll try that
Cheers,
-Wac
Jul 6, 2015 at 8:01 PM
Hey, I've got another question.
I tried to implement a BigNum class together with some operations on it. It works fine when compiled with gcc but when I try to compile it to arithetic circuit with vercomp.py a assertion fails.

Could you have a look at it? I am almost sure it doesn't violate any Pinocchio's restrictions on C.
The code is pretty simple, it adds two BigNums, each BigNum is an array of unsigneds, I treat it like bit-array and implement addition myself without the built-in addition.

bignum.h:
#ifndef _BIGNUM_H_
#define _BIGNUM_H_

#define u32 unsigned int

#define BITS 1024
#define GROUPS BITS/32

struct BigNum {
    u32 bits[GROUPS];
};

void add(struct BigNum *, struct BigNum *, struct BigNum *);

struct Input {
    u32 empty;
};

struct NIZKInput {
    struct BigNum x;
    struct BigNum y;
};

struct Output {
    struct BigNum z;
};

void outsource(struct Input *input, struct NIZKInput *nizkinput, struct Output *output);
#endif
bignum.c:
#include "bignum.h"

void add(struct BigNum *res, struct BigNum *x, struct BigNum *y){
    int g, i;
    int carry;

    carry = 0;
    for(g = 0; g < GROUPS; g += 1){
        res->bits[g] = 0;
        for(i = 0; i < 32; i += 1){
            if (x->bits[g] & (1<<i))
                carry += 1;
            if (y->bits[g] & (1<<i))
                carry += 1;
            if (carry & 1)
                res->bits[g] |= (1<<i);
            if (carry & 2)
                carry = 1;
            else
                carry = 0;
        }
    }
}

void outsource(struct Input *input, struct NIZKInput *nizkinput, struct Output *output) {
    add(&output->z, &nizkinput->x, &nizkinput->y);
}
And it fails with:
Traceback (most recent call last):
  File "pinocchio/ccompiler/src/vercomp.py", line 1184, in <module>
    main(sys.argv[1:])
  File "pinocchio/ccompiler/src/vercomp.py", line 1169, in main
    ArithFactory(args.arith_file, vercomp.inputs, vercomp.nizk_inputs, vercomp.output, vercomp.bit_width)
  File "pinocchio/ccompiler/src/ArithFactory.py", line 8, in __init__
    ReqFactory.__init__(self, output_filename, circuit_inputs, circuit_nizk_inputs, circuit_outputs, bit_width)
  File "pinocchio/ccompiler/src/ReqFactory.py", line 27, in __init__
    self.process_outputs(circuit_outputs)
  File "pinocchio/ccompiler/src/ReqFactory.py", line 70, in process_outputs
    self.make_req(expr, self.type()))
  File "pinocchio/ccompiler/src/Collapser.py", line 60, in collapse_tree
    self.table[key] = self.collapse_impl(key)
  File "pinocchio/ccompiler/src/ReqFactory.py", line 121, in collapse_impl
    bus = key.collapse_impl()
  File "pinocchio/ccompiler/src/BusReq.py", line 69, in collapse_impl
    return self.reqfactory.collapse_req(self)
  File "pinocchio/ccompiler/src/ArithFactory.py", line 62, in collapse_req
    return req.natural_impl()
  File "pinocchio/ccompiler/src/ArithBusReq.py", line 112, in natural_impl
    self.board(), buscond, bustrue, busfalse)
  File "pinocchio/ccompiler/src/ArithBuses.py", line 187, in __init__
    assert(buscond.get_trace_count()==1)
AssertionError
Thanks!
Jul 14, 2015 at 3:00 PM
hey,
I found a way to do it. The error was in the if statements.
Here is the code that works if anyone needs it:

void add(struct BigNum *res, struct BigNum *x, struct BigNum *y){
    u32 g, i;
    u32 carry;

    carry = 0;
    for(g = 0; g < GROUPS; g += 1){
        res->bits[g] = 0;
        for(i = 0; i < 32; i += 1){
            if ((x->bits[g] & (1<<i)) == (1<<i))
                carry += 1;
            if ((y->bits[g] & (1<<i)) == (1<<i))
                carry += 1;
            if ((carry & 1) == 1)
                res->bits[g] |= (1<<i);
            if ((carry & 2) == 2)
                carry = 1;
            else
                carry = 0;
        }
    }
}
Cheers,
-Wac