hermez-node/test/zkproof/zkproof_test.go
test/zkproof/zkproof_test.goRaw
1package zkproof
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "io/ioutil"
8 "os"
9 "testing"
10 "time"
11
12 "github.com/hermeznetwork/hermez-node/common"
13 "github.com/hermeznetwork/hermez-node/db/statedb"
14 "github.com/hermeznetwork/hermez-node/log"
15 "github.com/hermeznetwork/hermez-node/prover"
16 "github.com/hermeznetwork/hermez-node/test/til"
17 "github.com/hermeznetwork/hermez-node/test/txsets"
18 "github.com/hermeznetwork/hermez-node/txprocessor"
19 "github.com/stretchr/testify/assert"
20 "github.com/stretchr/testify/require"
21)
22
23var proofServerURL string
24
25const pollInterval = 200 * time.Millisecond
26
27func TestMain(m *testing.M) {
28 exitVal := 0
29 proofServerURL = os.Getenv("PROOF_SERVER_URL")
30 exitVal = m.Run()
31 os.Exit(exitVal)
32}
33
34const MaxTx = 352
35const NLevels = 32
36const MaxL1Tx = 256
37const MaxFeeTx = 64
38const ChainID uint16 = 1
39
40var txprocConfig = txprocessor.Config{
41 NLevels: uint32(NLevels),
42 MaxTx: MaxTx,
43 MaxL1Tx: MaxL1Tx,
44 MaxFeeTx: MaxFeeTx,
45 ChainID: ChainID,
46}
47
48func initStateDB(t *testing.T, typ statedb.TypeStateDB) *statedb.StateDB {
49 dir, err := ioutil.TempDir("", "tmpdb")
50 require.NoError(t, err)
51 defer assert.Nil(t, os.RemoveAll(dir))
52
53 sdb, err := statedb.NewStateDB(statedb.Config{Path: dir, Keep: 128, Type: typ, NLevels: NLevels})
54 require.NoError(t, err)
55 return sdb
56}
57
58func sendProofAndCheckResp(t *testing.T, zki *common.ZKInputs) {
59 if proofServerURL == "" {
60 log.Debug("No PROOF_SERVER_URL defined, not using ProofServer")
61 return
62 }
63
64 log.Infof("sending proof to %s", proofServerURL)
65 // Store zkinputs json for debugging purposes
66 zkInputsJSON, err := json.Marshal(zki)
67 require.NoError(t, err)
68 err = ioutil.WriteFile("/tmp/dbgZKInputs.json", zkInputsJSON, 0640) //nolint:gosec
69 require.NoError(t, err)
70
71 proofServerClient := prover.NewProofServerClient(proofServerURL, pollInterval)
72 err = proofServerClient.WaitReady(context.Background())
73 require.NoError(t, err)
74 err = proofServerClient.CalculateProof(context.Background(), zki)
75 require.NoError(t, err)
76 proof, pubInputs, err := proofServerClient.GetProof(context.Background())
77 require.NoError(t, err)
78 fmt.Printf("proof: %#v\n", proof)
79 fmt.Printf("pubInputs: %#v\n", pubInputs)
80}
81
82func TestZKInputsEmpty(t *testing.T) {
83 sdb := initStateDB(t, statedb.TypeBatchBuilder)
84
85 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
86
87 coordIdxs := []common.Idx{}
88 l1UserTxs := []common.L1Tx{}
89 l1CoordTxs := []common.L1Tx{}
90 l2Txs := []common.PoolL2Tx{}
91 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
92 require.NoError(t, err)
93
94 sendProofAndCheckResp(t, ptOut.ZKInputs) // test empty batch ZKInputs
95
96 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs = txsets.GenerateTxsZKInputs0(t, ChainID)
97
98 _, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
99 require.NoError(t, err)
100
101 coordIdxs = []common.Idx{}
102 l1UserTxs = []common.L1Tx{}
103 l1CoordTxs = []common.L1Tx{}
104 l2Txs = []common.PoolL2Tx{}
105 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
106 require.NoError(t, err)
107 sendProofAndCheckResp(t, ptOut.ZKInputs) // test empty batch ZKInputs after a non-empty batch
108}
109
110func TestZKInputs0(t *testing.T) {
111 sdb := initStateDB(t, statedb.TypeBatchBuilder)
112
113 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs0(t, ChainID)
114
115 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
116 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
117 require.NoError(t, err)
118
119 sendProofAndCheckResp(t, ptOut.ZKInputs)
120}
121func TestZKInputs1(t *testing.T) {
122 sdb := initStateDB(t, statedb.TypeBatchBuilder)
123
124 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs1(t, ChainID)
125
126 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
127 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
128 require.NoError(t, err)
129
130 sendProofAndCheckResp(t, ptOut.ZKInputs)
131}
132func TestZKInputs2(t *testing.T) {
133 sdb := initStateDB(t, statedb.TypeBatchBuilder)
134
135 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs2(t, ChainID)
136
137 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
138 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
139 require.NoError(t, err)
140
141 sendProofAndCheckResp(t, ptOut.ZKInputs)
142}
143func TestZKInputs3(t *testing.T) {
144 sdb := initStateDB(t, statedb.TypeBatchBuilder)
145
146 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs3(t, ChainID)
147
148 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
149 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
150 require.NoError(t, err)
151
152 sendProofAndCheckResp(t, ptOut.ZKInputs)
153}
154func TestZKInputs4(t *testing.T) {
155 sdb := initStateDB(t, statedb.TypeBatchBuilder)
156
157 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs4(t, ChainID)
158
159 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
160 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
161 require.NoError(t, err)
162
163 sendProofAndCheckResp(t, ptOut.ZKInputs)
164}
165
166func TestZKInputs5(t *testing.T) {
167 sdb := initStateDB(t, statedb.TypeBatchBuilder)
168
169 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs5(t, ChainID)
170
171 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
172 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
173 require.NoError(t, err)
174
175 sendProofAndCheckResp(t, ptOut.ZKInputs)
176}
177
178func TestZKInputs6(t *testing.T) {
179 sdb := initStateDB(t, statedb.TypeBatchBuilder)
180
181 tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
182 blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
183 require.NoError(t, err)
184
185 // restart nonces of TilContext, as will be set by generating directly
186 // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
187 tc.RestartNonces()
188
189 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
190 // batch1
191 ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
192 require.NoError(t, err)
193
194 sendProofAndCheckResp(t, ptOut.ZKInputs)
195
196 // batch2
197 l1UserTxs := []common.L1Tx{}
198 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
199 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
200 require.NoError(t, err)
201
202 sendProofAndCheckResp(t, ptOut.ZKInputs)
203
204 // batch3
205 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
206 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
207 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
208 require.NoError(t, err)
209
210 sendProofAndCheckResp(t, ptOut.ZKInputs)
211
212 // batch4
213 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
214 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[3].L2Txs)
215 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs)
216 require.NoError(t, err)
217
218 sendProofAndCheckResp(t, ptOut.ZKInputs)
219
220 // batch5
221 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
222 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[4].L2Txs)
223 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs)
224 require.NoError(t, err)
225
226 sendProofAndCheckResp(t, ptOut.ZKInputs)
227
228 // batch6
229 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
230 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[5].L2Txs)
231 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs)
232 require.NoError(t, err)
233
234 sendProofAndCheckResp(t, ptOut.ZKInputs)
235
236 // batch7
237 // simulate the PoolL2Txs of the batch7
238 batchPoolL2 := `
239 Type: PoolL2
240 PoolTransferToEthAddr(1) A-B: 200 (126)
241 PoolTransferToEthAddr(0) B-C: 100 (126)`
242 poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
243 require.NoError(t, err)
244
245 // Coordinator Idx where to send the fees
246 coordIdxs := []common.Idx{261, 262}
247 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
248 l2Txs = poolL2Txs
249 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs)
250 require.NoError(t, err)
251
252 sendProofAndCheckResp(t, ptOut.ZKInputs)
253
254 // batch8
255 // simulate the PoolL2Txs of the batch8
256 batchPoolL2 = `
257 Type: PoolL2
258 PoolTransfer(0) A-B: 100 (126)
259 PoolTransfer(0) C-A: 50 (126)
260 PoolTransfer(1) B-C: 100 (126)
261 PoolExit(0) A: 100 (126)`
262 poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
263 require.NoError(t, err)
264
265 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
266 l2Txs = poolL2Txs
267 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs)
268 require.NoError(t, err)
269
270 sendProofAndCheckResp(t, ptOut.ZKInputs)
271
272 // batch9
273 // simulate the PoolL2Txs of the batch9
274 batchPoolL2 = `
275 Type: PoolL2
276 PoolTransfer(0) D-A: 300 (126)
277 PoolTransfer(0) B-D: 100 (126)`
278 poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
279 require.NoError(t, err)
280
281 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
282 l2Txs = poolL2Txs
283 coordIdxs = []common.Idx{262}
284 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
285 require.NoError(t, err)
286
287 sendProofAndCheckResp(t, ptOut.ZKInputs)
288
289 // batch10
290 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
291 l2Txs = []common.PoolL2Tx{}
292 coordIdxs = []common.Idx{}
293 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
294 require.NoError(t, err)
295
296 sendProofAndCheckResp(t, ptOut.ZKInputs)
297}