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