mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 19:36:44 +01:00
Integrate purger to node
- Common - Add `IdxNonce` type used to track nonces in accounts to invalidate l2txs in the pool - Config - Update coordinator config will all the new configuration parameters used in the coordinator - Coordinator - Introduce the `Purger` to track how often to purge and do the job when needed according to a configuration. - Implement the methods to invalidate l2txs transactions due to l2txs selection in batches. For now these functions are not used in favour of the `Purger` methods, which check ALL the l2txs in the pool. - Call Invalidation and Purging methods of the purger both when the node is forging (in the pipeline when starting a new batch) and when the node is not forging (in coordinator when being notified about a new synced block) - L2DB: - Implement `GetPendingUniqueFromIdxs` to get all the unique idxs from pending transactions (used to get their nonces and then invalidate txs) - Redo `CheckNonces` with a single SQL query and using `common.IdxNonce` instead of `common.Account` - StateDB: - Expose GetIdx to check errors when invalidating pool txs - Synchronizer: - Test forged L1UserTxs processed by TxProcessor - Improve checks of Effective values - TxSelector: - Expose the internal LocalStateDB in order to check account nonces in the coordinator when not forging.
This commit is contained in:
152
coordinator/purger.go
Normal file
152
coordinator/purger.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package coordinator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/db/l2db"
|
||||
"github.com/hermeznetwork/hermez-node/db/statedb"
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
"github.com/hermeznetwork/tracerr"
|
||||
"github.com/iden3/go-merkletree/db"
|
||||
)
|
||||
|
||||
// PurgerCfg is the purger configuration
|
||||
type PurgerCfg struct {
|
||||
// PurgeBatchDelay is the delay between batches to purge outdated transactions
|
||||
PurgeBatchDelay int64
|
||||
// InvalidateBatchDelay is the delay between batches to mark invalid transactions
|
||||
InvalidateBatchDelay int64
|
||||
// PurgeBlockDelay is the delay between blocks to purge outdated transactions
|
||||
PurgeBlockDelay int64
|
||||
// InvalidateBlockDelay is the delay between blocks to mark invalid transactions
|
||||
InvalidateBlockDelay int64
|
||||
}
|
||||
|
||||
// Purger manages cleanup of transactions in the pool
|
||||
type Purger struct {
|
||||
cfg PurgerCfg
|
||||
lastPurgeBlock int64
|
||||
lastPurgeBatch int64
|
||||
lastInvalidateBlock int64
|
||||
lastInvalidateBatch int64
|
||||
}
|
||||
|
||||
// CanPurge returns true if it's a good time to purge according to the
|
||||
// configuration
|
||||
func (p *Purger) CanPurge(blockNum, batchNum int64) bool {
|
||||
if blockNum > p.lastPurgeBlock+p.cfg.PurgeBlockDelay {
|
||||
return true
|
||||
}
|
||||
if batchNum > p.lastPurgeBatch+p.cfg.PurgeBatchDelay {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CanInvalidate returns true if it's a good time to invalidate according to
|
||||
// the configuration
|
||||
func (p *Purger) CanInvalidate(blockNum, batchNum int64) bool {
|
||||
if blockNum > p.lastInvalidateBlock+p.cfg.InvalidateBlockDelay {
|
||||
return true
|
||||
}
|
||||
if batchNum > p.lastInvalidateBatch+p.cfg.InvalidateBatchDelay {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PurgeMaybe purges txs if it's a good time to do so
|
||||
func (p *Purger) PurgeMaybe(l2DB *l2db.L2DB, blockNum, batchNum int64) (bool, error) {
|
||||
if !p.CanPurge(blockNum, batchNum) {
|
||||
return false, nil
|
||||
}
|
||||
p.lastPurgeBlock = blockNum
|
||||
p.lastPurgeBatch = batchNum
|
||||
log.Debugw("Purger: purging l2txs in pool", "block", blockNum, "batch", batchNum)
|
||||
err := l2DB.Purge(common.BatchNum(batchNum))
|
||||
return true, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// InvalidateMaybe invalidates txs if it's a good time to do so
|
||||
func (p *Purger) InvalidateMaybe(l2DB *l2db.L2DB, stateDB *statedb.LocalStateDB,
|
||||
blockNum, batchNum int64) (bool, error) {
|
||||
if !p.CanInvalidate(blockNum, batchNum) {
|
||||
return false, nil
|
||||
}
|
||||
p.lastInvalidateBlock = blockNum
|
||||
p.lastInvalidateBatch = batchNum
|
||||
log.Debugw("Purger: invalidating l2txs in pool", "block", blockNum, "batch", batchNum)
|
||||
err := poolMarkInvalidOldNonces(l2DB, stateDB, common.BatchNum(batchNum))
|
||||
return true, err
|
||||
}
|
||||
|
||||
//nolint:unused,deadcode
|
||||
func idxsNonceFromL2Txs(txs []common.L2Tx) []common.IdxNonce {
|
||||
idxNonceMap := map[common.Idx]common.Nonce{}
|
||||
for _, tx := range txs {
|
||||
if nonce, ok := idxNonceMap[tx.FromIdx]; !ok {
|
||||
idxNonceMap[tx.FromIdx] = tx.Nonce
|
||||
} else if tx.Nonce > nonce {
|
||||
idxNonceMap[tx.FromIdx] = tx.Nonce
|
||||
}
|
||||
}
|
||||
idxsNonce := make([]common.IdxNonce, 0, len(idxNonceMap))
|
||||
for idx, nonce := range idxNonceMap {
|
||||
idxsNonce = append(idxsNonce, common.IdxNonce{Idx: idx, Nonce: nonce})
|
||||
}
|
||||
return idxsNonce
|
||||
}
|
||||
|
||||
func idxsNonceFromPoolL2Txs(txs []common.PoolL2Tx) []common.IdxNonce {
|
||||
idxNonceMap := map[common.Idx]common.Nonce{}
|
||||
for _, tx := range txs {
|
||||
if nonce, ok := idxNonceMap[tx.FromIdx]; !ok {
|
||||
idxNonceMap[tx.FromIdx] = tx.Nonce
|
||||
} else if tx.Nonce > nonce {
|
||||
idxNonceMap[tx.FromIdx] = tx.Nonce
|
||||
}
|
||||
}
|
||||
idxsNonce := make([]common.IdxNonce, 0, len(idxNonceMap))
|
||||
for idx, nonce := range idxNonceMap {
|
||||
idxsNonce = append(idxsNonce, common.IdxNonce{Idx: idx, Nonce: nonce})
|
||||
}
|
||||
return idxsNonce
|
||||
}
|
||||
|
||||
// poolMarkInvalidOldNoncesFromL2Txs marks as invalid the txs in the pool that
|
||||
// contain nonces equal or older to the highest nonce used in a forged l2Tx for
|
||||
// the
|
||||
// corresponding sender account
|
||||
func poolMarkInvalidOldNoncesFromL2Txs(l2DB *l2db.L2DB,
|
||||
idxsNonce []common.IdxNonce, batchNum common.BatchNum) error {
|
||||
return l2DB.CheckNonces(idxsNonce, batchNum)
|
||||
}
|
||||
|
||||
// poolMarkInvalidOldNonces marks as invalid txs in the pool that contain
|
||||
// nonces equal or older to the nonce of the corresponding sender account
|
||||
func poolMarkInvalidOldNonces(l2DB *l2db.L2DB, stateDB *statedb.LocalStateDB,
|
||||
batchNum common.BatchNum) error {
|
||||
idxs, err := l2DB.GetPendingUniqueFromIdxs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
idxsNonce := make([]common.IdxNonce, len(idxs))
|
||||
lastIdx, err := stateDB.GetIdx()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i, idx := range idxs {
|
||||
acc, err := stateDB.GetAccount(idx)
|
||||
if err != nil {
|
||||
if tracerr.Unwrap(err) != db.ErrNotFound {
|
||||
return err
|
||||
} else if idx <= lastIdx {
|
||||
return fmt.Errorf("account with idx %v not found: %w", idx, err)
|
||||
}
|
||||
}
|
||||
idxsNonce[i].Idx = idx
|
||||
idxsNonce[i].Nonce = acc.Nonce
|
||||
}
|
||||
return l2DB.CheckNonces(idxsNonce, batchNum)
|
||||
}
|
||||
Reference in New Issue
Block a user