From 05092df4d445fe3fba5a661f2d5ddab4470208db Mon Sep 17 00:00:00 2001 From: Ganesh Vanahalli Date: Tue, 7 May 2024 10:42:19 -0500 Subject: [PATCH 1/5] Improve error messages for syncing nitro nodes with a beacon chain client lacking old enough blobs for sync --- util/headerreader/blob_client.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/util/headerreader/blob_client.go b/util/headerreader/blob_client.go index 664dbb5e30..73849d0d3a 100644 --- a/util/headerreader/blob_client.go +++ b/util/headerreader/blob_client.go @@ -13,6 +13,7 @@ import ( "net/url" "os" "path" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -188,8 +189,14 @@ const trailingCharsOfResponse = 25 func (b *BlobClient) blobSidecars(ctx context.Context, slot uint64, versionedHashes []common.Hash) ([]kzg4844.Blob, error) { rawData, err := beaconRequest[json.RawMessage](b, ctx, fmt.Sprintf("/eth/v1/beacon/blob_sidecars/%d", slot)) - if err != nil { - return nil, fmt.Errorf("error calling beacon client in blobSidecars: %w", err) + if err != nil || len(rawData) == 0 { + // blobs are pruned after 4096 epochs (1 epoch = 32 slots), we determine if the requested slot were to be pruned by a non-archive endpoint + roughAgeOfSlot := uint64(time.Now().Unix()) - (b.genesisTime + slot*b.secondsPerSlot) + if roughAgeOfSlot > b.secondsPerSlot*32*4096 { + return nil, fmt.Errorf("beacon client in blobSidecars got error or empty response fetching older blobs in slot: %d, an archive endpoint is required, please refer to https://docs.arbitrum.io/run-arbitrum-node/l1-ethereum-beacon-chain-rpc-providers, err: %w", slot, err) + } else { + return nil, fmt.Errorf("beacon client in blobSidecars got error or empty response fetching non-expired blobs in slot: %d, if using a prysm endpoint, try --enable-experimental-backfill flag, err: %w", slot, err) + } } var response []blobResponseItem if err := json.Unmarshal(rawData, &response); err != nil { From b744328c6b4c01434a528d8e93f53eba15dc75ac Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Fri, 10 May 2024 00:51:55 -0500 Subject: [PATCH 2/5] Assume stake is elevated if currentRequiredStake reverts --- staker/l1_validator.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/staker/l1_validator.go b/staker/l1_validator.go index deaf4dc2dc..d68365ede0 100644 --- a/staker/l1_validator.go +++ b/staker/l1_validator.go @@ -12,6 +12,7 @@ import ( "github.com/offchainlabs/nitro/staker/txbuilder" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/validator" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -187,12 +188,16 @@ func (v *L1Validator) resolveNextNode(ctx context.Context, info *StakerInfo, lat func (v *L1Validator) isRequiredStakeElevated(ctx context.Context) (bool, error) { callOpts := v.getCallOpts(ctx) - requiredStake, err := v.rollup.CurrentRequiredStake(callOpts) + baseStake, err := v.rollup.BaseStake(callOpts) if err != nil { return false, err } - baseStake, err := v.rollup.BaseStake(callOpts) + requiredStake, err := v.rollup.CurrentRequiredStake(callOpts) if err != nil { + if headerreader.ExecutionRevertedRegexp.MatchString(err.Error()) { + log.Warn("execution reverted checking if required state is elevated; assuming elevated", "err", err) + return true, nil + } return false, err } return requiredStake.Cmp(baseStake) > 0, nil From 75112329a44848791ba7fc50b9b0b97463a0c59d Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 13 May 2024 09:38:27 -0500 Subject: [PATCH 3/5] Fix zero bid in data poster --- arbnode/dataposter/data_poster.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index b34552a9b9..6b7644c49e 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -592,7 +592,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u targetBlobCost := arbmath.BigMulByUint(newBlobFeeCap, blobGasUsed) targetNonBlobCost := arbmath.BigSub(targetMaxCost, targetBlobCost) newBaseFeeCap := arbmath.BigDivByUint(targetNonBlobCost, gasLimit) - if lastTx != nil && numBlobs > 0 && arbmath.BigDivToBips(newBaseFeeCap, lastTx.GasFeeCap()) < minRbfIncrease { + if lastTx != nil && numBlobs > 0 && lastTx.GasFeeCap().Sign() > 0 && arbmath.BigDivToBips(newBaseFeeCap, lastTx.GasFeeCap()) < minRbfIncrease { // Increase the non-blob fee cap to the minimum rbf increase newBaseFeeCap = arbmath.BigMulByBips(lastTx.GasFeeCap(), minRbfIncrease) newNonBlobCost := arbmath.BigMulByUint(newBaseFeeCap, gasLimit) @@ -665,6 +665,10 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u return lastTx.GasFeeCap(), lastTx.GasTipCap(), lastTx.BlobGasFeeCap(), nil } + // Ensure we bid at least 1 wei to prevent division by zero + newBaseFeeCap = arbmath.BigMax(newBaseFeeCap, common.Big1) + newBlobFeeCap = arbmath.BigMax(newBlobFeeCap, common.Big1) + return newBaseFeeCap, newTipCap, newBlobFeeCap, nil } @@ -934,8 +938,8 @@ func (p *DataPoster) replaceTx(ctx context.Context, prevTx *storage.QueuedTransa } newTx := *prevTx - if arbmath.BigDivToBips(newFeeCap, prevTx.FullTx.GasFeeCap()) < minRbfIncrease || - (prevTx.FullTx.BlobGasFeeCap() != nil && arbmath.BigDivToBips(newBlobFeeCap, prevTx.FullTx.BlobGasFeeCap()) < minRbfIncrease) { + if (prevTx.FullTx.GasFeeCap().Sign() > 0 && arbmath.BigDivToBips(newFeeCap, prevTx.FullTx.GasFeeCap()) < minRbfIncrease) || + (prevTx.FullTx.BlobGasFeeCap() != nil && prevTx.FullTx.BlobGasFeeCap().Sign() > 0 && arbmath.BigDivToBips(newBlobFeeCap, prevTx.FullTx.BlobGasFeeCap()) < minRbfIncrease) { log.Debug( "no need to replace by fee transaction", "nonce", prevTx.FullTx.Nonce(), From 4d164e4c8b5be72010da9d370ccf5adfc7837d24 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 13 May 2024 10:04:57 -0500 Subject: [PATCH 4/5] Don't return common.Big1 to prevent mutation issues --- arbnode/dataposter/data_poster.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 6b7644c49e..2b0275c735 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -666,8 +666,12 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u } // Ensure we bid at least 1 wei to prevent division by zero - newBaseFeeCap = arbmath.BigMax(newBaseFeeCap, common.Big1) - newBlobFeeCap = arbmath.BigMax(newBlobFeeCap, common.Big1) + if newBaseFeeCap.Sign() == 0 { + newBaseFeeCap.SetInt64(1) + } + if newBlobFeeCap.Sign() == 0 { + newBlobFeeCap.SetInt64(1) + } return newBaseFeeCap, newTipCap, newBlobFeeCap, nil } From 9348855a2f900c24069d378c822a9becaba0c0fa Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Mon, 13 May 2024 10:13:56 -0500 Subject: [PATCH 5/5] Also don't mutate new*feecap --- arbnode/dataposter/data_poster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index 2b0275c735..7bc18a2121 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -667,10 +667,10 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u // Ensure we bid at least 1 wei to prevent division by zero if newBaseFeeCap.Sign() == 0 { - newBaseFeeCap.SetInt64(1) + newBaseFeeCap = big.NewInt(1) } if newBlobFeeCap.Sign() == 0 { - newBlobFeeCap.SetInt64(1) + newBlobFeeCap = big.NewInt(1) } return newBaseFeeCap, newTipCap, newBlobFeeCap, nil