hermez-node/db/historydb/historydb_test.go
db/historydb/historydb_test.goRaw
1package historydb
2
3import (
4 "database/sql"
5 "math"
6 "math/big"
7 "os"
8 "testing"
9 "time"
10
11 ethCommon "github.com/ethereum/go-ethereum/common"
12 "github.com/hermeznetwork/hermez-node/common"
13 dbUtils "github.com/hermeznetwork/hermez-node/db"
14 "github.com/hermeznetwork/hermez-node/log"
15 "github.com/hermeznetwork/hermez-node/test"
16 "github.com/hermeznetwork/hermez-node/test/til"
17 "github.com/stretchr/testify/assert"
18 "github.com/stretchr/testify/require"
19)
20
21var historyDB *HistoryDB
22
23// In order to run the test you need to run a Posgres DB with
24// a database named "history" that is accessible by
25// user: "hermez"
26// pass: set it using the env var POSTGRES_PASS
27// This can be achieved by running: POSTGRES_PASS=your_strong_pass && sudo docker run --rm --name hermez-db-test -p 5432:5432 -e POSTGRES_DB=history -e POSTGRES_USER=hermez -e POSTGRES_PASSWORD=$POSTGRES_PASS -d postgres && sleep 2s && sudo docker exec -it hermez-db-test psql -a history -U hermez -c "CREATE DATABASE l2;"
28// After running the test you can stop the container by running: sudo docker kill hermez-db-test
29// If you already did that for the L2DB you don't have to do it again
30
31func TestMain(m *testing.M) {
32 // init DB
33 pass := os.Getenv("POSTGRES_PASS")
34 db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
35 if err != nil {
36 panic(err)
37 }
38 historyDB = NewHistoryDB(db)
39 if err != nil {
40 panic(err)
41 }
42 // Run tests
43 result := m.Run()
44 // Close DB
45 if err := db.Close(); err != nil {
46 log.Error("Error closing the history DB:", err)
47 }
48 os.Exit(result)
49}
50
51func TestBlocks(t *testing.T) {
52 var fromBlock, toBlock int64
53 fromBlock = 1
54 toBlock = 5
55 // Delete peviously created rows (clean previous test execs)
56 test.WipeDB(historyDB.DB())
57 // Generate fake blocks
58 blocks := test.GenBlocks(fromBlock, toBlock)
59 // Save timestamp of a block with UTC and change it without UTC
60 timestamp := time.Now().Add(time.Second * 13)
61 blocks[fromBlock].Timestamp = timestamp
62 // Insert blocks into DB
63 for i := 0; i < len(blocks); i++ {
64 err := historyDB.AddBlock(&blocks[i])
65 assert.NoError(t, err)
66 }
67 // Get all blocks from DB
68 fetchedBlocks, err := historyDB.GetBlocks(fromBlock, toBlock)
69 assert.Equal(t, len(blocks), len(fetchedBlocks))
70 // Compare generated vs getted blocks
71 assert.NoError(t, err)
72 for i := range fetchedBlocks {
73 assertEqualBlock(t, &blocks[i], &fetchedBlocks[i])
74 }
75 // Compare saved timestamp vs getted
76 nameZoneUTC, offsetUTC := timestamp.UTC().Zone()
77 zoneFetchedBlock, offsetFetchedBlock := fetchedBlocks[fromBlock].Timestamp.Zone()
78 assert.Equal(t, nameZoneUTC, zoneFetchedBlock)
79 assert.Equal(t, offsetUTC, offsetFetchedBlock)
80 // Get blocks from the DB one by one
81 for i := fromBlock; i < toBlock; i++ {
82 fetchedBlock, err := historyDB.GetBlock(i)
83 assert.NoError(t, err)
84 assertEqualBlock(t, &blocks[i-1], fetchedBlock)
85 }
86 // Get last block
87 lastBlock, err := historyDB.GetLastBlock()
88 assert.NoError(t, err)
89 assertEqualBlock(t, &blocks[len(blocks)-1], lastBlock)
90}
91
92func assertEqualBlock(t *testing.T, expected *common.Block, actual *common.Block) {
93 assert.Equal(t, expected.EthBlockNum, actual.EthBlockNum)
94 assert.Equal(t, expected.Hash, actual.Hash)
95 assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
96}
97
98func TestBatches(t *testing.T) {
99 const fromBlock int64 = 1
100 const toBlock int64 = 3
101 // Prepare blocks in the DB
102 blocks := setTestBlocks(fromBlock, toBlock)
103 // Generate fake batches
104 const nBatches = 9
105 batches := test.GenBatches(nBatches, blocks)
106 // Test GetLastL1TxsNum with no batches
107 fetchedLastL1TxsNum, err := historyDB.GetLastL1TxsNum()
108 assert.NoError(t, err)
109 assert.Nil(t, fetchedLastL1TxsNum)
110 // Add batches to the DB
111 err = historyDB.AddBatches(batches)
112 assert.NoError(t, err)
113 // Get batches from the DB
114 fetchedBatches, err := historyDB.GetBatches(0, common.BatchNum(nBatches))
115 assert.NoError(t, err)
116 for i, fetchedBatch := range fetchedBatches {
117 assert.Equal(t, batches[i], fetchedBatch)
118 }
119 // Test GetLastBatchNum
120 fetchedLastBatchNum, err := historyDB.GetLastBatchNum()
121 assert.NoError(t, err)
122 assert.Equal(t, batches[len(batches)-1].BatchNum, fetchedLastBatchNum)
123 // Test GetLastL1TxsNum
124 fetchedLastL1TxsNum, err = historyDB.GetLastL1TxsNum()
125 assert.NoError(t, err)
126 assert.Equal(t, *batches[nBatches-1].ForgeL1TxsNum, *fetchedLastL1TxsNum)
127 // Test total fee
128 // Generate fake tokens
129 const nTokens = 5
130 tokens, ethToken := test.GenTokens(nTokens, blocks)
131 err = historyDB.AddTokens(tokens)
132 assert.NoError(t, err)
133 tokens = append([]common.Token{ethToken}, tokens...)
134 feeBatch := batches[0]
135 feeBatch.BatchNum = 9999
136 feeBatch.CollectedFees = make(map[common.TokenID]*big.Int)
137 var total float64
138 for i, token := range tokens {
139 value := 3.019237 * float64(i)
140 assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
141 bigAmount := big.NewInt(345000000)
142 feeBatch.CollectedFees[token.TokenID] = bigAmount
143 f := new(big.Float).SetInt(bigAmount)
144 amount, _ := f.Float64()
145 total += value * (amount / math.Pow(10, float64(token.Decimals)))
146 }
147 err = historyDB.AddBatch(&feeBatch)
148 assert.NoError(t, err)
149 fetchedBatches, err = historyDB.GetBatches(feeBatch.BatchNum-1, feeBatch.BatchNum+1)
150 assert.NoError(t, err)
151 for _, fetchedBatch := range fetchedBatches {
152 if fetchedBatch.BatchNum == feeBatch.BatchNum {
153 assert.Equal(t, total, *fetchedBatch.TotalFeesUSD)
154 }
155 }
156}
157
158func TestBids(t *testing.T) {
159 const fromBlock int64 = 1
160 const toBlock int64 = 5
161 // Prepare blocks in the DB
162 blocks := setTestBlocks(fromBlock, toBlock)
163 // Generate fake coordinators
164 const nCoords = 5
165 coords := test.GenCoordinators(nCoords, blocks)
166 err := historyDB.AddCoordinators(coords)
167 assert.NoError(t, err)
168 // Generate fake bids
169 const nBids = 20
170 bids := test.GenBids(nBids, blocks, coords)
171 err = historyDB.AddBids(bids)
172 assert.NoError(t, err)
173 // Fetch bids
174 fetchedBids, err := historyDB.GetAllBids()
175 assert.NoError(t, err)
176 // Compare fetched bids vs generated bids
177 for i, bid := range fetchedBids {
178 assert.Equal(t, bids[i], bid)
179 }
180}
181
182func TestTokens(t *testing.T) {
183 const fromBlock int64 = 1
184 const toBlock int64 = 5
185 // Prepare blocks in the DB
186 blocks := setTestBlocks(fromBlock, toBlock)
187 // Generate fake tokens
188 const nTokens = 5
189 tokens, ethToken := test.GenTokens(nTokens, blocks)
190 err := historyDB.AddTokens(tokens)
191 assert.NoError(t, err)
192 tokens = append([]common.Token{ethToken}, tokens...)
193 limit := uint(10)
194 // Fetch tokens
195 fetchedTokens, _, err := historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
196 assert.NoError(t, err)
197 // Compare fetched tokens vs generated tokens
198 // All the tokens should have USDUpdate setted by the DB trigger
199 for i, token := range fetchedTokens {
200 assert.Equal(t, tokens[i].TokenID, token.TokenID)
201 assert.Equal(t, tokens[i].EthBlockNum, token.EthBlockNum)
202 assert.Equal(t, tokens[i].EthAddr, token.EthAddr)
203 assert.Equal(t, tokens[i].Name, token.Name)
204 assert.Equal(t, tokens[i].Symbol, token.Symbol)
205 assert.Nil(t, token.USD)
206 assert.Nil(t, token.USDUpdate)
207 }
208
209 // Update token value
210 for i, token := range tokens {
211 value := 1.01 * float64(i)
212 assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
213 }
214 // Fetch tokens
215 fetchedTokens, _, err = historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
216 assert.NoError(t, err)
217 // Compare fetched tokens vs generated tokens
218 // All the tokens should have USDUpdate setted by the DB trigger
219 for i, token := range fetchedTokens {
220 value := 1.01 * float64(i)
221 assert.Equal(t, value, *token.USD)
222 nameZone, offset := token.USDUpdate.Zone()
223 assert.Equal(t, "UTC", nameZone)
224 assert.Equal(t, 0, offset)
225 }
226}
227
228func TestAccounts(t *testing.T) {
229 const fromBlock int64 = 1
230 const toBlock int64 = 5
231 // Prepare blocks in the DB
232 blocks := setTestBlocks(fromBlock, toBlock)
233 // Generate fake tokens
234 const nTokens = 5
235 tokens, ethToken := test.GenTokens(nTokens, blocks)
236 err := historyDB.AddTokens(tokens)
237 assert.NoError(t, err)
238 tokens = append([]common.Token{ethToken}, tokens...)
239 // Generate fake batches
240 const nBatches = 10
241 batches := test.GenBatches(nBatches, blocks)
242 err = historyDB.AddBatches(batches)
243 assert.NoError(t, err)
244 // Generate fake accounts
245 const nAccounts = 3
246 accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
247 err = historyDB.AddAccounts(accs)
248 assert.NoError(t, err)
249 // Fetch accounts
250 fetchedAccs, err := historyDB.GetAccounts()
251 assert.NoError(t, err)
252 // Compare fetched accounts vs generated accounts
253 for i, acc := range fetchedAccs {
254 accs[i].Balance = nil
255 assert.Equal(t, accs[i], acc)
256 }
257}
258
259func TestTxs(t *testing.T) {
260 const fromBlock int64 = 1
261 const toBlock int64 = 5
262 // Prepare blocks in the DB
263 blocks := setTestBlocks(fromBlock, toBlock)
264 // Generate fake tokens
265 const nTokens = 500
266 tokens, ethToken := test.GenTokens(nTokens, blocks)
267 err := historyDB.AddTokens(tokens)
268 assert.NoError(t, err)
269 tokens = append([]common.Token{ethToken}, tokens...)
270 // Generate fake batches
271 const nBatches = 10
272 batches := test.GenBatches(nBatches, blocks)
273 err = historyDB.AddBatches(batches)
274 assert.NoError(t, err)
275 // Generate fake accounts
276 const nAccounts = 3
277 accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
278 err = historyDB.AddAccounts(accs)
279 assert.NoError(t, err)
280
281 /*
282 Uncomment once the transaction generation is fixed
283 !! test that batches that forge user L1s !!
284 !! Missing tests to check that historic USD is not set if USDUpdate is too old (24h) !!
285
286 // Generate fake L1 txs
287 const nL1s = 64
288 _, l1txs := test.GenL1Txs(256, nL1s, 0, nil, accs, tokens, blocks, batches)
289 err = historyDB.AddL1Txs(l1txs)
290 assert.NoError(t, err)
291 // Generate fake L2 txs
292 const nL2s = 2048 - nL1s
293 _, l2txs := test.GenL2Txs(256, nL2s, 0, nil, accs, tokens, blocks, batches)
294 err = historyDB.AddL2Txs(l2txs)
295 assert.NoError(t, err)
296 // Compare fetched txs vs generated txs.
297 fetchAndAssertTxs(t, l1txs, l2txs)
298 // Test trigger: L1 integrity
299 // from_eth_addr can't be null
300 l1txs[0].FromEthAddr = ethCommon.Address{}
301 err = historyDB.AddL1Txs(l1txs)
302 assert.Error(t, err)
303 l1txs[0].FromEthAddr = ethCommon.BigToAddress(big.NewInt(int64(5)))
304 // from_bjj can't be null
305 l1txs[0].FromBJJ = nil
306 err = historyDB.AddL1Txs(l1txs)
307 assert.Error(t, err)
308 privK := babyjub.NewRandPrivKey()
309 l1txs[0].FromBJJ = privK.Public()
310 // load_amount can't be null
311 l1txs[0].LoadAmount = nil
312 err = historyDB.AddL1Txs(l1txs)
313 assert.Error(t, err)
314 // Test trigger: L2 integrity
315 // batch_num can't be null
316 l2txs[0].BatchNum = 0
317 err = historyDB.AddL2Txs(l2txs)
318 assert.Error(t, err)
319 l2txs[0].BatchNum = 1
320 // nonce can't be null
321 l2txs[0].Nonce = 0
322 err = historyDB.AddL2Txs(l2txs)
323 assert.Error(t, err)
324 // Test trigger: forge L1 txs
325 // add next batch to DB
326 batchNum, toForgeL1TxsNum := test.GetNextToForgeNumAndBatch(batches)
327 batch := batches[0]
328 batch.BatchNum = batchNum
329 batch.ForgeL1TxsNum = toForgeL1TxsNum
330 assert.NoError(t, historyDB.AddBatch(&batch)) // This should update nL1s / 2 rows
331 // Set batch num in txs that should have been marked as forged in the DB
332 for i := 0; i < len(l1txs); i++ {
333 fetchedTx, err := historyDB.GetTx(l1txs[i].TxID)
334 assert.NoError(t, err)
335 if l1txs[i].ToForgeL1TxsNum == toForgeL1TxsNum {
336 assert.Equal(t, batchNum, *fetchedTx.BatchNum)
337 } else {
338 if fetchedTx.BatchNum != nil {
339 assert.NotEqual(t, batchNum, *fetchedTx.BatchNum)
340 }
341 }
342 }
343
344 // Test helper functions for Synchronizer
345 // GetLastTxsPosition
346 expectedPosition := -1
347 var choosenToForgeL1TxsNum int64 = -1
348 for _, tx := range l1txs {
349 if choosenToForgeL1TxsNum == -1 && tx.ToForgeL1TxsNum > 0 {
350 choosenToForgeL1TxsNum = tx.ToForgeL1TxsNum
351 expectedPosition = tx.Position
352 } else if choosenToForgeL1TxsNum == tx.ToForgeL1TxsNum && expectedPosition < tx.Position {
353 expectedPosition = tx.Position
354 }
355 }
356 position, err := historyDB.GetLastTxsPosition(choosenToForgeL1TxsNum)
357 assert.NoError(t, err)
358 assert.Equal(t, expectedPosition, position)
359
360 // GetL1UserTxs: not needed? tests were broken
361 // txs, err := historyDB.GetL1UserTxs(2)
362 // assert.NoError(t, err)
363 // assert.NotZero(t, len(txs))
364 // assert.NoError(t, err)
365 // assert.Equal(t, 22, position)
366 // // Test Update L1 TX Batch_num
367 // assert.Equal(t, common.BatchNum(0), txs[0].BatchNum)
368 // txs[0].BatchNum = common.BatchNum(1)
369 // txs, err = historyDB.GetL1UserTxs(2)
370 // assert.NoError(t, err)
371 // assert.NotZero(t, len(txs))
372 // assert.Equal(t, common.BatchNum(1), txs[0].BatchNum)
373 */
374}
375
376/*
377func fetchAndAssertTxs(t *testing.T, l1txs []common.L1Tx, l2txs []common.L2Tx) {
378 for i := 0; i < len(l1txs); i++ {
379 tx := l1txs[i].Tx()
380 fmt.Println("ASDF", i, tx.TxID)
381 fetchedTx, err := historyDB.GetTx(tx.TxID)
382 require.NoError(t, err)
383 test.AssertUSD(t, tx.USD, fetchedTx.USD)
384 test.AssertUSD(t, tx.LoadAmountUSD, fetchedTx.LoadAmountUSD)
385 assert.Equal(t, tx, fetchedTx)
386 }
387 for i := 0; i < len(l2txs); i++ {
388 tx := l2txs[i].Tx()
389 fetchedTx, err := historyDB.GetTx(tx.TxID)
390 tx.TokenID = fetchedTx.TokenID
391 assert.NoError(t, err)
392 test.AssertUSD(t, fetchedTx.USD, tx.USD)
393 test.AssertUSD(t, fetchedTx.FeeUSD, tx.FeeUSD)
394 assert.Equal(t, tx, fetchedTx)
395 }
396}
397*/
398
399func TestExitTree(t *testing.T) {
400 nBatches := 17
401 blocks := setTestBlocks(1, 10)
402 batches := test.GenBatches(nBatches, blocks)
403 err := historyDB.AddBatches(batches)
404 assert.NoError(t, err)
405 const nTokens = 50
406 tokens, ethToken := test.GenTokens(nTokens, blocks)
407 err = historyDB.AddTokens(tokens)
408 assert.NoError(t, err)
409 tokens = append([]common.Token{ethToken}, tokens...)
410 const nAccounts = 3
411 accs := test.GenAccounts(nAccounts, 0, tokens, nil, nil, batches)
412 assert.NoError(t, historyDB.AddAccounts(accs))
413 exitTree := test.GenExitTree(nBatches, batches, accs)
414 err = historyDB.AddExitTree(exitTree)
415 assert.NoError(t, err)
416}
417
418func TestGetL1UserTxs(t *testing.T) {
419 test.WipeDB(historyDB.DB())
420
421 set := `
422 Type: Blockchain
423 AddToken(1)
424 AddToken(2)
425 AddToken(3)
426
427 CreateAccountDeposit(1) A: 20
428 CreateAccountDeposit(2) A: 20
429 CreateAccountDeposit(1) B: 5
430 CreateAccountDeposit(1) C: 5
431 CreateAccountDeposit(1) D: 5
432
433 > block
434 `
435 tc := til.NewContext(128)
436 blocks, err := tc.GenerateBlocks(set)
437 require.Nil(t, err)
438 // Sanity check
439 require.Equal(t, 1, len(blocks))
440 require.Equal(t, 5, len(blocks[0].Rollup.L1UserTxs))
441 // fmt.Printf("DBG Blocks: %+v\n", blocks)
442
443 toForgeL1TxsNum := int64(1)
444
445 for i := range blocks {
446 err = historyDB.AddBlockSCData(&blocks[i])
447 require.Nil(t, err)
448 }
449
450 l1UserTxs, err := historyDB.GetL1UserTxs(toForgeL1TxsNum)
451 require.Nil(t, err)
452 assert.Equal(t, 5, len(l1UserTxs))
453 assert.Equal(t, blocks[0].Rollup.L1UserTxs, l1UserTxs)
454
455 // No l1UserTxs for this toForgeL1TxsNum
456 l1UserTxs, err = historyDB.GetL1UserTxs(2)
457 require.Nil(t, err)
458 assert.Equal(t, 0, len(l1UserTxs))
459}
460
461func TestSetInitialSCVars(t *testing.T) {
462 test.WipeDB(historyDB.DB())
463 _, _, _, err := historyDB.GetSCVars()
464 assert.Equal(t, sql.ErrNoRows, err)
465
466 //nolint:govet
467 rollup := &common.RollupVariables{
468 0,
469 big.NewInt(10),
470 12,
471 13,
472 [5]common.Bucket{},
473 }
474 //nolint:govet
475 auction := &common.AuctionVariables{
476 0,
477 ethCommon.BigToAddress(big.NewInt(2)),
478 ethCommon.BigToAddress(big.NewInt(3)),
479 [6]*big.Int{
480 big.NewInt(1), big.NewInt(2), big.NewInt(3),
481 big.NewInt(4), big.NewInt(5), big.NewInt(6),
482 },
483 2,
484 4320,
485 [3]uint16{10, 11, 12},
486 1000,
487 20,
488 }
489 //nolint:govet
490 wDelayer := &common.WDelayerVariables{
491 0,
492 ethCommon.BigToAddress(big.NewInt(2)),
493 ethCommon.BigToAddress(big.NewInt(3)),
494 ethCommon.BigToAddress(big.NewInt(4)),
495 13,
496 14,
497 false,
498 }
499 err = historyDB.SetInitialSCVars(rollup, auction, wDelayer)
500 require.Nil(t, err)
501 dbRollup, dbAuction, dbWDelayer, err := historyDB.GetSCVars()
502 assert.Nil(t, err)
503 require.Equal(t, rollup, dbRollup)
504 require.Equal(t, auction, dbAuction)
505 require.Equal(t, wDelayer, dbWDelayer)
506}
507
508func TestUpdateExitTree(t *testing.T) {
509 test.WipeDB(historyDB.DB())
510
511 set := `
512 Type: Blockchain
513
514 AddToken(1)
515
516 CreateAccountDeposit(1) C: 2000 // Idx=256+2=258
517 CreateAccountDeposit(1) D: 500 // Idx=256+3=259
518
519 CreateAccountCoordinator(1) A // Idx=256+0=256
520 CreateAccountCoordinator(1) B // Idx=256+1=257
521
522 > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{5}
523 > batchL1 // forge defined L1UserTxs{5}, freeze L1UserTxs{nil}
524 > block // blockNum=2
525
526 ForceExit(1) A: 100
527 ForceExit(1) B: 80
528
529 Exit(1) C: 50 (200)
530 Exit(1) D: 30 (200)
531
532 > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3}
533 > batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil}
534 > block // blockNum=3
535
536 > block // blockNum=4 (empty block)
537 `
538
539 tc := til.NewContext(common.RollupConstMaxL1UserTx)
540 tilCfgExtra := til.ConfigExtra{
541 BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
542 CoordUser: "A",
543 }
544 blocks, err := tc.GenerateBlocks(set)
545 require.Nil(t, err)
546 err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
547 assert.Nil(t, err)
548
549 // Add all blocks except for the last one
550 for i := range blocks[:len(blocks)-1] {
551 err = historyDB.AddBlockSCData(&blocks[i])
552 require.Nil(t, err)
553 }
554
555 // Add withdraws to the last block, and insert block into the DB
556 block := &blocks[len(blocks)-1]
557 require.Equal(t, int64(4), block.Block.EthBlockNum)
558 block.Rollup.Withdrawals = append(block.Rollup.Withdrawals,
559 common.WithdrawInfo{Idx: 256, NumExitRoot: 4, InstantWithdraw: true},
560 common.WithdrawInfo{Idx: 257, NumExitRoot: 4, InstantWithdraw: false},
561 common.WithdrawInfo{Idx: 258, NumExitRoot: 3, InstantWithdraw: true},
562 common.WithdrawInfo{Idx: 259, NumExitRoot: 3, InstantWithdraw: false},
563 )
564 err = historyDB.addBlock(historyDB.db, &block.Block)
565 require.Nil(t, err)
566
567 // update exit trees in DB
568 instantWithdrawn := []exitID{}
569 delayedWithdrawRequest := []exitID{}
570 for _, withdraw := range block.Rollup.Withdrawals {
571 exitID := exitID{
572 batchNum: int64(withdraw.NumExitRoot),
573 idx: int64(withdraw.Idx),
574 }
575 if withdraw.InstantWithdraw {
576 instantWithdrawn = append(instantWithdrawn, exitID)
577 } else {
578 delayedWithdrawRequest = append(delayedWithdrawRequest, exitID)
579 }
580 }
581 err = historyDB.updateExitTree(historyDB.db, block.Block.EthBlockNum, instantWithdrawn, delayedWithdrawRequest)
582 require.Nil(t, err)
583
584 // Check that exits in DB match with the expected values
585 dbExits, err := historyDB.GetAllExits()
586 require.Nil(t, err)
587 assert.Equal(t, 4, len(dbExits))
588 dbExitsByIdx := make(map[common.Idx]common.ExitInfo)
589 for _, dbExit := range dbExits {
590 dbExitsByIdx[dbExit.AccountIdx] = dbExit
591 }
592 for _, withdraw := range block.Rollup.Withdrawals {
593 assert.Equal(t, withdraw.NumExitRoot, dbExitsByIdx[withdraw.Idx].BatchNum)
594 if withdraw.InstantWithdraw {
595 assert.Equal(t, &block.Block.EthBlockNum, dbExitsByIdx[withdraw.Idx].InstantWithdrawn)
596 } else {
597 assert.Equal(t, &block.Block.EthBlockNum, dbExitsByIdx[withdraw.Idx].DelayedWithdrawRequest)
598 }
599 }
600}
601
602// setTestBlocks WARNING: this will delete the blocks and recreate them
603func setTestBlocks(from, to int64) []common.Block {
604 test.WipeDB(historyDB.DB())
605 blocks := test.GenBlocks(from, to)
606 if err := historyDB.AddBlocks(blocks); err != nil {
607 panic(err)
608 }
609 return blocks
610}