Skip to content

Commit c329947

Browse files
authored
op-challenger: Introduce generic Player (ethereum-optimism#18441)
* op-challenger: Extract generic game player Handles common checks before delegating to an actor to progress the game. * op-challenger: Remove remnants of fault.Player
1 parent 13e3a7c commit c329947

File tree

5 files changed

+184
-134
lines changed

5 files changed

+184
-134
lines changed

op-challenger/game/fault/agent.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,41 @@ import (
99
"sync/atomic"
1010
"time"
1111

12+
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims"
1213
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
14+
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages"
15+
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/responder"
1316
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver"
1417
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
18+
"github.com/ethereum-optimism/optimism/op-challenger/game/generic"
1519
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
1620
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
1721
"github.com/ethereum-optimism/optimism/op-service/clock"
22+
"github.com/ethereum-optimism/optimism/op-service/eth"
1823
"github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock"
24+
"github.com/ethereum-optimism/optimism/op-service/txmgr"
1925
"github.com/ethereum/go-ethereum/common"
2026
"github.com/ethereum/go-ethereum/log"
2127
)
2228

29+
type TxSender interface {
30+
From() common.Address
31+
SendAndWaitSimple(txPurpose string, txs ...txmgr.TxCandidate) error
32+
}
33+
34+
type GameContract interface {
35+
generic.GenericGameLoader
36+
preimages.PreimageGameContract
37+
responder.GameContract
38+
claims.BondContract
39+
ClaimLoader
40+
GetStatus(ctx context.Context) (gameTypes.GameStatus, error)
41+
GetMaxGameDepth(ctx context.Context) (types.Depth, error)
42+
GetMaxClockDuration(ctx context.Context) (time.Duration, error)
43+
GetOracle(ctx context.Context) (contracts.PreimageOracleContract, error)
44+
GetL1Head(ctx context.Context) (common.Hash, error)
45+
}
46+
2347
// Responder takes a response action & executes.
2448
// For full op-challenger this means executing the transaction on chain.
2549
type Responder interface {
@@ -31,6 +55,7 @@ type Responder interface {
3155
}
3256

3357
type ClaimLoader interface {
58+
GetClaimCount(ctx context.Context) (uint64, error)
3459
GetAllClaims(ctx context.Context, block rpcblock.Block) ([]types.Claim, error)
3560
IsL2BlockNumberChallenged(ctx context.Context, block rpcblock.Block) (bool, error)
3661
GetClockExtension(ctx context.Context) (time.Duration, error)
@@ -39,6 +64,8 @@ type ClaimLoader interface {
3964
GetOracle(ctx context.Context) (contracts.PreimageOracleContract, error)
4065
}
4166

67+
type resourceCreator func(ctx context.Context, logger log.Logger, gameDepth types.Depth, l1Head eth.BlockID, dir string) (types.TraceAccessor, error)
68+
4269
type Agent struct {
4370
metrics metrics.Metricer
4471
systemClock clock.Clock
@@ -56,6 +83,71 @@ type Agent struct {
5683
responseCount atomic.Uint64 // Number of responses made in this game
5784
}
5885

86+
func AgentCreator(
87+
systemClock clock.Clock,
88+
l1Clock types.ClockReader,
89+
m metrics.Metricer,
90+
dir string,
91+
txSender TxSender,
92+
loader GameContract,
93+
creator resourceCreator,
94+
selective bool,
95+
claimants []common.Address,
96+
responseDelay time.Duration,
97+
responseDelayAfter uint64,
98+
) generic.ActorCreator {
99+
return func(ctx context.Context, logger log.Logger, l1Head eth.BlockID) (generic.Actor, error) {
100+
maxClockDuration, err := loader.GetMaxClockDuration(ctx)
101+
if err != nil {
102+
return nil, fmt.Errorf("failed to fetch the game duration: %w", err)
103+
}
104+
105+
gameDepth, err := loader.GetMaxGameDepth(ctx)
106+
if err != nil {
107+
return nil, fmt.Errorf("failed to fetch the game depth: %w", err)
108+
}
109+
110+
accessor, err := creator(ctx, logger, gameDepth, l1Head, dir)
111+
if err != nil {
112+
return nil, fmt.Errorf("failed to create trace accessor: %w", err)
113+
}
114+
115+
oracle, err := loader.GetOracle(ctx)
116+
if err != nil {
117+
return nil, fmt.Errorf("failed to load oracle: %w", err)
118+
}
119+
120+
minLargePreimageSize, err := oracle.MinLargePreimageSize(ctx)
121+
if err != nil {
122+
return nil, fmt.Errorf("failed to load min large preimage size: %w", err)
123+
}
124+
direct := preimages.NewDirectPreimageUploader(logger, txSender, loader)
125+
large := preimages.NewLargePreimageUploader(logger, l1Clock, txSender, oracle)
126+
uploader := preimages.NewSplitPreimageUploader(direct, large, minLargePreimageSize)
127+
responder, err := responder.NewFaultResponder(logger, txSender, loader, uploader, oracle)
128+
if err != nil {
129+
return nil, fmt.Errorf("failed to create the responder: %w", err)
130+
}
131+
132+
agent := NewAgent(
133+
m,
134+
systemClock,
135+
l1Clock,
136+
loader,
137+
gameDepth,
138+
maxClockDuration,
139+
accessor,
140+
responder,
141+
logger,
142+
selective,
143+
claimants,
144+
responseDelay,
145+
responseDelayAfter,
146+
)
147+
return agent, nil
148+
}
149+
}
150+
59151
func NewAgent(
60152
m metrics.Metricer,
61153
systemClock clock.Clock,
@@ -126,6 +218,14 @@ func (a *Agent) Act(ctx context.Context) error {
126218
return nil
127219
}
128220

221+
func (a *Agent) AdditionalStatus(ctx context.Context) ([]any, error) {
222+
claimCount, err := a.loader.GetClaimCount(ctx)
223+
if err != nil {
224+
return nil, err
225+
}
226+
return []any{"claims", claimCount}, nil
227+
}
228+
129229
func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, game types.Game, action types.Action) {
130230
defer wg.Done()
131231
actionLog := a.log.New("action", action.Type)

op-challenger/game/fault/agent_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ func (s *stubClaimLoader) IsL2BlockNumberChallenged(_ context.Context, _ rpcbloc
236236
return s.blockNumChallenged, nil
237237
}
238238

239+
func (s *stubClaimLoader) GetClaimCount(_ context.Context) (uint64, error) {
240+
return uint64(len(s.claims)), nil
241+
}
242+
239243
func (s *stubClaimLoader) GetAllClaims(_ context.Context, _ rpcblock.Block) ([]types.Claim, error) {
240244
s.callCount++
241245
if s.callCount > s.maxLoads && s.maxLoads != 0 {

op-challenger/game/fault/register_task.go

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
2121
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
2222
faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
23+
"github.com/ethereum-optimism/optimism/op-challenger/game/generic"
2324
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
2425
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
2526
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
@@ -35,7 +36,7 @@ type RegisterTask struct {
3536
gameType gameTypes.GameType
3637
skipPrestateValidation bool
3738

38-
syncValidator SyncValidator
39+
syncValidator generic.SyncValidator
3940

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

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

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

@@ -65,7 +66,7 @@ func newSuperCannonVMRegisterTaskWithConfig(
6566
m caching.Metrics,
6667
serverExecutor vm.OracleServerExecutor,
6768
rootProvider super.RootProvider,
68-
syncValidator SyncValidator,
69+
syncValidator generic.SyncValidator,
6970
vmCfg vm.Config,
7071
preStateBaseURL *url.URL,
7172
preState string,
@@ -105,11 +106,11 @@ func newSuperCannonVMRegisterTaskWithConfig(
105106
}
106107
}
107108

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

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

@@ -120,7 +121,7 @@ func newCannonVMRegisterTaskWithConfig(
120121
serverExecutor vm.OracleServerExecutor,
121122
l2Client utils.L2HeaderSource,
122123
rollupClient outputs.OutputRollupClient,
123-
syncValidator SyncValidator,
124+
syncValidator generic.SyncValidator,
124125
vmCfg vm.Config,
125126
preStateBaseURL *url.URL,
126127
preState string,
@@ -162,7 +163,7 @@ func newCannonVMRegisterTaskWithConfig(
162163
}
163164
}
164165

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

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

233-
func NewSuperAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator SyncValidator) *RegisterTask {
234+
func NewSuperAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor, rootProvider super.RootProvider, syncValidator generic.SyncValidator) *RegisterTask {
234235
stateConverter := asterisc.NewStateConverter(cfg.AsteriscKona)
235236
return &RegisterTask{
236237
gameType: gameType,
@@ -266,7 +267,7 @@ func NewSuperAsteriscKonaRegisterTask(gameType gameTypes.GameType, cfg *config.C
266267
}
267268
}
268269

269-
func NewAlphabetRegisterTask(gameType gameTypes.GameType, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator SyncValidator) *RegisterTask {
270+
func NewAlphabetRegisterTask(gameType gameTypes.GameType, l2Client utils.L2HeaderSource, rollupClient outputs.OutputRollupClient, syncValidator generic.SyncValidator) *RegisterTask {
270271
return &RegisterTask{
271272
gameType: gameType,
272273
syncValidator: syncValidator,
@@ -323,7 +324,7 @@ func (e *RegisterTask) Register(
323324
txSender TxSender,
324325
gameFactory *contracts.DisputeGameFactoryContract,
325326
caller *batching.MultiCaller,
326-
l1HeaderSource L1HeaderSource,
327+
l1HeaderSource generic.L1HeaderSource,
327328
selective bool,
328329
claimants []common.Address,
329330
responseDelay time.Duration,
@@ -357,27 +358,32 @@ func (e *RegisterTask) Register(
357358
if err != nil {
358359
return nil, fmt.Errorf("failed to load split depth: %w", err)
359360
}
360-
l1HeadID, err := loadL1Head(contract, ctx, l1HeaderSource)
361-
if err != nil {
362-
return nil, err
363-
}
364361
prestateProvider, err := e.getTopPrestateProvider(ctx, prestateBlock)
365362
if err != nil {
366363
return nil, fmt.Errorf("failed to create top prestate provider: %w", err)
367364
}
368-
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) {
365+
creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, l1HeadID eth.BlockID, dir string) (faultTypes.TraceAccessor, error) {
369366
accessor, err := e.newTraceAccessor(logger, m, prestateProvider, vmPrestateProvider, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock)
370367
if err != nil {
371368
return nil, err
372369
}
373370
return accessor, nil
374371
}
375-
var validators []Validator
372+
var validators []generic.PrestateValidator
376373
if !e.skipPrestateValidation {
377374
validators = append(validators, NewPrestateValidator(e.gameType.String(), contract.GetAbsolutePrestateHash, vmPrestateProvider))
378375
validators = append(validators, NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider))
379376
}
380-
return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, e.syncValidator, validators, creator, l1HeaderSource, selective, claimants, responseDelay, responseDelayAfter)
377+
return generic.NewGenericGamePlayer(
378+
ctx,
379+
logger,
380+
game.Proxy,
381+
contract,
382+
e.syncValidator,
383+
validators,
384+
l1HeaderSource,
385+
AgentCreator(systemClock, l1Clock, m, dir, txSender, contract, creator, selective, claimants, responseDelay, responseDelayAfter),
386+
)
381387
}
382388
err := registerOracle(ctx, logger, oracles, gameFactory, e.gameType)
383389
if err != nil {
@@ -413,15 +419,3 @@ func registerOracle(ctx context.Context, logger log.Logger, oracles OracleRegist
413419
oracles.RegisterOracle(oracle)
414420
return nil
415421
}
416-
417-
func loadL1Head(contract contracts.FaultDisputeGameContract, ctx context.Context, l1HeaderSource L1HeaderSource) (eth.BlockID, error) {
418-
l1Head, err := contract.GetL1Head(ctx)
419-
if err != nil {
420-
return eth.BlockID{}, fmt.Errorf("failed to load L1 head: %w", err)
421-
}
422-
l1Header, err := l1HeaderSource.HeaderByHash(ctx, l1Head)
423-
if err != nil {
424-
return eth.BlockID{}, fmt.Errorf("failed to load L1 header: %w", err)
425-
}
426-
return eth.HeaderBlockID(l1Header), nil
427-
}

0 commit comments

Comments
 (0)