add allow import circuits in circuits language compiler
arnaucube arnaucube@gmail.com
Thu, 30 May 2019 21:39:00 +0200
8 files changed,
132 insertions(+),
1 deletions(-)
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'