hermez-node/db/statedb/txprocessors_test.go
db/statedb/txprocessors_test.goRaw
1package statedb
2
3import (
4 "encoding/json"
5 "fmt"
6 "io/ioutil"
7 "os"
8 "testing"
9
10 "github.com/hermeznetwork/hermez-node/common"
11 "github.com/hermeznetwork/hermez-node/log"
12 "github.com/hermeznetwork/hermez-node/test/til"
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15)
16
17func checkBalance(t *testing.T, tc *til.Context, sdb *StateDB, username string, tokenid int, expected string) {
18 idx := tc.Users[username].Accounts[common.TokenID(tokenid)].Idx
19 acc, err := sdb.GetAccount(idx)
20 require.Nil(t, err)
21 assert.Equal(t, expected, acc.Balance.String())
22}
23
24func TestProcessTxsBalances(t *testing.T) {
25 dir, err := ioutil.TempDir("", "tmpdb")
26 require.Nil(t, err)
27 defer assert.Nil(t, os.RemoveAll(dir))
28
29 sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
30 assert.Nil(t, err)
31
32 // generate test transactions from test.SetBlockchain0 code
33 tc := til.NewContext(common.RollupConstMaxL1UserTx)
34 blocks, err := tc.GenerateBlocks(til.SetBlockchainMinimumFlow0)
35 require.Nil(t, err)
36
37 // Coordinator Idx where to send the fees
38 coordIdxs := []common.Idx{256, 257}
39
40 log.Debug("block:0 batch:0, only L1CoordinatorTxs")
41 _, err = sdb.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
42 require.Nil(t, err)
43
44 log.Debug("block:0 batch:1")
45 l1UserTxs := []common.L1Tx{}
46 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
47 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
48 require.Nil(t, err)
49
50 log.Debug("block:0 batch:2")
51 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
52 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
53 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
54 require.Nil(t, err)
55 checkBalance(t, tc, sdb, "A", 0, "500")
56
57 log.Debug("block:0 batch:3")
58 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
59 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[3].L2Txs)
60 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs)
61 require.Nil(t, err)
62 checkBalance(t, tc, sdb, "A", 0, "500")
63 checkBalance(t, tc, sdb, "A", 1, "500")
64
65 log.Debug("block:0 batch:4")
66 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
67 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[4].L2Txs)
68 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs)
69 require.Nil(t, err)
70 checkBalance(t, tc, sdb, "A", 0, "500")
71 checkBalance(t, tc, sdb, "A", 1, "500")
72
73 log.Debug("block:0 batch:5")
74 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
75 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[5].L2Txs)
76 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs)
77 require.Nil(t, err)
78 checkBalance(t, tc, sdb, "A", 0, "600")
79 checkBalance(t, tc, sdb, "A", 1, "500")
80 checkBalance(t, tc, sdb, "B", 0, "400")
81
82 log.Debug("block:0 batch:6")
83 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
84 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[6].L2Txs)
85 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs)
86 require.Nil(t, err)
87 checkBalance(t, tc, sdb, "Coord", 0, "10")
88 checkBalance(t, tc, sdb, "Coord", 1, "20")
89 checkBalance(t, tc, sdb, "A", 0, "600")
90 checkBalance(t, tc, sdb, "A", 1, "280")
91 checkBalance(t, tc, sdb, "B", 0, "290")
92 checkBalance(t, tc, sdb, "B", 1, "200")
93 checkBalance(t, tc, sdb, "C", 0, "100")
94 checkBalance(t, tc, sdb, "D", 0, "800")
95
96 log.Debug("block:0 batch:7")
97 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
98 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[7].L2Txs)
99 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs)
100 require.Nil(t, err)
101 checkBalance(t, tc, sdb, "Coord", 0, "35")
102 checkBalance(t, tc, sdb, "Coord", 1, "30")
103 checkBalance(t, tc, sdb, "A", 0, "430")
104 checkBalance(t, tc, sdb, "A", 1, "280")
105 checkBalance(t, tc, sdb, "B", 0, "390")
106 checkBalance(t, tc, sdb, "B", 1, "90")
107 checkBalance(t, tc, sdb, "C", 0, "45")
108 checkBalance(t, tc, sdb, "C", 1, "100")
109 checkBalance(t, tc, sdb, "D", 0, "800")
110
111 log.Debug("block:1 batch:0")
112 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
113 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
114 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
115 require.Nil(t, err)
116 checkBalance(t, tc, sdb, "Coord", 0, "75")
117 checkBalance(t, tc, sdb, "Coord", 1, "30")
118 checkBalance(t, tc, sdb, "A", 0, "730")
119 checkBalance(t, tc, sdb, "A", 1, "280")
120 checkBalance(t, tc, sdb, "B", 0, "380")
121 checkBalance(t, tc, sdb, "B", 1, "90")
122 checkBalance(t, tc, sdb, "C", 0, "845")
123 checkBalance(t, tc, sdb, "C", 1, "100")
124 checkBalance(t, tc, sdb, "D", 0, "470")
125
126 log.Debug("block:1 batch:1")
127 l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
128 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
129 _, err = sdb.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
130 require.Nil(t, err)
131
132 // use Set of PoolL2 txs
133 poolL2Txs, err := tc.GeneratePoolL2Txs(til.SetPoolL2MinimumFlow0)
134 assert.Nil(t, err)
135
136 _, err = sdb.ProcessTxs(coordIdxs, []common.L1Tx{}, []common.L1Tx{}, poolL2Txs)
137 require.Nil(t, err)
138 checkBalance(t, tc, sdb, "Coord", 0, "105")
139 checkBalance(t, tc, sdb, "Coord", 1, "40")
140 checkBalance(t, tc, sdb, "A", 0, "510")
141 checkBalance(t, tc, sdb, "A", 1, "170")
142 checkBalance(t, tc, sdb, "B", 0, "480")
143 checkBalance(t, tc, sdb, "B", 1, "190")
144 checkBalance(t, tc, sdb, "C", 0, "845")
145 checkBalance(t, tc, sdb, "C", 1, "100")
146 checkBalance(t, tc, sdb, "D", 0, "360")
147 checkBalance(t, tc, sdb, "F", 0, "100")
148}
149
150func TestProcessTxsSynchronizer(t *testing.T) {
151 dir, err := ioutil.TempDir("", "tmpdb")
152 require.Nil(t, err)
153 defer assert.Nil(t, os.RemoveAll(dir))
154
155 sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
156 assert.Nil(t, err)
157
158 // generate test transactions from test.SetBlockchain0 code
159 tc := til.NewContext(common.RollupConstMaxL1UserTx)
160 blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
161 require.Nil(t, err)
162
163 assert.Equal(t, 31, len(blocks[0].Rollup.L1UserTxs))
164 assert.Equal(t, 4, len(blocks[0].Rollup.Batches[0].L1CoordinatorTxs))
165 assert.Equal(t, 0, len(blocks[0].Rollup.Batches[1].L1CoordinatorTxs))
166 assert.Equal(t, 22, len(blocks[0].Rollup.Batches[2].L2Txs))
167 assert.Equal(t, 1, len(blocks[1].Rollup.Batches[0].L1CoordinatorTxs))
168 assert.Equal(t, 62, len(blocks[1].Rollup.Batches[0].L2Txs))
169 assert.Equal(t, 1, len(blocks[1].Rollup.Batches[1].L1CoordinatorTxs))
170 assert.Equal(t, 8, len(blocks[1].Rollup.Batches[1].L2Txs))
171
172 // Coordinator Idx where to send the fees
173 coordIdxs := []common.Idx{256, 257, 258, 259}
174
175 // Idx of user 'A'
176 idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
177
178 // Process the 1st batch, which contains the L1CoordinatorTxs necessary
179 // to create the Coordinator accounts to receive the fees
180 log.Debug("block:0 batch:0, only L1CoordinatorTxs")
181 ptOut, err := sdb.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
182 require.Nil(t, err)
183 assert.Equal(t, 4, len(ptOut.CreatedAccounts))
184 assert.Equal(t, 0, len(ptOut.CollectedFees))
185
186 log.Debug("block:0 batch:1")
187 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
188 ptOut, err = sdb.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs,
189 blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
190 require.Nil(t, err)
191 assert.Equal(t, 0, len(ptOut.ExitInfos))
192 assert.Equal(t, 31, len(ptOut.CreatedAccounts))
193 assert.Equal(t, 4, len(ptOut.CollectedFees))
194 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
195 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
196 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
197 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
198 acc, err := sdb.GetAccount(idxA1)
199 require.Nil(t, err)
200 assert.Equal(t, "50", acc.Balance.String())
201
202 log.Debug("block:0 batch:2")
203 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
204 ptOut, err = sdb.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
205 require.Nil(t, err)
206 assert.Equal(t, 0, len(ptOut.ExitInfos))
207 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
208 assert.Equal(t, 4, len(ptOut.CollectedFees))
209 assert.Equal(t, "2", ptOut.CollectedFees[common.TokenID(0)].String())
210 assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
211 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
212 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
213 acc, err = sdb.GetAccount(idxA1)
214 require.Nil(t, err)
215 assert.Equal(t, "35", acc.Balance.String())
216
217 log.Debug("block:1 batch:0")
218 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
219 // before processing expect l2Txs[0:2].Nonce==0
220 assert.Equal(t, common.Nonce(0), l2Txs[0].Nonce)
221 assert.Equal(t, common.Nonce(0), l2Txs[1].Nonce)
222 assert.Equal(t, common.Nonce(0), l2Txs[2].Nonce)
223
224 ptOut, err = sdb.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
225 require.Nil(t, err)
226
227 // after processing expect l2Txs[0:2].Nonce!=0 and has expected value
228 assert.Equal(t, common.Nonce(6), l2Txs[0].Nonce)
229 assert.Equal(t, common.Nonce(7), l2Txs[1].Nonce)
230 assert.Equal(t, common.Nonce(8), l2Txs[2].Nonce)
231
232 assert.Equal(t, 4, len(ptOut.ExitInfos)) // the 'ForceExit(1)' is not computed yet, as the batch is without L1UserTxs
233 assert.Equal(t, 1, len(ptOut.CreatedAccounts))
234 assert.Equal(t, 4, len(ptOut.CollectedFees))
235 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
236 assert.Equal(t, "1", ptOut.CollectedFees[common.TokenID(1)].String())
237 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
238 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
239 acc, err = sdb.GetAccount(idxA1)
240 require.Nil(t, err)
241 assert.Equal(t, "57", acc.Balance.String())
242
243 log.Debug("block:1 batch:1")
244 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
245 ptOut, err = sdb.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs,
246 blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
247 require.Nil(t, err)
248
249 assert.Equal(t, 2, len(ptOut.ExitInfos)) // 2, as previous batch was without L1UserTxs, and has pending the 'ForceExit(1) A: 5'
250 assert.Equal(t, 1, len(ptOut.CreatedAccounts))
251 assert.Equal(t, 4, len(ptOut.CollectedFees))
252 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(0)].String())
253 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(1)].String())
254 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(2)].String())
255 assert.Equal(t, "0", ptOut.CollectedFees[common.TokenID(3)].String())
256 acc, err = sdb.GetAccount(idxA1)
257 assert.Nil(t, err)
258 assert.Equal(t, "77", acc.Balance.String())
259
260 idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
261 acc, err = sdb.GetAccount(idxB0)
262 require.Nil(t, err)
263 assert.Equal(t, "51", acc.Balance.String())
264
265 // get balance of Coordinator account for TokenID==0
266 acc, err = sdb.GetAccount(common.Idx(256))
267 require.Nil(t, err)
268 assert.Equal(t, "2", acc.Balance.String())
269}
270
271func TestProcessTxsBatchBuilder(t *testing.T) {
272 dir, err := ioutil.TempDir("", "tmpdb")
273 require.Nil(t, err)
274 defer assert.Nil(t, os.RemoveAll(dir))
275
276 sdb, err := NewStateDB(dir, TypeBatchBuilder, 32)
277 assert.Nil(t, err)
278
279 // generate test transactions from test.SetBlockchain0 code
280 tc := til.NewContext(common.RollupConstMaxL1UserTx)
281 blocks, err := tc.GenerateBlocks(til.SetBlockchain0)
282 require.Nil(t, err)
283
284 // Coordinator Idx where to send the fees
285 coordIdxs := []common.Idx{256, 257, 258, 259}
286
287 // Idx of user 'A'
288 idxA1 := tc.Users["A"].Accounts[common.TokenID(1)].Idx
289
290 // Process the 1st batch, which contains the L1CoordinatorTxs necessary
291 // to create the Coordinator accounts to receive the fees
292 log.Debug("block:0 batch:0, only L1CoordinatorTxs")
293 ptOut, err := sdb.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
294 require.Nil(t, err)
295 // expect 0 at CreatedAccount, as is only computed when StateDB.Type==TypeSynchronizer
296 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
297
298 log.Debug("block:0 batch:1")
299 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
300 ptOut, err = sdb.ProcessTxs(coordIdxs, blocks[0].Rollup.L1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
301 require.Nil(t, err)
302 assert.Equal(t, 0, len(ptOut.ExitInfos))
303 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
304 acc, err := sdb.GetAccount(idxA1)
305 require.Nil(t, err)
306 assert.Equal(t, "50", acc.Balance.String())
307
308 log.Debug("block:0 batch:2")
309 l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
310 ptOut, err = sdb.ProcessTxs(coordIdxs, nil, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
311 require.Nil(t, err)
312 assert.Equal(t, 0, len(ptOut.ExitInfos))
313 assert.Equal(t, 0, len(ptOut.CreatedAccounts))
314 acc, err = sdb.GetAccount(idxA1)
315 require.Nil(t, err)
316 assert.Equal(t, "35", acc.Balance.String())
317
318 log.Debug("block:1 batch:0")
319 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[0].L2Txs)
320 _, err = sdb.ProcessTxs(coordIdxs, nil, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
321 require.Nil(t, err)
322 acc, err = sdb.GetAccount(idxA1)
323 require.Nil(t, err)
324 assert.Equal(t, "57", acc.Balance.String())
325
326 log.Debug("block:1 batch:1")
327 l2Txs = common.L2TxsToPoolL2Txs(blocks[1].Rollup.Batches[1].L2Txs)
328 _, err = sdb.ProcessTxs(coordIdxs, blocks[1].Rollup.L1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
329 require.Nil(t, err)
330 acc, err = sdb.GetAccount(idxA1)
331 assert.Nil(t, err)
332 assert.Equal(t, "77", acc.Balance.String())
333
334 idxB0 := tc.Users["C"].Accounts[common.TokenID(0)].Idx
335 acc, err = sdb.GetAccount(idxB0)
336 require.Nil(t, err)
337 assert.Equal(t, "51", acc.Balance.String())
338
339 // get balance of Coordinator account for TokenID==0
340 acc, err = sdb.GetAccount(common.Idx(256))
341 require.Nil(t, err)
342 assert.Equal(t, common.TokenID(0), acc.TokenID)
343 assert.Equal(t, "2", acc.Balance.String())
344 acc, err = sdb.GetAccount(common.Idx(257))
345 require.Nil(t, err)
346 assert.Equal(t, common.TokenID(1), acc.TokenID)
347 assert.Equal(t, "2", acc.Balance.String())
348}
349
350func TestZKInputsGeneration(t *testing.T) {
351 dir, err := ioutil.TempDir("", "tmpdb")
352 require.Nil(t, err)
353 defer assert.Nil(t, os.RemoveAll(dir))
354
355 sdb, err := NewStateDB(dir, TypeBatchBuilder, 4)
356 assert.Nil(t, err)
357
358 set := `
359 Type: Blockchain
360 AddToken(1)
361 CreateAccountDeposit(1) A: 10
362 > batchL1
363 CreateAccountCoordinator(1) B
364 CreateAccountCoordinator(1) C
365 > batchL1
366 // idxs: A:258, B:256, C:257
367
368 Transfer(1) A-B: 6 (1)
369 Transfer(1) A-C: 2 (1)
370 > batch
371 > block
372 `
373 // generate test transactions from test.SetBlockchain0 code
374 tc := til.NewContext(common.RollupConstMaxL1UserTx)
375 blocks, err := tc.GenerateBlocks(set)
376 require.Nil(t, err)
377
378 // Coordinator Idx where to send the fees
379 coordIdxs := []common.Idx{256}
380
381 log.Debug("block:0 batch:0, only L1UserTx")
382 _, err = sdb.ProcessTxs(nil, blocks[0].Rollup.L1UserTxs, nil, nil)
383 require.Nil(t, err)
384
385 log.Debug("block:0 batch:1, only L1CoordinatorTxs")
386 _, err = sdb.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, nil)
387 require.Nil(t, err)
388
389 log.Debug("block:0 batch:2, only L2Txs")
390 l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
391 ptOut, err := sdb.ProcessTxs(coordIdxs, nil, nil, l2Txs)
392 require.Nil(t, err)
393 checkBalance(t, tc, sdb, "A", 1, "2")
394
395 s, err := json.Marshal(ptOut.ZKInputs)
396 require.Nil(t, err)
397 debug := false
398 if debug {
399 fmt.Println(string(s))
400 }
401}