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 = 376
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 // Store zkinputs json for debugging purposes
65 zkInputsJSON, err := json.Marshal(zki)
66 require.NoError(t, err)
67 err = ioutil.WriteFile("/tmp/dbgZKInputs.json", zkInputsJSON, 0640) //nolint:gosec
68 require.NoError(t, err)
69
70 proofServerClient := prover.NewProofServerClient(proofServerURL, pollInterval)
71 err = proofServerClient.WaitReady(context.Background())
72 require.NoError(t, err)
73 err = proofServerClient.CalculateProof(context.Background(), zki)
74 require.NoError(t, err)
75 proof, pubInputs, err := proofServerClient.GetProof(context.Background())
76 require.NoError(t, err)
77 fmt.Printf("proof: %#v\n", proof)
78 fmt.Printf("pubInputs: %#v\n", pubInputs)
79}
80
81func TestZKInputsEmpty(t *testing.T) {
82 sdb := initStateDB(t, statedb.TypeBatchBuilder)
83
84 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
85
86 coordIdxs := []common.Idx{}
87 l1UserTxs := []common.L1Tx{}
88 l1CoordTxs := []common.L1Tx{}
89 l2Txs := []common.PoolL2Tx{}
90 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
91 require.NoError(t, err)
92
93 sendProofAndCheckResp(t, ptOut.ZKInputs) // test empty batch ZKInputs
94
95 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs = txsets.GenerateTxsZKInputs0(t, ChainID)
96
97 _, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
98 require.NoError(t, err)
99
100 coordIdxs = []common.Idx{}
101 l1UserTxs = []common.L1Tx{}
102 l1CoordTxs = []common.L1Tx{}
103 l2Txs = []common.PoolL2Tx{}
104 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
105 require.NoError(t, err)
106 sendProofAndCheckResp(t, ptOut.ZKInputs) // test empty batch ZKInputs after a non-empty batch
107}
108
109func TestZKInputs0(t *testing.T) {
110 sdb := initStateDB(t, statedb.TypeBatchBuilder)
111
112 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs0(t, ChainID)
113
114 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
115 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
116 require.NoError(t, err)
117
118 sendProofAndCheckResp(t, ptOut.ZKInputs)
119}
120func TestZKInputs1(t *testing.T) {
121 sdb := initStateDB(t, statedb.TypeBatchBuilder)
122
123 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs1(t, ChainID)
124
125 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
126 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
127 require.NoError(t, err)
128
129 sendProofAndCheckResp(t, ptOut.ZKInputs)
130}
131func TestZKInputs2(t *testing.T) {
132 sdb := initStateDB(t, statedb.TypeBatchBuilder)
133
134 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs2(t, ChainID)
135
136 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
137 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
138 require.NoError(t, err)
139
140 sendProofAndCheckResp(t, ptOut.ZKInputs)
141}
142func TestZKInputs3(t *testing.T) {
143 sdb := initStateDB(t, statedb.TypeBatchBuilder)
144
145 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs3(t, ChainID)
146
147 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
148 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
149 require.NoError(t, err)
150
151 sendProofAndCheckResp(t, ptOut.ZKInputs)
152}
153func TestZKInputs4(t *testing.T) {
154 sdb := initStateDB(t, statedb.TypeBatchBuilder)
155
156 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs4(t, ChainID)
157
158 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
159 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
160 require.NoError(t, err)
161
162 sendProofAndCheckResp(t, ptOut.ZKInputs)
163}
164
165func TestZKInputs5(t *testing.T) {
166 sdb := initStateDB(t, statedb.TypeBatchBuilder)
167
168 _, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs5(t, ChainID)
169
170 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
171 ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
172 require.NoError(t, err)
173
174 sendProofAndCheckResp(t, ptOut.ZKInputs)
175}
176
177func TestZKInputs6(t *testing.T) {
178 sdb := initStateDB(t, statedb.TypeBatchBuilder)
179
180 tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
181 blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
182 require.NoError(t, err)
183
184 // restart nonces of TilContext, as will be set by generating directly
185 // the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
186 tc.RestartNonces()
187
188 tp := txprocessor.NewTxProcessor(sdb, txprocConfig)
189 // batch1
190 ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
191 require.NoError(t, err)
192
193 sendProofAndCheckResp(t, ptOut.ZKInputs)
194
195 // batch2
196 l1UserTxs := []common.L1Tx{}
197 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
198 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
199 require.NoError(t, err)
200
201 sendProofAndCheckResp(t, ptOut.ZKInputs)
202
203 // batch3
204 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
205 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
206 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
207 require.NoError(t, err)
208
209 sendProofAndCheckResp(t, ptOut.ZKInputs)
210
211 // batch4
212 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
213 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[3].L2Txs)
214 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs)
215 require.NoError(t, err)
216
217 sendProofAndCheckResp(t, ptOut.ZKInputs)
218
219 // batch5
220 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
221 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[4].L2Txs)
222 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs)
223 require.NoError(t, err)
224
225 sendProofAndCheckResp(t, ptOut.ZKInputs)
226
227 // batch6
228 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
229 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[5].L2Txs)
230 ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs)
231 require.NoError(t, err)
232
233 sendProofAndCheckResp(t, ptOut.ZKInputs)
234
235 // batch7
236 // simulate the PoolL2Txs of the batch7
237 batchPoolL2 := `
238 Type: PoolL2
239 PoolTransferToEthAddr(1) A-B: 200 (126)
240 PoolTransferToEthAddr(0) B-C: 100 (126)`
241 poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
242 require.NoError(t, err)
243
244 // Coordinator Idx where to send the fees
245 coordIdxs := []common.Idx{261, 262}
246 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
247 l2Txs = poolL2Txs
248 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs)
249 require.NoError(t, err)
250
251 sendProofAndCheckResp(t, ptOut.ZKInputs)
252
253 // batch8
254 // simulate the PoolL2Txs of the batch8
255 batchPoolL2 = `
256 Type: PoolL2
257 PoolTransfer(0) A-B: 100 (126)
258 PoolTransfer(0) C-A: 50 (126)
259 PoolTransfer(1) B-C: 100 (126)
260 PoolExit(0) A: 100 (126)`
261 poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
262 require.NoError(t, err)
263
264 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
265 l2Txs = poolL2Txs
266 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs)
267 require.NoError(t, err)
268
269 sendProofAndCheckResp(t, ptOut.ZKInputs)
270
271 // batch9
272 // simulate the PoolL2Txs of the batch9
273 batchPoolL2 = `
274 Type: PoolL2
275 PoolTransfer(0) D-A: 300 (126)
276 PoolTransfer(0) B-D: 100 (126)`
277 poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
278 require.NoError(t, err)
279
280 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
281 l2Txs = poolL2Txs
282 coordIdxs = []common.Idx{262}
283 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
284 require.NoError(t, err)
285
286 sendProofAndCheckResp(t, ptOut.ZKInputs)
287
288 // batch10
289 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
290 l2Txs = []common.PoolL2Tx{}
291 coordIdxs = []common.Idx{}
292 ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
293 require.NoError(t, err)
294
295 sendProofAndCheckResp(t, ptOut.ZKInputs)
296}