Commit f8da0f3d authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

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.
parent b8242180
...@@ -163,6 +163,7 @@ func registerCannon( ...@@ -163,6 +163,7 @@ func registerCannon(
l2Client cannon.L2HeaderSource, l2Client cannon.L2HeaderSource,
l1HeaderSource L1HeaderSource, l1HeaderSource L1HeaderSource,
) error { ) error {
cannonPrestateProvider := cannon.NewPrestateProvider(cfg.CannonAbsolutePreState)
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
contract, err := contracts.NewFaultDisputeGameContract(game.Proxy, caller) contract, err := contracts.NewFaultDisputeGameContract(game.Proxy, caller)
if err != nil { if err != nil {
...@@ -188,7 +189,7 @@ func registerCannon( ...@@ -188,7 +189,7 @@ func registerCannon(
} }
return accessor, nil 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) genesisValidator := NewPrestateValidator("output root", contract.GetGenesisOutputRoot, prestateProvider)
return NewGamePlayer(ctx, cl, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, genesisValidator}, creator, l1HeaderSource) return NewGamePlayer(ctx, cl, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, genesisValidator}, creator, l1HeaderSource)
} }
......
...@@ -14,10 +14,12 @@ var _ types.PrestateProvider = (*CannonPrestateProvider)(nil) ...@@ -14,10 +14,12 @@ var _ types.PrestateProvider = (*CannonPrestateProvider)(nil)
type CannonPrestateProvider struct { type CannonPrestateProvider struct {
prestate string prestate string
prestateCommitment common.Hash
} }
func NewPrestateProvider(prestate string) *CannonPrestateProvider { func NewPrestateProvider(prestate string) *CannonPrestateProvider {
return &CannonPrestateProvider{prestate} return &CannonPrestateProvider{prestate: prestate}
} }
func (p *CannonPrestateProvider) absolutePreState() ([]byte, error) { func (p *CannonPrestateProvider) absolutePreState() ([]byte, error) {
...@@ -29,6 +31,9 @@ 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) { func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) {
if p.prestateCommitment != (common.Hash{}) {
return p.prestateCommitment, nil
}
state, err := p.absolutePreState() state, err := p.absolutePreState()
if err != nil { if err != nil {
return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err)
...@@ -37,5 +42,6 @@ func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) ( ...@@ -37,5 +42,6 @@ func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (
if err != nil { if err != nil {
return common.Hash{}, fmt.Errorf("cannot hash absolute pre-state: %w", err) return common.Hash{}, fmt.Errorf("cannot hash absolute pre-state: %w", err)
} }
p.prestateCommitment = hash
return hash, nil return hash, nil
} }
...@@ -58,6 +58,21 @@ func TestAbsolutePreStateCommitment(t *testing.T) { ...@@ -58,6 +58,21 @@ func TestAbsolutePreStateCommitment(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expected, actual) 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) { func setupPreState(t *testing.T, dataDir string, filename string) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment