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.

173 lines
5.5 KiB

  1. package l2db
  2. import (
  3. "fmt"
  4. "strconv"
  5. "time"
  6. eth "github.com/ethereum/go-ethereum/common"
  7. "github.com/gobuffalo/packr/v2"
  8. "github.com/hermeznetwork/hermez-node/common"
  9. "github.com/hermeznetwork/hermez-node/db"
  10. "github.com/jmoiron/sqlx"
  11. _ "github.com/lib/pq" // driver for postgres DB
  12. migrate "github.com/rubenv/sql-migrate"
  13. "github.com/russross/meddler"
  14. )
  15. // L2DB stores L2 txs and authorization registers received by the coordinator and keeps them until they are no longer relevant
  16. // due to them being forged or invalid after a safety period
  17. type L2DB struct {
  18. db *sqlx.DB
  19. safetyPeriod uint16
  20. ttl time.Duration
  21. maxTxs uint32
  22. }
  23. // NewL2DB creates a L2DB.
  24. // More info on how to set dbDialect and dbArgs here: http://gorm.io/docs/connecting_to_the_database.html
  25. // safetyPeriod is the ammount of blockchain blocks that must be waited before deleting anything (to avoid reorg problems).
  26. // maxTxs indicates the desired maximum amount of txs stored on the L2DB.
  27. // TTL indicates the maximum amount of time that a tx can be in the L2DB
  28. // (to prevent tx that won't ever be forged to stay there, will be used if maxTxs is exceeded).
  29. // autoPurgePeriod will be used as delay between calls to Purge. If the value is 0, it will be disabled.
  30. func NewL2DB(
  31. port int, host, user, password, dbname string,
  32. safetyPeriod uint16,
  33. maxTxs uint32,
  34. TTL time.Duration,
  35. ) (*L2DB, error) {
  36. // init meddler
  37. db.InitMeddler()
  38. meddler.Default = meddler.PostgreSQL
  39. // Stablish DB connection
  40. psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
  41. db, err := sqlx.Connect("postgres", psqlconn)
  42. if err != nil {
  43. return nil, err
  44. }
  45. // Run DB migrations
  46. migrations := &migrate.PackrMigrationSource{
  47. Box: packr.New("history-migrations", "./migrations"),
  48. }
  49. if _, err := migrate.Exec(db.DB, "postgres", migrations, migrate.Up); err != nil {
  50. return nil, err
  51. }
  52. return &L2DB{
  53. db: db,
  54. safetyPeriod: safetyPeriod,
  55. ttl: TTL,
  56. maxTxs: maxTxs,
  57. }, nil
  58. }
  59. // AddTx inserts a tx into the L2DB
  60. func (l2db *L2DB) AddTx(tx *common.PoolL2Tx) error {
  61. return meddler.Insert(l2db.db, "tx_pool", tx)
  62. }
  63. // AddAccountCreationAuth inserts an account creation authorization into the DB
  64. func (l2db *L2DB) AddAccountCreationAuth(auth *common.AccountCreationAuth) error {
  65. // TODO: impl
  66. return nil
  67. }
  68. // GetTx return the specified Tx
  69. func (l2db *L2DB) GetTx(txID common.TxID) (*common.PoolL2Tx, error) {
  70. tx := new(common.PoolL2Tx)
  71. return tx, meddler.QueryRow(
  72. l2db.db, tx,
  73. "SELECT * FROM tx_pool WHERE tx_id = $1;",
  74. txID,
  75. )
  76. }
  77. // GetPendingTxs return all the pending txs of the L2DB
  78. func (l2db *L2DB) GetPendingTxs() ([]*common.PoolL2Tx, error) {
  79. var txs []*common.PoolL2Tx
  80. err := meddler.QueryAll(
  81. l2db.db, &txs,
  82. "SELECT * FROM tx_pool WHERE state = $1",
  83. common.PoolL2TxStatePending,
  84. )
  85. return txs, err
  86. }
  87. // GetAccountCreationAuth return the authorization to make registers of an Ethereum address
  88. func (l2db *L2DB) GetAccountCreationAuth(ethAddr eth.Address) (*common.AccountCreationAuth, error) {
  89. // TODO: impl
  90. return nil, nil
  91. }
  92. // StartForging updates the state of the transactions that will begin the forging process.
  93. // The state of the txs referenced by txIDs will be changed from Pending -> Forging
  94. func (l2db *L2DB) StartForging(txIDs []common.TxID, batchNum common.BatchNum) error {
  95. query, args, err := sqlx.In(
  96. `UPDATE tx_pool
  97. SET state = ?, batch_num = ?
  98. WHERE state = ? AND tx_id IN (?);`,
  99. string(common.PoolL2TxStateForging),
  100. strconv.Itoa(int(batchNum)),
  101. string(common.PoolL2TxStatePending),
  102. txIDs,
  103. )
  104. if err != nil {
  105. return err
  106. }
  107. query = l2db.db.Rebind(query)
  108. _, err = l2db.db.Exec(query, args...)
  109. return err
  110. }
  111. // DoneForging updates the state of the transactions that have been forged
  112. // so the state of the txs referenced by txIDs will be changed from Forging -> Forged
  113. func (l2db *L2DB) DoneForging(txIDs []common.TxID) error {
  114. // TODO: impl
  115. return nil
  116. }
  117. // InvalidateTxs updates the state of the transactions that are invalid.
  118. // The state of the txs referenced by txIDs will be changed from * -> Invalid
  119. func (l2db *L2DB) InvalidateTxs(txIDs []common.TxID) error {
  120. return nil
  121. }
  122. // CheckNonces invalidate txs with nonces that are smaller than their respective accounts nonces.
  123. // The state of the affected txs will be changed from Pending -> Invalid
  124. func (l2db *L2DB) CheckNonces(updatedAccounts []common.Account) error {
  125. // TODO: impl
  126. return nil
  127. }
  128. // GetTxsByAbsoluteFeeUpdate return the txs that have an AbsoluteFee updated before olderThan
  129. func (l2db *L2DB) GetTxsByAbsoluteFeeUpdate(olderThan time.Time) ([]*common.PoolL2Tx, error) {
  130. // TODO: impl
  131. return nil, nil
  132. }
  133. // UpdateTxs update existing txs from the pool (TxID must exist)
  134. func (l2db *L2DB) UpdateTxs(txs []*common.PoolL2Tx) error {
  135. // TODO: impl
  136. return nil
  137. }
  138. // Reorg updates the state of txs that were updated in a batch that has been discarted due to a blockchian reorg.
  139. // The state of the affected txs can change form Forged -> Pending or from Invalid -> Pending
  140. func (l2db *L2DB) Reorg(lastValidBatch common.BatchNum) error {
  141. // TODO: impl
  142. return nil
  143. }
  144. // Purge deletes transactions that have been forged or marked as invalid for longer than the safety period
  145. // it also deletes txs that has been in the L2DB for longer than the ttl if maxTxs has been exceeded
  146. func (l2db *L2DB) Purge() error {
  147. // TODO: impl
  148. return nil
  149. }
  150. // Close frees the resources used by the L2DB
  151. func (l2db *L2DB) Close() error {
  152. return l2db.db.Close()
  153. }