Skip to content

Commit

Permalink
Also try to fast confirm past nodes when inactive
Browse files Browse the repository at this point in the history
  • Loading branch information
PlasmaPower committed Aug 1, 2024
1 parent c6f803d commit 5e0f780
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 32 deletions.
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ require (
gopkg.in/natefinch/lumberjack.v2 v2.0.0
)

require github.com/google/go-querystring v1.1.0 // indirect
require (
github.com/google/btree v1.1.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
)

require (
github.com/DataDog/zstd v1.4.5 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,10 @@ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXi
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw=
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
Expand Down
97 changes: 66 additions & 31 deletions staker/staker.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rpc"
"github.com/google/btree"
flag "github.com/spf13/pflag"

"github.com/offchainlabs/nitro/arbnode/dataposter"
Expand Down Expand Up @@ -246,6 +247,11 @@ type LatestConfirmedNotifier interface {
UpdateLatestConfirmed(count arbutil.MessageIndex, globalState validator.GoGlobalState)
}

type validatedNode struct {
number uint64
hash common.Hash
}

type Staker struct {
*L1Validator
stopwaiter.StopWaiter
Expand All @@ -258,6 +264,7 @@ type Staker struct {
highGasBlocksBuffer *big.Int
lastActCalledBlock *big.Int
inactiveLastCheckedNode *nodeAndHash
inactiveValidatedNodes *btree.BTreeG[validatedNode]
bringActiveUntilNode uint64
inboxReader InboxReaderInterface
statelessBlockValidator *StatelessBlockValidator
Expand Down Expand Up @@ -326,6 +333,9 @@ func NewStaker(
return nil, err
}
}
inactiveValidatedNodes := btree.NewG(2, func(a, b validatedNode) bool {
return a.number < b.number || (a.number == b.number && a.hash.Cmp(b.hash) < 0)
})
return &Staker{
L1Validator: val,
l1Reader: l1Reader,
Expand All @@ -339,6 +349,7 @@ func NewStaker(
statelessBlockValidator: statelessBlockValidator,
fatalErr: fatalErr,
fastConfirmSafe: fastConfirmSafe,
inactiveValidatedNodes: inactiveValidatedNodes,
}, nil
}

Expand Down Expand Up @@ -683,12 +694,40 @@ func (s *Staker) Act(ctx context.Context) (*types.Transaction, error) {
StakeExists: rawInfo != nil,
}

effectiveStrategy := s.config.strategy
nodesLinear, err := s.validatorUtils.AreUnresolvedNodesLinear(callOpts, s.rollupAddress)
if err != nil {
return nil, fmt.Errorf("error checking for rollup assertion fork: %w", err)
}
if !nodesLinear {
log.Warn("rollup assertion fork detected")
if effectiveStrategy == DefensiveStrategy {
effectiveStrategy = StakeLatestStrategy
}
s.inactiveLastCheckedNode = nil
}
if s.bringActiveUntilNode != 0 {
if info.LatestStakedNode < s.bringActiveUntilNode {
if effectiveStrategy == DefensiveStrategy {
effectiveStrategy = StakeLatestStrategy
}
} else {
log.Info("defensive validator staked past incorrect node; waiting here")
s.bringActiveUntilNode = 0
}
s.inactiveLastCheckedNode = nil
}
if effectiveStrategy <= DefensiveStrategy && s.inactiveLastCheckedNode != nil {
info.LatestStakedNode = s.inactiveLastCheckedNode.id
info.LatestStakedNodeHash = s.inactiveLastCheckedNode.hash
}

if s.config.EnableFastConfirmation {
firstUnresolvedNode, err := s.rollup.FirstUnresolvedNode(callOpts)
if err != nil {
return nil, err
}
if latestStakedNodeNum >= firstUnresolvedNode {
if info.LatestStakedNode >= firstUnresolvedNode {
lastHeader, err := s.l1Reader.LastHeader(ctx)
if err != nil {
return nil, err
Expand All @@ -698,15 +737,23 @@ func (s *Staker) Act(ctx context.Context) (*types.Transaction, error) {
// To keep this call consistent with the GetNode call, we pin a specific parent chain block hash.
checkNodeCorrectCallOpts := s.getCallOpts(ctx)
checkNodeCorrectCallOpts.BlockHash = lastHeader.ParentHash
stakedOnNode, err := s.rollup.NodeHasStaker(checkNodeCorrectCallOpts, firstUnresolvedNode, walletAddressOrZero)
nodeInfo, err := s.rollup.GetNode(checkNodeCorrectCallOpts, firstUnresolvedNode)
if err != nil {
return nil, err
}
if stakedOnNode {
nodeInfo, err := s.rollup.GetNode(checkNodeCorrectCallOpts, firstUnresolvedNode)
validatedNode, haveValidated := s.inactiveValidatedNodes.Get(validatedNode{
number: firstUnresolvedNode,
hash: nodeInfo.NodeHash,
})
confirmedCorrect := haveValidated && validatedNode.hash == nodeInfo.NodeHash
if !confirmedCorrect {
stakedOnNode, err := s.rollup.NodeHasStaker(checkNodeCorrectCallOpts, firstUnresolvedNode, walletAddressOrZero)
if err != nil {
return nil, err
}
confirmedCorrect = stakedOnNode
}
if confirmedCorrect {
err = s.tryFastConfirmationNodeNumber(ctx, firstUnresolvedNode, nodeInfo.NodeHash)
if err != nil {
return nil, err
Expand All @@ -720,37 +767,21 @@ func (s *Staker) Act(ctx context.Context) (*types.Transaction, error) {
}
}

effectiveStrategy := s.config.strategy
nodesLinear, err := s.validatorUtils.AreUnresolvedNodesLinear(callOpts, s.rollupAddress)
latestConfirmedNode, err := s.rollup.LatestConfirmed(callOpts)
if err != nil {
return nil, fmt.Errorf("error checking for rollup assertion fork: %w", err)
return nil, fmt.Errorf("error getting latest confirmed node: %w", err)
}
if !nodesLinear {
log.Warn("rollup assertion fork detected")
if effectiveStrategy == DefensiveStrategy {
effectiveStrategy = StakeLatestStrategy

// Clear s.inactiveValidatedNodes of any entries before or equal to latestConfirmedNode
for {
validatedNode, ok := s.inactiveValidatedNodes.Min()
if !ok {
break
}
s.inactiveLastCheckedNode = nil
}
if s.bringActiveUntilNode != 0 {
if info.LatestStakedNode < s.bringActiveUntilNode {
if effectiveStrategy == DefensiveStrategy {
effectiveStrategy = StakeLatestStrategy
}
} else {
log.Info("defensive validator staked past incorrect node; waiting here")
s.bringActiveUntilNode = 0
if validatedNode.number > latestConfirmedNode {
break
}
s.inactiveLastCheckedNode = nil
}
if effectiveStrategy <= DefensiveStrategy && s.inactiveLastCheckedNode != nil {
info.LatestStakedNode = s.inactiveLastCheckedNode.id
info.LatestStakedNodeHash = s.inactiveLastCheckedNode.hash
}

latestConfirmedNode, err := s.rollup.LatestConfirmed(callOpts)
if err != nil {
return nil, fmt.Errorf("error getting latest confirmed node: %w", err)
s.inactiveValidatedNodes.DeleteMin()
}

requiredStakeElevated, err := s.isRequiredStakeElevated(ctx)
Expand Down Expand Up @@ -992,6 +1023,10 @@ func (s *Staker) advanceStake(ctx context.Context, info *OurStakerInfo, effectiv
id: action.number,
hash: action.hash,
}
s.inactiveValidatedNodes.ReplaceOrInsert(validatedNode{
number: action.number,
hash: action.hash,
})
}
return s.tryFastConfirmationNodeNumber(ctx, action.number, action.hash)
}
Expand Down

0 comments on commit 5e0f780

Please sign in to comment.