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.

125 lines
3.9 KiB

  1. package l2db
  2. import (
  3. "fmt"
  4. ethCommon "github.com/ethereum/go-ethereum/common"
  5. "github.com/hermeznetwork/hermez-node/common"
  6. "github.com/hermeznetwork/tracerr"
  7. "github.com/russross/meddler"
  8. )
  9. var (
  10. errPoolFull = fmt.Errorf("the pool is at full capacity. More transactions are not accepted currently")
  11. )
  12. // AddAccountCreationAuthAPI inserts an account creation authorization into the DB
  13. func (l2db *L2DB) AddAccountCreationAuthAPI(auth *common.AccountCreationAuth) error {
  14. cancel, err := l2db.apiConnCon.Acquire()
  15. defer cancel()
  16. if err != nil {
  17. return tracerr.Wrap(err)
  18. }
  19. defer l2db.apiConnCon.Release()
  20. return l2db.AddAccountCreationAuth(auth)
  21. }
  22. // GetAccountCreationAuthAPI returns an account creation authorization from the DB
  23. func (l2db *L2DB) GetAccountCreationAuthAPI(addr ethCommon.Address) (*AccountCreationAuthAPI, error) {
  24. cancel, err := l2db.apiConnCon.Acquire()
  25. defer cancel()
  26. if err != nil {
  27. return nil, tracerr.Wrap(err)
  28. }
  29. defer l2db.apiConnCon.Release()
  30. auth := new(AccountCreationAuthAPI)
  31. return auth, tracerr.Wrap(meddler.QueryRow(
  32. l2db.dbRead, auth,
  33. "SELECT * FROM account_creation_auth WHERE eth_addr = $1;",
  34. addr,
  35. ))
  36. }
  37. // AddTxAPI inserts a tx to the pool
  38. func (l2db *L2DB) AddTxAPI(tx *PoolL2TxWrite) error {
  39. cancel, err := l2db.apiConnCon.Acquire()
  40. defer cancel()
  41. if err != nil {
  42. return tracerr.Wrap(err)
  43. }
  44. defer l2db.apiConnCon.Release()
  45. row := l2db.dbRead.QueryRow(`SELECT
  46. ($1::NUMERIC * COALESCE(token.usd, 0) * fee_percentage($2::NUMERIC)) /
  47. (10.0 ^ token.decimals::NUMERIC)
  48. FROM token WHERE token.token_id = $3;`,
  49. tx.AmountFloat, tx.Fee, tx.TokenID)
  50. var feeUSD float64
  51. if err := row.Scan(&feeUSD); err != nil {
  52. return tracerr.Wrap(err)
  53. }
  54. if feeUSD < l2db.minFeeUSD {
  55. return tracerr.Wrap(fmt.Errorf("tx.feeUSD (%v) < minFeeUSD (%v)",
  56. feeUSD, l2db.minFeeUSD))
  57. }
  58. // Prepare insert SQL query argument parameters
  59. namesPart, err := meddler.Default.ColumnsQuoted(tx, false)
  60. if err != nil {
  61. return err
  62. }
  63. valuesPart, err := meddler.Default.PlaceholdersString(tx, false)
  64. if err != nil {
  65. return err
  66. }
  67. values, err := meddler.Default.Values(tx, false)
  68. if err != nil {
  69. return err
  70. }
  71. q := fmt.Sprintf(
  72. `INSERT INTO tx_pool (%s)
  73. SELECT %s
  74. WHERE (SELECT COUNT(*) FROM tx_pool WHERE state = $%v) < $%v;`,
  75. namesPart, valuesPart,
  76. len(values)+1, len(values)+2) //nolint:gomnd
  77. values = append(values, common.PoolL2TxStatePending, l2db.maxTxs)
  78. res, err := l2db.dbWrite.Exec(q, values...)
  79. if err != nil {
  80. return tracerr.Wrap(err)
  81. }
  82. rowsAffected, err := res.RowsAffected()
  83. if err != nil {
  84. return tracerr.Wrap(err)
  85. }
  86. if rowsAffected == 0 {
  87. return tracerr.Wrap(errPoolFull)
  88. }
  89. return nil
  90. }
  91. // selectPoolTxAPI select part of queries to get PoolL2TxRead
  92. const selectPoolTxAPI = `SELECT tx_pool.tx_id, hez_idx(tx_pool.from_idx, token.symbol) AS from_idx, tx_pool.effective_from_eth_addr,
  93. tx_pool.effective_from_bjj, hez_idx(tx_pool.to_idx, token.symbol) AS to_idx, tx_pool.effective_to_eth_addr,
  94. tx_pool.effective_to_bjj, tx_pool.token_id, tx_pool.amount, tx_pool.fee, tx_pool.nonce,
  95. tx_pool.state, tx_pool.info, tx_pool.signature, tx_pool.timestamp, tx_pool.batch_num, hez_idx(tx_pool.rq_from_idx, token.symbol) AS rq_from_idx,
  96. hez_idx(tx_pool.rq_to_idx, token.symbol) AS rq_to_idx, tx_pool.rq_to_eth_addr, tx_pool.rq_to_bjj, tx_pool.rq_token_id, tx_pool.rq_amount,
  97. tx_pool.rq_fee, tx_pool.rq_nonce, tx_pool.tx_type,
  98. token.item_id AS token_item_id, token.eth_block_num, token.eth_addr, token.name, token.symbol, token.decimals, token.usd, token.usd_update
  99. FROM tx_pool INNER JOIN token ON tx_pool.token_id = token.token_id `
  100. // GetTxAPI return the specified Tx in PoolTxAPI format
  101. func (l2db *L2DB) GetTxAPI(txID common.TxID) (*PoolTxAPI, error) {
  102. cancel, err := l2db.apiConnCon.Acquire()
  103. defer cancel()
  104. if err != nil {
  105. return nil, tracerr.Wrap(err)
  106. }
  107. defer l2db.apiConnCon.Release()
  108. tx := new(PoolTxAPI)
  109. return tx, tracerr.Wrap(meddler.QueryRow(
  110. l2db.dbRead, tx,
  111. selectPoolTxAPI+"WHERE tx_id = $1;",
  112. txID,
  113. ))
  114. }