arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/db/l2db/l2db_test.go
db/l2db/l2db_test.goRaw
  1package l2db
  2
  3import (
  4	"math"
  5	"math/big"
  6	"os"
  7	"testing"
  8	"time"
  9
 10	ethCommon "github.com/ethereum/go-ethereum/common"
 11	"github.com/hermeznetwork/hermez-node/common"
 12	dbUtils "github.com/hermeznetwork/hermez-node/db"
 13	"github.com/hermeznetwork/hermez-node/db/historydb"
 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/hermeznetwork/tracerr"
 18	"github.com/stretchr/testify/assert"
 19	"github.com/stretchr/testify/require"
 20)
 21
 22var l2DB *L2DB
 23var historyDB *historydb.HistoryDB
 24var tc *til.Context
 25var tokens map[common.TokenID]historydb.TokenWithUSD
 26var tokensValue map[common.TokenID]float64
 27var accs map[common.Idx]common.Account
 28
 29func TestMain(m *testing.M) {
 30	// init DB
 31	pass := os.Getenv("POSTGRES_PASS")
 32	db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
 33	if err != nil {
 34		panic(err)
 35	}
 36	l2DB = NewL2DB(db, 10, 100, 24*time.Hour)
 37	test.WipeDB(l2DB.DB())
 38	historyDB = historydb.NewHistoryDB(db)
 39	// Run tests
 40	result := m.Run()
 41	// Close DB
 42	if err := db.Close(); err != nil {
 43		log.Error("Error closing the history DB:", err)
 44	}
 45	os.Exit(result)
 46}
 47
 48func prepareHistoryDB(historyDB *historydb.HistoryDB) error {
 49	// Reset DB
 50	test.WipeDB(l2DB.DB())
 51	// Generate pool txs using til
 52	setBlockchain := `
 53			Type: Blockchain
 54
 55			AddToken(1)
 56			AddToken(2)
 57			CreateAccountDeposit(1) A: 2000
 58			CreateAccountDeposit(2) A: 2000
 59			CreateAccountDeposit(1) B: 1000
 60			CreateAccountDeposit(2) B: 1000
 61			> batchL1 
 62			> batchL1
 63			> block
 64			> block
 65			`
 66
 67	tc = til.NewContext(uint16(0), common.RollupConstMaxL1UserTx)
 68	tilCfgExtra := til.ConfigExtra{
 69		BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
 70		CoordUser:     "A",
 71	}
 72	blocks, err := tc.GenerateBlocks(setBlockchain)
 73	if err != nil {
 74		return tracerr.Wrap(err)
 75	}
 76
 77	err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
 78	if err != nil {
 79		return tracerr.Wrap(err)
 80	}
 81	tokens = make(map[common.TokenID]historydb.TokenWithUSD)
 82	tokensValue = make(map[common.TokenID]float64)
 83	accs = make(map[common.Idx]common.Account)
 84	value := 5 * 5.389329
 85	now := time.Now().UTC()
 86	// Add all blocks except for the last one
 87	for i := range blocks[:len(blocks)-1] {
 88		err = historyDB.AddBlockSCData(&blocks[i])
 89		if err != nil {
 90			return tracerr.Wrap(err)
 91		}
 92		for _, batch := range blocks[i].Rollup.Batches {
 93			for _, account := range batch.CreatedAccounts {
 94				accs[account.Idx] = account
 95			}
 96		}
 97		for _, token := range blocks[i].Rollup.AddedTokens {
 98			readToken := historydb.TokenWithUSD{
 99				TokenID:     token.TokenID,
100				EthBlockNum: token.EthBlockNum,
101				EthAddr:     token.EthAddr,
102				Name:        token.Name,
103				Symbol:      token.Symbol,
104				Decimals:    token.Decimals,
105			}
106			tokensValue[token.TokenID] = value / math.Pow(10, float64(token.Decimals))
107			readToken.USDUpdate = &now
108			readToken.USD = &value
109			tokens[token.TokenID] = readToken
110		}
111		// Set value to the tokens (tokens have no symbol)
112		tokenSymbol := ""
113		err := historyDB.UpdateTokenValue(tokenSymbol, value)
114		if err != nil {
115			return tracerr.Wrap(err)
116		}
117	}
118	return nil
119}
120
121func generatePoolL2Txs() ([]common.PoolL2Tx, error) {
122	setPool := `
123			Type: PoolL2
124			PoolTransfer(1) A-B: 6 (4)
125			PoolTransfer(2) A-B: 3 (1)
126			PoolTransfer(1) B-A: 5 (2)
127			PoolTransfer(2) B-A: 10 (3)
128			PoolTransfer(1) A-B: 7 (2)
129			PoolTransfer(2) A-B: 2 (1)
130			PoolTransfer(1) B-A: 8 (2)
131			PoolTransfer(2) B-A: 1 (1)
132			PoolTransfer(1) A-B: 3 (1)
133			PoolTransfer(2) B-A: 5 (2)
134
135			PoolExit(1) A: 5 (2)
136			PoolExit(2) B: 3 (1)
137		`
138	poolL2Txs, err := tc.GeneratePoolL2Txs(setPool)
139	if err != nil {
140		return nil, tracerr.Wrap(err)
141	}
142	return poolL2Txs, nil
143}
144
145func TestAddTxTest(t *testing.T) {
146	err := prepareHistoryDB(historyDB)
147	if err != nil {
148		log.Error("Error prepare historyDB", err)
149	}
150	poolL2Txs, err := generatePoolL2Txs()
151	assert.NoError(t, err)
152	for i := range poolL2Txs {
153		err := l2DB.AddTxTest(&poolL2Txs[i])
154		assert.NoError(t, err)
155		fetchedTx, err := l2DB.GetTx(poolL2Txs[i].TxID)
156		assert.NoError(t, err)
157		assertTx(t, &poolL2Txs[i], fetchedTx)
158		nameZone, offset := fetchedTx.Timestamp.Zone()
159		assert.Equal(t, "UTC", nameZone)
160		assert.Equal(t, 0, offset)
161	}
162}
163
164func assertTx(t *testing.T, expected, actual *common.PoolL2Tx) {
165	// Check that timestamp has been set within the last 3 seconds
166	assert.Less(t, time.Now().UTC().Unix()-3, actual.Timestamp.Unix())
167	assert.GreaterOrEqual(t, time.Now().UTC().Unix(), actual.Timestamp.Unix())
168	expected.Timestamp = actual.Timestamp
169	// Check absolute fee
170	// find token
171	token := tokens[expected.TokenID]
172	// If the token has value in USD setted
173	if token.USDUpdate != nil {
174		assert.Less(t, token.USDUpdate.Unix()-3, actual.AbsoluteFeeUpdate.Unix())
175		expected.AbsoluteFeeUpdate = actual.AbsoluteFeeUpdate
176		// Set expected fee
177		f := new(big.Float).SetInt(expected.Amount)
178		amountF, _ := f.Float64()
179		expected.AbsoluteFee = *token.USD * amountF * expected.Fee.Percentage()
180		test.AssertUSD(t, &expected.AbsoluteFee, &actual.AbsoluteFee)
181	}
182	assert.Equal(t, expected, actual)
183}
184
185// NO UPDATE: benchmarks will be done after impl is finished
186// func BenchmarkAddTxTest(b *testing.B) {
187// 	const nInserts = 20
188// 	test.WipeDB(l2DB.DB())
189// 	txs := test.GenPoolTxs(nInserts, tokens)
190// 	now := time.Now()
191// 	for _, tx := range txs {
192// 		_ = l2DB.AddTxTest(tx)
193// 	}
194// 	elapsedTime := time.Since(now)
195// 	log.Info("Time to insert 2048 txs:", elapsedTime)
196// }
197
198func TestGetPending(t *testing.T) {
199	err := prepareHistoryDB(historyDB)
200	if err != nil {
201		log.Error("Error prepare historyDB", err)
202	}
203	poolL2Txs, err := generatePoolL2Txs()
204	assert.NoError(t, err)
205	var pendingTxs []*common.PoolL2Tx
206	for i := range poolL2Txs {
207		err := l2DB.AddTxTest(&poolL2Txs[i])
208		assert.NoError(t, err)
209		pendingTxs = append(pendingTxs, &poolL2Txs[i])
210	}
211	fetchedTxs, err := l2DB.GetPendingTxs()
212	assert.NoError(t, err)
213	assert.Equal(t, len(pendingTxs), len(fetchedTxs))
214	for i := range fetchedTxs {
215		assertTx(t, pendingTxs[i], &fetchedTxs[i])
216	}
217}
218
219func TestStartForging(t *testing.T) {
220	// Generate txs
221	var fakeBatchNum common.BatchNum = 33
222	err := prepareHistoryDB(historyDB)
223	if err != nil {
224		log.Error("Error prepare historyDB", err)
225	}
226	poolL2Txs, err := generatePoolL2Txs()
227	assert.NoError(t, err)
228	var startForgingTxIDs []common.TxID
229	randomizer := 0
230	// Add txs to DB
231	for i := range poolL2Txs {
232		err := l2DB.AddTxTest(&poolL2Txs[i])
233		assert.NoError(t, err)
234		if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
235			startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
236		}
237		randomizer++
238	}
239	// Start forging txs
240	err = l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
241	assert.NoError(t, err)
242	// Fetch txs and check that they've been updated correctly
243	for _, id := range startForgingTxIDs {
244		fetchedTx, err := l2DB.GetTxAPI(id)
245		assert.NoError(t, err)
246		assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State)
247		assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
248	}
249}
250
251func TestDoneForging(t *testing.T) {
252	// Generate txs
253	var fakeBatchNum common.BatchNum = 33
254	err := prepareHistoryDB(historyDB)
255	if err != nil {
256		log.Error("Error prepare historyDB", err)
257	}
258	poolL2Txs, err := generatePoolL2Txs()
259	assert.NoError(t, err)
260	var startForgingTxIDs []common.TxID
261	randomizer := 0
262	// Add txs to DB
263	for i := range poolL2Txs {
264		err := l2DB.AddTxTest(&poolL2Txs[i])
265		assert.NoError(t, err)
266		if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
267			startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
268		}
269		randomizer++
270	}
271	// Start forging txs
272	err = l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
273	assert.NoError(t, err)
274
275	var doneForgingTxIDs []common.TxID
276	randomizer = 0
277	for _, txID := range startForgingTxIDs {
278		if randomizer%2 == 0 {
279			doneForgingTxIDs = append(doneForgingTxIDs, txID)
280		}
281		randomizer++
282	}
283	// Done forging txs
284	err = l2DB.DoneForging(doneForgingTxIDs, fakeBatchNum)
285	assert.NoError(t, err)
286
287	// Fetch txs and check that they've been updated correctly
288	for _, id := range doneForgingTxIDs {
289		fetchedTx, err := l2DB.GetTxAPI(id)
290		assert.NoError(t, err)
291		assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State)
292		assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
293	}
294}
295
296func TestInvalidate(t *testing.T) {
297	// Generate txs
298	var fakeBatchNum common.BatchNum = 33
299	err := prepareHistoryDB(historyDB)
300	if err != nil {
301		log.Error("Error prepare historyDB", err)
302	}
303	poolL2Txs, err := generatePoolL2Txs()
304	assert.NoError(t, err)
305	var invalidTxIDs []common.TxID
306	randomizer := 0
307	// Add txs to DB
308	for i := range poolL2Txs {
309		err := l2DB.AddTxTest(&poolL2Txs[i])
310		assert.NoError(t, err)
311		if poolL2Txs[i].State != common.PoolL2TxStateInvalid && randomizer%2 == 0 {
312			randomizer++
313			invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
314		}
315	}
316	// Invalidate txs
317	err = l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
318	assert.NoError(t, err)
319	// Fetch txs and check that they've been updated correctly
320	for _, id := range invalidTxIDs {
321		fetchedTx, err := l2DB.GetTxAPI(id)
322		assert.NoError(t, err)
323		assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
324		assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
325	}
326}
327
328func TestInvalidateOldNonces(t *testing.T) {
329	// Generate txs
330	var fakeBatchNum common.BatchNum = 33
331	err := prepareHistoryDB(historyDB)
332	if err != nil {
333		log.Error("Error prepare historyDB", err)
334	}
335	poolL2Txs, err := generatePoolL2Txs()
336	assert.NoError(t, err)
337	// Update Accounts currentNonce
338	var updateAccounts []common.IdxNonce
339	var currentNonce = common.Nonce(1)
340	for i := range accs {
341		updateAccounts = append(updateAccounts, common.IdxNonce{
342			Idx:   accs[i].Idx,
343			Nonce: common.Nonce(currentNonce),
344		})
345	}
346	// Add txs to DB
347	var invalidTxIDs []common.TxID
348	for i := range poolL2Txs {
349		if poolL2Txs[i].Nonce < currentNonce {
350			invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
351		}
352		err := l2DB.AddTxTest(&poolL2Txs[i])
353		assert.NoError(t, err)
354	}
355	// sanity check
356	require.Greater(t, len(invalidTxIDs), 0)
357
358	err = l2DB.InvalidateOldNonces(updateAccounts, fakeBatchNum)
359	assert.NoError(t, err)
360	// Fetch txs and check that they've been updated correctly
361	for _, id := range invalidTxIDs {
362		fetchedTx, err := l2DB.GetTxAPI(id)
363		require.NoError(t, err)
364		assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
365		assert.Equal(t, &fakeBatchNum, fetchedTx.BatchNum)
366	}
367}
368
369// TestReorg: first part of the test with reorg
370// With invalidated transactions BEFORE reorgBatch
371// And forged transactions in reorgBatch
372func TestReorg(t *testing.T) {
373	// Generate txs
374	const lastValidBatch common.BatchNum = 20
375	const reorgBatch common.BatchNum = lastValidBatch + 1
376	err := prepareHistoryDB(historyDB)
377	if err != nil {
378		log.Error("Error prepare historyDB", err)
379	}
380	poolL2Txs, err := generatePoolL2Txs()
381	assert.NoError(t, err)
382
383	reorgedTxIDs := []common.TxID{}
384	nonReorgedTxIDs := []common.TxID{}
385	var startForgingTxIDs []common.TxID
386	var invalidTxIDs []common.TxID
387	var allTxRandomize []common.TxID
388	randomizer := 0
389	// Add txs to DB
390	for i := range poolL2Txs {
391		err := l2DB.AddTxTest(&poolL2Txs[i])
392		assert.NoError(t, err)
393		if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
394			startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
395			allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
396		} else if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%3 == 0 {
397			invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
398			allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
399		}
400		randomizer++
401	}
402	// Start forging txs
403	err = l2DB.StartForging(startForgingTxIDs, lastValidBatch)
404	assert.NoError(t, err)
405
406	var doneForgingTxIDs []common.TxID
407	randomizer = 0
408	for _, txID := range allTxRandomize {
409		invalidTx := false
410		for i := range invalidTxIDs {
411			if invalidTxIDs[i] == txID {
412				invalidTx = true
413				nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
414			}
415		}
416		if !invalidTx {
417			if randomizer%2 == 0 {
418				doneForgingTxIDs = append(doneForgingTxIDs, txID)
419				reorgedTxIDs = append(reorgedTxIDs, txID)
420			} else {
421				nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
422			}
423			randomizer++
424		}
425	}
426
427	// Invalidate txs BEFORE reorgBatch --> nonReorg
428	err = l2DB.InvalidateTxs(invalidTxIDs, lastValidBatch)
429	assert.NoError(t, err)
430	// Done forging txs in reorgBatch --> Reorg
431	err = l2DB.DoneForging(doneForgingTxIDs, reorgBatch)
432	assert.NoError(t, err)
433
434	err = l2DB.Reorg(lastValidBatch)
435	assert.NoError(t, err)
436	for _, id := range reorgedTxIDs {
437		tx, err := l2DB.GetTxAPI(id)
438		assert.NoError(t, err)
439		assert.Nil(t, tx.BatchNum)
440		assert.Equal(t, common.PoolL2TxStatePending, tx.State)
441	}
442	for _, id := range nonReorgedTxIDs {
443		fetchedTx, err := l2DB.GetTxAPI(id)
444		assert.NoError(t, err)
445		assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
446	}
447}
448
449// TestReorg: second part of test with reorg
450// With invalidated transactions in reorgBatch
451// And forged transactions BEFORE reorgBatch
452func TestReorg2(t *testing.T) {
453	// Generate txs
454	const lastValidBatch common.BatchNum = 20
455	const reorgBatch common.BatchNum = lastValidBatch + 1
456	err := prepareHistoryDB(historyDB)
457	if err != nil {
458		log.Error("Error prepare historyDB", err)
459	}
460	poolL2Txs, err := generatePoolL2Txs()
461	assert.NoError(t, err)
462
463	reorgedTxIDs := []common.TxID{}
464	nonReorgedTxIDs := []common.TxID{}
465	var startForgingTxIDs []common.TxID
466	var invalidTxIDs []common.TxID
467	var allTxRandomize []common.TxID
468	randomizer := 0
469	// Add txs to DB
470	for i := range poolL2Txs {
471		err := l2DB.AddTxTest(&poolL2Txs[i])
472		assert.NoError(t, err)
473		if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%2 == 0 {
474			startForgingTxIDs = append(startForgingTxIDs, poolL2Txs[i].TxID)
475			allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
476		} else if poolL2Txs[i].State == common.PoolL2TxStatePending && randomizer%3 == 0 {
477			invalidTxIDs = append(invalidTxIDs, poolL2Txs[i].TxID)
478			allTxRandomize = append(allTxRandomize, poolL2Txs[i].TxID)
479		}
480		randomizer++
481	}
482	// Start forging txs
483	err = l2DB.StartForging(startForgingTxIDs, lastValidBatch)
484	assert.NoError(t, err)
485
486	var doneForgingTxIDs []common.TxID
487	randomizer = 0
488	for _, txID := range allTxRandomize {
489		invalidTx := false
490		for i := range invalidTxIDs {
491			if invalidTxIDs[i] == txID {
492				invalidTx = true
493				reorgedTxIDs = append(reorgedTxIDs, txID)
494			}
495		}
496		if !invalidTx {
497			if randomizer%2 == 0 {
498				doneForgingTxIDs = append(doneForgingTxIDs, txID)
499			}
500			nonReorgedTxIDs = append(nonReorgedTxIDs, txID)
501			randomizer++
502		}
503	}
504	// Done forging txs BEFORE reorgBatch --> nonReorg
505	err = l2DB.DoneForging(doneForgingTxIDs, lastValidBatch)
506	assert.NoError(t, err)
507	// Invalidate txs in reorgBatch --> Reorg
508	err = l2DB.InvalidateTxs(invalidTxIDs, reorgBatch)
509	assert.NoError(t, err)
510
511	err = l2DB.Reorg(lastValidBatch)
512	assert.NoError(t, err)
513	for _, id := range reorgedTxIDs {
514		tx, err := l2DB.GetTxAPI(id)
515		assert.NoError(t, err)
516		assert.Nil(t, tx.BatchNum)
517		assert.Equal(t, common.PoolL2TxStatePending, tx.State)
518	}
519	for _, id := range nonReorgedTxIDs {
520		fetchedTx, err := l2DB.GetTxAPI(id)
521		assert.NoError(t, err)
522		assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
523	}
524}
525
526func TestPurge(t *testing.T) {
527	// Generate txs
528	err := prepareHistoryDB(historyDB)
529	if err != nil {
530		log.Error("Error prepare historyDB", err)
531	}
532	// generatePoolL2Txs generate 10 txs
533	generateTx := int(l2DB.maxTxs/10 + 1)
534	var poolL2Tx []common.PoolL2Tx
535	for i := 0; i < generateTx; i++ {
536		poolL2TxAux, err := generatePoolL2Txs()
537		assert.NoError(t, err)
538		poolL2Tx = append(poolL2Tx, poolL2TxAux...)
539	}
540
541	deletedIDs := []common.TxID{}
542	keepedIDs := []common.TxID{}
543	var invalidTxIDs []common.TxID
544	var doneForgingTxIDs []common.TxID
545	const toDeleteBatchNum common.BatchNum = 30
546	safeBatchNum := toDeleteBatchNum + l2DB.safetyPeriod + 1
547	// Add txs to the DB
548	for i := 0; i < int(l2DB.maxTxs); i++ {
549		tx := poolL2Tx[i]
550		if i%2 == 0 { // keep tx
551			keepedIDs = append(keepedIDs, tx.TxID)
552		} else { // delete after safety period
553			if i%3 == 0 {
554				doneForgingTxIDs = append(doneForgingTxIDs, tx.TxID)
555			} else {
556				invalidTxIDs = append(invalidTxIDs, tx.TxID)
557			}
558			deletedIDs = append(deletedIDs, tx.TxID)
559		}
560		err := l2DB.AddTxTest(&tx)
561		assert.NoError(t, err)
562	}
563	// Set batchNum keeped txs
564	for i := range keepedIDs {
565		_, err = l2DB.db.Exec(
566			"UPDATE tx_pool SET batch_num = $1 WHERE tx_id = $2;",
567			safeBatchNum, keepedIDs[i],
568		)
569		assert.NoError(t, err)
570	}
571	// Start forging txs and set batchNum
572	err = l2DB.StartForging(doneForgingTxIDs, toDeleteBatchNum)
573	assert.NoError(t, err)
574	// Done forging txs and set batchNum
575	err = l2DB.DoneForging(doneForgingTxIDs, toDeleteBatchNum)
576	assert.NoError(t, err)
577	// Invalidate txs and set batchNum
578	err = l2DB.InvalidateTxs(invalidTxIDs, toDeleteBatchNum)
579	assert.NoError(t, err)
580	for i := int(l2DB.maxTxs); i < len(poolL2Tx); i++ {
581		// Delete after TTL
582		deletedIDs = append(deletedIDs, poolL2Tx[i].TxID)
583		err := l2DB.AddTxTest(&poolL2Tx[i])
584		assert.NoError(t, err)
585		// Set timestamp
586		deleteTimestamp := time.Unix(time.Now().UTC().Unix()-int64(l2DB.ttl.Seconds()+float64(4*time.Second)), 0)
587		_, err = l2DB.db.Exec(
588			"UPDATE tx_pool SET timestamp = $1 WHERE tx_id = $2;",
589			deleteTimestamp, poolL2Tx[i].TxID,
590		)
591		assert.NoError(t, err)
592	}
593
594	// Purge txs
595	err = l2DB.Purge(safeBatchNum)
596	assert.NoError(t, err)
597	// Check results
598	for _, id := range deletedIDs {
599		tx, err := l2DB.GetTx(id)
600		if err == nil {
601			log.Debug(tx)
602		}
603		assert.Error(t, err)
604	}
605	for _, id := range keepedIDs {
606		_, err := l2DB.GetTx(id)
607		assert.NoError(t, err)
608	}
609}
610
611func TestAuth(t *testing.T) {
612	test.WipeDB(l2DB.DB())
613	const nAuths = 5
614	chainID := uint16(0)
615	hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
616	// Generate authorizations
617	auths := test.GenAuths(nAuths, chainID, hermezContractAddr)
618	for i := 0; i < len(auths); i++ {
619		// Add to the DB
620		err := l2DB.AddAccountCreationAuth(auths[i])
621		assert.NoError(t, err)
622		// Fetch from DB
623		auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
624		assert.NoError(t, err)
625		// Check fetched vs generated
626		assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
627		assert.Equal(t, auths[i].BJJ, auth.BJJ)
628		assert.Equal(t, auths[i].Signature, auth.Signature)
629		assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix())
630		nameZone, offset := auths[i].Timestamp.Zone()
631		assert.Equal(t, "UTC", nameZone)
632		assert.Equal(t, 0, offset)
633	}
634}