arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/db/l2db/l2db_test.go
db/l2db/l2db_test.goRaw
  1package l2db
  2
  3import (
  4	"fmt"
  5	"math/big"
  6	"os"
  7	"strconv"
  8	"testing"
  9	"time"
 10
 11	eth "github.com/ethereum/go-ethereum/common"
 12	"github.com/hermeznetwork/hermez-node/common"
 13	"github.com/iden3/go-iden3-crypto/babyjub"
 14	"github.com/stretchr/testify/assert"
 15)
 16
 17var l2DB *L2DB
 18
 19// In order to run the test you need to run a Posgres DB with
 20// a database named "l2" that is accessible by
 21// user: "hermez"
 22// pass: set it using the env var POSTGRES_PASS
 23// This can be achieved by running: POSTGRES_PASS=your_strong_pass && sudo docker run --rm --name hermez-db-test -p 5432:5432 -e POSTGRES_DB=history -e POSTGRES_USER=hermez -e POSTGRES_PASSWORD=$POSTGRES_PASS -d postgres && sleep 2s && sudo docker exec -it hermez-db-test psql -a history -U hermez -c "CREATE DATABASE l2;"
 24// After running the test you can stop the container by running: sudo docker kill hermez-ydb-test
 25// If you already did that for the HistoryDB you don't have to do it again
 26func TestMain(m *testing.M) {
 27	// init DB
 28	var err error
 29	pass := os.Getenv("POSTGRES_PASS")
 30	l2DB, err = NewL2DB(5432, "localhost", "hermez", pass, "l2", 10, 512, 24*time.Hour)
 31	if err != nil {
 32		panic(err)
 33	}
 34	// Run tests
 35	result := m.Run()
 36	// Close DB
 37	if err := l2DB.Close(); err != nil {
 38		fmt.Println("Error closing the history DB:", err)
 39	}
 40	os.Exit(result)
 41}
 42
 43func TestAddTx(t *testing.T) {
 44	const nInserts = 20
 45	cleanDB()
 46	txs := genTxs(nInserts)
 47	for _, tx := range txs {
 48		err := l2DB.AddTx(tx)
 49		assert.NoError(t, err)
 50		fetchedTx, err := l2DB.GetTx(tx.TxID)
 51		assert.NoError(t, err)
 52		assert.Equal(t, tx.Timestamp.Unix(), fetchedTx.Timestamp.Unix())
 53		tx.Timestamp = fetchedTx.Timestamp
 54		assert.Equal(t, tx.AbsoluteFeeUpdate.Unix(), fetchedTx.AbsoluteFeeUpdate.Unix())
 55		tx.Timestamp = fetchedTx.Timestamp
 56		tx.AbsoluteFeeUpdate = fetchedTx.AbsoluteFeeUpdate
 57		assert.Equal(t, tx, fetchedTx)
 58	}
 59}
 60
 61func BenchmarkAddTx(b *testing.B) {
 62	const nInserts = 20
 63	cleanDB()
 64	txs := genTxs(nInserts)
 65	now := time.Now()
 66	for _, tx := range txs {
 67		_ = l2DB.AddTx(tx)
 68	}
 69	elapsedTime := time.Since(now)
 70	fmt.Println("Time to insert 2048 txs:", elapsedTime)
 71}
 72
 73func TestGetPending(t *testing.T) {
 74	const nInserts = 20
 75	cleanDB()
 76	txs := genTxs(nInserts)
 77	var pendingTxs []*common.PoolL2Tx
 78	for _, tx := range txs {
 79		err := l2DB.AddTx(tx)
 80		assert.NoError(t, err)
 81		if tx.State == common.PoolL2TxStatePending {
 82			pendingTxs = append(pendingTxs, tx)
 83		}
 84	}
 85	fetchedTxs, err := l2DB.GetPendingTxs()
 86	assert.NoError(t, err)
 87	assert.Equal(t, len(pendingTxs), len(fetchedTxs))
 88	for i, fetchedTx := range fetchedTxs {
 89		assert.Equal(t, pendingTxs[i].Timestamp.Unix(), fetchedTx.Timestamp.Unix())
 90		pendingTxs[i].Timestamp = fetchedTx.Timestamp
 91		assert.Equal(t, pendingTxs[i].AbsoluteFeeUpdate.Unix(), fetchedTx.AbsoluteFeeUpdate.Unix())
 92		pendingTxs[i].AbsoluteFeeUpdate = fetchedTx.AbsoluteFeeUpdate
 93		assert.Equal(t, pendingTxs[i], fetchedTx)
 94	}
 95}
 96
 97func TestStartForging(t *testing.T) {
 98	const nInserts = 24
 99	const fakeBlockNum = 33
100	cleanDB()
101	txs := genTxs(nInserts)
102	var startForgingTxs []*common.PoolL2Tx
103	var startForgingTxIDs []common.TxID
104	randomizer := 0
105	for _, tx := range txs {
106		err := l2DB.AddTx(tx)
107		assert.NoError(t, err)
108		if tx.State == common.PoolL2TxStatePending && randomizer%2 == 0 {
109			randomizer++
110			startForgingTxs = append(startForgingTxs, tx)
111			startForgingTxIDs = append(startForgingTxIDs, tx.TxID)
112		}
113		if tx.State == common.PoolL2TxStateForging {
114			startForgingTxs = append(startForgingTxs, tx)
115		}
116	}
117	fmt.Println(startForgingTxs) // TODO added print here to avoid lint complaining about startForgingTxs not being used
118	err := l2DB.StartForging(startForgingTxIDs, fakeBlockNum)
119	assert.NoError(t, err)
120	// TODO: Fetch txs and check that they've been updated correctly
121}
122
123func genTxs(n int) []*common.PoolL2Tx {
124	// WARNING: This tx doesn't follow the protocol (signature, txID, ...)
125	// it's just to test getting/setting from/to the DB.
126	// Type and RqTxCompressedData: not initialized because it's not stored
127	// on the DB and add noise when checking results.
128	txs := make([]*common.PoolL2Tx, 0, n)
129	privK := babyjub.NewRandPrivKey()
130	for i := 0; i < n; i++ {
131		var state common.PoolL2TxState
132		if i%4 == 0 {
133			state = common.PoolL2TxStatePending
134		} else if i%4 == 1 {
135			state = common.PoolL2TxStateInvalid
136		} else if i%4 == 2 {
137			state = common.PoolL2TxStateForging
138		} else if i%4 == 3 {
139			state = common.PoolL2TxStateForged
140		}
141		tx := &common.PoolL2Tx{
142			TxID:      common.TxID(common.Hash([]byte(strconv.Itoa(i)))),
143			FromIdx:   47,
144			ToIdx:     96,
145			ToEthAddr: eth.BigToAddress(big.NewInt(234523534)),
146			ToBJJ:     privK.Public(),
147			TokenID:   73,
148			Amount:    big.NewInt(3487762374627846747),
149			Fee:       99,
150			Nonce:     28,
151			State:     state,
152			Signature: privK.SignPoseidon(big.NewInt(674238462)),
153			Timestamp: time.Now().UTC(),
154		}
155		if i%2 == 0 { // Optional parameters: rq
156			tx.RqFromIdx = 893
157			tx.RqToIdx = 334
158			tx.RqToEthAddr = eth.BigToAddress(big.NewInt(239457111187))
159			tx.RqToBJJ = privK.Public()
160			tx.RqTokenID = 222
161			tx.RqAmount = big.NewInt(3487762374627846747)
162			tx.RqFee = 11
163			tx.RqNonce = 78
164		}
165		if i%3 == 0 { // Optional parameters: things that get updated "a posteriori"
166			tx.BatchNum = 489
167			tx.AbsoluteFee = 39.12345
168			tx.AbsoluteFeeUpdate = time.Now().UTC()
169		}
170		txs = append(txs, tx)
171	}
172	return txs
173}
174
175func cleanDB() {
176	if _, err := l2DB.db.Exec("DELETE FROM tx_pool"); err != nil {
177		panic(err)
178	}
179	if _, err := l2DB.db.Exec("DELETE FROM account_creation_auth"); err != nil {
180		panic(err)
181	}
182}