You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.3 KiB

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