forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ethereum-optimism#8110 from ethereum-optimism/aj/s…
…plit-providers op-challenger: Add a provider selector function for split output games
- Loading branch information
Showing
10 changed files
with
460 additions
and
217 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package outputs | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" | ||
) | ||
|
||
var ( | ||
errRefClaimNotDeepEnough = errors.New("reference claim is not deep enough") | ||
) | ||
|
||
type ProviderCreator func(ctx context.Context, pre types.Claim, post types.Claim) (types.TraceProvider, error) | ||
|
||
func newSplitProviderSelector(topProvider types.TraceProvider, topDepth int, bottomProviderCreator ProviderCreator) trace.ProviderSelector { | ||
return func(ctx context.Context, game types.Game, ref types.Claim, pos types.Position) (types.TraceProvider, error) { | ||
if pos.Depth() <= topDepth { | ||
return topProvider, nil | ||
} | ||
if ref.Position.Depth() < topDepth { | ||
return nil, fmt.Errorf("%w, claim depth: %v, depth required: %v", errRefClaimNotDeepEnough, ref.Position.Depth(), topDepth) | ||
} | ||
|
||
// Find the ancestor claim at the leaf level for the top game. | ||
topLeaf, err := findAncestorAtDepth(game, ref, topDepth) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var pre, post types.Claim | ||
// If pos is to the right of the leaf from the top game, we must be defending that output root | ||
// otherwise, we're attacking it. | ||
if pos.TraceIndex(pos.Depth()).Cmp(topLeaf.TraceIndex(pos.Depth())) > 0 { | ||
// Defending the top leaf claim, so use it as the pre-claim and find the post | ||
pre = topLeaf | ||
postTraceIdx := new(big.Int).Add(pre.TraceIndex(topDepth), big.NewInt(1)) | ||
post, err = findAncestorWithTraceIndex(game, topLeaf, topDepth, postTraceIdx) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to find post claim: %w", err) | ||
} | ||
} else { | ||
// Attacking the top leaf claim, so use it as the post-claim and find the pre | ||
post = topLeaf | ||
postTraceIdx := post.TraceIndex(topDepth) | ||
if postTraceIdx.Cmp(big.NewInt(0)) == 0 { | ||
pre = types.Claim{} | ||
} else { | ||
preTraceIdx := new(big.Int).Sub(postTraceIdx, big.NewInt(1)) | ||
pre, err = findAncestorWithTraceIndex(game, topLeaf, topDepth, preTraceIdx) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to find pre claim: %w", err) | ||
} | ||
} | ||
} | ||
provider, err := bottomProviderCreator(ctx, pre, post) | ||
if err != nil { | ||
return nil, err | ||
} | ||
// Translate such that the root of the bottom game is the level below the top game leaf | ||
return trace.Translate(provider, uint64(topDepth)+1), nil | ||
} | ||
} | ||
|
||
func findAncestorAtDepth(game types.Game, claim types.Claim, depth int) (types.Claim, error) { | ||
for claim.Depth() > depth { | ||
parent, err := game.GetParent(claim) | ||
if err != nil { | ||
return types.Claim{}, fmt.Errorf("failed to find ancestor at depth %v: %w", depth, err) | ||
} | ||
claim = parent | ||
} | ||
return claim, nil | ||
} | ||
|
||
func findAncestorWithTraceIndex(game types.Game, ref types.Claim, depth int, traceIdx *big.Int) (types.Claim, error) { | ||
candidate := ref | ||
for candidate.TraceIndex(depth).Cmp(traceIdx) != 0 { | ||
parent, err := game.GetParent(candidate) | ||
if err != nil { | ||
return types.Claim{}, fmt.Errorf("failed to get parent of claim %v: %w", candidate.ContractIndex, err) | ||
} | ||
candidate = parent | ||
} | ||
return candidate, nil | ||
} |
Oops, something went wrong.