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