arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/db/l2db/l2db.go
db/l2db/l2db.goRaw
  1package l2db
  2
  3import (
  4	"fmt"
  5	"strconv"
  6	"time"
  7
  8	eth "github.com/ethereum/go-ethereum/common"
  9	"github.com/gobuffalo/packr/v2"
 10	"github.com/hermeznetwork/hermez-node/common"
 11	"github.com/hermeznetwork/hermez-node/db"
 12	"github.com/jmoiron/sqlx"
 13	_ "github.com/lib/pq" // driver for postgres DB
 14	migrate "github.com/rubenv/sql-migrate"
 15	"github.com/russross/meddler"
 16)
 17
 18// L2DB stores L2 txs and authorization registers received by the coordinator and keeps them until they are no longer relevant
 19// due to them being forged or invalid after a safety period
 20type L2DB struct {
 21	db           *sqlx.DB
 22	safetyPeriod uint16
 23	ttl          time.Duration
 24	maxTxs       uint32
 25}
 26
 27// NewL2DB creates a L2DB.
 28// More info on how to set dbDialect and dbArgs here: http://gorm.io/docs/connecting_to_the_database.html
 29// safetyPeriod is the ammount of blockchain blocks that must be waited before deleting anything (to avoid reorg problems).
 30// maxTxs indicates the desired maximum amount of txs stored on the L2DB.
 31// TTL indicates the maximum amount of time that a tx can be in the L2DB
 32// (to prevent tx that won't ever be forged to stay there, will be used if maxTxs is exceeded).
 33// autoPurgePeriod will be used as delay between calls to Purge. If the value is 0, it will be disabled.
 34func NewL2DB(
 35	port int, host, user, password, dbname string,
 36	safetyPeriod uint16,
 37	maxTxs uint32,
 38	TTL time.Duration,
 39) (*L2DB, error) {
 40	// init meddler
 41	db.InitMeddler()
 42	meddler.Default = meddler.PostgreSQL
 43	// Stablish DB connection
 44	psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
 45	db, err := sqlx.Connect("postgres", psqlconn)
 46	if err != nil {
 47		return nil, err
 48	}
 49
 50	// Run DB migrations
 51	migrations := &migrate.PackrMigrationSource{
 52		Box: packr.New("history-migrations", "./migrations"),
 53	}
 54	if _, err := migrate.Exec(db.DB, "postgres", migrations, migrate.Up); err != nil {
 55		return nil, err
 56	}
 57
 58	return &L2DB{
 59		db:           db,
 60		safetyPeriod: safetyPeriod,
 61		ttl:          TTL,
 62		maxTxs:       maxTxs,
 63	}, nil
 64}
 65
 66// AddTx inserts a tx into the L2DB
 67func (l2db *L2DB) AddTx(tx *common.PoolL2Tx) error {
 68	return meddler.Insert(l2db.db, "tx_pool", tx)
 69}
 70
 71// AddAccountCreationAuth inserts an account creation authorization into the DB
 72func (l2db *L2DB) AddAccountCreationAuth(auth *common.AccountCreationAuth) error {
 73	// TODO: impl
 74	return nil
 75}
 76
 77// GetTx return the specified Tx
 78func (l2db *L2DB) GetTx(txID common.TxID) (*common.PoolL2Tx, error) {
 79	tx := new(common.PoolL2Tx)
 80	return tx, meddler.QueryRow(
 81		l2db.db, tx,
 82		"SELECT * FROM tx_pool WHERE tx_id = $1;",
 83		txID,
 84	)
 85}
 86
 87// GetPendingTxs return all the pending txs of the L2DB
 88func (l2db *L2DB) GetPendingTxs() ([]*common.PoolL2Tx, error) {
 89	var txs []*common.PoolL2Tx
 90	err := meddler.QueryAll(
 91		l2db.db, &txs,
 92		"SELECT * FROM tx_pool WHERE state = $1",
 93		common.PoolL2TxStatePending,
 94	)
 95	return txs, err
 96}
 97
 98// GetAccountCreationAuth return the authorization to make registers of an Ethereum address
 99func (l2db *L2DB) GetAccountCreationAuth(ethAddr eth.Address) (*common.AccountCreationAuth, error) {
100	// TODO: impl
101	return nil, nil
102}
103
104// StartForging updates the state of the transactions that will begin the forging process.
105// The state of the txs referenced by txIDs will be changed from Pending -> Forging
106func (l2db *L2DB) StartForging(txIDs []common.TxID, batchNum common.BatchNum) error {
107	query, args, err := sqlx.In(
108		`UPDATE tx_pool
109		SET state = ?, batch_num = ?
110		WHERE state = ? AND tx_id IN (?);`,
111		string(common.PoolL2TxStateForging),
112		strconv.Itoa(int(batchNum)),
113		string(common.PoolL2TxStatePending),
114		txIDs,
115	)
116	if err != nil {
117		return err
118	}
119	query = l2db.db.Rebind(query)
120	_, err = l2db.db.Exec(query, args...)
121	return err
122}
123
124// DoneForging updates the state of the transactions that have been forged
125// so the state of the txs referenced by txIDs will be changed from Forging -> Forged
126func (l2db *L2DB) DoneForging(txIDs []common.TxID) error {
127	// TODO: impl
128	return nil
129}
130
131// InvalidateTxs updates the state of the transactions that are invalid.
132// The state of the txs referenced by txIDs will be changed from * -> Invalid
133func (l2db *L2DB) InvalidateTxs(txIDs []common.TxID) error {
134	return nil
135}
136
137// CheckNonces invalidate txs with nonces that are smaller than their respective accounts nonces.
138// The state of the affected txs will be changed from Pending -> Invalid
139func (l2db *L2DB) CheckNonces(updatedAccounts []common.Account) error {
140	// TODO: impl
141	return nil
142}
143
144// GetTxsByAbsoluteFeeUpdate return the txs that have an AbsoluteFee updated before olderThan
145func (l2db *L2DB) GetTxsByAbsoluteFeeUpdate(olderThan time.Time) ([]*common.PoolL2Tx, error) {
146	// TODO: impl
147	return nil, nil
148}
149
150// UpdateTxs update existing txs from the pool (TxID must exist)
151func (l2db *L2DB) UpdateTxs(txs []*common.PoolL2Tx) error {
152	// TODO: impl
153	return nil
154}
155
156// Reorg updates the state of txs that were updated in a batch that has been discarted due to a blockchian reorg.
157// The state of the affected txs can change form Forged -> Pending or from Invalid -> Pending
158func (l2db *L2DB) Reorg(lastValidBatch common.BatchNum) error {
159	// TODO: impl
160	return nil
161}
162
163// Purge deletes transactions that have been forged or marked as invalid for longer than the safety period
164// it also deletes txs that has been in the L2DB for longer than the ttl if maxTxs has been exceeded
165func (l2db *L2DB) Purge() error {
166	// TODO: impl
167	return nil
168}
169
170// Close frees the resources used by the L2DB
171func (l2db *L2DB) Close() error {
172	return l2db.db.Close()
173}