Commit 58f74b1d authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

Introduce fast dispute game type (#10715)

* Introduce fast dispute game type

Avoids the need to change configuration to support fast withdrawals via fault proofs.

* e2e: Wait for game to become resolvable.

* Update kontrol snapshots.

* e2e: Set correct game type for proposer.

* challenger: Fast games are alphabet vm, not cannon.

* Set fast game clock duration to 0.

* Update snapshots again

* Use game type consistently.
parent f41e8f1e
...@@ -132,8 +132,6 @@ def init_devnet_l1_deploy_config(paths, update_timestamp=False): ...@@ -132,8 +132,6 @@ def init_devnet_l1_deploy_config(paths, update_timestamp=False):
deploy_config['l1GenesisBlockTimestamp'] = '{:#x}'.format(int(time.time())) deploy_config['l1GenesisBlockTimestamp'] = '{:#x}'.format(int(time.time()))
if DEVNET_FPAC: if DEVNET_FPAC:
deploy_config['useFaultProofs'] = True deploy_config['useFaultProofs'] = True
deploy_config['faultGameMaxClockDuration'] = 10
deploy_config['faultGameWithdrawalDelay'] = 0
if DEVNET_PLASMA: if DEVNET_PLASMA:
deploy_config['usePlasma'] = True deploy_config['usePlasma'] = True
if GENERIC_PLASMA: if GENERIC_PLASMA:
...@@ -269,7 +267,7 @@ def devnet_deploy(paths): ...@@ -269,7 +267,7 @@ def devnet_deploy(paths):
# Must be done selectively because op-proposer throws if both are set. # Must be done selectively because op-proposer throws if both are set.
if DEVNET_FPAC: if DEVNET_FPAC:
docker_env['DGF_ADDRESS'] = dispute_game_factory docker_env['DGF_ADDRESS'] = dispute_game_factory
docker_env['DG_TYPE'] = '0' docker_env['DG_TYPE'] = '254'
docker_env['PROPOSAL_INTERVAL'] = '10s' docker_env['PROPOSAL_INTERVAL'] = '10s'
else: else:
docker_env['L2OO_ADDRESS'] = l2_output_oracle docker_env['L2OO_ADDRESS'] = l2_output_oracle
......
...@@ -54,12 +54,13 @@ type TraceType string ...@@ -54,12 +54,13 @@ type TraceType string
const ( const (
TraceTypeAlphabet TraceType = "alphabet" TraceTypeAlphabet TraceType = "alphabet"
TraceTypeFast TraceType = "fast"
TraceTypeCannon TraceType = "cannon" TraceTypeCannon TraceType = "cannon"
TraceTypeAsterisc TraceType = "asterisc" TraceTypeAsterisc TraceType = "asterisc"
TraceTypePermissioned TraceType = "permissioned" TraceTypePermissioned TraceType = "permissioned"
) )
var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc} var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc, TraceTypeFast}
func (t TraceType) String() string { func (t TraceType) String() string {
return string(t) return string(t)
......
...@@ -398,7 +398,7 @@ func TestRequireConfigForMultipleTraceTypesForCannonAndAsterisc(t *testing.T) { ...@@ -398,7 +398,7 @@ func TestRequireConfigForMultipleTraceTypesForCannonAndAsterisc(t *testing.T) {
cfg := validConfig(TraceTypeCannon) cfg := validConfig(TraceTypeCannon)
applyValidConfigForAsterisc(&cfg) applyValidConfigForAsterisc(&cfg)
cfg.TraceTypes = []TraceType{TraceTypeCannon, TraceTypeAsterisc, TraceTypeAlphabet} cfg.TraceTypes = []TraceType{TraceTypeCannon, TraceTypeAsterisc, TraceTypeAlphabet, TraceTypeFast}
// Set all required options and check its valid // Set all required options and check its valid
cfg.RollupRpc = validRollupRpc cfg.RollupRpc = validRollupRpc
require.NoError(t, cfg.Check()) require.NoError(t, cfg.Check())
......
...@@ -346,7 +346,7 @@ func CheckRequired(ctx *cli.Context, traceTypes []config.TraceType) error { ...@@ -346,7 +346,7 @@ func CheckRequired(ctx *cli.Context, traceTypes []config.TraceType) error {
if err := CheckAsteriscFlags(ctx); err != nil { if err := CheckAsteriscFlags(ctx); err != nil {
return err return err
} }
case config.TraceTypeAlphabet: case config.TraceTypeAlphabet, config.TraceTypeFast:
default: default:
return fmt.Errorf("invalid trace type. must be one of %v", config.TraceTypes) return fmt.Errorf("invalid trace type. must be one of %v", config.TraceTypes)
} }
......
...@@ -88,8 +88,13 @@ func RegisterGameTypes( ...@@ -88,8 +88,13 @@ func RegisterGameTypes(
return nil, fmt.Errorf("failed to register asterisc game type: %w", err) return nil, fmt.Errorf("failed to register asterisc game type: %w", err)
} }
} }
if cfg.TraceTypeEnabled(config.TraceTypeFast) {
if err := registerAlphabet(faultTypes.FastGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, syncValidator, rollupClient, l2Client, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register fast game type: %w", err)
}
}
if cfg.TraceTypeEnabled(config.TraceTypeAlphabet) { if cfg.TraceTypeEnabled(config.TraceTypeAlphabet) {
if err := registerAlphabet(registry, oracles, ctx, systemClock, l1Clock, logger, m, syncValidator, rollupClient, l2Client, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil { if err := registerAlphabet(faultTypes.AlphabetGameType, registry, oracles, ctx, systemClock, l1Clock, logger, m, syncValidator, rollupClient, l2Client, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil {
return nil, fmt.Errorf("failed to register alphabet game type: %w", err) return nil, fmt.Errorf("failed to register alphabet game type: %w", err)
} }
} }
...@@ -97,6 +102,7 @@ func RegisterGameTypes( ...@@ -97,6 +102,7 @@ func RegisterGameTypes(
} }
func registerAlphabet( func registerAlphabet(
gameType uint32,
registry Registry, registry Registry,
oracles OracleRegistry, oracles OracleRegistry,
ctx context.Context, ctx context.Context,
...@@ -148,16 +154,16 @@ func registerAlphabet( ...@@ -148,16 +154,16 @@ func registerAlphabet(
startingValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider) 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) return NewGamePlayer(ctx, systemClock, l1Clock, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, startingValidator}, creator, l1HeaderSource, selective, claimants)
} }
err := registerOracle(ctx, m, oracles, gameFactory, caller, faultTypes.AlphabetGameType) err := registerOracle(ctx, m, oracles, gameFactory, caller, gameType)
if err != nil { if err != nil {
return err return err
} }
registry.RegisterGameType(faultTypes.AlphabetGameType, playerCreator) registry.RegisterGameType(gameType, playerCreator)
contractCreator := func(game types.GameMetadata) (claims.BondContract, error) { contractCreator := func(game types.GameMetadata) (claims.BondContract, error) {
return contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller) return contracts.NewFaultDisputeGameContract(ctx, m, game.Proxy, caller)
} }
registry.RegisterBondContract(faultTypes.AlphabetGameType, contractCreator) registry.RegisterBondContract(gameType, contractCreator)
return nil return nil
} }
......
...@@ -22,6 +22,7 @@ const ( ...@@ -22,6 +22,7 @@ const (
CannonGameType uint32 = 0 CannonGameType uint32 = 0
PermissionedGameType uint32 = 1 PermissionedGameType uint32 = 1
AsteriscGameType uint32 = 2 AsteriscGameType uint32 = 2
FastGameType uint32 = 254
AlphabetGameType uint32 = 255 AlphabetGameType uint32 = 255
) )
......
...@@ -57,10 +57,14 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -57,10 +57,14 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
var proposer *L2Proposer var proposer *L2Proposer
if e2eutils.UseFPAC() { if e2eutils.UseFPAC() {
optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2(sd.DeploymentsL1.OptimismPortalProxy, miner.EthClient())
require.NoError(t, err)
respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{})
require.NoError(t, err)
proposer = NewL2Proposer(t, log, &ProposerCfg{ proposer = NewL2Proposer(t, log, &ProposerCfg{
DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy, DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy,
ProposalInterval: 6 * time.Second, ProposalInterval: 6 * time.Second,
DisputeGameType: 0, DisputeGameType: respectedGameType,
ProposerKey: dp.Secrets.Proposer, ProposerKey: dp.Secrets.Proposer,
AllowNonFinalized: true, AllowNonFinalized: true,
}, miner.EthClient(), rollupSeqCl) }, miner.EthClient(), rollupSeqCl)
......
package actions package actions
import ( import (
"context"
"crypto/ecdsa" "crypto/ecdsa"
"errors" "errors"
"fmt" "fmt"
...@@ -8,6 +9,10 @@ import ( ...@@ -8,6 +9,10 @@ import (
"math/rand" "math/rand"
"time" "time"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -450,7 +455,7 @@ func (s *CrossLayerUser) getLatestWithdrawalParams(t Testing) (*withdrawals.Prov ...@@ -450,7 +455,7 @@ func (s *CrossLayerUser) getLatestWithdrawalParams(t Testing) (*withdrawals.Prov
return &params, nil return &params, nil
} }
func (s *CrossLayerUser) getDisputeGame(t Testing, params withdrawals.ProvenWithdrawalParameters) (*legacybindings.FaultDisputeGame, error) { func (s *CrossLayerUser) getDisputeGame(t Testing, params withdrawals.ProvenWithdrawalParameters) (*legacybindings.FaultDisputeGame, common.Address, error) {
wd := crossdomain.Withdrawal{ wd := crossdomain.Withdrawal{
Nonce: params.Nonce, Nonce: params.Nonce,
Sender: &params.Sender, Sender: &params.Sender,
...@@ -473,7 +478,7 @@ func (s *CrossLayerUser) getDisputeGame(t Testing, params withdrawals.ProvenWith ...@@ -473,7 +478,7 @@ func (s *CrossLayerUser) getDisputeGame(t Testing, params withdrawals.ProvenWith
proxy, err := legacybindings.NewFaultDisputeGame(game.DisputeGameProxy, s.L1.env.EthCl) proxy, err := legacybindings.NewFaultDisputeGame(game.DisputeGameProxy, s.L1.env.EthCl)
require.Nil(t, err) require.Nil(t, err)
return proxy, nil return proxy, game.DisputeGameProxy, nil
} }
// ActCompleteWithdrawal creates a L1 proveWithdrawal tx for latest withdrawal. // ActCompleteWithdrawal creates a L1 proveWithdrawal tx for latest withdrawal.
...@@ -562,13 +567,21 @@ func (s *CrossLayerUser) ResolveClaim(t Testing, l2TxHash common.Hash) common.Ha ...@@ -562,13 +567,21 @@ func (s *CrossLayerUser) ResolveClaim(t Testing, l2TxHash common.Hash) common.Ha
return common.Hash{} return common.Hash{}
} }
game, err := s.getDisputeGame(t, *params) game, gameAddr, err := s.getDisputeGame(t, *params)
require.NoError(t, err) require.NoError(t, err)
expiry, err := game.MaxClockDuration(&bind.CallOpts{}) caller := batching.NewMultiCaller(s.L1.env.EthCl.Client(), batching.DefaultBatchSize)
gameContract, err := contracts.NewFaultDisputeGameContract(context.Background(), metrics.NoopContractMetrics, gameAddr, caller)
require.Nil(t, err) require.Nil(t, err)
time.Sleep(time.Duration(expiry) * time.Second) timedCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
require.NoError(t, wait.For(timedCtx, time.Second, func() (bool, error) {
err := gameContract.CallResolveClaim(context.Background(), 0)
t.Logf("Could not resolve dispute game claim: %v", err)
return err == nil, nil
}))
resolveClaimTx, err := game.ResolveClaim(&s.L1.txOpts, common.Big0, common.Big0) resolveClaimTx, err := game.ResolveClaim(&s.L1.txOpts, common.Big0, common.Big0)
require.Nil(t, err) require.Nil(t, err)
...@@ -592,7 +605,7 @@ func (s *CrossLayerUser) Resolve(t Testing, l2TxHash common.Hash) common.Hash { ...@@ -592,7 +605,7 @@ func (s *CrossLayerUser) Resolve(t Testing, l2TxHash common.Hash) common.Hash {
return common.Hash{} return common.Hash{}
} }
game, err := s.getDisputeGame(t, *params) game, _, err := s.getDisputeGame(t, *params)
require.NoError(t, err) require.NoError(t, err)
resolveTx, err := game.Resolve(&s.L1.txOpts) resolveTx, err := game.Resolve(&s.L1.txOpts)
......
...@@ -6,6 +6,8 @@ import ( ...@@ -6,6 +6,8 @@ import (
"testing" "testing"
"time" "time"
bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -135,10 +137,14 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { ...@@ -135,10 +137,14 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) {
var proposer *L2Proposer var proposer *L2Proposer
if e2eutils.UseFPAC() { if e2eutils.UseFPAC() {
optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2(sd.DeploymentsL1.OptimismPortalProxy, miner.EthClient())
require.NoError(t, err)
respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{})
require.NoError(t, err)
proposer = NewL2Proposer(t, log, &ProposerCfg{ proposer = NewL2Proposer(t, log, &ProposerCfg{
DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy, DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy,
ProposalInterval: 6 * time.Second, ProposalInterval: 6 * time.Second,
DisputeGameType: 0, DisputeGameType: respectedGameType,
ProposerKey: dp.Secrets.Proposer, ProposerKey: dp.Secrets.Proposer,
AllowNonFinalized: true, AllowNonFinalized: true,
}, miner.EthClient(), seq.RollupClient()) }, miner.EthClient(), seq.RollupClient())
......
...@@ -133,6 +133,12 @@ func WithAlphabet() Option { ...@@ -133,6 +133,12 @@ func WithAlphabet() Option {
} }
} }
func WithFastGames() Option {
return func(c *config.Config) {
c.TraceTypes = append(c.TraceTypes, config.TraceTypeFast)
}
}
func NewChallenger(t *testing.T, ctx context.Context, sys EndpointProvider, name string, options ...Option) *Helper { func NewChallenger(t *testing.T, ctx context.Context, sys EndpointProvider, name string, options ...Option) *Helper {
log := testlog.Logger(t, log.LevelDebug).New("role", name) log := testlog.Logger(t, log.LevelDebug).New("role", name)
log.Info("Creating challenger") log.Info("Creating challenger")
......
...@@ -303,7 +303,7 @@ func TestHighestActedL1BlockMetric(t *testing.T) { ...@@ -303,7 +303,7 @@ func TestHighestActedL1BlockMetric(t *testing.T) {
t.Cleanup(sys.Close) t.Cleanup(sys.Close)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
honestChallenger := disputeGameFactory.StartChallenger(ctx, "Honest", challenger.WithAlphabet(), challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) honestChallenger := disputeGameFactory.StartChallenger(ctx, "Honest", challenger.WithAlphabet(), challenger.WithFastGames(), challenger.WithPrivKey(sys.Cfg.Secrets.Alice))
game1 := disputeGameFactory.StartOutputAlphabetGame(ctx, "sequencer", 1, common.Hash{0xaa}) game1 := disputeGameFactory.StartOutputAlphabetGame(ctx, "sequencer", 1, common.Hash{0xaa})
sys.AdvanceTime(game1.MaxClockDuration(ctx)) sys.AdvanceTime(game1.MaxClockDuration(ctx))
......
...@@ -782,7 +782,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste ...@@ -782,7 +782,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste
RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(),
DGFAddress: config.L1Deployments.DisputeGameFactoryProxy.Hex(), DGFAddress: config.L1Deployments.DisputeGameFactoryProxy.Hex(),
ProposalInterval: 6 * time.Second, ProposalInterval: 6 * time.Second,
DisputeGameType: 0, DisputeGameType: 254, // Fast game type
PollInterval: 50 * time.Millisecond, PollInterval: 50 * time.Millisecond,
TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer), TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer),
AllowNonFinalized: cfg.NonFinalizedProposals, AllowNonFinalized: cfg.NonFinalizedProposals,
......
...@@ -659,7 +659,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { ...@@ -659,7 +659,7 @@ func TestMixedWithdrawalValidity(t *testing.T) {
// Start a challenger to resolve claims and games once the clock expires // Start a challenger to resolve claims and games once the clock expires
factoryHelper := disputegame.NewFactoryHelper(t, ctx, sys) factoryHelper := disputegame.NewFactoryHelper(t, ctx, sys)
factoryHelper.StartChallenger(ctx, "Challenger", factoryHelper.StartChallenger(ctx, "Challenger",
challenger.WithCannon(t, sys.RollupConfig, sys.L2GenesisCfg), challenger.WithFastGames(),
challenger.WithPrivKey(sys.Cfg.Secrets.Mallory)) challenger.WithPrivKey(sys.Cfg.Secrets.Mallory))
} }
receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash())
......
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"time" "time"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics"
legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
...@@ -17,6 +19,7 @@ import ( ...@@ -17,6 +19,7 @@ import (
bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview"
"github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -201,10 +204,18 @@ func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Clie ...@@ -201,10 +204,18 @@ func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Clie
proxy, err := legacybindings.NewFaultDisputeGame(game.DisputeGameProxy, l1Client) proxy, err := legacybindings.NewFaultDisputeGame(game.DisputeGameProxy, l1Client)
require.Nil(t, err) require.Nil(t, err)
expiry, err := proxy.MaxClockDuration(&bind.CallOpts{}) caller := batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize)
gameContract, err := contracts.NewFaultDisputeGameContract(context.Background(), metrics.NoopContractMetrics, game.DisputeGameProxy, caller)
require.Nil(t, err) require.Nil(t, err)
time.Sleep(time.Duration(expiry) * time.Second) timedCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
require.NoError(t, wait.For(timedCtx, time.Second, func() (bool, error) {
err := gameContract.CallResolveClaim(context.Background(), 0)
t.Logf("Could not resolve dispute game claim: %v", err)
return err == nil, nil
}))
resolveClaimTx, err := proxy.ResolveClaim(opts, common.Big0, common.Big0) resolveClaimTx, err := proxy.ResolveClaim(opts, common.Big0, common.Big0)
require.Nil(t, err) require.Nil(t, err)
......
...@@ -178,7 +178,7 @@ services: ...@@ -178,7 +178,7 @@ services:
# Note: this will need to be updated to point to a L1 consensus node when there is one in the devnet # Note: this will need to be updated to point to a L1 consensus node when there is one in the devnet
OP_CHALLENGER_L1_BEACON: "unset" OP_CHALLENGER_L1_BEACON: "unset"
OP_CHALLENGER_ROLLUP_RPC: http://op-node:8545 OP_CHALLENGER_ROLLUP_RPC: http://op-node:8545
OP_CHALLENGER_TRACE_TYPE: cannon OP_CHALLENGER_TRACE_TYPE: cannon,fast
OP_CHALLENGER_GAME_FACTORY_ADDRESS: ${DGF_ADDRESS} OP_CHALLENGER_GAME_FACTORY_ADDRESS: ${DGF_ADDRESS}
# The devnet can't set the absolute prestate output root because the contracts are deployed in L1 genesis # The devnet can't set the absolute prestate output root because the contracts are deployed in L1 genesis
# before the L2 genesis is known. # before the L2 genesis is known.
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
"preimageOracleChallengePeriod": 120, "preimageOracleChallengePeriod": 120,
"proofMaturityDelaySeconds": 12, "proofMaturityDelaySeconds": 12,
"disputeGameFinalityDelaySeconds": 6, "disputeGameFinalityDelaySeconds": 6,
"respectedGameType": 0, "respectedGameType": 254,
"useFaultProofs": false, "useFaultProofs": false,
"usePlasma": false, "usePlasma": false,
"daCommitmentType": "KeccakCommitment", "daCommitmentType": "KeccakCommitment",
......
...@@ -80,6 +80,7 @@ contract Deploy is Deployer { ...@@ -80,6 +80,7 @@ contract Deploy is Deployer {
Claim absolutePrestate; Claim absolutePrestate;
IBigStepper faultVm; IBigStepper faultVm;
uint256 maxGameDepth; uint256 maxGameDepth;
Duration maxClockDuration;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
...@@ -343,6 +344,7 @@ contract Deploy is Deployer { ...@@ -343,6 +344,7 @@ contract Deploy is Deployer {
initializeImplementations(); initializeImplementations();
setAlphabetFaultGameImplementation({ _allowUpgrade: false }); setAlphabetFaultGameImplementation({ _allowUpgrade: false });
setFastFaultGameImplementation({ _allowUpgrade: false });
setCannonFaultGameImplementation({ _allowUpgrade: false }); setCannonFaultGameImplementation({ _allowUpgrade: false });
setPermissionedCannonFaultGameImplementation({ _allowUpgrade: false }); setPermissionedCannonFaultGameImplementation({ _allowUpgrade: false });
...@@ -361,9 +363,9 @@ contract Deploy is Deployer { ...@@ -361,9 +363,9 @@ contract Deploy is Deployer {
deployERC1967Proxy("OptimismMintableERC20FactoryProxy"); deployERC1967Proxy("OptimismMintableERC20FactoryProxy");
deployERC1967Proxy("L1ERC721BridgeProxy"); deployERC1967Proxy("L1ERC721BridgeProxy");
// Both the DisputeGameFactory and L2OutputOracle proxies are deployed regardles of whether FPAC is enabled // Both the DisputeGameFactory and L2OutputOracle proxies are deployed regardless of whether fault proofs is
// to prevent a nastier refactor to the deploy scripts. In the future, the L2OutputOracle will be removed. If // enabled to prevent a nastier refactor to the deploy scripts. In the future, the L2OutputOracle will be
// fault proofs are not enabled, the DisputeGameFactory proxy will be unused. // removed. If fault proofs are not enabled, the DisputeGameFactory proxy will be unused.
deployERC1967Proxy("DisputeGameFactoryProxy"); deployERC1967Proxy("DisputeGameFactoryProxy");
deployERC1967Proxy("L2OutputOracleProxy"); deployERC1967Proxy("L2OutputOracleProxy");
deployERC1967Proxy("DelayedWETHProxy"); deployERC1967Proxy("DelayedWETHProxy");
...@@ -396,10 +398,9 @@ contract Deploy is Deployer { ...@@ -396,10 +398,9 @@ contract Deploy is Deployer {
function initializeImplementations() public { function initializeImplementations() public {
console.log("Initializing implementations"); console.log("Initializing implementations");
// Selectively initialize either the original OptimismPortal or the new OptimismPortal2. Since this will upgrade // Selectively initialize either the original OptimismPortal or the new OptimismPortal2. Since this will upgrade
// the proxy, we cannot initialize both. FPAC warning can be removed once we're done with the old OptimismPortal // the proxy, we cannot initialize both.
// contract.
if (cfg.useFaultProofs()) { if (cfg.useFaultProofs()) {
console.log("WARNING: FPAC is enabled. Initializing the OptimismPortal proxy with the OptimismPortal2."); console.log("Fault proofs enabled. Initializing the OptimismPortal proxy with the OptimismPortal2.");
initializeOptimismPortal2(); initializeOptimismPortal2();
} else { } else {
initializeOptimismPortal(); initializeOptimismPortal();
...@@ -956,7 +957,7 @@ contract Deploy is Deployer { ...@@ -956,7 +957,7 @@ contract Deploy is Deployer {
address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy"); address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy");
address anchorStateRegistry = mustGetAddress("AnchorStateRegistry"); address anchorStateRegistry = mustGetAddress("AnchorStateRegistry");
AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](4); AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](5);
roots[0] = AnchorStateRegistry.StartingAnchorRoot({ roots[0] = AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.CANNON, gameType: GameTypes.CANNON,
outputRoot: OutputRoot({ outputRoot: OutputRoot({
...@@ -985,6 +986,13 @@ contract Deploy is Deployer { ...@@ -985,6 +986,13 @@ contract Deploy is Deployer {
l2BlockNumber: cfg.faultGameGenesisBlock() l2BlockNumber: cfg.faultGameGenesisBlock()
}) })
}); });
roots[4] = AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.FAST,
outputRoot: OutputRoot({
root: Hash.wrap(cfg.faultGameGenesisOutputRoot()),
l2BlockNumber: cfg.faultGameGenesisBlock()
})
});
_upgradeAndCallViaSafe({ _upgradeAndCallViaSafe({
_proxy: payable(anchorStateRegistryProxy), _proxy: payable(anchorStateRegistryProxy),
...@@ -1376,7 +1384,8 @@ contract Deploy is Deployer { ...@@ -1376,7 +1384,8 @@ contract Deploy is Deployer {
gameType: GameTypes.CANNON, gameType: GameTypes.CANNON,
absolutePrestate: loadMipsAbsolutePrestate(), absolutePrestate: loadMipsAbsolutePrestate(),
faultVm: IBigStepper(mustGetAddress("Mips")), faultVm: IBigStepper(mustGetAddress("Mips")),
maxGameDepth: cfg.faultGameMaxDepth() maxGameDepth: cfg.faultGameMaxDepth(),
maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration()))
}) })
}); });
} }
...@@ -1397,7 +1406,8 @@ contract Deploy is Deployer { ...@@ -1397,7 +1406,8 @@ contract Deploy is Deployer {
gameType: GameTypes.PERMISSIONED_CANNON, gameType: GameTypes.PERMISSIONED_CANNON,
absolutePrestate: loadMipsAbsolutePrestate(), absolutePrestate: loadMipsAbsolutePrestate(),
faultVm: IBigStepper(mustGetAddress("Mips")), faultVm: IBigStepper(mustGetAddress("Mips")),
maxGameDepth: cfg.faultGameMaxDepth() maxGameDepth: cfg.faultGameMaxDepth(),
maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration()))
}) })
}); });
} }
...@@ -1419,7 +1429,31 @@ contract Deploy is Deployer { ...@@ -1419,7 +1429,31 @@ contract Deploy is Deployer {
absolutePrestate: outputAbsolutePrestate, absolutePrestate: outputAbsolutePrestate,
faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, PreimageOracle(mustGetAddress("PreimageOracle")))), faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, PreimageOracle(mustGetAddress("PreimageOracle")))),
// The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive. // The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive.
maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1 maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1,
maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration()))
})
});
}
/// @notice Sets the implementation for the `ALPHABET` game type in the `DisputeGameFactory`
function setFastFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast {
console.log("Setting Fast FaultDisputeGame implementation");
DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy"));
Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate()));
_setFaultGameImplementation({
_factory: factory,
_allowUpgrade: _allowUpgrade,
_params: FaultDisputeGameParams({
anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")),
weth: weth,
gameType: GameTypes.FAST,
absolutePrestate: outputAbsolutePrestate,
faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, PreimageOracle(mustGetAddress("PreimageOracle")))),
// The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive.
maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1,
maxClockDuration: Duration.wrap(0) // Resolvable immediately
}) })
}); });
} }
...@@ -1450,7 +1484,7 @@ contract Deploy is Deployer { ...@@ -1450,7 +1484,7 @@ contract Deploy is Deployer {
_maxGameDepth: _params.maxGameDepth, _maxGameDepth: _params.maxGameDepth,
_splitDepth: cfg.faultGameSplitDepth(), _splitDepth: cfg.faultGameSplitDepth(),
_clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), _clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())),
_maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), _maxClockDuration: _params.maxClockDuration,
_vm: _params.faultVm, _vm: _params.faultVm,
_weth: _params.weth, _weth: _params.weth,
_anchorStateRegistry: _params.anchorStateRegistry, _anchorStateRegistry: _params.anchorStateRegistry,
......
...@@ -33,6 +33,10 @@ library GameTypes { ...@@ -33,6 +33,10 @@ library GameTypes {
/// @notice A dispute game type the uses the asterisc VM /// @notice A dispute game type the uses the asterisc VM
GameType internal constant ASTERISC = GameType.wrap(2); GameType internal constant ASTERISC = GameType.wrap(2);
/// @notice A dispute game type with short game duration for testing withdrawals.
/// Not intended for production use.
GameType internal constant FAST = GameType.wrap(254);
/// @notice A dispute game type that uses an alphabet vm. /// @notice A dispute game type that uses an alphabet vm.
/// Not intended for production use. /// Not intended for production use.
GameType internal constant ALPHABET = GameType.wrap(255); GameType internal constant ALPHABET = GameType.wrap(255);
......
...@@ -600,6 +600,9 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -600,6 +600,9 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
slot = hex"d9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f"; slot = hex"d9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f";
value = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; value = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
vm.store(anchorStateRegistryProxyAddress, slot, value); vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"1d32deecea32fd1365d10df47fc6666a05871102e61a115a5c569bca7e5de14d";
value = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
vm.store(anchorStateRegistryProxyAddress, slot, value);
slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; slot = hex"0000000000000000000000000000000000000000000000000000000000000000";
value = hex"0000000000000000000000000000000000000000000000000000000000000001"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
vm.store(anchorStateRegistryProxyAddress, slot, value); vm.store(anchorStateRegistryProxyAddress, slot, value);
......
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