package circuitcompiler import ( "bufio" "math/big" "os" "strings" "testing" "github.com/stretchr/testify/assert" ) func TestCircuitParser(t *testing.T) { // y = x^3 + x + 5 flat := ` func main(private s0, public s1): s2 = s0 * s0 s3 = s2 * s0 s4 = s3 + s0 s5 = s4 + 5 equals(s1, s5) out = 1 * 1 ` parser := NewParser(strings.NewReader(flat)) 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", "s2", "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, b0, b1, 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, b1, 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}, []*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) } func TestCircuitWithFuncCallsParser(t *testing.T) { // y = x^3 + x + 5 code := ` func exp3(private a): b = a * a c = a * b return c func sum(private a, private b): c = a + b return c func main(private s0, public s1): s3 = exp3(s0) s4 = sum(s3, s0) s5 = s4 + 5 equals(s1, s5) out = 1 * 1 ` parser := NewParser(strings.NewReader(code)) 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) } 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) }