Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve stability of getNodeCreationBlock for L3s #2682

Merged
merged 5 commits into from
Oct 1, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions staker/rollup_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@
package staker

import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
"math/big"
"strings"
"sync/atomic"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/offchainlabs/nitro/arbutil"
"github.com/offchainlabs/nitro/solgen/go/rollupgen"
"github.com/offchainlabs/nitro/util/headerreader"
Expand Down Expand Up @@ -51,6 +54,7 @@ type RollupWatcher struct {
client arbutil.L1Interface
baseCallOpts bind.CallOpts
unSupportedL3Method atomic.Bool
supportedL3Method atomic.Bool
}

func NewRollupWatcher(address common.Address, client arbutil.L1Interface, callOpts bind.CallOpts) (*RollupWatcher, error) {
Expand All @@ -73,15 +77,41 @@ func (r *RollupWatcher) getCallOpts(ctx context.Context) *bind.CallOpts {
return &opts
}

const noNodeErr string = "NO_NODE"

func looksLikeNoNodeError(err error) bool {
if err == nil {
return false
}
if strings.Contains(err.Error(), noNodeErr) {
return true
}
var errWithData rpc.DataError
ok := errors.As(err, &errWithData)
if !ok {
return false
}
dataString, ok := errWithData.ErrorData().(string)
if !ok {
return false
}
data := common.FromHex(dataString)
return bytes.Contains(data, []byte(noNodeErr))
}

func (r *RollupWatcher) getNodeCreationBlock(ctx context.Context, nodeNum uint64) (*big.Int, error) {
callOpts := r.getCallOpts(ctx)
if !r.unSupportedL3Method.Load() {
createdAtBlock, err := r.GetNodeCreationBlockForLogLookup(callOpts, nodeNum)
if err == nil {
r.supportedL3Method.Store(true)
return createdAtBlock, nil
}
log.Trace("failed to call getNodeCreationBlockForLogLookup, falling back on node CreatedAtBlock field", "err", err)
if headerreader.ExecutionRevertedRegexp.MatchString(err.Error()) {
if headerreader.ExecutionRevertedRegexp.MatchString(err.Error()) && !looksLikeNoNodeError(err) {
if r.supportedL3Method.Load() {
return nil, fmt.Errorf("getNodeCreationBlockForLogLookup failed despite previously succeeding: %w", err)
}
log.Trace("failed to call getNodeCreationBlockForLogLookup, falling back on node CreatedAtBlock field", "err", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be at least Info - since this will be printed exactly once, and could help debugging some weird cases.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I'm a bit hesitant in general to make stuff like this "info" because 3rd party teams will complain about the "issue" in their logs, or think it's the cause of some other issue, but it indeed might be useful for debugging. I'll upgrade it to info, and maybe think about rewording it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upgraded to info and reworded a bit to help clarify it for 3rd party teams

r.unSupportedL3Method.Store(true)
} else {
return nil, err
Expand Down
Loading