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// DB returns a pointer to the L2DB.db. This method should be used only for
 69// internal testing purposes.
 70func (l2db *L2DB) DB() *sqlx.DB {
 71	return l2db.db
 72}
 73
 74// AddTx inserts a tx into the L2DB
 75func (l2db *L2DB) AddTx(tx *common.PoolL2Tx) error {
 76	return meddler.Insert(l2db.db, "tx_pool", tx)
 77}
 78
 79// AddAccountCreationAuth inserts an account creation authorization into the DB
 80func (l2db *L2DB) AddAccountCreationAuth(auth *common.AccountCreationAuth) error {
 81	// TODO: impl
 82	return nil
 83}
 84
 85// GetTx return the specified Tx
 86func (l2db *L2DB) GetTx(txID common.TxID) (*common.PoolL2Tx, error) {
 87	tx := new(common.PoolL2Tx)
 88	return tx, meddler.QueryRow(
 89		l2db.db, tx,
 90		"SELECT * FROM tx_pool WHERE tx_id = $1;",
 91		txID,
 92	)
 93}
 94
 95// GetPendingTxs return all the pending txs of the L2DB
 96func (l2db *L2DB) GetPendingTxs() ([]*common.PoolL2Tx, error) {
 97	var txs []*common.PoolL2Tx
 98	err := meddler.QueryAll(
 99		l2db.db, &txs,
100		"SELECT * FROM tx_pool WHERE state = $1",
101		common.PoolL2TxStatePending,
102	)
103	return txs, err
104}
105
106// GetAccountCreationAuth return the authorization to make registers of an Ethereum address
107func (l2db *L2DB) GetAccountCreationAuth(ethAddr eth.Address) (*common.AccountCreationAuth, error) {
108	// TODO: impl
109	return nil, nil
110}
111
112// StartForging updates the state of the transactions that will begin the forging process.
113// The state of the txs referenced by txIDs will be changed from Pending -> Forging
114func (l2db *L2DB) StartForging(txIDs []common.TxID, batchNum common.BatchNum) error {
115	query, args, err := sqlx.In(
116		`UPDATE tx_pool
117		SET state = ?, batch_num = ?
118		WHERE state = ? AND tx_id IN (?);`,
119		string(common.PoolL2TxStateForging),
120		strconv.Itoa(int(batchNum)),
121		string(common.PoolL2TxStatePending),
122		txIDs,
123	)
124	if err != nil {
125		return err
126	}
127	query = l2db.db.Rebind(query)
128	_, err = l2db.db.Exec(query, args...)
129	return err
130}
131
132// DoneForging updates the state of the transactions that have been forged
133// so the state of the txs referenced by txIDs will be changed from Forging -> Forged
134func (l2db *L2DB) DoneForging(txIDs []common.TxID) error {
135	// TODO: impl
136	return nil
137}
138
139// InvalidateTxs updates the state of the transactions that are invalid.
140// The state of the txs referenced by txIDs will be changed from * -> Invalid
141func (l2db *L2DB) InvalidateTxs(txIDs []common.TxID) error {
142	return nil
143}
144
145// CheckNonces invalidate txs with nonces that are smaller than their respective accounts nonces.
146// The state of the affected txs will be changed from Pending -> Invalid
147func (l2db *L2DB) CheckNonces(updatedAccounts []common.Account) error {
148	// TODO: impl
149	return nil
150}
151
152// GetTxsByAbsoluteFeeUpdate return the txs that have an AbsoluteFee updated before olderThan
153func (l2db *L2DB) GetTxsByAbsoluteFeeUpdate(olderThan time.Time) ([]*common.PoolL2Tx, error) {
154	// TODO: impl
155	return nil, nil
156}
157
158// UpdateTxs update existing txs from the pool (TxID must exist)
159func (l2db *L2DB) UpdateTxs(txs []*common.PoolL2Tx) error {
160	// TODO: impl
161	return nil
162}
163
164// Reorg updates the state of txs that were updated in a batch that has been discarted due to a blockchain reorg.
165// The state of the affected txs can change form Forged -> Pending or from Invalid -> Pending
166func (l2db *L2DB) Reorg(lastValidBatch common.BatchNum) error {
167	// TODO: impl
168	return nil
169}
170
171// Purge deletes transactions that have been forged or marked as invalid for longer than the safety period
172// it also deletes txs that has been in the L2DB for longer than the ttl if maxTxs has been exceeded
173func (l2db *L2DB) Purge() error {
174	// TODO: impl
175	return nil
176}
177
178// Close frees the resources used by the L2DB
179func (l2db *L2DB) Close() error {
180	return l2db.db.Close()
181}