arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
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 uint64) (*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 uint64) ([]*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 uint64) 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 uint64,
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 uint64,
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}