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 }
473 //nolint:govet
474 auction := &common.AuctionVariables{
475 0,
476 ethCommon.BigToAddress(big.NewInt(2)),
477 ethCommon.BigToAddress(big.NewInt(3)),
478 [6]*big.Int{
479 big.NewInt(1), big.NewInt(2), big.NewInt(3),
480 big.NewInt(4), big.NewInt(5), big.NewInt(6),
481 },
482 2,
483 4320,
484 [3]uint16{10, 11, 12},
485 1000,
486 20,
487 }
488 //nolint:govet
489 wDelayer := &common.WDelayerVariables{
490 0,
491 ethCommon.BigToAddress(big.NewInt(2)),
492 ethCommon.BigToAddress(big.NewInt(3)),
493 ethCommon.BigToAddress(big.NewInt(4)),
494 13,
495 14,
496 false,
497 }
498 err = historyDB.SetInitialSCVars(rollup, auction, wDelayer)
499 require.Nil(t, err)
500 dbRollup, dbAuction, dbWDelayer, err := historyDB.GetSCVars()
501 assert.Nil(t, err)
502 require.Equal(t, rollup, dbRollup)
503 require.Equal(t, auction, dbAuction)
504 require.Equal(t, wDelayer, dbWDelayer)
505}
506
507func TestUpdateExitTree(t *testing.T) {
508 test.WipeDB(historyDB.DB())
509
510 set := `
511 Type: Blockchain
512
513 AddToken(1)
514
515 CreateAccountDeposit(1) C: 2000 // Idx=256+2=258
516 CreateAccountDeposit(1) D: 500 // Idx=256+3=259
517
518 CreateAccountCoordinator(1) A // Idx=256+0=256
519 CreateAccountCoordinator(1) B // Idx=256+1=257
520
521 > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{5}
522 > batchL1 // forge defined L1UserTxs{5}, freeze L1UserTxs{nil}
523 > block // blockNum=2
524
525 ForceExit(1) A: 100
526 ForceExit(1) B: 80
527
528 Exit(1) C: 50 (200)
529 Exit(1) D: 30 (200)
530
531 > batchL1 // forge L1UserTxs{nil}, freeze defined L1UserTxs{3}
532 > batchL1 // forge L1UserTxs{3}, freeze defined L1UserTxs{nil}
533 > block // blockNum=3
534
535 > block // blockNum=4 (empty block)
536 `
537
538 tc := til.NewContext(common.RollupConstMaxL1UserTx)
539 tilCfgExtra := til.ConfigExtra{
540 BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
541 CoordUser: "A",
542 }
543 blocks, err := tc.GenerateBlocks(set)
544 require.Nil(t, err)
545 err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
546 assert.Nil(t, err)
547
548 // Add all blocks except for the last one
549 for i := range blocks[:len(blocks)-1] {
550 err = historyDB.AddBlockSCData(&blocks[i])
551 require.Nil(t, err)
552 }
553
554 // Add withdraws to the last block, and insert block into the DB
555 block := &blocks[len(blocks)-1]
556 require.Equal(t, int64(4), block.Block.EthBlockNum)
557 block.Rollup.Withdrawals = append(block.Rollup.Withdrawals,
558 common.WithdrawInfo{Idx: 256, NumExitRoot: 4, InstantWithdraw: true},
559 common.WithdrawInfo{Idx: 257, NumExitRoot: 4, InstantWithdraw: false},
560 common.WithdrawInfo{Idx: 258, NumExitRoot: 3, InstantWithdraw: true},
561 common.WithdrawInfo{Idx: 259, NumExitRoot: 3, InstantWithdraw: false},
562 )
563 err = historyDB.addBlock(historyDB.db, &block.Block)
564 require.Nil(t, err)
565
566 // update exit trees in DB
567 instantWithdrawn := []exitID{}
568 delayedWithdrawRequest := []exitID{}
569 for _, withdraw := range block.Rollup.Withdrawals {
570 exitID := exitID{
571 batchNum: int64(withdraw.NumExitRoot),
572 idx: int64(withdraw.Idx),
573 }
574 if withdraw.InstantWithdraw {
575 instantWithdrawn = append(instantWithdrawn, exitID)
576 } else {
577 delayedWithdrawRequest = append(delayedWithdrawRequest, exitID)
578 }
579 }
580 err = historyDB.updateExitTree(historyDB.db, block.Block.EthBlockNum, instantWithdrawn, delayedWithdrawRequest)
581 require.Nil(t, err)
582
583 // Check that exits in DB match with the expected values
584 dbExits, err := historyDB.GetAllExits()
585 require.Nil(t, err)
586 assert.Equal(t, 4, len(dbExits))
587 dbExitsByIdx := make(map[common.Idx]common.ExitInfo)
588 for _, dbExit := range dbExits {
589 dbExitsByIdx[dbExit.AccountIdx] = dbExit
590 }
591 for _, withdraw := range block.Rollup.Withdrawals {
592 assert.Equal(t, withdraw.NumExitRoot, dbExitsByIdx[withdraw.Idx].BatchNum)
593 if withdraw.InstantWithdraw {
594 assert.Equal(t, &block.Block.EthBlockNum, dbExitsByIdx[withdraw.Idx].InstantWithdrawn)
595 } else {
596 assert.Equal(t, &block.Block.EthBlockNum, dbExitsByIdx[withdraw.Idx].DelayedWithdrawRequest)
597 }
598 }
599}
600
601// setTestBlocks WARNING: this will delete the blocks and recreate them
602func setTestBlocks(from, to int64) []common.Block {
603 test.WipeDB(historyDB.DB())
604 blocks := test.GenBlocks(from, to)
605 if err := historyDB.AddBlocks(blocks); err != nil {
606 panic(err)
607 }
608 return blocks
609}