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	_ "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}