hermez-node/db/historydb/historydb.go
db/historydb/historydb.goRaw
1package historydb
2
3import (
4 "fmt"
5
6 "github.com/gobuffalo/packr/v2"
7 "github.com/hermeznetwork/hermez-node/common"
8 "github.com/hermeznetwork/hermez-node/db"
9 "github.com/jmoiron/sqlx"
10
11 //nolint:errcheck // driver for postgres DB
12 _ "github.com/lib/pq"
13 migrate "github.com/rubenv/sql-migrate"
14 "github.com/russross/meddler"
15)
16
17// HistoryDB persist the historic of the rollup
18type HistoryDB struct {
19 db *sqlx.DB
20}
21
22// NewHistoryDB initialize the DB
23func NewHistoryDB(port int, host, user, password, dbname string) (*HistoryDB, error) {
24 // Connect to DB
25 psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
26 hdb, err := sqlx.Connect("postgres", psqlconn)
27 if err != nil {
28 return nil, err
29 }
30 // Init meddler
31 db.InitMeddler()
32 meddler.Default = meddler.PostgreSQL
33
34 // Run DB migrations
35 migrations := &migrate.PackrMigrationSource{
36 Box: packr.New("history-migrations", "./migrations"),
37 }
38 if _, err := migrate.Exec(hdb.DB, "postgres", migrations, migrate.Up); err != nil {
39 return nil, err
40 }
41
42 return &HistoryDB{hdb}, nil
43}
44
45// AddBlock insert a block into the DB
46func (hdb *HistoryDB) AddBlock(block *common.Block) error {
47 return meddler.Insert(hdb.db, "block", block)
48}
49
50// GetBlock retrieve a block from the DB, given a block number
51func (hdb *HistoryDB) GetBlock(blockNum int64) (*common.Block, error) {
52 block := &common.Block{}
53 err := meddler.QueryRow(
54 hdb.db, block,
55 "SELECT * FROM block WHERE eth_block_num = $1;", blockNum,
56 )
57 return block, err
58}
59
60// GetBlocks retrieve blocks from the DB, given a range of block numbers defined by from and to
61func (hdb *HistoryDB) GetBlocks(from, to int64) ([]*common.Block, error) {
62 var blocks []*common.Block
63 err := meddler.QueryAll(
64 hdb.db, &blocks,
65 "SELECT * FROM block WHERE $1 <= eth_block_num AND eth_block_num < $2",
66 from, to,
67 )
68 return blocks, err
69}
70
71// GetLastBlock retrieve the block with the highest block number from the DB
72func (hdb *HistoryDB) GetLastBlock() (*common.Block, error) {
73 block := &common.Block{}
74 err := meddler.QueryRow(
75 hdb.db, block, "SELECT * FROM block ORDER BY eth_block_num DESC LIMIT 1;",
76 )
77 return block, err
78}
79
80// addBatches insert Bids into the DB
81func (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
99// GetBatches retrieve batches from the DB, given a range of batch numbers defined by from and to
100func (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
110// GetLastBatchNum returns the BatchNum of the latest forged batch
111func (hdb *HistoryDB) GetLastBatchNum() (common.BatchNum, error) {
112 row := hdb.db.QueryRow("SELECT batch_num FROM batch ORDER BY batch_num DESC LIMIT 1;")
113 var batchNum common.BatchNum
114 return batchNum, row.Scan(&batchNum)
115}
116
117// GetLastL1TxsNum returns the greatest ForgeL1TxsNum in the DB
118func (hdb *HistoryDB) GetLastL1TxsNum() (uint32, error) {
119 row := hdb.db.QueryRow("SELECT MAX(forge_l1_txs_num) FROM batch;")
120 var lastL1TxsNum uint32
121 return lastL1TxsNum, row.Scan(&lastL1TxsNum)
122}
123
124// Reorg deletes all the information that was added into the DB after the lastValidBlock
125func (hdb *HistoryDB) Reorg(lastValidBlock int64) error {
126 _, err := hdb.db.Exec("DELETE FROM block WHERE eth_block_num > $1;", lastValidBlock)
127 return err
128}
129
130// SyncRollup stores all the data that can be changed / added on a block in the Rollup SC
131func (hdb *HistoryDB) SyncRollup(
132 blockNum int64,
133 l1txs []common.L1Tx,
134 l2txs []common.L2Tx,
135 registeredAccounts []common.Account,
136 exitTree common.ExitInfo,
137 withdrawals common.ExitInfo,
138 registeredTokens []common.Token,
139 batches []common.Batch,
140 vars *common.RollupVars,
141) error {
142 // TODO: make all in a single DB commit
143 if err := hdb.addBatches(batches); err != nil {
144 return err
145 }
146 return nil
147}
148
149// SyncPoD stores all the data that can be changed / added on a block in the PoD SC
150func (hdb *HistoryDB) SyncPoD(
151 blockNum int64,
152 bids []common.Bid,
153 coordinators []common.Coordinator,
154 vars *common.AuctionVars,
155) error {
156 return nil
157}
158
159// addBids insert Bids into the DB
160func (hdb *HistoryDB) addBids(bids []common.Bid) error {
161 // TODO: check the coordinator info
162 return db.BulkInsert(
163 hdb.db,
164 "INSERT INTO bid (slot_num, forger_addr, bid_value, eth_block_num) VALUES %s",
165 bids[:],
166 )
167}
168
169// GetBidsBySlot return the bids for a specific slot
170func (hdb *HistoryDB) GetBidsBySlot(slotNum common.SlotNum) ([]*common.Bid, error) {
171 var bids []*common.Bid
172 err := meddler.QueryAll(
173 hdb.db, &bids,
174 "SELECT * FROM bid WHERE $1 = slot_num;",
175 slotNum,
176 )
177 return bids, err
178}
179
180// Close frees the resources used by HistoryDB
181func (hdb *HistoryDB) Close() error {
182 return hdb.db.Close()
183}