Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
100 changes: 100 additions & 0 deletions op-challenger/game/fault/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,41 @@ import (
"sync/atomic"
"time"

"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/preimages"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/responder"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/generic"
gameTypes "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/rpcblock"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)

type TxSender interface {
From() common.Address
SendAndWaitSimple(txPurpose string, txs ...txmgr.TxCandidate) error
}

type GameContract interface {
generic.GenericGameLoader
preimages.PreimageGameContract
responder.GameContract
claims.BondContract
ClaimLoader
GetStatus(ctx context.Context) (gameTypes.GameStatus, error)
GetMaxGameDepth(ctx context.Context) (types.Depth, error)
GetMaxClockDuration(ctx context.Context) (time.Duration, error)
GetOracle(ctx context.Context) (contracts.PreimageOracleContract, error)
GetL1Head(ctx context.Context) (common.Hash, error)
}

// Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain.
type Responder interface {
Expand All @@ -31,6 +55,7 @@ type Responder interface {
}

type ClaimLoader interface {
GetClaimCount(ctx context.Context) (uint64, error)
GetAllClaims(ctx context.Context, block rpcblock.Block) ([]types.Claim, error)
IsL2BlockNumberChallenged(ctx context.Context, block rpcblock.Block) (bool, error)
GetClockExtension(ctx context.Context) (time.Duration, error)
Expand All @@ -39,6 +64,8 @@ type ClaimLoader interface {
GetOracle(ctx context.Context) (contracts.PreimageOracleContract, error)
}

type resourceCreator func(ctx context.Context, logger log.Logger, gameDepth types.Depth, l1Head eth.BlockID, dir string) (types.TraceAccessor, error)

type Agent struct {
metrics metrics.Metricer
systemClock clock.Clock
Expand All @@ -56,6 +83,71 @@ type Agent struct {
responseCount atomic.Uint64 // Number of responses made in this game
}

func AgentCreator(
systemClock clock.Clock,
l1Clock types.ClockReader,
m metrics.Metricer,
dir string,
txSender TxSender,
loader GameContract,
creator resourceCreator,
selective bool,
claimants []common.Address,
responseDelay time.Duration,
responseDelayAfter uint64,
) generic.ActorCreator {
return func(ctx context.Context, logger log.Logger, l1Head eth.BlockID) (generic.Actor, error) {
maxClockDuration, err := loader.GetMaxClockDuration(ctx)
if err != nil {
return nil, fmt.Errorf("failed to fetch the game duration: %w", err)
}

gameDepth, err := loader.GetMaxGameDepth(ctx)
if err != nil {
return nil, fmt.Errorf("failed to fetch the game depth: %w", err)
}

accessor, err := creator(ctx, logger, gameDepth, l1Head, dir)
if err != nil {
return nil, fmt.Errorf("failed to create trace accessor: %w", err)
}

oracle, err := loader.GetOracle(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load oracle: %w", err)
}

minLargePreimageSize, err := oracle.MinLargePreimageSize(ctx)
if err != nil {
return nil, fmt.Errorf("failed to load min large preimage size: %w", err)
}
direct := preimages.NewDirectPreimageUploader(logger, txSender, loader)
large := preimages.NewLargePreimageUploader(logger, l1Clock, txSender, oracle)
uploader := preimages.NewSplitPreimageUploader(direct, large, minLargePreimageSize)
responder, err := responder.NewFaultResponder(logger, txSender, loader, uploader, oracle)
if err != nil {
return nil, fmt.Errorf("failed to create the responder: %w", err)
}

agent := NewAgent(
m,
systemClock,
l1Clock,
loader,
gameDepth,
maxClockDuration,
accessor,
responder,
logger,
selective,
claimants,
responseDelay,
responseDelayAfter,
)
return agent, nil
}
}

func NewAgent(
m metrics.Metricer,
systemClock clock.Clock,
Expand Down Expand Up @@ -126,6 +218,14 @@ func (a *Agent) Act(ctx context.Context) error {
return nil
}

func (a *Agent) AdditionalStatus(ctx context.Context) ([]any, error) {
claimCount, err := a.loader.GetClaimCount(ctx)
if err != nil {
return nil, err
}
return []any{"claims", claimCount}, nil
}

func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, game types.Game, action types.Action) {
defer wg.Done()
actionLog := a.log.New("action", action.Type)
Expand Down
4 changes: 4 additions & 0 deletions op-challenger/game/fault/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ func (s *stubClaimLoader) IsL2BlockNumberChallenged(_ context.Context, _ rpcbloc
return s.blockNumChallenged, nil
}

func (s *stubClaimLoader) GetClaimCount(_ context.Context) (uint64, error) {
return uint64(len(s.claims)), nil
}

func (s *stubClaimLoader) GetAllClaims(_ context.Context, _ rpcblock.Block) ([]types.Claim, error) {
s.callCount++
if s.callCount > s.maxLoads && s.maxLoads != 0 {
Expand Down
56 changes: 25 additions & 31 deletions op-challenger/game/fault/register_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"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/generic"
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
Expand All @@ -35,7 +36,7 @@ type RegisterTask struct {
gameType gameTypes.GameType
skipPrestateValidation bool

syncValidator SyncValidator
syncValidator generic.SyncValidator

getTopPrestateProvider func(ctx context.Context, prestateBlock uint64) (faultTypes.PrestateProvider, error)
getBottomPrestateProvider func(ctx context.Context, prestateHash common.Hash) (faultTypes.PrestateProvider, error)
Expand All @@ -51,11 +52,11 @@ type RegisterTask struct {
poststateBlock uint64) (*trace.Accessor, error)
}

func NewSuperCannonRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator SyncValidator) *RegisterTask {
func NewSuperCannonRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator generic.SyncValidator) *RegisterTask {
return newSuperCannonVMRegisterTaskWithConfig(gameType, cfg, m, serverExecutor, rootProvider, syncValidator, cfg.Cannon, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState)
}

func NewSuperCannonKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator SyncValidator) *RegisterTask {
func NewSuperCannonKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator generic.SyncValidator) *RegisterTask {
return newSuperCannonVMRegisterTaskWithConfig(gameType, cfg, m, serverExecutor, rootProvider, syncValidator, cfg.CannonKona, cfg.CannonKonaAbsolutePreStateBaseURL, cfg.CannonKonaAbsolutePreState)
}

Expand All @@ -65,7 +66,7 @@ func newSuperCannonVMRegisterTaskWithConfig(
m caching.Metrics,
serverExecutor vm.OracleServerExecutor,
rootProvider super.RootProvider,
syncValidator SyncValidator,
syncValidator generic.SyncValidator,
vmCfg vm.Config,
preStateBaseURL *url.URL,
preState string,
Expand Down Expand Up @@ -105,11 +106,11 @@ func newSuperCannonVMRegisterTaskWithConfig(
}
}

func NewCannonRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
func NewCannonRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator generic.SyncValidator) *RegisterTask {
return newCannonVMRegisterTaskWithConfig(gameType, cfg, m, serverExecutor, l2Client, rollupClient, syncValidator, cfg.Cannon, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState)
}

func NewCannonKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
func NewCannonKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator generic.SyncValidator) *RegisterTask {
return newCannonVMRegisterTaskWithConfig(gameType, cfg, m, serverExecutor, l2Client, rollupClient, syncValidator, cfg.CannonKona, cfg.CannonKonaAbsolutePreStateBaseURL, cfg.CannonKonaAbsolutePreState)
}

Expand All @@ -120,7 +121,7 @@ func newCannonVMRegisterTaskWithConfig(
serverExecutor vm.OracleServerExecutor,
l2Client utils.L2HeaderSource,
rollupClient outputs.OutputRollupClient,
syncValidator SyncValidator,
syncValidator generic.SyncValidator,
vmCfg vm.Config,
preStateBaseURL *url.URL,
preState string,
Expand Down Expand Up @@ -162,7 +163,7 @@ func newCannonVMRegisterTaskWithConfig(
}
}

func NewAsteriscRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
func NewAsteriscRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator generic.SyncValidator) *RegisterTask {
stateConverter := asterisc.NewStateConverter(cfg.Asterisc)
return &RegisterTask{
gameType: gameType,
Expand Down Expand Up @@ -196,7 +197,7 @@ func NewAsteriscRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m
}
}

func NewAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
func NewAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator generic.SyncValidator) *RegisterTask {
stateConverter := asterisc.NewStateConverter(cfg.Asterisc)
return &RegisterTask{
gameType: gameType,
Expand Down Expand Up @@ -230,7 +231,7 @@ func NewAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config
}
}

func NewSuperAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator SyncValidator) *RegisterTask {
func NewSuperAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator generic.SyncValidator) *RegisterTask {
stateConverter := asterisc.NewStateConverter(cfg.AsteriscKona)
return &RegisterTask{
gameType: gameType,
Expand Down Expand Up @@ -266,7 +267,7 @@ func NewSuperAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.C
}
}

func NewAlphabetRegisterTask(gameType gameTypes.GameType, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
func NewAlphabetRegisterTask(gameType gameTypes.GameType, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator generic.SyncValidator) *RegisterTask {
return &RegisterTask{
gameType: gameType,
syncValidator: syncValidator,
Expand Down Expand Up @@ -323,7 +324,7 @@ func (e *RegisterTask) Register(
txSender TxSender,
gameFactory *contracts.DisputeGameFactoryContract,
caller *batching.MultiCaller,
l1HeaderSource L1HeaderSource,
l1HeaderSource generic.L1HeaderSource,
selective bool,
claimants []common.Address,
responseDelay time.Duration,
Expand Down Expand Up @@ -357,27 +358,32 @@ func (e *RegisterTask) Register(
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, err := e.getTopPrestateProvider(ctx, prestateBlock)
if err != nil {
return nil, fmt.Errorf("failed to create top prestate provider: %w", err)
}
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) {
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, l1HeadID eth.BlockID, dir string) (faultTypes.TraceAccessor, error) {
accessor, err := e.newTraceAccessor(logger, m, prestateProvider, vmPrestateProvider, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock)
if err != nil {
return nil, err
}
return accessor, nil
}
var validators []Validator
var validators []generic.PrestateValidator
if !e.skipPrestateValidation {
validators = append(validators, NewPrestateValidator(e.gameType.String(), contract.GetAbsolutePrestateHash, vmPrestateProvider))
validators = append(validators, NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider))
}
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, e.syncValidator, validators, creator, l1HeaderSource, selective, claimants, responseDelay, responseDelayAfter)
return generic.NewGenericGamePlayer(
ctx,
logger,
game.Proxy,
contract,
e.syncValidator,
validators,
l1HeaderSource,
AgentCreator(systemClock, l1Clock, m, dir, txSender, contract, creator, selective, claimants, responseDelay, responseDelayAfter),
)
}
err := registerOracle(ctx, logger, oracles, gameFactory, e.gameType)
if err != nil {
Expand Down Expand Up @@ -413,15 +419,3 @@ func registerOracle(ctx context.Context, logger log.Logger, oracles OracleRegist
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
}
Loading