arnaucube
arnaucube/go-snarkPublic Self-hosted repository
add allow import circuits in circuits language compiler
arnaucube arnaucube@gmail.com
Thu, 30 May 2019 21:39:00 +0200
commit

de5b60b82602db203f100c5f4f8f4eaa9796dddf

parent

165699b58f8d4ad7ecff804f899dad3b775b83d9

M README.md → README.md

@@ -32,7 +32,7 @@ - [x] verify proofs with BN128 pairing

Improvements from the minimal implementation: - [x] allow to call functions in circuits language -- [ ] allow `import` in circuits language +- [x] allow `import` in circuits language - [ ] allow `for` in circuits language - [ ] move witness values calculation outside the setup phase - [ ] Groth16
A circuitcompiler/circuit-test-1.circuit

@@ -0,0 +1,8 @@

+import "circuit-test-2.circuit" + +func main(private s0, public s1): + s3 = exp3(s0) + s4 = sum(s3, s0) + s5 = s4 + 5 + equals(s1, s5) + out = 1 * 1
A circuitcompiler/circuit-test-2.circuit

@@ -0,0 +1,7 @@

+func exp3(private a): + b = a * a + c = a * b + return c +func sum(private a, private b): + c = a + b + return c
M circuitcompiler/circuit_test.go → circuitcompiler/circuit_test.go

@@ -1,7 +1,9 @@

package circuitcompiler import ( + "bufio" "math/big" + "os" "strings" "testing"

@@ -172,3 +174,75 @@ assert.Equal(t, circuit.NPublic, 1)

assert.Equal(t, len(circuit.PublicInputs), 1) assert.Equal(t, len(circuit.PrivateInputs), 1) } + +func TestCircuitFromFileWithImports(t *testing.T) { + circuitFile, err := os.Open("./circuit-test-1.circuit") + assert.Nil(t, err) + + parser := NewParser(bufio.NewReader(circuitFile)) + circuit, err := parser.Parse() + assert.Nil(t, err) + + // flat code to R1CS + a, b, c := circuit.GenerateR1CS() + assert.Equal(t, "s0", circuit.PrivateInputs[0]) + assert.Equal(t, "s1", circuit.PublicInputs[0]) + + assert.Equal(t, []string{"one", "s1", "s0", "b0", "s3", "s4", "s5", "out"}, circuit.Signals) + + // expected result + b0 := big.NewInt(int64(0)) + b1 := big.NewInt(int64(1)) + b5 := big.NewInt(int64(5)) + aExpected := [][]*big.Int{ + []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0}, + []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0}, + []*big.Int{b0, b0, b1, b0, b1, b0, b0, b0}, + []*big.Int{b5, b0, b0, b0, b0, b1, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0}, + []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + } + bExpected := [][]*big.Int{ + []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0}, + []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0}, + } + cExpected := [][]*big.Int{ + []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0}, + []*big.Int{b0, b0, b0, b0, b1, b0, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b1, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0}, + []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0}, + []*big.Int{b0, b0, b0, b0, b0, b0, b0, b1}, + } + + assert.Equal(t, aExpected, a) + assert.Equal(t, bExpected, b) + assert.Equal(t, cExpected, c) + + b3 := big.NewInt(int64(3)) + privateInputs := []*big.Int{b3} + b35 := big.NewInt(int64(35)) + publicInputs := []*big.Int{b35} + // Calculate Witness + w, err := circuit.CalculateWitness(privateInputs, publicInputs) + assert.Nil(t, err) + b9 := big.NewInt(int64(9)) + b27 := big.NewInt(int64(27)) + b30 := big.NewInt(int64(30)) + wExpected := []*big.Int{b1, b35, b3, b9, b27, b30, b35, b1} + assert.Equal(t, wExpected, w) + + // circuitJson, _ := json.Marshal(circuit) + // fmt.Println("circuit:", string(circuitJson)) + + assert.Equal(t, circuit.NPublic, 1) + assert.Equal(t, len(circuit.PublicInputs), 1) + assert.Equal(t, len(circuit.PrivateInputs), 1) +}
M circuitcompiler/parser.go → circuitcompiler/parser.go

@@ -1,6 +1,7 @@

package circuitcompiler import ( + "bufio" "errors" "fmt" "io"

@@ -115,6 +116,19 @@ }

if c.Literal == "return" { _, varToReturn := p.scanIgnoreWhitespace() c.Out = varToReturn + return c, nil + } + if c.Literal == "import" { + line, err := p.s.r.ReadString('\n') + if err != nil { + return c, err + } + // read string inside " " + path := strings.TrimLeft(strings.TrimRight(line, `"`), `"`) + path = strings.Replace(path, `"`, "", -1) + path = strings.Replace(path, " ", "", -1) + path = strings.Replace(path, "\n", "", -1) + c.Out = path return c, nil }

@@ -301,6 +315,15 @@ }

callsCount++ continue + } + if constraint.Literal == "import" { + circuitFile, err := os.Open(constraint.Out) + if err != nil { + panic(errors.New("imported path error: " + constraint.Out)) + } + parser := NewParser(bufio.NewReader(circuitFile)) + _, err = parser.Parse() // this will add the imported file funcs into the `circuits` map + continue } circuits[currCircuit].Constraints = append(circuits[currCircuit].Constraints, *constraint)
A circuitexamples/import-example.circuit

@@ -0,0 +1,8 @@

+import "imported-example.circuit" + +func main(private s0, public s1): + s3 = exp3(s0) + s4 = sum(s3, s0) + s5 = s4 + 5 + equals(s1, s5) + out = 1 * 1
A circuitexamples/imported-example.circuit

@@ -0,0 +1,7 @@

+func exp3(private a): + b = a * a + c = a * b + return c +func sum(private a, private b): + c = a + b + return c
M vim-syntax/syntax/go-snark-circuit.vim → vim-syntax/syntax/go-snark-circuit.vim

@@ -24,12 +24,14 @@ syn keyword goSnarkCircuitPrivatePublic private public

syn keyword goSnarkCircuitOut out syn keyword goSnarkCircuitEquals equals syn keyword goSnarkCircuitFunction func +syn keyword goSnarkCircuitImport import syn match goSnarkCircuitFuncCall /\<\K\k*\ze\s*(/ syn keyword goSnarkCircuitPrivate private nextgroup=goSnarkCircuitInputName skipwhite syn keyword goSnarkCircuitPublic public nextgroup=goSnarkCircuitInputName skipwhite syn match goSnarkCircuitInputName '\i\+' contained syn match goSnarkCircuitBraces "[{}\[\]]" syn match goSnarkCircuitParens "[()]" +syn region goSnarkCircuitPath start=+"+ skip=+\\\\\|\\"+ end=+"\|$+ syn sync fromstart syn sync maxlines=100

@@ -44,12 +46,14 @@ hi def link goSnarkCircuitOpSymbols Operator

hi def link goSnarkCircuitFuncCall Function hi def link goSnarkCircuitEquals Identifier hi def link goSnarkCircuitFunction Keyword +hi def link goSnarkCircuitImport Keyword hi def link goSnarkCircuitBraces Function hi def link goSnarkCircuitPrivate Keyword hi def link goSnarkCircuitPublic Keyword hi def link goSnarkCircuitInputName Special hi def link goSnarkCircuitOut Special hi def link goSnarkCircuitPrivatePublic Keyword +hi def link goSnarkCircuitPath String let b:current_syntax = "go-snark-circuit" if main_syntax == 'go-snark-circuit'