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