From a3fbf8ceab445572844d4094e2d93d42acd28f03 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 24 May 2024 15:12:57 -0700 Subject: [PATCH 1/3] Don't post a batch that would cause a reorg due to being outside (or near) the time bounds --- arbnode/batch_poster.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index ee00cdc618..551ede8bd9 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -156,6 +156,8 @@ type BatchPosterConfig struct { L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` UseAccessLists bool `koanf:"use-access-lists" reload:"hot"` GasEstimateBaseFeeMultipleBips arbmath.Bips `koanf:"gas-estimate-base-fee-multiple-bips"` + ReorgResistanceMargin time.Duration `koanf:"reorg-resistance-margin" reload:"hot"` + IgnoreReorgResistanceMargin bool `koanf:"ignore-reorg-resistance-margin" reload:"hot"` gasRefunder common.Address l1BlockBound l1BlockBound @@ -207,6 +209,8 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay") f.Bool(prefix+".use-access-lists", DefaultBatchPosterConfig.UseAccessLists, "post batches with access lists to reduce gas usage (disabled for L3s)") f.Uint64(prefix+".gas-estimate-base-fee-multiple-bips", uint64(DefaultBatchPosterConfig.GasEstimateBaseFeeMultipleBips), "for gas estimation, use this multiple of the basefee (measured in basis points) as the max fee per gas") + f.Duration(prefix+".reorg-resistance-margin", DefaultBatchPosterConfig.ReorgResistanceMargin, "do not post batch if its within this duration from max-delay") + f.Bool(prefix+".ignore-reorg-resistance-margin", DefaultBatchPosterConfig.IgnoreReorgResistanceMargin, "setting this to true will allow posting of batch even when it falls within the reorg-resistance-margin from max-delay, given the batch duration exceeds max-delay") redislock.AddConfigOptions(prefix+".redis-lock", f) dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfig) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultBatchPosterConfig.ParentChainWallet.Pathname) @@ -235,6 +239,8 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ UseAccessLists: true, RedisLock: redislock.DefaultCfg, GasEstimateBaseFeeMultipleBips: arbmath.OneInBips * 3 / 2, + ReorgResistanceMargin: 10 * time.Minute, + IgnoreReorgResistanceMargin: false, } var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ @@ -1231,7 +1237,15 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) b.building.msgCount++ } - if !forcePostBatch || !b.building.haveUsefulMessage { + var disablePosting bool + batchDuration := time.Since(firstMsgTime) + if (config.ReorgResistanceMargin > 0 && config.ReorgResistanceMargin < config.MaxDelay) && + (batchDuration >= config.MaxDelay-config.ReorgResistanceMargin) && + (batchDuration <= config.MaxDelay || (batchDuration <= config.MaxDelay+config.ReorgResistanceMargin && !config.IgnoreReorgResistanceMargin)) { + disablePosting = true + } + + if disablePosting || !forcePostBatch || !b.building.haveUsefulMessage { // the batch isn't full yet and we've posted a batch recently // don't post anything for now return false, nil From 285a39971e604dec588f2b36b939f0ec0e534758 Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Fri, 31 May 2024 13:19:34 -0500 Subject: [PATCH 2/3] address PR comments --- arbnode/batch_poster.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 72f90a17aa..0c59baba72 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -1243,6 +1243,12 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if (config.ReorgResistanceMargin > 0 && config.ReorgResistanceMargin < config.MaxDelay) && (batchDuration >= config.MaxDelay-config.ReorgResistanceMargin) && (batchDuration <= config.MaxDelay || (batchDuration <= config.MaxDelay+config.ReorgResistanceMargin && !config.IgnoreReorgResistanceMargin)) { + log.Error( + "disabling batch posting as batch duration falls within the reorg-resistance-margin from max-delay", + "batchDuration", batchDuration, + "reorgResistanceMargin", config.ReorgResistanceMargin, + "maxDelay", config.MaxDelay, + ) disablePosting = true } From d78b0721e9b1f1a2a8bfe70f312f6e4e5d2e4bce Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Mon, 3 Jun 2024 12:02:09 -0500 Subject: [PATCH 3/3] address PR comments --- arbnode/batch_poster.go | 84 +++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 0c59baba72..ead2e082a8 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -141,23 +141,23 @@ type BatchPosterConfig struct { // Batch post polling interval. PollInterval time.Duration `koanf:"poll-interval" reload:"hot"` // Batch posting error delay. - ErrorDelay time.Duration `koanf:"error-delay" reload:"hot"` - CompressionLevel int `koanf:"compression-level" reload:"hot"` - DASRetentionPeriod time.Duration `koanf:"das-retention-period" reload:"hot"` - GasRefunderAddress string `koanf:"gas-refunder-address" reload:"hot"` - DataPoster dataposter.DataPosterConfig `koanf:"data-poster" reload:"hot"` - RedisUrl string `koanf:"redis-url"` - RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` - ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"` - Post4844Blobs bool `koanf:"post-4844-blobs" reload:"hot"` - IgnoreBlobPrice bool `koanf:"ignore-blob-price" reload:"hot"` - ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` - L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` - L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` - UseAccessLists bool `koanf:"use-access-lists" reload:"hot"` - GasEstimateBaseFeeMultipleBips arbmath.Bips `koanf:"gas-estimate-base-fee-multiple-bips"` - ReorgResistanceMargin time.Duration `koanf:"reorg-resistance-margin" reload:"hot"` - IgnoreReorgResistanceMargin bool `koanf:"ignore-reorg-resistance-margin" reload:"hot"` + ErrorDelay time.Duration `koanf:"error-delay" reload:"hot"` + CompressionLevel int `koanf:"compression-level" reload:"hot"` + DASRetentionPeriod time.Duration `koanf:"das-retention-period" reload:"hot"` + GasRefunderAddress string `koanf:"gas-refunder-address" reload:"hot"` + DataPoster dataposter.DataPosterConfig `koanf:"data-poster" reload:"hot"` + RedisUrl string `koanf:"redis-url"` + RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"` + ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"` + Post4844Blobs bool `koanf:"post-4844-blobs" reload:"hot"` + IgnoreBlobPrice bool `koanf:"ignore-blob-price" reload:"hot"` + ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` + L1BlockBound string `koanf:"l1-block-bound" reload:"hot"` + L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"` + UseAccessLists bool `koanf:"use-access-lists" reload:"hot"` + GasEstimateBaseFeeMultipleBips arbmath.Bips `koanf:"gas-estimate-base-fee-multiple-bips"` + ReorgResistanceMargin time.Duration `koanf:"reorg-resistance-margin" reload:"hot"` + PrioritizeMaxDelayOverReorgResistance bool `koanf:"prioritize-max-delay-over-reorg-resistance" reload:"hot"` gasRefunder common.Address l1BlockBound l1BlockBound @@ -210,7 +210,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Bool(prefix+".use-access-lists", DefaultBatchPosterConfig.UseAccessLists, "post batches with access lists to reduce gas usage (disabled for L3s)") f.Uint64(prefix+".gas-estimate-base-fee-multiple-bips", uint64(DefaultBatchPosterConfig.GasEstimateBaseFeeMultipleBips), "for gas estimation, use this multiple of the basefee (measured in basis points) as the max fee per gas") f.Duration(prefix+".reorg-resistance-margin", DefaultBatchPosterConfig.ReorgResistanceMargin, "do not post batch if its within this duration from max-delay") - f.Bool(prefix+".ignore-reorg-resistance-margin", DefaultBatchPosterConfig.IgnoreReorgResistanceMargin, "setting this to true will allow posting of batch even when it falls within the reorg-resistance-margin from max-delay, given the batch duration exceeds max-delay") + f.Bool(prefix+".prioritize-max-delay-over-reorg-resistance", DefaultBatchPosterConfig.PrioritizeMaxDelayOverReorgResistance, "setting this to true will allow posting of batch even when it falls within the reorg-resistance-margin from max-delay, given the batch duration exceeds max-delay") redislock.AddConfigOptions(prefix+".redis-lock", f) dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfig) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultBatchPosterConfig.ParentChainWallet.Pathname) @@ -222,26 +222,26 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ // This default is overridden for L3 chains in applyChainParameters in cmd/nitro/nitro.go MaxSize: 100000, // Try to fill 3 blobs per batch - Max4844BatchSize: blobs.BlobEncodableData*(params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob)/2 - 2000, - PollInterval: time.Second * 10, - ErrorDelay: time.Second * 10, - MaxDelay: time.Hour, - WaitForMaxDelay: false, - CompressionLevel: brotli.BestCompression, - DASRetentionPeriod: time.Hour * 24 * 15, - GasRefunderAddress: "", - ExtraBatchGas: 50_000, - Post4844Blobs: false, - IgnoreBlobPrice: false, - DataPoster: dataposter.DefaultDataPosterConfig, - ParentChainWallet: DefaultBatchPosterL1WalletConfig, - L1BlockBound: "", - L1BlockBoundBypass: time.Hour, - UseAccessLists: true, - RedisLock: redislock.DefaultCfg, - GasEstimateBaseFeeMultipleBips: arbmath.OneInBips * 3 / 2, - ReorgResistanceMargin: 10 * time.Minute, - IgnoreReorgResistanceMargin: false, + Max4844BatchSize: blobs.BlobEncodableData*(params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob)/2 - 2000, + PollInterval: time.Second * 10, + ErrorDelay: time.Second * 10, + MaxDelay: time.Hour, + WaitForMaxDelay: false, + CompressionLevel: brotli.BestCompression, + DASRetentionPeriod: time.Hour * 24 * 15, + GasRefunderAddress: "", + ExtraBatchGas: 50_000, + Post4844Blobs: false, + IgnoreBlobPrice: false, + DataPoster: dataposter.DefaultDataPosterConfig, + ParentChainWallet: DefaultBatchPosterL1WalletConfig, + L1BlockBound: "", + L1BlockBoundBypass: time.Hour, + UseAccessLists: true, + RedisLock: redislock.DefaultCfg, + GasEstimateBaseFeeMultipleBips: arbmath.OneInBips * 3 / 2, + ReorgResistanceMargin: 10 * time.Minute, + PrioritizeMaxDelayOverReorgResistance: false, } var DefaultBatchPosterL1WalletConfig = genericconf.WalletConfig{ @@ -1240,9 +1240,11 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) var disablePosting bool batchDuration := time.Since(firstMsgTime) - if (config.ReorgResistanceMargin > 0 && config.ReorgResistanceMargin < config.MaxDelay) && - (batchDuration >= config.MaxDelay-config.ReorgResistanceMargin) && - (batchDuration <= config.MaxDelay || (batchDuration <= config.MaxDelay+config.ReorgResistanceMargin && !config.IgnoreReorgResistanceMargin)) { + reorgResistanceMarginIsValid := config.ReorgResistanceMargin > 0 && config.ReorgResistanceMargin < config.MaxDelay + batchDurationLiesInLeftMargin := batchDuration >= config.MaxDelay-config.ReorgResistanceMargin && batchDuration < config.MaxDelay + batchDurationLiesInRightMargin := batchDuration <= config.MaxDelay+config.ReorgResistanceMargin && batchDuration >= config.MaxDelay + if reorgResistanceMarginIsValid && + (batchDurationLiesInLeftMargin || (batchDurationLiesInRightMargin && !config.PrioritizeMaxDelayOverReorgResistance)) { log.Error( "disabling batch posting as batch duration falls within the reorg-resistance-margin from max-delay", "batchDuration", batchDuration,