go-snark/circuitcompiler/circuit_test.go
circuitcompiler/circuit_test.goRaw
1package circuitcompiler
2
3import (
4 "bufio"
5 "math/big"
6 "os"
7 "strings"
8 "testing"
9
10 "github.com/stretchr/testify/assert"
11)
12
13func TestCircuitParser(t *testing.T) {
14 // y = x^3 + x + 5
15 flat := `
16 func main(private s0, public s1):
17 s2 = s0 * s0
18 s3 = s2 * s0
19 s4 = s3 + s0
20 s5 = s4 + 5
21 equals(s1, s5)
22 out = 1 * 1
23 `
24 parser := NewParser(strings.NewReader(flat))
25 circuit, err := parser.Parse()
26 assert.Nil(t, err)
27
28 // flat code to R1CS
29 a, b, c := circuit.GenerateR1CS()
30 assert.Equal(t, "s0", circuit.PrivateInputs[0])
31 assert.Equal(t, "s1", circuit.PublicInputs[0])
32
33 assert.Equal(t, []string{"one", "s1", "s0", "s2", "s3", "s4", "s5", "out"}, circuit.Signals)
34
35 // expected result
36 b0 := big.NewInt(int64(0))
37 b1 := big.NewInt(int64(1))
38 b5 := big.NewInt(int64(5))
39 aExpected := [][]*big.Int{
40 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
41 []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0},
42 []*big.Int{b0, b0, b1, b0, b1, b0, b0, b0},
43 []*big.Int{b5, b0, b0, b0, b0, b1, b0, b0},
44 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
45 []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0},
46 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
47 }
48 bExpected := [][]*big.Int{
49 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
50 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
51 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
52 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
53 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
54 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
55 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
56 }
57 cExpected := [][]*big.Int{
58 []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0},
59 []*big.Int{b0, b0, b0, b0, b1, b0, b0, b0},
60 []*big.Int{b0, b0, b0, b0, b0, b1, b0, b0},
61 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
62 []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0},
63 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
64 []*big.Int{b0, b0, b0, b0, b0, b0, b0, b1},
65 }
66
67 assert.Equal(t, aExpected, a)
68 assert.Equal(t, bExpected, b)
69 assert.Equal(t, cExpected, c)
70
71 b3 := big.NewInt(int64(3))
72 privateInputs := []*big.Int{b3}
73 b35 := big.NewInt(int64(35))
74 publicInputs := []*big.Int{b35}
75 // Calculate Witness
76 w, err := circuit.CalculateWitness(privateInputs, publicInputs)
77 assert.Nil(t, err)
78 b9 := big.NewInt(int64(9))
79 b27 := big.NewInt(int64(27))
80 b30 := big.NewInt(int64(30))
81 wExpected := []*big.Int{b1, b35, b3, b9, b27, b30, b35, b1}
82 assert.Equal(t, wExpected, w)
83
84 // circuitJson, _ := json.Marshal(circuit)
85 // fmt.Println("circuit:", string(circuitJson))
86
87 assert.Equal(t, circuit.NPublic, 1)
88 assert.Equal(t, len(circuit.PublicInputs), 1)
89 assert.Equal(t, len(circuit.PrivateInputs), 1)
90}
91
92func TestCircuitWithFuncCallsParser(t *testing.T) {
93 // y = x^3 + x + 5
94 code := `
95 func exp3(private a):
96 b = a * a
97 c = a * b
98 return c
99 func sum(private a, private b):
100 c = a + b
101 return c
102
103 func main(private s0, public s1):
104 s3 = exp3(s0)
105 s4 = sum(s3, s0)
106 s5 = s4 + 5
107 equals(s1, s5)
108 out = 1 * 1
109 `
110 parser := NewParser(strings.NewReader(code))
111 circuit, err := parser.Parse()
112 assert.Nil(t, err)
113
114 // flat code to R1CS
115 a, b, c := circuit.GenerateR1CS()
116 assert.Equal(t, "s0", circuit.PrivateInputs[0])
117 assert.Equal(t, "s1", circuit.PublicInputs[0])
118
119 assert.Equal(t, []string{"one", "s1", "s0", "b0", "s3", "s4", "s5", "out"}, circuit.Signals)
120
121 // expected result
122 b0 := big.NewInt(int64(0))
123 b1 := big.NewInt(int64(1))
124 b5 := big.NewInt(int64(5))
125 aExpected := [][]*big.Int{
126 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
127 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
128 []*big.Int{b0, b0, b1, b0, b1, b0, b0, b0},
129 []*big.Int{b5, b0, b0, b0, b0, b1, b0, b0},
130 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
131 []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0},
132 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
133 }
134 bExpected := [][]*big.Int{
135 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
136 []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0},
137 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
138 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
139 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
140 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
141 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
142 }
143 cExpected := [][]*big.Int{
144 []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0},
145 []*big.Int{b0, b0, b0, b0, b1, b0, b0, b0},
146 []*big.Int{b0, b0, b0, b0, b0, b1, b0, b0},
147 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
148 []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0},
149 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
150 []*big.Int{b0, b0, b0, b0, b0, b0, b0, b1},
151 }
152
153 assert.Equal(t, aExpected, a)
154 assert.Equal(t, bExpected, b)
155 assert.Equal(t, cExpected, c)
156
157 b3 := big.NewInt(int64(3))
158 privateInputs := []*big.Int{b3}
159 b35 := big.NewInt(int64(35))
160 publicInputs := []*big.Int{b35}
161 // Calculate Witness
162 w, err := circuit.CalculateWitness(privateInputs, publicInputs)
163 assert.Nil(t, err)
164 b9 := big.NewInt(int64(9))
165 b27 := big.NewInt(int64(27))
166 b30 := big.NewInt(int64(30))
167 wExpected := []*big.Int{b1, b35, b3, b9, b27, b30, b35, b1}
168 assert.Equal(t, wExpected, w)
169
170 // circuitJson, _ := json.Marshal(circuit)
171 // fmt.Println("circuit:", string(circuitJson))
172
173 assert.Equal(t, circuit.NPublic, 1)
174 assert.Equal(t, len(circuit.PublicInputs), 1)
175 assert.Equal(t, len(circuit.PrivateInputs), 1)
176}
177
178func TestCircuitFromFileWithImports(t *testing.T) {
179 circuitFile, err := os.Open("./circuit-test-1.circuit")
180 assert.Nil(t, err)
181
182 parser := NewParser(bufio.NewReader(circuitFile))
183 circuit, err := parser.Parse()
184 assert.Nil(t, err)
185
186 // flat code to R1CS
187 a, b, c := circuit.GenerateR1CS()
188 assert.Equal(t, "s0", circuit.PrivateInputs[0])
189 assert.Equal(t, "s1", circuit.PublicInputs[0])
190
191 assert.Equal(t, []string{"one", "s1", "s0", "b0", "s3", "s4", "s5", "out"}, circuit.Signals)
192
193 // expected result
194 b0 := big.NewInt(int64(0))
195 b1 := big.NewInt(int64(1))
196 b5 := big.NewInt(int64(5))
197 aExpected := [][]*big.Int{
198 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
199 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
200 []*big.Int{b0, b0, b1, b0, b1, b0, b0, b0},
201 []*big.Int{b5, b0, b0, b0, b0, b1, b0, b0},
202 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
203 []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0},
204 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
205 }
206 bExpected := [][]*big.Int{
207 []*big.Int{b0, b0, b1, b0, b0, b0, b0, b0},
208 []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0},
209 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
210 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
211 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
212 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
213 []*big.Int{b1, b0, b0, b0, b0, b0, b0, b0},
214 }
215 cExpected := [][]*big.Int{
216 []*big.Int{b0, b0, b0, b1, b0, b0, b0, b0},
217 []*big.Int{b0, b0, b0, b0, b1, b0, b0, b0},
218 []*big.Int{b0, b0, b0, b0, b0, b1, b0, b0},
219 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
220 []*big.Int{b0, b1, b0, b0, b0, b0, b0, b0},
221 []*big.Int{b0, b0, b0, b0, b0, b0, b1, b0},
222 []*big.Int{b0, b0, b0, b0, b0, b0, b0, b1},
223 }
224
225 assert.Equal(t, aExpected, a)
226 assert.Equal(t, bExpected, b)
227 assert.Equal(t, cExpected, c)
228
229 b3 := big.NewInt(int64(3))
230 privateInputs := []*big.Int{b3}
231 b35 := big.NewInt(int64(35))
232 publicInputs := []*big.Int{b35}
233 // Calculate Witness
234 w, err := circuit.CalculateWitness(privateInputs, publicInputs)
235 assert.Nil(t, err)
236 b9 := big.NewInt(int64(9))
237 b27 := big.NewInt(int64(27))
238 b30 := big.NewInt(int64(30))
239 wExpected := []*big.Int{b1, b35, b3, b9, b27, b30, b35, b1}
240 assert.Equal(t, wExpected, w)
241
242 // circuitJson, _ := json.Marshal(circuit)
243 // fmt.Println("circuit:", string(circuitJson))
244
245 assert.Equal(t, circuit.NPublic, 1)
246 assert.Equal(t, len(circuit.PublicInputs), 1)
247 assert.Equal(t, len(circuit.PrivateInputs), 1)
248}