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.

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