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.

336 lines
8.0 KiB

4 years ago
  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. // TODO(Edu): Document here how HistoryDB is kept consistent
  14. // HistoryDB persist the historic of the rollup
  15. type HistoryDB struct {
  16. db *sqlx.DB
  17. }
  18. // NewHistoryDB initialize the DB
  19. func NewHistoryDB(port int, host, user, password, dbname string) (*HistoryDB, error) {
  20. // Connect to DB
  21. psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
  22. hdb, err := sqlx.Connect("postgres", psqlconn)
  23. if err != nil {
  24. return nil, err
  25. }
  26. // Init meddler
  27. db.InitMeddler()
  28. meddler.Default = meddler.PostgreSQL
  29. // Run DB migrations
  30. migrations := &migrate.PackrMigrationSource{
  31. Box: packr.New("history-migrations", "./migrations"),
  32. }
  33. if _, err := migrate.Exec(hdb.DB, "postgres", migrations, migrate.Up); err != nil {
  34. return nil, err
  35. }
  36. return &HistoryDB{hdb}, nil
  37. }
  38. // AddBlock insert a block into the DB
  39. func (hdb *HistoryDB) AddBlock(block *common.Block) error {
  40. return meddler.Insert(hdb.db, "block", block)
  41. }
  42. // AddBlocks inserts blocks into the DB
  43. func (hdb *HistoryDB) AddBlocks(blocks []common.Block) error {
  44. return db.BulkInsert(
  45. hdb.db,
  46. `INSERT INTO block (
  47. eth_block_num,
  48. timestamp,
  49. hash
  50. ) VALUES %s;`,
  51. blocks[:],
  52. )
  53. }
  54. // GetBlock retrieve a block from the DB, given a block number
  55. func (hdb *HistoryDB) GetBlock(blockNum int64) (*common.Block, error) {
  56. block := &common.Block{}
  57. err := meddler.QueryRow(
  58. hdb.db, block,
  59. "SELECT * FROM block WHERE eth_block_num = $1;", blockNum,
  60. )
  61. return block, err
  62. }
  63. // GetBlocks retrieve blocks from the DB, given a range of block numbers defined by from and to
  64. func (hdb *HistoryDB) GetBlocks(from, to int64) ([]*common.Block, error) {
  65. var blocks []*common.Block
  66. err := meddler.QueryAll(
  67. hdb.db, &blocks,
  68. "SELECT * FROM block WHERE $1 <= eth_block_num AND eth_block_num < $2",
  69. from, to,
  70. )
  71. return blocks, err
  72. }
  73. // GetLastBlock retrieve the block with the highest block number from the DB
  74. func (hdb *HistoryDB) GetLastBlock() (*common.Block, error) {
  75. block := &common.Block{}
  76. err := meddler.QueryRow(
  77. hdb.db, block, "SELECT * FROM block ORDER BY eth_block_num DESC LIMIT 1;",
  78. )
  79. return block, err
  80. }
  81. // AddBatches insert Bids into the DB
  82. func (hdb *HistoryDB) AddBatches(batches []common.Batch) error {
  83. return db.BulkInsert(
  84. hdb.db,
  85. `INSERT INTO batch (
  86. batch_num,
  87. eth_block_num,
  88. forger_addr,
  89. fees_collected,
  90. state_root,
  91. num_accounts,
  92. exit_root,
  93. forge_l1_txs_num,
  94. slot_num
  95. ) VALUES %s;`,
  96. batches[:],
  97. )
  98. }
  99. // GetBatches retrieve batches from the DB, given a range of batch numbers defined by from and to
  100. func (hdb *HistoryDB) GetBatches(from, to common.BatchNum) ([]*common.Batch, error) {
  101. var batches []*common.Batch
  102. err := meddler.QueryAll(
  103. hdb.db, &batches,
  104. "SELECT * FROM batch WHERE $1 <= batch_num AND batch_num < $2",
  105. from, to,
  106. )
  107. return batches, err
  108. }
  109. // GetLastBatchNum returns the BatchNum of the latest forged batch
  110. func (hdb *HistoryDB) GetLastBatchNum() (common.BatchNum, error) {
  111. row := hdb.db.QueryRow("SELECT batch_num FROM batch ORDER BY batch_num DESC LIMIT 1;")
  112. var batchNum common.BatchNum
  113. return batchNum, row.Scan(&batchNum)
  114. }
  115. // GetLastL1TxsNum returns the greatest ForgeL1TxsNum in the DB. If there's no
  116. // batch in the DB (nil, nil) is returned.
  117. func (hdb *HistoryDB) GetLastL1TxsNum() (*int64, error) {
  118. row := hdb.db.QueryRow("SELECT MAX(forge_l1_txs_num) FROM batch;")
  119. lastL1TxsNum := new(int64)
  120. return lastL1TxsNum, row.Scan(&lastL1TxsNum)
  121. }
  122. // Reorg deletes all the information that was added into the DB after the lastValidBlock
  123. func (hdb *HistoryDB) Reorg(lastValidBlock int64) error {
  124. _, err := hdb.db.Exec("DELETE FROM block WHERE eth_block_num > $1;", lastValidBlock)
  125. return err
  126. }
  127. // SyncRollup stores all the data that can be changed / added on a block in the Rollup SC
  128. func (hdb *HistoryDB) SyncRollup(
  129. blockNum uint64,
  130. l1txs []common.L1Tx,
  131. l2txs []common.L2Tx,
  132. registeredAccounts []common.Account,
  133. exitTree common.ExitInfo,
  134. withdrawals common.ExitInfo,
  135. registeredTokens []common.Token,
  136. batches []common.Batch,
  137. vars *common.RollupVars,
  138. ) error {
  139. // TODO: make all in a single DB commit
  140. if err := hdb.AddBatches(batches); err != nil {
  141. return err
  142. }
  143. return nil
  144. }
  145. // SyncPoD stores all the data that can be changed / added on a block in the PoD SC
  146. func (hdb *HistoryDB) SyncPoD(
  147. blockNum uint64,
  148. bids []common.Bid,
  149. coordinators []common.Coordinator,
  150. vars *common.AuctionVars,
  151. ) error {
  152. return nil
  153. }
  154. // addBids insert Bids into the DB
  155. func (hdb *HistoryDB) addBids(bids []common.Bid) error {
  156. // TODO: check the coordinator info
  157. return db.BulkInsert(
  158. hdb.db,
  159. "INSERT INTO bid (slot_num, forger_addr, bid_value, eth_block_num) VALUES %s",
  160. bids[:],
  161. )
  162. }
  163. // GetBids return the bids
  164. func (hdb *HistoryDB) GetBids() ([]*common.Bid, error) {
  165. var bids []*common.Bid
  166. err := meddler.QueryAll(
  167. hdb.db, &bids,
  168. "SELECT * FROM bid;",
  169. )
  170. return bids, err
  171. }
  172. // AddToken insert a token into the DB
  173. func (hdb *HistoryDB) AddToken(token *common.Token) error {
  174. return meddler.Insert(hdb.db, "token", token)
  175. }
  176. // AddTokens insert tokens into the DB
  177. func (hdb *HistoryDB) AddTokens(tokens []common.Token) error {
  178. return db.BulkInsert(
  179. hdb.db,
  180. `INSERT INTO token (
  181. token_id,
  182. eth_block_num,
  183. eth_addr,
  184. name,
  185. symbol,
  186. decimals,
  187. usd,
  188. usd_update
  189. ) VALUES %s;`,
  190. tokens[:],
  191. )
  192. }
  193. // UpdateTokenValue updates the USD value of a token
  194. func (hdb *HistoryDB) UpdateTokenValue(tokenID common.TokenID, value float64) error {
  195. _, err := hdb.db.Exec(
  196. "UPDATE token SET usd = $1 WHERE token_id = $2;",
  197. value, tokenID,
  198. )
  199. return err
  200. }
  201. // GetTokens returns a list of tokens from the DB
  202. func (hdb *HistoryDB) GetTokens() ([]*common.Token, error) {
  203. var tokens []*common.Token
  204. err := meddler.QueryAll(
  205. hdb.db, &tokens,
  206. "SELECT * FROM token ORDER BY token_id;",
  207. )
  208. return tokens, err
  209. }
  210. // AddAccounts insert accounts into the DB
  211. func (hdb *HistoryDB) AddAccounts(accounts []common.Account) error {
  212. return db.BulkInsert(
  213. hdb.db,
  214. `INSERT INTO account (
  215. idx,
  216. token_id,
  217. batch_num,
  218. bjj,
  219. eth_addr
  220. ) VALUES %s;`,
  221. accounts[:],
  222. )
  223. }
  224. // GetAccounts returns a list of accounts from the DB
  225. func (hdb *HistoryDB) GetAccounts() ([]*common.Account, error) {
  226. var accs []*common.Account
  227. err := meddler.QueryAll(
  228. hdb.db, &accs,
  229. "SELECT * FROM account ORDER BY idx;",
  230. )
  231. return accs, err
  232. }
  233. // AddL1Txs inserts L1 txs to the DB
  234. func (hdb *HistoryDB) AddL1Txs(l1txs []common.L1Tx) error {
  235. txs := []common.Tx{}
  236. for _, tx := range l1txs {
  237. txs = append(txs, *tx.Tx())
  238. }
  239. return hdb.AddTxs(txs)
  240. }
  241. // AddL2Txs inserts L2 txs to the DB
  242. func (hdb *HistoryDB) AddL2Txs(l2txs []common.L2Tx) error {
  243. txs := []common.Tx{}
  244. for _, tx := range l2txs {
  245. txs = append(txs, *tx.Tx())
  246. }
  247. return hdb.AddTxs(txs)
  248. }
  249. // AddTxs insert L1 txs into the DB
  250. func (hdb *HistoryDB) AddTxs(txs []common.Tx) error {
  251. return db.BulkInsert(
  252. hdb.db,
  253. `INSERT INTO tx (
  254. is_l1,
  255. id,
  256. type,
  257. position,
  258. from_idx,
  259. to_idx,
  260. amount,
  261. amount_f,
  262. token_id,
  263. amount_usd,
  264. batch_num,
  265. eth_block_num,
  266. to_forge_l1_txs_num,
  267. user_origin,
  268. from_eth_addr,
  269. from_bjj,
  270. load_amount,
  271. load_amount_f,
  272. load_amount_usd,
  273. fee,
  274. fee_usd,
  275. nonce
  276. ) VALUES %s;`,
  277. txs[:],
  278. )
  279. }
  280. // GetTxs returns a list of txs from the DB
  281. func (hdb *HistoryDB) GetTxs() ([]*common.Tx, error) {
  282. var txs []*common.Tx
  283. err := meddler.QueryAll(
  284. hdb.db, &txs,
  285. `SELECT * FROM tx
  286. ORDER BY (batch_num, position) ASC`,
  287. )
  288. return txs, err
  289. }
  290. // GetTx returns a tx from the DB
  291. func (hdb *HistoryDB) GetTx(txID common.TxID) (*common.Tx, error) {
  292. tx := new(common.Tx)
  293. return tx, meddler.QueryRow(
  294. hdb.db, tx,
  295. "SELECT * FROM tx WHERE id = $1;",
  296. txID,
  297. )
  298. }
  299. // Close frees the resources used by HistoryDB
  300. func (hdb *HistoryDB) Close() error {
  301. return hdb.db.Close()
  302. }