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