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