From f8da0f3df4d0ea63ea4ed68370aed69400e92501 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Thu, 7 Mar 2024 05:47:33 +1000 Subject: [PATCH] op-challenger: Cache the cannon absolute prestate (#9756) The prestate is large so can be slow to load. Verifying the prestate for hundreds of games at startup is repeatedly loading the configured prestate file, adding a large delay to being able to start playing games. --- op-challenger/game/fault/register.go | 3 ++- op-challenger/game/fault/trace/cannon/prestate.go | 8 +++++++- .../game/fault/trace/cannon/prestate_test.go | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/op-challenger/game/fault/register.go b/op-challenger/game/fault/register.go index 03345c902507..46515d0d6e12 100644 --- a/op-challenger/game/fault/register.go +++ b/op-challenger/game/fault/register.go @@ -163,6 +163,7 @@ func registerCannon( l2Client cannon.L2HeaderSource, l1HeaderSource L1HeaderSource, ) error { + cannonPrestateProvider := cannon.NewPrestateProvider(cfg.CannonAbsolutePreState) playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { contract, err := contracts.NewFaultDisputeGameContract(game.Proxy, caller) if err != nil { @@ -188,7 +189,7 @@ func registerCannon( } return accessor, nil } - prestateValidator := NewPrestateValidator("cannon", contract.GetAbsolutePrestateHash, cannon.NewPrestateProvider(cfg.CannonAbsolutePreState)) + prestateValidator := NewPrestateValidator("cannon", contract.GetAbsolutePrestateHash, cannonPrestateProvider) genesisValidator := NewPrestateValidator("output root", contract.GetGenesisOutputRoot, prestateProvider) return NewGamePlayer(ctx, cl, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, genesisValidator}, creator, l1HeaderSource) } diff --git a/op-challenger/game/fault/trace/cannon/prestate.go b/op-challenger/game/fault/trace/cannon/prestate.go index ae6237ca4c72..67d7c55389c2 100644 --- a/op-challenger/game/fault/trace/cannon/prestate.go +++ b/op-challenger/game/fault/trace/cannon/prestate.go @@ -14,10 +14,12 @@ var _ types.PrestateProvider = (*CannonPrestateProvider)(nil) type CannonPrestateProvider struct { prestate string + + prestateCommitment common.Hash } func NewPrestateProvider(prestate string) *CannonPrestateProvider { - return &CannonPrestateProvider{prestate} + return &CannonPrestateProvider{prestate: prestate} } func (p *CannonPrestateProvider) absolutePreState() ([]byte, error) { @@ -29,6 +31,9 @@ func (p *CannonPrestateProvider) absolutePreState() ([]byte, error) { } func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { + if p.prestateCommitment != (common.Hash{}) { + return p.prestateCommitment, nil + } state, err := p.absolutePreState() if err != nil { return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) @@ -37,5 +42,6 @@ func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) ( if err != nil { return common.Hash{}, fmt.Errorf("cannot hash absolute pre-state: %w", err) } + p.prestateCommitment = hash return hash, nil } diff --git a/op-challenger/game/fault/trace/cannon/prestate_test.go b/op-challenger/game/fault/trace/cannon/prestate_test.go index 14b49cf4744d..1f14ebac118e 100644 --- a/op-challenger/game/fault/trace/cannon/prestate_test.go +++ b/op-challenger/game/fault/trace/cannon/prestate_test.go @@ -58,6 +58,21 @@ func TestAbsolutePreStateCommitment(t *testing.T) { require.NoError(t, err) require.Equal(t, expected, actual) }) + + t.Run("CacheAbsolutePreState", func(t *testing.T) { + setupPreState(t, dataDir, "state.json") + provider := newCannonPrestateProvider(dataDir, prestate) + first, err := provider.AbsolutePreStateCommitment(context.Background()) + require.NoError(t, err) + + // Remove the prestate from disk + require.NoError(t, os.Remove(provider.prestate)) + + // Value should still be available from cache + cached, err := provider.AbsolutePreStateCommitment(context.Background()) + require.NoError(t, err) + require.Equal(t, first, cached) + }) } func setupPreState(t *testing.T, dataDir string, filename string) {