diff --git a/cli/node/cfg.buidler.toml b/cli/node/cfg.buidler.toml index 452a22d..6efebad 100644 --- a/cli/node/cfg.buidler.toml +++ b/cli/node/cfg.buidler.toml @@ -86,6 +86,8 @@ SyncRetryInterval = "1s" ForgeDelay = "10s" ForgeNoTxsDelay = "0s" PurgeByExtDelInterval = "1m" +MustForgeAtSlotDeadline = true +IgnoreSlotCommitment = false [Coordinator.FeeAccount] Address = "0x56232B1c5B10038125Bc7345664B4AFD745bcF8E" diff --git a/config/config.go b/config/config.go index 0961c9c..b20fb21 100644 --- a/config/config.go +++ b/config/config.go @@ -102,6 +102,14 @@ type Coordinator struct { // to 0s, the coordinator will continuously forge even if the batches // are empty. ForgeNoTxsDelay Duration `validate:"-"` + // MustForgeAtSlotDeadline enables the coordinator to forge slots if + // the empty slots reach the slot deadline. + MustForgeAtSlotDeadline bool + // IgnoreSlotCommitment IgnoreSlotCommitment disables forcing the + // coordinator to forge a slot immediately when the slot is not + // committed. If set to false, the coordinator will immediately forge + // a batch at the beginning of a slot if it's the slot winner. + IgnoreSlotCommitment bool // SyncRetryInterval is the waiting interval between calls to the main // handler of a synced block after an error SyncRetryInterval Duration `validate:"required"` diff --git a/coordinator/coordinator.go b/coordinator/coordinator.go index deb243a..1fe4eb4 100644 --- a/coordinator/coordinator.go +++ b/coordinator/coordinator.go @@ -84,6 +84,14 @@ type Config struct { // to 0s, the coordinator will continuously forge even if the batches // are empty. ForgeNoTxsDelay time.Duration + // MustForgeAtSlotDeadline enables the coordinator to forge slots if + // the empty slots reach the slot deadline. + MustForgeAtSlotDeadline bool + // IgnoreSlotCommitment disables forcing the coordinator to forge a + // slot immediately when the slot is not committed. If set to false, + // the coordinator will immediately forge a batch at the beginning of + // a slot if it's the slot winner. + IgnoreSlotCommitment bool // SyncRetryInterval is the waiting interval between calls to the main // handler of a synced block after an error SyncRetryInterval time.Duration @@ -318,7 +326,8 @@ func (c *Coordinator) syncSCVars(vars synchronizer.SCVariablesPtr) { } func canForge(auctionConstants *common.AuctionConstants, auctionVars *common.AuctionVariables, - currentSlot *common.Slot, nextSlot *common.Slot, addr ethCommon.Address, blockNum int64) bool { + currentSlot *common.Slot, nextSlot *common.Slot, addr ethCommon.Address, blockNum int64, + mustForgeAtDeadline bool) bool { if blockNum < auctionConstants.GenesisBlockNum { log.Infow("canForge: requested blockNum is < genesis", "blockNum", blockNum, "genesis", auctionConstants.GenesisBlockNum) @@ -343,7 +352,7 @@ func canForge(auctionConstants *common.AuctionConstants, auctionVars *common.Auc "block", blockNum) anyoneForge = true } - if slot.Forger == addr || anyoneForge { + if slot.Forger == addr || (anyoneForge && mustForgeAtDeadline) { return true } log.Debugw("canForge: can't forge", "slot.Forger", slot.Forger) @@ -353,14 +362,14 @@ func canForge(auctionConstants *common.AuctionConstants, auctionVars *common.Auc func (c *Coordinator) canForgeAt(blockNum int64) bool { return canForge(&c.consts.Auction, &c.vars.Auction, &c.stats.Sync.Auction.CurrentSlot, &c.stats.Sync.Auction.NextSlot, - c.cfg.ForgerAddress, blockNum) + c.cfg.ForgerAddress, blockNum, c.cfg.MustForgeAtSlotDeadline) } func (c *Coordinator) canForge() bool { blockNum := c.stats.Eth.LastBlock.Num + 1 return canForge(&c.consts.Auction, &c.vars.Auction, &c.stats.Sync.Auction.CurrentSlot, &c.stats.Sync.Auction.NextSlot, - c.cfg.ForgerAddress, blockNum) + c.cfg.ForgerAddress, blockNum, c.cfg.MustForgeAtSlotDeadline) } func (c *Coordinator) syncStats(ctx context.Context, stats *synchronizer.Stats) error { diff --git a/coordinator/coordinator_test.go b/coordinator/coordinator_test.go index acdb780..28299d7 100644 --- a/coordinator/coordinator_test.go +++ b/coordinator/coordinator_test.go @@ -159,14 +159,15 @@ func newTestCoordinator(t *testing.T, forgerAddr ethCommon.Address, ethClient *t deleteme = append(deleteme, debugBatchPath) conf := Config{ - ForgerAddress: forgerAddr, - ConfirmBlocks: 5, - L1BatchTimeoutPerc: 0.5, - EthClientAttempts: 5, - SyncRetryInterval: 400 * time.Microsecond, - EthClientAttemptsDelay: 100 * time.Millisecond, - TxManagerCheckInterval: 300 * time.Millisecond, - DebugBatchPath: debugBatchPath, + ForgerAddress: forgerAddr, + ConfirmBlocks: 5, + L1BatchTimeoutPerc: 0.5, + EthClientAttempts: 5, + SyncRetryInterval: 400 * time.Microsecond, + EthClientAttemptsDelay: 100 * time.Millisecond, + TxManagerCheckInterval: 300 * time.Millisecond, + DebugBatchPath: debugBatchPath, + MustForgeAtSlotDeadline: true, Purger: PurgerCfg{ PurgeBatchDelay: 10, PurgeBlockDelay: 10, @@ -391,6 +392,10 @@ func TestCoordCanForge(t *testing.T) { assert.Equal(t, true, coord.canForge()) assert.Equal(t, true, bootCoord.canForge()) + // Anyone can forge but the node MustForgeAtSlotDeadline as set as false + coord.cfg.MustForgeAtSlotDeadline = false + assert.Equal(t, false, coord.canForge()) + // Slot 3. coordinator bid, so the winner is the coordinator stats.Eth.LastBlock.Num = ethClientSetup.AuctionConstants.GenesisBlockNum + 3*int64(ethClientSetup.AuctionConstants.BlocksPerSlot) diff --git a/coordinator/pipeline.go b/coordinator/pipeline.go index 2be1a6b..e9822ce 100644 --- a/coordinator/pipeline.go +++ b/coordinator/pipeline.go @@ -414,7 +414,7 @@ func (p *Pipeline) forgeBatch(batchNum common.BatchNum) (batchInfo *BatchInfo, e var coordIdxs []common.Idx // Check if the slot is not yet fulfilled - slotCommitted := false + slotCommitted := p.cfg.IgnoreSlotCommitment if p.stats.Sync.Auction.CurrentSlot.ForgerCommitment || p.stats.Sync.Auction.CurrentSlot.SlotNum == p.state.lastSlotForged { slotCommitted = true diff --git a/coordinator/txmanager.go b/coordinator/txmanager.go index 9ca29f8..9ef3422 100644 --- a/coordinator/txmanager.go +++ b/coordinator/txmanager.go @@ -608,7 +608,7 @@ func (t *TxManager) removeBadBatchInfos(ctx context.Context) error { func (t *TxManager) canForgeAt(blockNum int64) bool { return canForge(&t.consts.Auction, &t.vars.Auction, &t.stats.Sync.Auction.CurrentSlot, &t.stats.Sync.Auction.NextSlot, - t.cfg.ForgerAddress, blockNum) + t.cfg.ForgerAddress, blockNum, t.cfg.MustForgeAtSlotDeadline) } func (t *TxManager) mustL1L2Batch(blockNum int64) bool { diff --git a/node/node.go b/node/node.go index 4b696e0..a2044d9 100644 --- a/node/node.go +++ b/node/node.go @@ -334,22 +334,24 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { coord, err = coordinator.NewCoordinator( coordinator.Config{ - ForgerAddress: cfg.Coordinator.ForgerAddress, - ConfirmBlocks: cfg.Coordinator.ConfirmBlocks, - L1BatchTimeoutPerc: cfg.Coordinator.L1BatchTimeoutPerc, - ForgeRetryInterval: cfg.Coordinator.ForgeRetryInterval.Duration, - ForgeDelay: cfg.Coordinator.ForgeDelay.Duration, - ForgeNoTxsDelay: cfg.Coordinator.ForgeNoTxsDelay.Duration, - SyncRetryInterval: cfg.Coordinator.SyncRetryInterval.Duration, - PurgeByExtDelInterval: cfg.Coordinator.PurgeByExtDelInterval.Duration, - EthClientAttempts: cfg.Coordinator.EthClient.Attempts, - EthClientAttemptsDelay: cfg.Coordinator.EthClient.AttemptsDelay.Duration, - EthNoReuseNonce: cfg.Coordinator.EthClient.NoReuseNonce, - EthTxResendTimeout: cfg.Coordinator.EthClient.TxResendTimeout.Duration, - MaxGasPrice: cfg.Coordinator.EthClient.MaxGasPrice, - GasPriceIncPerc: cfg.Coordinator.EthClient.GasPriceIncPerc, - TxManagerCheckInterval: cfg.Coordinator.EthClient.CheckLoopInterval.Duration, - DebugBatchPath: cfg.Coordinator.Debug.BatchPath, + ForgerAddress: cfg.Coordinator.ForgerAddress, + ConfirmBlocks: cfg.Coordinator.ConfirmBlocks, + L1BatchTimeoutPerc: cfg.Coordinator.L1BatchTimeoutPerc, + ForgeRetryInterval: cfg.Coordinator.ForgeRetryInterval.Duration, + ForgeDelay: cfg.Coordinator.ForgeDelay.Duration, + MustForgeAtSlotDeadline: cfg.Coordinator.MustForgeAtSlotDeadline, + IgnoreSlotCommitment: cfg.Coordinator.IgnoreSlotCommitment, + ForgeNoTxsDelay: cfg.Coordinator.ForgeNoTxsDelay.Duration, + SyncRetryInterval: cfg.Coordinator.SyncRetryInterval.Duration, + PurgeByExtDelInterval: cfg.Coordinator.PurgeByExtDelInterval.Duration, + EthClientAttempts: cfg.Coordinator.EthClient.Attempts, + EthClientAttemptsDelay: cfg.Coordinator.EthClient.AttemptsDelay.Duration, + EthNoReuseNonce: cfg.Coordinator.EthClient.NoReuseNonce, + EthTxResendTimeout: cfg.Coordinator.EthClient.TxResendTimeout.Duration, + MaxGasPrice: cfg.Coordinator.EthClient.MaxGasPrice, + GasPriceIncPerc: cfg.Coordinator.EthClient.GasPriceIncPerc, + TxManagerCheckInterval: cfg.Coordinator.EthClient.CheckLoopInterval.Duration, + DebugBatchPath: cfg.Coordinator.Debug.BatchPath, Purger: coordinator.PurgerCfg{ PurgeBatchDelay: cfg.Coordinator.L2DB.PurgeBatchDelay, InvalidateBatchDelay: cfg.Coordinator.L2DB.InvalidateBatchDelay,