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.
op-challenger: Extract RegistrationTask to dedeuplicate registration …
…code between different game types. (ethereum-optimism#11413)
- Loading branch information
Showing
18 changed files
with
313 additions
and
331 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
Large diffs are not rendered by default.
Oops, something went wrong.
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,254 @@ | ||
package fault | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/url" | ||
"path/filepath" | ||
|
||
"github.com/ethereum-optimism/optimism/op-challenger/config" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/asterisc" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/prestates" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" | ||
faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" | ||
"github.com/ethereum-optimism/optimism/op-challenger/game/types" | ||
"github.com/ethereum-optimism/optimism/op-challenger/metrics" | ||
"github.com/ethereum-optimism/optimism/op-service/clock" | ||
"github.com/ethereum-optimism/optimism/op-service/eth" | ||
"github.com/ethereum-optimism/optimism/op-service/sources/batching" | ||
"github.com/ethereum-optimism/optimism/op-service/sources/caching" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/log" | ||
) | ||
|
||
type RegisterTask struct { | ||
gameType faultTypes.GameType | ||
|
||
getPrestateProvider func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) | ||
newTraceAccessor func( | ||
logger log.Logger, | ||
m metrics.Metricer, | ||
l2Client utils.L2HeaderSource, | ||
prestateProvider faultTypes.PrestateProvider, | ||
vmPrestateProvider faultTypes.PrestateProvider, | ||
rollupClient outputs.OutputRollupClient, | ||
dir string, | ||
l1Head eth.BlockID, | ||
splitDepth faultTypes.Depth, | ||
prestateBlock uint64, | ||
poststateBlock uint64) (*trace.Accessor, error) | ||
} | ||
|
||
func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { | ||
return &RegisterTask{ | ||
gameType: gameType, | ||
getPrestateProvider: cachePrestates( | ||
gameType, | ||
m, | ||
cfg.CannonAbsolutePreStateBaseURL, | ||
cfg.CannonAbsolutePreState, | ||
filepath.Join(cfg.Datadir, "cannon-prestates"), | ||
func(path string) faultTypes.PrestateProvider { | ||
return cannon.NewPrestateProvider(path) | ||
}), | ||
newTraceAccessor: func( | ||
logger log.Logger, | ||
m metrics.Metricer, | ||
l2Client utils.L2HeaderSource, | ||
prestateProvider faultTypes.PrestateProvider, | ||
vmPrestateProvider faultTypes.PrestateProvider, | ||
rollupClient outputs.OutputRollupClient, | ||
dir string, | ||
l1Head eth.BlockID, | ||
splitDepth faultTypes.Depth, | ||
prestateBlock uint64, | ||
poststateBlock uint64) (*trace.Accessor, error) { | ||
provider := vmPrestateProvider.(*cannon.CannonPrestateProvider) | ||
return outputs.NewOutputCannonTraceAccessor(logger, m, cfg.Cannon, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) | ||
}, | ||
} | ||
} | ||
|
||
func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { | ||
return &RegisterTask{ | ||
gameType: gameType, | ||
getPrestateProvider: cachePrestates( | ||
gameType, | ||
m, | ||
cfg.AsteriscAbsolutePreStateBaseURL, | ||
cfg.AsteriscAbsolutePreState, | ||
filepath.Join(cfg.Datadir, "asterisc-prestates"), | ||
func(path string) faultTypes.PrestateProvider { | ||
return asterisc.NewPrestateProvider(path) | ||
}), | ||
newTraceAccessor: func( | ||
logger log.Logger, | ||
m metrics.Metricer, | ||
l2Client utils.L2HeaderSource, | ||
prestateProvider faultTypes.PrestateProvider, | ||
vmPrestateProvider faultTypes.PrestateProvider, | ||
rollupClient outputs.OutputRollupClient, | ||
dir string, | ||
l1Head eth.BlockID, | ||
splitDepth faultTypes.Depth, | ||
prestateBlock uint64, | ||
poststateBlock uint64) (*trace.Accessor, error) { | ||
provider := vmPrestateProvider.(*asterisc.AsteriscPreStateProvider) | ||
return outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.Asterisc, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) | ||
}, | ||
} | ||
} | ||
|
||
func NewAlphabetRegisterTask(gameType faultTypes.GameType) *RegisterTask { | ||
return &RegisterTask{ | ||
gameType: gameType, | ||
getPrestateProvider: func(_ common.Hash) (faultTypes.PrestateProvider, error) { | ||
return alphabet.PrestateProvider, nil | ||
}, | ||
newTraceAccessor: func( | ||
logger log.Logger, | ||
m metrics.Metricer, | ||
l2Client utils.L2HeaderSource, | ||
prestateProvider faultTypes.PrestateProvider, | ||
vmPrestateProvider faultTypes.PrestateProvider, | ||
rollupClient outputs.OutputRollupClient, | ||
dir string, | ||
l1Head eth.BlockID, | ||
splitDepth faultTypes.Depth, | ||
prestateBlock uint64, | ||
poststateBlock uint64) (*trace.Accessor, error) { | ||
return outputs.NewOutputAlphabetTraceAccessor(logger, m, prestateProvider, rollupClient, l2Client, l1Head, splitDepth, prestateBlock, poststateBlock) | ||
}, | ||
} | ||
} | ||
|
||
func cachePrestates( | ||
gameType faultTypes.GameType, | ||
m caching.Metrics, | ||
prestateBaseURL *url.URL, | ||
preStatePath string, | ||
prestateDir string, | ||
newPrestateProvider func(path string) faultTypes.PrestateProvider, | ||
) func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) { | ||
prestateSource := prestates.NewPrestateSource(prestateBaseURL, preStatePath, prestateDir) | ||
prestateProviderCache := prestates.NewPrestateProviderCache(m, fmt.Sprintf("prestates-%v", gameType), func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) { | ||
prestatePath, err := prestateSource.PrestatePath(prestateHash) | ||
if err != nil { | ||
return nil, fmt.Errorf("required prestate %v not available: %w", prestateHash, err) | ||
} | ||
return newPrestateProvider(prestatePath), nil | ||
}) | ||
return prestateProviderCache.GetOrCreate | ||
} | ||
|
||
func (e *RegisterTask) Register( | ||
ctx context.Context, | ||
registry Registry, | ||
oracles OracleRegistry, | ||
systemClock clock.Clock, | ||
l1Clock faultTypes.ClockReader, | ||
logger log.Logger, | ||
m metrics.Metricer, | ||
syncValidator SyncValidator, | ||
rollupClient outputs.OutputRollupClient, | ||
txSender TxSender, | ||
gameFactory *contracts.DisputeGameFactoryContract, | ||
caller *batching.MultiCaller, | ||
l2Client utils.L2HeaderSource, | ||
l1HeaderSource L1HeaderSource, | ||
selective bool, | ||
claimants []common.Address) error { | ||
|
||
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { | ||
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create fault dispute game contracts: %w", err) | ||
} | ||
requiredPrestatehash, err := contract.GetAbsolutePrestateHash(ctx) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to load prestate hash for game %v: %w", game.Proxy, err) | ||
} | ||
|
||
vmPrestateProvider, err := e.getPrestateProvider(requiredPrestatehash) | ||
if err != nil { | ||
return nil, fmt.Errorf("required prestate %v not available for game %v: %w", requiredPrestatehash, game.Proxy, err) | ||
} | ||
|
||
oracle, err := contract.GetOracle(ctx) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to load oracle for game %v: %w", game.Proxy, err) | ||
} | ||
oracles.RegisterOracle(oracle) | ||
prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
splitDepth, err := contract.GetSplitDepth(ctx) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to load split depth: %w", err) | ||
} | ||
l1HeadID, err := loadL1Head(contract, ctx, l1HeaderSource) | ||
if err != nil { | ||
return nil, err | ||
} | ||
prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) | ||
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) { | ||
accessor, err := e.newTraceAccessor(logger, m, l2Client, prestateProvider, vmPrestateProvider, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return accessor, nil | ||
} | ||
prestateValidator := NewPrestateValidator(e.gameType.String(), contract.GetAbsolutePrestateHash, vmPrestateProvider) | ||
startingValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider) | ||
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, startingValidator}, creator, l1HeaderSource, selective, claimants) | ||
} | ||
err := registerOracle(ctx, m, oracles, gameFactory, caller, e.gameType) | ||
if err != nil { | ||
return err | ||
} | ||
registry.RegisterGameType(e.gameType, playerCreator) | ||
|
||
contractCreator := func(game types.GameMetadata) (claims.BondContract, error) { | ||
return contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller) | ||
} | ||
registry.RegisterBondContract(e.gameType, contractCreator) | ||
return nil | ||
} | ||
|
||
func registerOracle(ctx context.Context, m metrics.Metricer, oracles OracleRegistry, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller, gameType faultTypes.GameType) error { | ||
implAddr, err := gameFactory.GetGameImpl(ctx, gameType) | ||
if err != nil { | ||
return fmt.Errorf("failed to load implementation for game type %v: %w", gameType, err) | ||
} | ||
contract, err := contracts.NewFaultDisputeGameContract(ctx, m, implAddr, caller) | ||
if err != nil { | ||
return fmt.Errorf("failed to create fault dispute game contracts: %w", err) | ||
} | ||
oracle, err := contract.GetOracle(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to load oracle address: %w", err) | ||
} | ||
oracles.RegisterOracle(oracle) | ||
return nil | ||
} | ||
|
||
func loadL1Head(contract contracts.FaultDisputeGameContract, ctx context.Context, l1HeaderSource L1HeaderSource) (eth.BlockID, error) { | ||
l1Head, err := contract.GetL1Head(ctx) | ||
if err != nil { | ||
return eth.BlockID{}, fmt.Errorf("failed to load L1 head: %w", err) | ||
} | ||
l1Header, err := l1HeaderSource.HeaderByHash(ctx, l1Head) | ||
if err != nil { | ||
return eth.BlockID{}, fmt.Errorf("failed to load L1 header: %w", err) | ||
} | ||
return eth.HeaderBlockID(l1Header), nil | ||
} |
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
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
Oops, something went wrong.