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.

686 lines
19 KiB

  1. package historydb
  2. import (
  3. "database/sql"
  4. "errors"
  5. "fmt"
  6. "math/big"
  7. ethCommon "github.com/ethereum/go-ethereum/common"
  8. "github.com/hermeznetwork/hermez-node/common"
  9. "github.com/hermeznetwork/hermez-node/db"
  10. "github.com/hermeznetwork/hermez-node/log"
  11. "github.com/iden3/go-iden3-crypto/babyjub"
  12. "github.com/jmoiron/sqlx"
  13. //nolint:errcheck // driver for postgres DB
  14. _ "github.com/lib/pq"
  15. "github.com/russross/meddler"
  16. )
  17. // TODO(Edu): Document here how HistoryDB is kept consistent
  18. // HistoryDB persist the historic of the rollup
  19. type HistoryDB struct {
  20. db *sqlx.DB
  21. }
  22. // BlockData contains the information of a Block
  23. type BlockData struct {
  24. Block *common.Block
  25. // Rollup
  26. // L1UserTxs that were submitted in the block
  27. L1UserTxs []common.L1Tx
  28. Batches []BatchData
  29. RegisteredTokens []common.Token
  30. RollupVars *common.RollupVars
  31. // Auction
  32. Bids []common.Bid
  33. Coordinators []common.Coordinator
  34. AuctionVars *common.AuctionVars
  35. WithdrawDelayerVars *common.WithdrawDelayerVars
  36. // TODO: enable when common.WithdrawalDelayerVars is Merged from Synchronizer PR
  37. // WithdrawalDelayerVars *common.WithdrawalDelayerVars
  38. }
  39. // BatchData contains the information of a Batch
  40. type BatchData struct {
  41. // L1UserTxs that were forged in the batch
  42. L1Batch bool // TODO: Remove once Batch.ForgeL1TxsNum is a pointer
  43. L1UserTxs []common.L1Tx
  44. L1CoordinatorTxs []common.L1Tx
  45. L2Txs []common.L2Tx
  46. CreatedAccounts []common.Account
  47. ExitTree []common.ExitInfo
  48. Batch *common.Batch
  49. }
  50. // NewBatchData creates an empty BatchData with the slices initialized.
  51. func NewBatchData() *BatchData {
  52. return &BatchData{
  53. L1Batch: false,
  54. L1UserTxs: make([]common.L1Tx, 0),
  55. L1CoordinatorTxs: make([]common.L1Tx, 0),
  56. L2Txs: make([]common.L2Tx, 0),
  57. CreatedAccounts: make([]common.Account, 0),
  58. ExitTree: make([]common.ExitInfo, 0),
  59. Batch: &common.Batch{},
  60. }
  61. }
  62. // NewHistoryDB initialize the DB
  63. func NewHistoryDB(db *sqlx.DB) *HistoryDB {
  64. return &HistoryDB{db: db}
  65. }
  66. // AddBlock insert a block into the DB
  67. func (hdb *HistoryDB) AddBlock(block *common.Block) error { return hdb.addBlock(hdb.db, block) }
  68. func (hdb *HistoryDB) addBlock(d meddler.DB, block *common.Block) error {
  69. return meddler.Insert(d, "block", block)
  70. }
  71. // AddBlocks inserts blocks into the DB
  72. func (hdb *HistoryDB) AddBlocks(blocks []common.Block) error {
  73. return hdb.addBlocks(hdb.db, blocks)
  74. }
  75. func (hdb *HistoryDB) addBlocks(d meddler.DB, blocks []common.Block) error {
  76. return db.BulkInsert(
  77. d,
  78. `INSERT INTO block (
  79. eth_block_num,
  80. timestamp,
  81. hash
  82. ) VALUES %s;`,
  83. blocks[:],
  84. )
  85. }
  86. // GetBlock retrieve a block from the DB, given a block number
  87. func (hdb *HistoryDB) GetBlock(blockNum int64) (*common.Block, error) {
  88. block := &common.Block{}
  89. err := meddler.QueryRow(
  90. hdb.db, block,
  91. "SELECT * FROM block WHERE eth_block_num = $1;", blockNum,
  92. )
  93. return block, err
  94. }
  95. // GetBlocks retrieve blocks from the DB, given a range of block numbers defined by from and to
  96. func (hdb *HistoryDB) GetBlocks(from, to int64) ([]common.Block, error) {
  97. var blocks []*common.Block
  98. err := meddler.QueryAll(
  99. hdb.db, &blocks,
  100. "SELECT * FROM block WHERE $1 <= eth_block_num AND eth_block_num < $2;",
  101. from, to,
  102. )
  103. return db.SlicePtrsToSlice(blocks).([]common.Block), err
  104. }
  105. // GetLastBlock retrieve the block with the highest block number from the DB
  106. func (hdb *HistoryDB) GetLastBlock() (*common.Block, error) {
  107. block := &common.Block{}
  108. err := meddler.QueryRow(
  109. hdb.db, block, "SELECT * FROM block ORDER BY eth_block_num DESC LIMIT 1;",
  110. )
  111. return block, err
  112. }
  113. // AddBatch insert a Batch into the DB
  114. func (hdb *HistoryDB) AddBatch(batch *common.Batch) error { return hdb.addBatch(hdb.db, batch) }
  115. func (hdb *HistoryDB) addBatch(d meddler.DB, batch *common.Batch) error {
  116. return meddler.Insert(d, "batch", batch)
  117. }
  118. // AddBatches insert Bids into the DB
  119. func (hdb *HistoryDB) AddBatches(batches []common.Batch) error {
  120. return hdb.addBatches(hdb.db, batches)
  121. }
  122. func (hdb *HistoryDB) addBatches(d meddler.DB, batches []common.Batch) error {
  123. // TODO: Calculate and insert total_fees_usd
  124. return db.BulkInsert(
  125. d,
  126. `INSERT INTO batch (
  127. batch_num,
  128. eth_block_num,
  129. forger_addr,
  130. fees_collected,
  131. state_root,
  132. num_accounts,
  133. exit_root,
  134. forge_l1_txs_num,
  135. slot_num
  136. ) VALUES %s;`,
  137. batches[:],
  138. )
  139. }
  140. // GetBatches retrieve batches from the DB, given a range of batch numbers defined by from and to
  141. func (hdb *HistoryDB) GetBatches(from, to common.BatchNum) ([]common.Batch, error) {
  142. var batches []*common.Batch
  143. err := meddler.QueryAll(
  144. hdb.db, &batches,
  145. "SELECT * FROM batch WHERE $1 <= batch_num AND batch_num < $2;",
  146. from, to,
  147. )
  148. return db.SlicePtrsToSlice(batches).([]common.Batch), err
  149. }
  150. // GetLastBatchNum returns the BatchNum of the latest forged batch
  151. func (hdb *HistoryDB) GetLastBatchNum() (common.BatchNum, error) {
  152. row := hdb.db.QueryRow("SELECT batch_num FROM batch ORDER BY batch_num DESC LIMIT 1;")
  153. var batchNum common.BatchNum
  154. return batchNum, row.Scan(&batchNum)
  155. }
  156. // GetLastL1TxsNum returns the greatest ForgeL1TxsNum in the DB. If there's no
  157. // batch in the DB (nil, nil) is returned.
  158. func (hdb *HistoryDB) GetLastL1TxsNum() (*int64, error) {
  159. row := hdb.db.QueryRow("SELECT MAX(forge_l1_txs_num) FROM batch;")
  160. lastL1TxsNum := new(int64)
  161. return lastL1TxsNum, row.Scan(&lastL1TxsNum)
  162. }
  163. // Reorg deletes all the information that was added into the DB after the
  164. // lastValidBlock. If lastValidBlock is negative, all block information is
  165. // deleted.
  166. func (hdb *HistoryDB) Reorg(lastValidBlock int64) error {
  167. var err error
  168. if lastValidBlock < 0 {
  169. _, err = hdb.db.Exec("DELETE FROM block;")
  170. } else {
  171. _, err = hdb.db.Exec("DELETE FROM block WHERE eth_block_num > $1;", lastValidBlock)
  172. }
  173. return err
  174. }
  175. // SyncPoD stores all the data that can be changed / added on a block in the PoD SC
  176. func (hdb *HistoryDB) SyncPoD(
  177. blockNum uint64,
  178. bids []common.Bid,
  179. coordinators []common.Coordinator,
  180. vars *common.AuctionVars,
  181. ) error {
  182. return nil
  183. }
  184. // AddBids insert Bids into the DB
  185. func (hdb *HistoryDB) AddBids(bids []common.Bid) error { return hdb.addBids(hdb.db, bids) }
  186. func (hdb *HistoryDB) addBids(d meddler.DB, bids []common.Bid) error {
  187. // TODO: check the coordinator info
  188. return db.BulkInsert(
  189. d,
  190. "INSERT INTO bid (slot_num, bid_value, eth_block_num, bidder_addr) VALUES %s;",
  191. bids[:],
  192. )
  193. }
  194. // GetBids return the bids
  195. func (hdb *HistoryDB) GetBids() ([]common.Bid, error) {
  196. var bids []*common.Bid
  197. err := meddler.QueryAll(
  198. hdb.db, &bids,
  199. "SELECT * FROM bid;",
  200. )
  201. return db.SlicePtrsToSlice(bids).([]common.Bid), err
  202. }
  203. // AddCoordinators insert Coordinators into the DB
  204. func (hdb *HistoryDB) AddCoordinators(coordinators []common.Coordinator) error {
  205. return hdb.addCoordinators(hdb.db, coordinators)
  206. }
  207. func (hdb *HistoryDB) addCoordinators(d meddler.DB, coordinators []common.Coordinator) error {
  208. return db.BulkInsert(
  209. d,
  210. "INSERT INTO coordinator (bidder_addr, forger_addr, eth_block_num, url) VALUES %s;",
  211. coordinators[:],
  212. )
  213. }
  214. // AddExitTree insert Exit tree into the DB
  215. func (hdb *HistoryDB) AddExitTree(exitTree []common.ExitInfo) error {
  216. return hdb.addExitTree(hdb.db, exitTree)
  217. }
  218. func (hdb *HistoryDB) addExitTree(d meddler.DB, exitTree []common.ExitInfo) error {
  219. return db.BulkInsert(
  220. d,
  221. "INSERT INTO exit_tree (batch_num, account_idx, merkle_proof, balance, "+
  222. "instant_withdrawn, delayed_withdraw_request, delayed_withdrawn) VALUES %s;",
  223. exitTree[:],
  224. )
  225. }
  226. // AddToken insert a token into the DB
  227. func (hdb *HistoryDB) AddToken(token *common.Token) error {
  228. return meddler.Insert(hdb.db, "token", token)
  229. }
  230. // AddTokens insert tokens into the DB
  231. func (hdb *HistoryDB) AddTokens(tokens []common.Token) error { return hdb.addTokens(hdb.db, tokens) }
  232. func (hdb *HistoryDB) addTokens(d meddler.DB, tokens []common.Token) error {
  233. return db.BulkInsert(
  234. d,
  235. `INSERT INTO token (
  236. token_id,
  237. eth_block_num,
  238. eth_addr,
  239. name,
  240. symbol,
  241. decimals
  242. ) VALUES %s;`,
  243. tokens[:],
  244. )
  245. }
  246. // UpdateTokenValue updates the USD value of a token
  247. func (hdb *HistoryDB) UpdateTokenValue(tokenSymbol string, value float64) error {
  248. _, err := hdb.db.Exec(
  249. "UPDATE token SET usd = $1 WHERE symbol = $2;",
  250. value, tokenSymbol,
  251. )
  252. return err
  253. }
  254. // GetTokens returns a list of tokens from the DB
  255. func (hdb *HistoryDB) GetTokens() ([]TokenRead, error) {
  256. var tokens []*TokenRead
  257. err := meddler.QueryAll(
  258. hdb.db, &tokens,
  259. "SELECT * FROM token ORDER BY token_id;",
  260. )
  261. return db.SlicePtrsToSlice(tokens).([]TokenRead), err
  262. }
  263. // GetTokenSymbols returns all the token symbols from the DB
  264. func (hdb *HistoryDB) GetTokenSymbols() ([]string, error) {
  265. var tokenSymbols []string
  266. rows, err := hdb.db.Query("SELECT symbol FROM token;")
  267. if err != nil {
  268. return nil, err
  269. }
  270. sym := new(string)
  271. for rows.Next() {
  272. err = rows.Scan(sym)
  273. if err != nil {
  274. return nil, err
  275. }
  276. tokenSymbols = append(tokenSymbols, *sym)
  277. }
  278. return tokenSymbols, nil
  279. }
  280. // AddAccounts insert accounts into the DB
  281. func (hdb *HistoryDB) AddAccounts(accounts []common.Account) error {
  282. return hdb.addAccounts(hdb.db, accounts)
  283. }
  284. func (hdb *HistoryDB) addAccounts(d meddler.DB, accounts []common.Account) error {
  285. return db.BulkInsert(
  286. d,
  287. `INSERT INTO account (
  288. idx,
  289. token_id,
  290. batch_num,
  291. bjj,
  292. eth_addr
  293. ) VALUES %s;`,
  294. accounts[:],
  295. )
  296. }
  297. // GetAccounts returns a list of accounts from the DB
  298. func (hdb *HistoryDB) GetAccounts() ([]common.Account, error) {
  299. var accs []*common.Account
  300. err := meddler.QueryAll(
  301. hdb.db, &accs,
  302. "SELECT * FROM account ORDER BY idx;",
  303. )
  304. return db.SlicePtrsToSlice(accs).([]common.Account), err
  305. }
  306. // AddL1Txs inserts L1 txs to the DB. USD and LoadAmountUSD will be set automatically before storing the tx.
  307. // If the tx is originated by a coordinator, BatchNum must be provided. If it's originated by a user,
  308. // BatchNum should be null, and the value will be setted by a trigger when a batch forges the tx.
  309. func (hdb *HistoryDB) AddL1Txs(l1txs []common.L1Tx) error { return hdb.addL1Txs(hdb.db, l1txs) }
  310. // addL1Txs inserts L1 txs to the DB. USD and LoadAmountUSD will be set automatically before storing the tx.
  311. // If the tx is originated by a coordinator, BatchNum must be provided. If it's originated by a user,
  312. // BatchNum should be null, and the value will be setted by a trigger when a batch forges the tx.
  313. func (hdb *HistoryDB) addL1Txs(d meddler.DB, l1txs []common.L1Tx) error {
  314. txs := []txWrite{}
  315. for i := 0; i < len(l1txs); i++ {
  316. af := new(big.Float).SetInt(l1txs[i].Amount)
  317. amountFloat, _ := af.Float64()
  318. laf := new(big.Float).SetInt(l1txs[i].LoadAmount)
  319. loadAmountFloat, _ := laf.Float64()
  320. txs = append(txs, txWrite{
  321. // Generic
  322. IsL1: true,
  323. TxID: l1txs[i].TxID,
  324. Type: l1txs[i].Type,
  325. Position: l1txs[i].Position,
  326. FromIdx: &l1txs[i].FromIdx,
  327. ToIdx: l1txs[i].ToIdx,
  328. Amount: l1txs[i].Amount,
  329. AmountFloat: amountFloat,
  330. TokenID: l1txs[i].TokenID,
  331. BatchNum: l1txs[i].BatchNum,
  332. EthBlockNum: l1txs[i].EthBlockNum,
  333. // L1
  334. ToForgeL1TxsNum: l1txs[i].ToForgeL1TxsNum,
  335. UserOrigin: &l1txs[i].UserOrigin,
  336. FromEthAddr: &l1txs[i].FromEthAddr,
  337. FromBJJ: l1txs[i].FromBJJ,
  338. LoadAmount: l1txs[i].LoadAmount,
  339. LoadAmountFloat: &loadAmountFloat,
  340. })
  341. }
  342. return hdb.addTxs(d, txs)
  343. }
  344. // AddL2Txs inserts L2 txs to the DB. TokenID, USD and FeeUSD will be set automatically before storing the tx.
  345. func (hdb *HistoryDB) AddL2Txs(l2txs []common.L2Tx) error { return hdb.addL2Txs(hdb.db, l2txs) }
  346. // addL2Txs inserts L2 txs to the DB. TokenID, USD and FeeUSD will be set automatically before storing the tx.
  347. func (hdb *HistoryDB) addL2Txs(d meddler.DB, l2txs []common.L2Tx) error {
  348. txs := []txWrite{}
  349. for i := 0; i < len(l2txs); i++ {
  350. f := new(big.Float).SetInt(l2txs[i].Amount)
  351. amountFloat, _ := f.Float64()
  352. txs = append(txs, txWrite{
  353. // Generic
  354. IsL1: false,
  355. TxID: l2txs[i].TxID,
  356. Type: l2txs[i].Type,
  357. Position: l2txs[i].Position,
  358. FromIdx: &l2txs[i].FromIdx,
  359. ToIdx: l2txs[i].ToIdx,
  360. Amount: l2txs[i].Amount,
  361. AmountFloat: amountFloat,
  362. BatchNum: &l2txs[i].BatchNum,
  363. EthBlockNum: l2txs[i].EthBlockNum,
  364. // L2
  365. Fee: &l2txs[i].Fee,
  366. Nonce: &l2txs[i].Nonce,
  367. })
  368. }
  369. return hdb.addTxs(d, txs)
  370. }
  371. func (hdb *HistoryDB) addTxs(d meddler.DB, txs []txWrite) error {
  372. return db.BulkInsert(
  373. d,
  374. `INSERT INTO tx (
  375. is_l1,
  376. id,
  377. type,
  378. position,
  379. from_idx,
  380. to_idx,
  381. amount,
  382. amount_f,
  383. token_id,
  384. batch_num,
  385. eth_block_num,
  386. to_forge_l1_txs_num,
  387. user_origin,
  388. from_eth_addr,
  389. from_bjj,
  390. load_amount,
  391. load_amount_f,
  392. fee,
  393. nonce
  394. ) VALUES %s;`,
  395. txs[:],
  396. )
  397. }
  398. // // GetTxs returns a list of txs from the DB
  399. // func (hdb *HistoryDB) GetTxs() ([]common.Tx, error) {
  400. // var txs []*common.Tx
  401. // err := meddler.QueryAll(
  402. // hdb.db, &txs,
  403. // `SELECT * FROM tx
  404. // ORDER BY (batch_num, position) ASC`,
  405. // )
  406. // return db.SlicePtrsToSlice(txs).([]common.Tx), err
  407. // }
  408. // GetHistoryTxs returns a list of txs from the DB using the HistoryTx struct
  409. func (hdb *HistoryDB) GetHistoryTxs(
  410. ethAddr *ethCommon.Address, bjj *babyjub.PublicKey,
  411. tokenID, idx, batchNum *uint, txType *common.TxType,
  412. offset, limit *uint, last bool,
  413. ) ([]HistoryTx, int, error) {
  414. if ethAddr != nil && bjj != nil {
  415. return nil, 0, errors.New("ethAddr and bjj are incompatible")
  416. }
  417. var query string
  418. var args []interface{}
  419. queryStr := `SELECT tx.is_l1, tx.id, tx.type, tx.position, tx.from_idx, tx.to_idx,
  420. tx.amount, tx.token_id, tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num,
  421. tx.user_origin, tx.from_eth_addr, tx.from_bjj, tx.load_amount, tx.fee, tx.nonce,
  422. token.token_id, token.eth_block_num AS token_block,
  423. token.eth_addr, token.name, token.symbol, token.decimals, token.usd,
  424. token.usd_update, block.timestamp, count(*) OVER() AS total_items
  425. FROM tx
  426. INNER JOIN token ON tx.token_id = token.token_id
  427. INNER JOIN block ON tx.eth_block_num = block.eth_block_num `
  428. // Apply filters
  429. nextIsAnd := false
  430. // ethAddr filter
  431. if ethAddr != nil {
  432. queryStr = `WITH acc AS
  433. (select idx from account where eth_addr = ?) ` + queryStr
  434. queryStr += ", acc WHERE (tx.from_idx IN(acc.idx) OR tx.to_idx IN(acc.idx)) "
  435. nextIsAnd = true
  436. args = append(args, ethAddr)
  437. } else if bjj != nil { // bjj filter
  438. queryStr = `WITH acc AS
  439. (select idx from account where bjj = ?) ` + queryStr
  440. queryStr += ", acc WHERE (tx.from_idx IN(acc.idx) OR tx.to_idx IN(acc.idx)) "
  441. nextIsAnd = true
  442. args = append(args, bjj)
  443. }
  444. // tokenID filter
  445. if tokenID != nil {
  446. if nextIsAnd {
  447. queryStr += "AND "
  448. } else {
  449. queryStr += "WHERE "
  450. }
  451. queryStr += "tx.token_id = ? "
  452. args = append(args, tokenID)
  453. nextIsAnd = true
  454. }
  455. // idx filter
  456. if idx != nil {
  457. if nextIsAnd {
  458. queryStr += "AND "
  459. } else {
  460. queryStr += "WHERE "
  461. }
  462. queryStr += "(tx.from_idx = ? OR tx.to_idx = ?) "
  463. args = append(args, idx, idx)
  464. nextIsAnd = true
  465. }
  466. // batchNum filter
  467. if batchNum != nil {
  468. if nextIsAnd {
  469. queryStr += "AND "
  470. } else {
  471. queryStr += "WHERE "
  472. }
  473. queryStr += "tx.batch_num = ? "
  474. args = append(args, batchNum)
  475. nextIsAnd = true
  476. }
  477. // txType filter
  478. if txType != nil {
  479. if nextIsAnd {
  480. queryStr += "AND "
  481. } else {
  482. queryStr += "WHERE "
  483. }
  484. queryStr += "tx.type = ? "
  485. args = append(args, txType)
  486. // nextIsAnd = true
  487. }
  488. // pagination
  489. if last {
  490. queryStr += "ORDER BY (batch_num, position) DESC NULLS FIRST "
  491. } else {
  492. queryStr += "ORDER BY (batch_num, position) ASC NULLS LAST "
  493. queryStr += fmt.Sprintf("OFFSET %d ", *offset)
  494. }
  495. queryStr += fmt.Sprintf("LIMIT %d;", *limit)
  496. query = hdb.db.Rebind(queryStr)
  497. // log.Debug(query)
  498. txsPtrs := []*HistoryTx{}
  499. if err := meddler.QueryAll(hdb.db, &txsPtrs, query, args...); err != nil {
  500. return nil, 0, err
  501. }
  502. txs := db.SlicePtrsToSlice(txsPtrs).([]HistoryTx)
  503. if len(txs) == 0 {
  504. return nil, 0, sql.ErrNoRows
  505. } else if last {
  506. tmp := []HistoryTx{}
  507. for i := len(txs) - 1; i >= 0; i-- {
  508. tmp = append(tmp, txs[i])
  509. }
  510. txs = tmp
  511. }
  512. return txs, txs[0].TotalItems, nil
  513. }
  514. // // GetTx returns a tx from the DB
  515. // func (hdb *HistoryDB) GetTx(txID common.TxID) (*common.Tx, error) {
  516. // tx := new(common.Tx)
  517. // return tx, meddler.QueryRow(
  518. // hdb.db, tx,
  519. // "SELECT * FROM tx WHERE id = $1;",
  520. // txID,
  521. // )
  522. // }
  523. // // GetL1UserTxs gets L1 User Txs to be forged in a batch that will create an account
  524. // // TODO: This is currently not used. Figure out if it should be used somewhere or removed.
  525. // func (hdb *HistoryDB) GetL1UserTxs(toForgeL1TxsNum int64) ([]*common.Tx, error) {
  526. // var txs []*common.Tx
  527. // err := meddler.QueryAll(
  528. // hdb.db, &txs,
  529. // "SELECT * FROM tx WHERE to_forge_l1_txs_num = $1 AND is_l1 = TRUE AND user_origin = TRUE;",
  530. // toForgeL1TxsNum,
  531. // )
  532. // return txs, err
  533. // }
  534. // TODO: Think about chaning all the queries that return a last value, to queries that return the next valid value.
  535. // GetLastTxsPosition for a given to_forge_l1_txs_num
  536. func (hdb *HistoryDB) GetLastTxsPosition(toForgeL1TxsNum int64) (int, error) {
  537. row := hdb.db.QueryRow("SELECT MAX(position) FROM tx WHERE to_forge_l1_txs_num = $1;", toForgeL1TxsNum)
  538. var lastL1TxsPosition int
  539. return lastL1TxsPosition, row.Scan(&lastL1TxsPosition)
  540. }
  541. // AddBlockSCData stores all the information of a block retrieved by the Synchronizer
  542. func (hdb *HistoryDB) AddBlockSCData(blockData *BlockData) (err error) {
  543. txn, err := hdb.db.Begin()
  544. if err != nil {
  545. return err
  546. }
  547. defer func() {
  548. if err != nil {
  549. errRollback := txn.Rollback()
  550. if errRollback != nil {
  551. log.Errorw("Rollback", "err", errRollback)
  552. }
  553. }
  554. }()
  555. // Add block
  556. err = hdb.addBlock(txn, blockData.Block)
  557. if err != nil {
  558. return err
  559. }
  560. // Add Coordinators
  561. if len(blockData.Coordinators) > 0 {
  562. err = hdb.addCoordinators(txn, blockData.Coordinators)
  563. if err != nil {
  564. return err
  565. }
  566. }
  567. // Add Bids
  568. if len(blockData.Bids) > 0 {
  569. err = hdb.addBids(txn, blockData.Bids)
  570. if err != nil {
  571. return err
  572. }
  573. }
  574. // Add Tokens
  575. if len(blockData.RegisteredTokens) > 0 {
  576. err = hdb.addTokens(txn, blockData.RegisteredTokens)
  577. if err != nil {
  578. return err
  579. }
  580. }
  581. // Add l1 Txs
  582. if len(blockData.L1UserTxs) > 0 {
  583. err = hdb.addL1Txs(txn, blockData.L1UserTxs)
  584. if err != nil {
  585. return err
  586. }
  587. }
  588. // Add Batches
  589. for _, batch := range blockData.Batches {
  590. // Add Batch: this will trigger an update on the DB
  591. // that will set the batch num of forged L1 txs in this batch
  592. err = hdb.addBatch(txn, batch.Batch)
  593. if err != nil {
  594. return err
  595. }
  596. // Add unforged l1 Txs
  597. if batch.L1Batch {
  598. if len(batch.L1CoordinatorTxs) > 0 {
  599. err = hdb.addL1Txs(txn, batch.L1CoordinatorTxs)
  600. if err != nil {
  601. return err
  602. }
  603. }
  604. }
  605. // Add l2 Txs
  606. if len(batch.L2Txs) > 0 {
  607. err = hdb.addL2Txs(txn, batch.L2Txs)
  608. if err != nil {
  609. return err
  610. }
  611. }
  612. // Add accounts
  613. if len(batch.CreatedAccounts) > 0 {
  614. err = hdb.addAccounts(txn, batch.CreatedAccounts)
  615. if err != nil {
  616. return err
  617. }
  618. }
  619. // Add exit tree
  620. if len(batch.ExitTree) > 0 {
  621. err = hdb.addExitTree(txn, batch.ExitTree)
  622. if err != nil {
  623. return err
  624. }
  625. }
  626. // TODO: INSERT CONTRACTS VARS
  627. }
  628. return txn.Commit()
  629. }