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