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.

183 lines
5.0 KiB

  1. package historydb
  2. import (
  3. "fmt"
  4. "github.com/gobuffalo/packr/v2"
  5. "github.com/hermeznetwork/hermez-node/common"
  6. "github.com/hermeznetwork/hermez-node/db"
  7. "github.com/jmoiron/sqlx"
  8. //nolint:errcheck // driver for postgres DB
  9. _ "github.com/lib/pq"
  10. migrate "github.com/rubenv/sql-migrate"
  11. "github.com/russross/meddler"
  12. )
  13. // HistoryDB persist the historic of the rollup
  14. type HistoryDB struct {
  15. db *sqlx.DB
  16. }
  17. // NewHistoryDB initialize the DB
  18. func NewHistoryDB(port int, host, user, password, dbname string) (*HistoryDB, error) {
  19. // Connect to DB
  20. psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
  21. hdb, err := sqlx.Connect("postgres", psqlconn)
  22. if err != nil {
  23. return nil, err
  24. }
  25. // Init meddler
  26. db.InitMeddler()
  27. meddler.Default = meddler.PostgreSQL
  28. // Run DB migrations
  29. migrations := &migrate.PackrMigrationSource{
  30. Box: packr.New("history-migrations", "./migrations"),
  31. }
  32. if _, err := migrate.Exec(hdb.DB, "postgres", migrations, migrate.Up); err != nil {
  33. return nil, err
  34. }
  35. return &HistoryDB{hdb}, nil
  36. }
  37. // AddBlock insert a block into the DB
  38. func (hdb *HistoryDB) AddBlock(block *common.Block) error {
  39. return meddler.Insert(hdb.db, "block", block)
  40. }
  41. // GetBlock retrieve a block from the DB, given a block number
  42. func (hdb *HistoryDB) GetBlock(blockNum int64) (*common.Block, error) {
  43. block := &common.Block{}
  44. err := meddler.QueryRow(
  45. hdb.db, block,
  46. "SELECT * FROM block WHERE eth_block_num = $1;", blockNum,
  47. )
  48. return block, err
  49. }
  50. // GetBlocks retrieve blocks from the DB, given a range of block numbers defined by from and to
  51. func (hdb *HistoryDB) GetBlocks(from, to int64) ([]*common.Block, error) {
  52. var blocks []*common.Block
  53. err := meddler.QueryAll(
  54. hdb.db, &blocks,
  55. "SELECT * FROM block WHERE $1 <= eth_block_num AND eth_block_num < $2",
  56. from, to,
  57. )
  58. return blocks, err
  59. }
  60. // GetLastBlock retrieve the block with the highest block number from the DB
  61. func (hdb *HistoryDB) GetLastBlock() (*common.Block, error) {
  62. block := &common.Block{}
  63. err := meddler.QueryRow(
  64. hdb.db, block, "SELECT * FROM block ORDER BY eth_block_num DESC LIMIT 1;",
  65. )
  66. return block, err
  67. }
  68. // addBatches insert Bids into the DB
  69. func (hdb *HistoryDB) addBatches(batches []common.Batch) error {
  70. return db.BulkInsert(
  71. hdb.db,
  72. `INSERT INTO batch (
  73. batch_num,
  74. eth_block_num,
  75. forger_addr,
  76. fees_collected,
  77. state_root,
  78. num_accounts,
  79. exit_root,
  80. forge_l1_txs_num,
  81. slot_num
  82. ) VALUES %s;`,
  83. batches[:],
  84. )
  85. }
  86. // GetBatches retrieve batches from the DB, given a range of batch numbers defined by from and to
  87. func (hdb *HistoryDB) GetBatches(from, to common.BatchNum) ([]*common.Batch, error) {
  88. var batches []*common.Batch
  89. err := meddler.QueryAll(
  90. hdb.db, &batches,
  91. "SELECT * FROM batch WHERE $1 <= batch_num AND batch_num < $2",
  92. from, to,
  93. )
  94. return batches, err
  95. }
  96. // GetLastBatchNum returns the BatchNum of the latest forged batch
  97. func (hdb *HistoryDB) GetLastBatchNum() (common.BatchNum, error) {
  98. row := hdb.db.QueryRow("SELECT batch_num FROM batch ORDER BY batch_num DESC LIMIT 1;")
  99. var batchNum common.BatchNum
  100. return batchNum, row.Scan(&batchNum)
  101. }
  102. // GetLastL1TxsNum returns the greatest ForgeL1TxsNum in the DB
  103. func (hdb *HistoryDB) GetLastL1TxsNum() (uint32, error) {
  104. row := hdb.db.QueryRow("SELECT MAX(forge_l1_txs_num) FROM batch;")
  105. var lastL1TxsNum uint32
  106. return lastL1TxsNum, row.Scan(&lastL1TxsNum)
  107. }
  108. // Reorg deletes all the information that was added into the DB after the lastValidBlock
  109. func (hdb *HistoryDB) Reorg(lastValidBlock int64) error {
  110. _, err := hdb.db.Exec("DELETE FROM block WHERE eth_block_num > $1;", lastValidBlock)
  111. return err
  112. }
  113. // SyncRollup stores all the data that can be changed / added on a block in the Rollup SC
  114. func (hdb *HistoryDB) SyncRollup(
  115. blockNum int64,
  116. l1txs []common.L1Tx,
  117. l2txs []common.L2Tx,
  118. registeredAccounts []common.Account,
  119. exitTree common.ExitInfo,
  120. withdrawals common.ExitInfo,
  121. registeredTokens []common.Token,
  122. batches []common.Batch,
  123. vars *common.RollupVars,
  124. ) error {
  125. // TODO: make all in a single DB commit
  126. if err := hdb.addBatches(batches); err != nil {
  127. return err
  128. }
  129. return nil
  130. }
  131. // SyncPoD stores all the data that can be changed / added on a block in the PoD SC
  132. func (hdb *HistoryDB) SyncPoD(
  133. blockNum int64,
  134. bids []common.Bid,
  135. coordinators []common.Coordinator,
  136. vars *common.AuctionVars,
  137. ) error {
  138. return nil
  139. }
  140. // addBids insert Bids into the DB
  141. func (hdb *HistoryDB) addBids(bids []common.Bid) error {
  142. // TODO: check the coordinator info
  143. return db.BulkInsert(
  144. hdb.db,
  145. "INSERT INTO bid (slot_num, forger_addr, bid_value, eth_block_num) VALUES %s",
  146. bids[:],
  147. )
  148. }
  149. // GetBidsBySlot return the bids for a specific slot
  150. func (hdb *HistoryDB) GetBidsBySlot(slotNum common.SlotNum) ([]*common.Bid, error) {
  151. var bids []*common.Bid
  152. err := meddler.QueryAll(
  153. hdb.db, &bids,
  154. "SELECT * FROM bid WHERE $1 = slot_num;",
  155. slotNum,
  156. )
  157. return bids, err
  158. }
  159. // Close frees the resources used by HistoryDB
  160. func (hdb *HistoryDB) Close() error {
  161. return hdb.db.Close()
  162. }