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.

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