Commit 12a38d0d authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-challenger: Skip prestate verifications for the permissioned game. (#12140)

Simplifies deployment with minimal risk given that only permissioned actors are involved in the game and typically the challenger is only resolving games.
parent 874c0e98
......@@ -31,6 +31,7 @@ import (
type RegisterTask struct {
gameType faultTypes.GameType
skipPrestateValidation bool
getPrestateProvider func(prestateHash common.Hash) (faultTypes.PrestateProvider, error)
newTraceAccessor func(
......@@ -51,6 +52,10 @@ func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m c
stateConverter := cannon.NewStateConverter()
return &RegisterTask{
gameType: gameType,
// Don't validate the absolute prestate or genesis output root for permissioned games
// Only trusted actors participate in these games so they aren't expected to reach the step() call and
// are often configured without valid prestates but the challenger should still resolve the games.
skipPrestateValidation: gameType == faultTypes.PermissionedGameType,
getPrestateProvider: cachePrestates(
gameType,
stateConverter,
......@@ -244,9 +249,12 @@ func (e *RegisterTask) Register(
}
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)
var validators []Validator
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, syncValidator, validators, creator, l1HeaderSource, selective, claimants)
}
err := registerOracle(ctx, m, oracles, gameFactory, caller, e.gameType)
if err != nil {
......
......@@ -58,7 +58,7 @@ func NewHelper(log log.Logger, t *testing.T, require *require.Assertions, dir st
}
}
type Option func(config2 *config.Config)
type Option func(c *config.Config)
func WithFactoryAddress(addr common.Address) Option {
return func(c *config.Config) {
......@@ -84,6 +84,18 @@ func WithPollInterval(pollInterval time.Duration) Option {
}
}
func WithValidPrestateRequired() Option {
return func(c *config.Config) {
c.AllowInvalidPrestate = false
}
}
func WithInvalidCannonPrestate() Option {
return func(c *config.Config) {
c.CannonAbsolutePreState = "/tmp/not-a-real-prestate.foo"
}
}
// FindMonorepoRoot finds the relative path to the monorepo root
// Different tests might be nested in subdirectories of the op-e2e dir.
func FindMonorepoRoot(t *testing.T) string {
......@@ -136,6 +148,13 @@ func WithCannon(t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis)
}
}
func WithPermissioned(t *testing.T, rollupCfg *rollup.Config, l2Genesis *core.Genesis) Option {
return func(c *config.Config) {
c.TraceTypes = append(c.TraceTypes, types.TraceTypePermissioned)
applyCannonConfig(c, t, rollupCfg, l2Genesis)
}
}
func WithAlphabet() Option {
return func(c *config.Config) {
c.TraceTypes = append(c.TraceTypes, types.TraceTypeAlphabet)
......
......@@ -42,6 +42,7 @@ var (
const (
cannonGameType uint32 = 0
permissionedGameType uint32 = 1
alphabetGameType uint32 = 255
)
......@@ -95,13 +96,28 @@ type FactoryHelper struct {
Factory *bindings.DisputeGameFactory
}
func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) *FactoryHelper {
type FactoryCfg struct {
PrivKey *ecdsa.PrivateKey
}
type FactoryOption func(c *FactoryCfg)
func WithFactoryPrivKey(privKey *ecdsa.PrivateKey) FactoryOption {
return func(c *FactoryCfg) {
c.PrivKey = privKey
}
}
func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem, opts ...FactoryOption) *FactoryHelper {
require := require.New(t)
client := system.NodeClient("l1")
chainID, err := client.ChainID(ctx)
require.NoError(err)
privKey := TestKey
opts, err := bind.NewKeyedTransactorWithChainID(privKey, chainID)
factoryCfg := &FactoryCfg{PrivKey: TestKey}
for _, opt := range opts {
opt(factoryCfg)
}
txOpts, err := bind.NewKeyedTransactorWithChainID(factoryCfg.PrivKey, chainID)
require.NoError(err)
l1Deployments := system.L1Deployments()
......@@ -114,8 +130,8 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) *
Require: require,
System: system,
Client: client,
Opts: opts,
PrivKey: privKey,
Opts: txOpts,
PrivKey: factoryCfg.PrivKey,
Factory: factory,
FactoryAddr: factoryAddr,
}
......@@ -152,6 +168,14 @@ func (h *FactoryHelper) StartOutputCannonGameWithCorrectRoot(ctx context.Context
}
func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string, l2BlockNumber uint64, rootClaim common.Hash, opts ...GameOpt) *OutputCannonGameHelper {
return h.startOutputCannonGameOfType(ctx, l2Node, l2BlockNumber, rootClaim, cannonGameType, opts...)
}
func (h *FactoryHelper) StartPermissionedGame(ctx context.Context, l2Node string, l2BlockNumber uint64, rootClaim common.Hash, opts ...GameOpt) *OutputCannonGameHelper {
return h.startOutputCannonGameOfType(ctx, l2Node, l2BlockNumber, rootClaim, permissionedGameType, opts...)
}
func (h *FactoryHelper) startOutputCannonGameOfType(ctx context.Context, l2Node string, l2BlockNumber uint64, rootClaim common.Hash, gameType uint32, opts ...GameOpt) *OutputCannonGameHelper {
cfg := NewGameCfg(opts...)
logger := testlog.Logger(h.T, log.LevelInfo).New("role", "OutputCannonGameHelper")
rollupClient := h.System.RollupClient(l2Node)
......@@ -163,7 +187,7 @@ func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string
defer cancel()
tx, err := transactions.PadGasEstimate(h.Opts, 2, func(opts *bind.TransactOpts) (*types.Transaction, error) {
return h.Factory.Create(opts, cannonGameType, rootClaim, extraData)
return h.Factory.Create(opts, gameType, rootClaim, extraData)
})
h.Require.NoError(err, "create fault dispute game")
rcpt, err := wait.ForReceiptOK(ctx, h.Client, tx.Hash())
......
package faultproofs
import (
"context"
"testing"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
"github.com/ethereum/go-ethereum/common"
)
func TestPermissionedGameType(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, _ := StartFaultDisputeSystem(t)
t.Cleanup(sys.Close)
gameFactory := disputegame.NewFactoryHelper(t, ctx, sys, disputegame.WithFactoryPrivKey(sys.Cfg.Secrets.Proposer))
game := gameFactory.StartPermissionedGame(ctx, "sequencer", 1, common.Hash{0x01, 0xaa})
// Start a challenger with both cannon and alphabet support
gameFactory.StartChallenger(ctx, "TowerDefense",
challenger.WithValidPrestateRequired(),
challenger.WithInvalidCannonPrestate(),
challenger.WithPermissioned(t, sys.RollupConfig, sys.L2GenesisCfg),
challenger.WithPrivKey(sys.Cfg.Secrets.Alice),
)
// Wait for the challenger to respond
game.RootClaim(ctx).WaitForCounterClaim(ctx)
}
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