Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

op-deployer: Add support for additional dispute games #13346

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions op-deployer/pkg/deployer/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,11 @@ func ApplyPipeline(
L2: l2ArtifactsFS,
}

var deployer common.Address
deployer := common.Address{0x01}
if opts.DeployerPrivateKey != nil {
deployer = crypto.PubkeyToAddress(opts.DeployerPrivateKey.PublicKey)
}

var bcaster broadcaster.Broadcaster
var l1Client *ethclient.Client
var l1Host *script.Host
Expand All @@ -193,7 +197,6 @@ func ApplyPipeline(
}

signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(opts.DeployerPrivateKey, chainID))
deployer = crypto.PubkeyToAddress(opts.DeployerPrivateKey.PublicKey)

bcaster, err = broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{
Logger: opts.Logger,
Expand Down Expand Up @@ -235,7 +238,6 @@ func ApplyPipeline(
return fmt.Errorf("failed to select fork: %w", err)
}
} else {
deployer = common.Address{0x01}
bcaster = broadcaster.NoopBroadcaster()
l1Host, err = env.DefaultScriptHost(
bcaster,
Expand Down Expand Up @@ -286,6 +288,11 @@ func ApplyPipeline(
func() error {
return pipeline.DeployAltDA(pEnv, intent, st, chainID)
},
}, pipelineStage{
fmt.Sprintf("deploy-additional-dispute-games-%s", chainID.Hex()),
func() error {
return pipeline.DeployAdditionalDisputeGames(pEnv, intent, st, chainID)
},
}, pipelineStage{
fmt.Sprintf("generate-l2-genesis-%s", chainID.Hex()),
func() error {
Expand Down
3 changes: 2 additions & 1 deletion op-deployer/pkg/deployer/bootstrap/dispute_game.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"strings"

artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
Expand Down Expand Up @@ -224,7 +225,7 @@ func DisputeGame(ctx context.Context, cfg DisputeGameConfig) (opcm.DeployDispute
MaxClockDuration: cfg.MaxClockDuration,
DelayedWethProxy: cfg.DelayedWethProxy,
AnchorStateRegistryProxy: cfg.AnchorStateRegistryProxy,
L2ChainId: cfg.L2ChainId,
L2ChainId: common.BigToHash(new(big.Int).SetUint64(cfg.L2ChainId)),
Proposer: cfg.Proposer,
Challenger: cfg.Challenger,
},
Expand Down
42 changes: 41 additions & 1 deletion op-deployer/pkg/deployer/integration_test/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,47 @@ func TestInvalidL2Genesis(t *testing.T) {
}
}

func TestAdditionalDisputeGames(t *testing.T) {
op_e2e.InitParallel(t)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

opts, intent, st := setupGenesisChain(t, defaultL1ChainID)
(&intent.Chains[0].Roles).L1ProxyAdminOwner = crypto.PubkeyToAddress(opts.DeployerPrivateKey.PublicKey)
intent.GlobalDeployOverrides = map[string]any{
"challengePeriodSeconds": 1,
}
intent.Chains[0].AdditionalDisputeGames = []state.AdditionalDisputeGame{
{
ChainProofParams: state.ChainProofParams{
DisputeGameType: 255,
DisputeAbsolutePrestate: standard.DisputeAbsolutePrestate,
DisputeMaxGameDepth: 50,
DisputeSplitDepth: 14,
DisputeClockExtension: 0,
DisputeMaxClockDuration: 1200,
DangerouslyAllowCustomDisputeParameters: true,
},
UseCustomOracle: true,
OracleMinProposalSize: 10000,
OracleChallengePeriodSeconds: 120,
VMType: state.VMTypeAlphabet,
},
}

require.NoError(t, deployer.ApplyPipeline(ctx, opts))

chainState := st.Chains[0]
require.Equal(t, 1, len(chainState.AdditionalDisputeGames))

gameInfo := chainState.AdditionalDisputeGames[0]
require.NotEmpty(t, gameInfo.VMAddress)
require.NotEmpty(t, gameInfo.GameAddress)
require.NotEmpty(t, gameInfo.OracleAddress)
require.NotEqual(t, st.ImplementationsDeployment.PreimageOracleSingletonAddress, gameInfo.OracleAddress)
}

func setupGenesisChain(t *testing.T, l1ChainID uint64) (deployer.ApplyPipelineOpts, *state.Intent, *state.State) {
lgr := testlog.Logger(t, slog.LevelDebug)

Expand All @@ -711,7 +752,6 @@ func setupGenesisChain(t *testing.T, l1ChainID uint64) (deployer.ApplyPipelineOp
loc, _ := testutil.LocalArtifacts(t)

intent, st := newIntent(t, l1ChainIDBig, dk, l2ChainID1, loc, loc)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainIDBig, l2ChainID1))
intent.DeploymentStrategy = state.DeploymentStrategyGenesis

opts := deployer.ApplyPipelineOpts{
Expand Down
2 changes: 1 addition & 1 deletion op-deployer/pkg/deployer/opcm/dispute_game.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type DeployDisputeGameInput struct {
MaxClockDuration uint64
DelayedWethProxy common.Address
AnchorStateRegistryProxy common.Address
L2ChainId uint64
L2ChainId common.Hash
Proposer common.Address
Challenger common.Address
}
Expand Down
3 changes: 2 additions & 1 deletion op-deployer/pkg/deployer/opcm/dispute_game_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package opcm

import (
"math/big"
"testing"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
Expand Down Expand Up @@ -47,7 +48,7 @@ func TestDeployDisputeGame(t *testing.T) {
MaxClockDuration: standard.DisputeMaxClockDuration,
DelayedWethProxy: common.Address{'D'},
AnchorStateRegistryProxy: common.Address{'A'},
L2ChainId: 69,
L2ChainId: common.BigToHash(big.NewInt(69)),
Proposer: common.Address{'P'},
Challenger: common.Address{'C'},
}
Expand Down
145 changes: 145 additions & 0 deletions op-deployer/pkg/deployer/pipeline/dispute_games.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package pipeline

import (
"fmt"
"math/big"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum/go-ethereum/common"
)

func DeployAdditionalDisputeGames(
env *Env,
intent *state.Intent,
st *state.State,
chainID common.Hash,
) error {
lgr := env.Logger.New("stage", "deploy-additional-dispute-games")

thisIntent, err := intent.Chain(chainID)
if err != nil {
return fmt.Errorf("failed to get chain intent: %w", err)
}

thisState, err := st.Chain(chainID)
if err != nil {
return fmt.Errorf("failed to get chain state: %w", err)
}

if !shouldDeployAdditionalDisputeGames(thisIntent, thisState) {
lgr.Info("additional dispute games deployment not needed")
return nil
}

if thisIntent.Roles.L1ProxyAdminOwner != env.Deployer {
return fmt.Errorf("cannot deploy additional dispute games when deployer is not L1PAO")
}

for _, game := range thisIntent.AdditionalDisputeGames {
if err := deployDisputeGame(env, st, thisIntent, thisState, game); err != nil {
return fmt.Errorf("failed to deploy additional dispute game: %w", err)
}
}

return nil
}

func deployDisputeGame(
env *Env,
st *state.State,
thisIntent *state.ChainIntent,
thisState *state.ChainState,
game state.AdditionalDisputeGame,
) error {
lgr := env.Logger.New("gameType", game.DisputeGameType)

var oracleAddr common.Address
if game.UseCustomOracle {
lgr.Info("deploying custom oracle")

out, err := opcm.DeployPreimageOracle(env.L1ScriptHost, opcm.DeployPreimageOracleInput{
MinProposalSize: new(big.Int).SetUint64(game.OracleMinProposalSize),
ChallengePeriod: new(big.Int).SetUint64(game.OracleChallengePeriodSeconds),
})
if err != nil {
return fmt.Errorf("failed to deploy preimage oracle: %w", err)
}
oracleAddr = out.PreimageOracle
} else {
lgr.Debug("using existing preimage oracle")
}

lgr.Info("deploying VM", "vmType", game.VMType)
var vmAddr common.Address
switch game.VMType {
case state.VMTypeAlphabet:
out, err := opcm.DeployAlphabetVM(env.L1ScriptHost, opcm.DeployAlphabetVMInput{
AbsolutePrestate: game.DisputeAbsolutePrestate,
PreimageOracle: st.ImplementationsDeployment.PreimageOracleSingletonAddress,
})
if err != nil {
return fmt.Errorf("failed to deploy Alphabet VM: %w", err)
}
vmAddr = out.AlphabetVM
default:
return fmt.Errorf("unsupported VM type: %v", game.VMType)
}
lgr.Info("vm deployed", "vmAddr", vmAddr)

lgr.Info("deploying dispute game")
out, err := opcm.DeployDisputeGame(env.L1ScriptHost, opcm.DeployDisputeGameInput{
Release: "dev",
VmAddress: vmAddr,
GameKind: "FaultDisputeGame",
GameType: game.DisputeGameType,
AbsolutePrestate: standard.DisputeAbsolutePrestate,
MaxGameDepth: game.DisputeMaxGameDepth,
SplitDepth: game.DisputeSplitDepth,
ClockExtension: game.DisputeClockExtension,
MaxClockDuration: game.DisputeMaxClockDuration,
DelayedWethProxy: thisState.DelayedWETHPermissionedGameProxyAddress,
AnchorStateRegistryProxy: thisState.AnchorStateRegistryProxyAddress,
L2ChainId: thisIntent.ID,
Proposer: thisIntent.Roles.Proposer,
Challenger: thisIntent.Roles.Challenger,
})
if err != nil {
return fmt.Errorf("failed to deploy dispute game: %w", err)
}
lgr.Info("dispute game deployed", "impl", out.DisputeGameImpl)

lgr.Info("setting dispute game impl on factory")
if err := opcm.SetDisputeGameImpl(
env.L1ScriptHost,
opcm.SetDisputeGameImplInput{
Factory: thisState.DisputeGameFactoryProxyAddress,
Impl: out.DisputeGameImpl,
},
); err != nil {
return fmt.Errorf("failed to set dispute game impl: %w", err)
}

thisState.AdditionalDisputeGames = append(thisState.AdditionalDisputeGames, state.AdditionalDisputeGameState{
GameType: game.DisputeGameType,
VMType: game.VMType,
GameAddress: out.DisputeGameImpl,
OracleAddress: oracleAddr,
VMAddress: vmAddr,
})

return nil
}

func shouldDeployAdditionalDisputeGames(thisIntent *state.ChainIntent, thisState *state.ChainState) bool {
if len(thisIntent.AdditionalDisputeGames) == 0 {
return false
}

if len(thisState.AdditionalDisputeGames) > 0 {
return false
}

return true
}
13 changes: 2 additions & 11 deletions op-deployer/pkg/deployer/pipeline/implementations.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,13 @@ import (
"fmt"
"math/big"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
)

type SuperchainProofParams struct {
WithdrawalDelaySeconds uint64 `json:"withdrawalDelaySeconds" toml:"withdrawalDelaySeconds"`
MinProposalSizeBytes uint64 `json:"minProposalSizeBytes" toml:"minProposalSizeBytes"`
ChallengePeriodSeconds uint64 `json:"challengePeriodSeconds" toml:"challengePeriodSeconds"`
ProofMaturityDelaySeconds uint64 `json:"proofMaturityDelaySeconds" toml:"proofMaturityDelaySeconds"`
DisputeGameFinalityDelaySeconds uint64 `json:"disputeGameFinalityDelaySeconds" toml:"disputeGameFinalityDelaySeconds"`
MIPSVersion uint64 `json:"mipsVersion" toml:"mipsVersion"`
}

func DeployImplementations(env *Env, intent *state.Intent, st *state.State) error {
lgr := env.Logger.New("stage", "deploy-implementations")

Expand All @@ -46,7 +37,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
}

proofParams, err := jsonutil.MergeJSON(
SuperchainProofParams{
state.SuperchainProofParams{
WithdrawalDelaySeconds: standard.WithdrawalDelaySeconds,
MinProposalSizeBytes: standard.MinProposalSizeBytes,
ChallengePeriodSeconds: standard.ChallengePeriodSeconds,
Expand Down
14 changes: 2 additions & 12 deletions op-deployer/pkg/deployer/pipeline/opchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package pipeline
import (
"fmt"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum/go-ethereum/common"
)
Expand Down Expand Up @@ -89,19 +89,9 @@ func DeployOPChain(env *Env, intent *state.Intent, st *state.State, chainID comm
return nil
}

type ChainProofParams struct {
DisputeGameType uint32 `json:"disputeGameType" toml:"disputeGameType"`
DisputeAbsolutePrestate common.Hash `json:"disputeAbsolutePrestate" toml:"disputeAbsolutePrestate"`
DisputeMaxGameDepth uint64 `json:"disputeMaxGameDepth" toml:"disputeMaxGameDepth"`
DisputeSplitDepth uint64 `json:"disputeSplitDepth" toml:"disputeSplitDepth"`
DisputeClockExtension uint64 `json:"disputeClockExtension" toml:"disputeClockExtension"`
DisputeMaxClockDuration uint64 `json:"disputeMaxClockDuration" toml:"disputeMaxClockDuration"`
DangerouslyAllowCustomDisputeParameters bool `json:"dangerouslyAllowCustomDisputeParameters" toml:"dangerouslyAllowCustomDisputeParameters"`
}

func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID common.Hash, st *state.State) (opcm.DeployOPChainInputV160, error) {
proofParams, err := jsonutil.MergeJSON(
ChainProofParams{
state.ChainProofParams{
DisputeGameType: standard.DisputeGameType,
DisputeAbsolutePrestate: standard.DisputeAbsolutePrestate,
DisputeMaxGameDepth: standard.DisputeMaxGameDepth,
Expand Down
25 changes: 25 additions & 0 deletions op-deployer/pkg/deployer/state/chain_intent.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,30 @@ import (
"github.com/ethereum/go-ethereum/common"
)

type VMType string

const (
VMTypeAlphabet = "ALPHABET"
)

type ChainProofParams struct {
DisputeGameType uint32 `json:"disputeGameType" toml:"disputeGameType"`
DisputeAbsolutePrestate common.Hash `json:"disputeAbsolutePrestate" toml:"disputeAbsolutePrestate"`
DisputeMaxGameDepth uint64 `json:"disputeMaxGameDepth" toml:"disputeMaxGameDepth"`
DisputeSplitDepth uint64 `json:"disputeSplitDepth" toml:"disputeSplitDepth"`
DisputeClockExtension uint64 `json:"disputeClockExtension" toml:"disputeClockExtension"`
DisputeMaxClockDuration uint64 `json:"disputeMaxClockDuration" toml:"disputeMaxClockDuration"`
DangerouslyAllowCustomDisputeParameters bool `json:"dangerouslyAllowCustomDisputeParameters" toml:"dangerouslyAllowCustomDisputeParameters"`
}

type AdditionalDisputeGame struct {
ChainProofParams
VMType VMType
UseCustomOracle bool
OracleMinProposalSize uint64
OracleChallengePeriodSeconds uint64
}

type ChainIntent struct {
ID common.Hash `json:"id" toml:"id"`
BaseFeeVaultRecipient common.Address `json:"baseFeeVaultRecipient" toml:"baseFeeVaultRecipient"`
Expand All @@ -19,6 +43,7 @@ type ChainIntent struct {
Roles ChainRoles `json:"roles" toml:"roles"`
DeployOverrides map[string]any `json:"deployOverrides" toml:"deployOverrides"`
DangerousAltDAConfig genesis.AltDADeployConfig `json:"dangerousAltDAConfig,omitempty" toml:"dangerousAltDAConfig,omitempty"`
AdditionalDisputeGames []AdditionalDisputeGame `json:"dangerousAdditionalDisputeGames" toml:"dangerousAdditionalDisputeGames,omitempty"`
}

type ChainRoles struct {
Expand Down
Loading