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/big"
  5	"os"
  6	"testing"
  7	"time"
  8
  9	"github.com/hermeznetwork/hermez-node/common"
 10	dbUtils "github.com/hermeznetwork/hermez-node/db"
 11	"github.com/hermeznetwork/hermez-node/db/historydb"
 12	"github.com/hermeznetwork/hermez-node/log"
 13	"github.com/hermeznetwork/hermez-node/test"
 14	"github.com/jmoiron/sqlx"
 15	"github.com/stretchr/testify/assert"
 16)
 17
 18var l2DB *L2DB
 19var tokens []common.Token
 20var tokensUSD []historydb.TokenWithUSD
 21
 22func TestMain(m *testing.M) {
 23	// init DB
 24	pass := os.Getenv("POSTGRES_PASS")
 25	db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
 26	if err != nil {
 27		panic(err)
 28	}
 29	l2DB = NewL2DB(db, 10, 100, 24*time.Hour)
 30	test.WipeDB(l2DB.DB())
 31	tokens, tokensUSD = prepareHistoryDB(db)
 32	// Run tests
 33	result := m.Run()
 34	// Close DB
 35	if err := db.Close(); err != nil {
 36		log.Error("Error closing the history DB:", err)
 37	}
 38	os.Exit(result)
 39}
 40
 41func prepareHistoryDB(db *sqlx.DB) ([]common.Token, []historydb.TokenWithUSD) {
 42	historyDB := historydb.NewHistoryDB(db)
 43	const fromBlock int64 = 1
 44	const toBlock int64 = 5
 45	// Store blocks to historyDB
 46	blocks := test.GenBlocks(fromBlock, toBlock)
 47	if err := historyDB.AddBlocks(blocks); err != nil {
 48		panic(err)
 49	}
 50	// Store tokens to historyDB
 51	const nTokens = 5
 52	tokens, ethToken := test.GenTokens(nTokens, blocks)
 53	if err := historyDB.AddTokens(tokens); err != nil {
 54		panic(err)
 55	}
 56	tokens = append([]common.Token{ethToken}, tokens...)
 57	readTokens := []historydb.TokenWithUSD{}
 58	for i, token := range tokens {
 59		readToken := historydb.TokenWithUSD{
 60			TokenID:     token.TokenID,
 61			EthBlockNum: token.EthBlockNum,
 62			EthAddr:     token.EthAddr,
 63			Name:        token.Name,
 64			Symbol:      token.Symbol,
 65			Decimals:    token.Decimals,
 66		}
 67		if i%2 != 0 {
 68			value := float64(i) * 5.4321
 69			if err := historyDB.UpdateTokenValue(token.Symbol, value); err != nil {
 70				panic(err)
 71			}
 72			now := time.Now().UTC()
 73			readToken.USDUpdate = &now
 74			readToken.USD = &value
 75		}
 76		readTokens = append(readTokens, readToken)
 77	}
 78	return tokens, readTokens
 79}
 80
 81func TestAddTxTest(t *testing.T) {
 82	// Gen poolTxs
 83	const nInserts = 20
 84	test.WipeDB(l2DB.DB())
 85	txs := test.GenPoolTxs(nInserts, tokens)
 86	for _, tx := range txs {
 87		// TODO: UPDATE with til
 88		err := l2DB.AddTxTest(tx)
 89		assert.NoError(t, err)
 90		fetchedTx, err := l2DB.GetTx(tx.TxID)
 91		assert.NoError(t, err)
 92		// assertReadTx(t, commonToRead(tx, tokens), fetchedTx)
 93		assertTx(t, tx, fetchedTx)
 94		nameZone, offset := fetchedTx.Timestamp.Zone()
 95		assert.Equal(t, "UTC", nameZone)
 96		assert.Equal(t, 0, offset)
 97	}
 98}
 99
100func assertTx(t *testing.T, expected, actual *common.PoolL2Tx) {
101	// Check that timestamp has been set within the last 3 seconds
102	assert.Less(t, time.Now().UTC().Unix()-3, actual.Timestamp.Unix())
103	assert.GreaterOrEqual(t, time.Now().UTC().Unix(), actual.Timestamp.Unix())
104	expected.Timestamp = actual.Timestamp
105	// Check absolute fee
106	// find token
107	token := historydb.TokenWithUSD{}
108	for _, tkn := range tokensUSD {
109		if expected.TokenID == tkn.TokenID {
110			token = tkn
111			break
112		}
113	}
114	// If the token has value in USD setted
115	if token.USDUpdate != nil {
116		assert.Equal(t, token.USDUpdate.Unix(), actual.AbsoluteFeeUpdate.Unix())
117		expected.AbsoluteFeeUpdate = actual.AbsoluteFeeUpdate
118		// Set expected fee
119		f := new(big.Float).SetInt(expected.Amount)
120		amountF, _ := f.Float64()
121		expected.AbsoluteFee = *token.USD * amountF * expected.Fee.Percentage()
122		test.AssertUSD(t, &expected.AbsoluteFee, &actual.AbsoluteFee)
123	}
124	assert.Equal(t, expected, actual)
125}
126
127// NO UPDATE: benchmarks will be done after impl is finished
128// func BenchmarkAddTxTest(b *testing.B) {
129// 	const nInserts = 20
130// 	test.WipeDB(l2DB.DB())
131// 	txs := test.GenPoolTxs(nInserts, tokens)
132// 	now := time.Now()
133// 	for _, tx := range txs {
134// 		_ = l2DB.AddTxTest(tx)
135// 	}
136// 	elapsedTime := time.Since(now)
137// 	log.Info("Time to insert 2048 txs:", elapsedTime)
138// }
139
140func TestGetPending(t *testing.T) {
141	const nInserts = 20
142	test.WipeDB(l2DB.DB())
143	// TODO: UPDATE with til
144	txs := test.GenPoolTxs(nInserts, tokens)
145	var pendingTxs []*common.PoolL2Tx
146	for _, tx := range txs {
147		err := l2DB.AddTxTest(tx)
148		assert.NoError(t, err)
149		if tx.State == common.PoolL2TxStatePending {
150			pendingTxs = append(pendingTxs, tx)
151		}
152	}
153	fetchedTxs, err := l2DB.GetPendingTxs()
154	assert.NoError(t, err)
155	assert.Equal(t, len(pendingTxs), len(fetchedTxs))
156	for i := range fetchedTxs {
157		assertTx(t, pendingTxs[i], &fetchedTxs[i])
158	}
159}
160
161/*
162		TODO: update with til
163func TestStartForging(t *testing.T) {
164	// Generate txs
165	const nInserts = 60
166	const fakeBatchNum common.BatchNum = 33
167	test.WipeDB(l2DB.DB())
168	txs := test.GenPoolTxs(nInserts, tokens)
169	var startForgingTxIDs []common.TxID
170	randomizer := 0
171	// Add txs to DB
172	for _, tx := range txs {
173		err := l2DB.AddTxTest(tx)
174		assert.NoError(t, err)
175		if tx.State == common.PoolL2TxStatePending && randomizer%2 == 0 {
176			randomizer++
177			startForgingTxIDs = append(startForgingTxIDs, tx.TxID)
178		}
179	}
180	// Start forging txs
181	err := l2DB.StartForging(startForgingTxIDs, fakeBatchNum)
182	assert.NoError(t, err)
183	// Fetch txs and check that they've been updated correctly
184	for _, id := range startForgingTxIDs {
185		fetchedTx, err := l2DB.GetTx(id)
186		assert.NoError(t, err)
187		assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State)
188		assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
189	}
190}
191*/
192
193/*
194		TODO: update with til
195func TestDoneForging(t *testing.T) {
196	// Generate txs
197	const nInserts = 60
198	const fakeBatchNum common.BatchNum = 33
199	test.WipeDB(l2DB.DB())
200	txs := test.GenPoolTxs(nInserts, tokens)
201	var doneForgingTxIDs []common.TxID
202	randomizer := 0
203	// Add txs to DB
204	for _, tx := range txs {
205		err := l2DB.AddTxTest(tx)
206		assert.NoError(t, err)
207		if tx.State == common.PoolL2TxStateForging && randomizer%2 == 0 {
208			randomizer++
209			doneForgingTxIDs = append(doneForgingTxIDs, tx.TxID)
210		}
211	}
212	// Start forging txs
213	err := l2DB.DoneForging(doneForgingTxIDs, fakeBatchNum)
214	assert.NoError(t, err)
215	// Fetch txs and check that they've been updated correctly
216	for _, id := range doneForgingTxIDs {
217		fetchedTx, err := l2DB.GetTx(id)
218		assert.NoError(t, err)
219		assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State)
220		assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
221	}
222}
223*/
224
225/*
226		TODO: update with til
227func TestInvalidate(t *testing.T) {
228	// Generate txs
229	const nInserts = 60
230	const fakeBatchNum common.BatchNum = 33
231	test.WipeDB(l2DB.DB())
232	txs := test.GenPoolTxs(nInserts, tokens)
233	var invalidTxIDs []common.TxID
234	randomizer := 0
235	// Add txs to DB
236	for _, tx := range txs {
237		err := l2DB.AddTxTest(tx)
238		assert.NoError(t, err)
239		if tx.State != common.PoolL2TxStateInvalid && randomizer%2 == 0 {
240			randomizer++
241			invalidTxIDs = append(invalidTxIDs, tx.TxID)
242		}
243	}
244	// Start forging txs
245	err := l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
246	assert.NoError(t, err)
247	// Fetch txs and check that they've been updated correctly
248	for _, id := range invalidTxIDs {
249		fetchedTx, err := l2DB.GetTx(id)
250		assert.NoError(t, err)
251		assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
252		assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
253	}
254}
255*/
256
257/*
258
259		TODO: update with til
260
261
262func TestCheckNonces(t *testing.T) {
263	// Generate txs
264	const nInserts = 60
265	const fakeBatchNum common.BatchNum = 33
266	test.WipeDB(l2DB.DB())
267	txs := test.GenPoolTxs(nInserts, tokens)
268	var invalidTxIDs []common.TxID
269	// Generate accounts
270	const nAccoutns = 2
271	const currentNonce = 2
272	accs := []common.Account{}
273	for i := 0; i < nAccoutns; i++ {
274		accs = append(accs, common.Account{
275			Idx:   common.Idx(i),
276			Nonce: currentNonce,
277		})
278	}
279	// Add txs to DB
280	for i := 0; i < len(txs); i++ {
281		if txs[i].State != common.PoolL2TxStateInvalid {
282			if i%2 == 0 { // Ensure transaction will be marked as invalid due to old nonce
283				txs[i].Nonce = accs[i%len(accs)].Nonce
284				txs[i].FromIdx = accs[i%len(accs)].Idx
285				invalidTxIDs = append(invalidTxIDs, txs[i].TxID)
286			} else { // Ensure transaction will NOT be marked as invalid due to old nonce
287				txs[i].Nonce = currentNonce + 1
288			}
289		}
290		err := l2DB.AddTxTest(txs[i])
291		assert.NoError(t, err)
292	}
293	// Start forging txs
294	err := l2DB.InvalidateTxs(invalidTxIDs, fakeBatchNum)
295	assert.NoError(t, err)
296	// Fetch txs and check that they've been updated correctly
297	for _, id := range invalidTxIDs {
298		fetchedTx, err := l2DB.GetTx(id)
299		assert.NoError(t, err)
300		assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
301		assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
302	}
303}
304*/
305
306func TestReorg(t *testing.T) {
307	// Generate txs
308	const nInserts = 20
309	const lastValidBatch common.BatchNum = 20
310	const reorgBatch common.BatchNum = lastValidBatch + 1
311	test.WipeDB(l2DB.DB())
312	// TODO: update with til
313	txs := test.GenPoolTxs(nInserts, tokens)
314	// Add txs to the DB
315	reorgedTxIDs := []common.TxID{}
316	nonReorgedTxIDs := []common.TxID{}
317	for i := 0; i < len(txs); i++ {
318		err := l2DB.AddTxTest(txs[i])
319		assert.NoError(t, err)
320		var batchNum common.BatchNum
321		if txs[i].State == common.PoolL2TxStateForged || txs[i].State == common.PoolL2TxStateInvalid {
322			reorgedTxIDs = append(reorgedTxIDs, txs[i].TxID)
323			batchNum = reorgBatch
324		} else {
325			nonReorgedTxIDs = append(nonReorgedTxIDs, txs[i].TxID)
326			batchNum = lastValidBatch
327		}
328		_, err = l2DB.db.Exec(
329			"UPDATE tx_pool SET batch_num = $1 WHERE tx_id = $2;",
330			batchNum, txs[i].TxID,
331		)
332		assert.NoError(t, err)
333	}
334	err := l2DB.Reorg(lastValidBatch)
335	assert.NoError(t, err)
336	for _, id := range reorgedTxIDs {
337		tx, err := l2DB.GetTxAPI(id)
338		assert.NoError(t, err)
339		assert.Nil(t, tx.BatchNum)
340		assert.Equal(t, common.PoolL2TxStatePending, tx.State)
341	}
342	for _, id := range nonReorgedTxIDs {
343		fetchedTx, err := l2DB.GetTxAPI(id)
344		assert.NoError(t, err)
345		assert.Equal(t, lastValidBatch, *fetchedTx.BatchNum)
346	}
347}
348
349func TestPurge(t *testing.T) {
350	/*
351
352		TODO: update with til
353
354		WARNING: this should be fixed once transaktio is ready
355		// Generate txs
356		nInserts := l2DB.maxTxs + 20
357		test.WipeDB(l2DB.DB())
358		txs := test.GenPoolTxs(int(nInserts), tokens)
359		deletedIDs := []common.TxID{}
360		keepedIDs := []common.TxID{}
361		const toDeleteBatchNum common.BatchNum = 30
362		safeBatchNum := toDeleteBatchNum + l2DB.safetyPeriod + 1
363		// Add txs to the DB
364		for i := 0; i < int(l2DB.maxTxs); i++ {
365			var batchNum common.BatchNum
366			if i%2 == 0 { // keep tx
367				batchNum = safeBatchNum
368				keepedIDs = append(keepedIDs, txs[i].TxID)
369			} else { // delete after safety period
370				batchNum = toDeleteBatchNum
371				if i%3 == 0 {
372					txs[i].State = common.PoolL2TxStateForged
373				} else {
374					txs[i].State = common.PoolL2TxStateInvalid
375				}
376				deletedIDs = append(deletedIDs, txs[i].TxID)
377			}
378			err := l2DB.AddTxTest(txs[i])
379			assert.NoError(t, err)
380			// Set batchNum
381			_, err = l2DB.db.Exec(
382				"UPDATE tx_pool SET batch_num = $1 WHERE tx_id = $2;",
383				batchNum, txs[i].TxID,
384			)
385			assert.NoError(t, err)
386		}
387		for i := int(l2DB.maxTxs); i < len(txs); i++ {
388			// Delete after TTL
389			deletedIDs = append(deletedIDs, txs[i].TxID)
390			err := l2DB.AddTxTest(txs[i])
391			assert.NoError(t, err)
392			// Set timestamp
393			deleteTimestamp := time.Unix(time.Now().UTC().Unix()-int64(l2DB.ttl.Seconds()+float64(4*time.Second)), 0)
394			_, err = l2DB.db.Exec(
395				"UPDATE tx_pool SET timestamp = $1 WHERE tx_id = $2;",
396				deleteTimestamp, txs[i].TxID,
397			)
398			assert.NoError(t, err)
399		}
400		// Purge txs
401		err := l2DB.Purge(safeBatchNum)
402		assert.NoError(t, err)
403		// Check results
404		for _, id := range deletedIDs {
405			tx, err := l2DB.GetTx(id)
406			if err == nil {
407				log.Debug(tx)
408			}
409			assert.Error(t, err)
410		}
411		for _, id := range keepedIDs {
412			_, err := l2DB.GetTx(id)
413			assert.NoError(t, err)
414		}
415	*/
416}
417
418func TestAuth(t *testing.T) {
419	test.WipeDB(l2DB.DB())
420	const nAuths = 5
421	// Generate authorizations
422	auths := test.GenAuths(nAuths)
423	for i := 0; i < len(auths); i++ {
424		// Add to the DB
425		err := l2DB.AddAccountCreationAuth(auths[i])
426		assert.NoError(t, err)
427		// Fetch from DB
428		auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
429		assert.NoError(t, err)
430		// Check fetched vs generated
431		assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
432		assert.Equal(t, auths[i].BJJ, auth.BJJ)
433		assert.Equal(t, auths[i].Signature, auth.Signature)
434		assert.Equal(t, auths[i].Timestamp.Unix(), auths[i].Timestamp.Unix())
435		nameZone, offset := auths[i].Timestamp.Zone()
436		assert.Equal(t, "UTC", nameZone)
437		assert.Equal(t, 0, offset)
438	}
439}