Skip to content

Commit

Permalink
op-deployer: Add deploy mips script (#12835)
Browse files Browse the repository at this point in the history
* op-deployer: Add deploy mips script

* op-deployer: Explicitly set the PreimageOracle to use with deployed MIPS

* op-deployer: Validate mips version in go code.
  • Loading branch information
ajsutton authored Nov 6, 2024
1 parent dd10e2e commit 11843b4
Show file tree
Hide file tree
Showing 7 changed files with 429 additions and 2 deletions.
2 changes: 1 addition & 1 deletion op-deployer/pkg/deployer/bootstrap/dispute_game.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type DisputeGameConfig struct {

MinProposalSizeBytes uint64
ChallengePeriodSeconds uint64
MipsVersion uint8
MipsVersion uint64
GameKind string
GameType uint32
AbsolutePrestate common.Hash
Expand Down
21 changes: 21 additions & 0 deletions op-deployer/pkg/deployer/bootstrap/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
L2ChainIdFlagName = "l2-chain-id"
ProposerFlagName = "proposer"
ChallengerFlagName = "challenger"
PreimageOracleFlagName = "preimage-oracle"
)

var (
Expand Down Expand Up @@ -140,6 +141,12 @@ var (
EnvVars: deployer.PrefixEnvVar("CHALLENGER"),
Value: common.Address{}.Hex(),
}
PreimageOracleFlag = &cli.StringFlag{
Name: PreimageOracleFlagName,
Usage: "Preimage oracle address.",
EnvVars: deployer.PrefixEnvVar("PREIMAGE_ORACLE"),
Value: common.Address{}.Hex(),
}
)

var OPCMFlags = []cli.Flag{
Expand Down Expand Up @@ -181,6 +188,14 @@ var DisputeGameFlags = []cli.Flag{
ChallengerFlag,
}

var MIPSFlags = []cli.Flag{
deployer.L1RPCURLFlag,
deployer.PrivateKeyFlag,
ArtifactsLocatorFlag,
PreimageOracleFlag,
MIPSVersionFlag,
}

var Commands = []*cli.Command{
{
Name: "opcm",
Expand All @@ -200,4 +215,10 @@ var Commands = []*cli.Command{
Flags: cliapp.ProtectFlags(DisputeGameFlags),
Action: DisputeGameCLI,
},
{
Name: "mips",
Usage: "Bootstrap an instance of MIPS.",
Flags: cliapp.ProtectFlags(MIPSFlags),
Action: MIPSCLI,
},
}
196 changes: 196 additions & 0 deletions op-deployer/pkg/deployer/bootstrap/mips.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package bootstrap

import (
"context"
"crypto/ecdsa"
"fmt"
"strings"

artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum/go-ethereum/common"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto"
"github.com/ethereum-optimism/optimism/op-service/ctxinterrupt"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
)

type MIPSConfig struct {
L1RPCUrl string
PrivateKey string
Logger log.Logger
ArtifactsLocator *artifacts2.Locator

privateKeyECDSA *ecdsa.PrivateKey

PreimageOracle common.Address
MipsVersion uint64
}

func (c *MIPSConfig) Check() error {
if c.L1RPCUrl == "" {
return fmt.Errorf("l1RPCUrl must be specified")
}

if c.PrivateKey == "" {
return fmt.Errorf("private key must be specified")
}

privECDSA, err := crypto.HexToECDSA(strings.TrimPrefix(c.PrivateKey, "0x"))
if err != nil {
return fmt.Errorf("failed to parse private key: %w", err)
}
c.privateKeyECDSA = privECDSA

if c.Logger == nil {
return fmt.Errorf("logger must be specified")
}

if c.ArtifactsLocator == nil {
return fmt.Errorf("artifacts locator must be specified")
}

if c.PreimageOracle == (common.Address{}) {
return fmt.Errorf("preimage oracle must be specified")
}

if c.MipsVersion == 0 {
return fmt.Errorf("mips version must be specified")
}
if c.MipsVersion != 1 && c.MipsVersion != 2 {
return fmt.Errorf("mips version must be either 1 or 2")
}

return nil
}

func MIPSCLI(cliCtx *cli.Context) error {
logCfg := oplog.ReadCLIConfig(cliCtx)
l := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg)
oplog.SetGlobalLogHandler(l.Handler())

l1RPCUrl := cliCtx.String(deployer.L1RPCURLFlagName)
privateKey := cliCtx.String(deployer.PrivateKeyFlagName)
artifactsURLStr := cliCtx.String(ArtifactsLocatorFlagName)
artifactsLocator := new(artifacts2.Locator)
if err := artifactsLocator.UnmarshalText([]byte(artifactsURLStr)); err != nil {
return fmt.Errorf("failed to parse artifacts URL: %w", err)
}

mipsVersion := cliCtx.Uint64(MIPSVersionFlagName)
preimageOracle := common.HexToAddress(cliCtx.String(PreimageOracleFlagName))

ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context)

return MIPS(ctx, MIPSConfig{
L1RPCUrl: l1RPCUrl,
PrivateKey: privateKey,
Logger: l,
ArtifactsLocator: artifactsLocator,
MipsVersion: mipsVersion,
PreimageOracle: preimageOracle,
})
}

func MIPS(ctx context.Context, cfg MIPSConfig) error {
if err := cfg.Check(); err != nil {
return fmt.Errorf("invalid config for MIPS: %w", err)
}

lgr := cfg.Logger
progressor := func(curr, total int64) {
lgr.Info("artifacts download progress", "current", curr, "total", total)
}

artifactsFS, cleanup, err := artifacts2.Download(ctx, cfg.ArtifactsLocator, progressor)
if err != nil {
return fmt.Errorf("failed to download artifacts: %w", err)
}
defer func() {
if err := cleanup(); err != nil {
lgr.Warn("failed to clean up artifacts", "err", err)
}
}()

l1Client, err := ethclient.Dial(cfg.L1RPCUrl)
if err != nil {
return fmt.Errorf("failed to connect to L1 RPC: %w", err)
}

chainID, err := l1Client.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to get chain ID: %w", err)
}

signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID))
chainDeployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey)

bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{
Logger: lgr,
ChainID: chainID,
Client: l1Client,
Signer: signer,
From: chainDeployer,
})
if err != nil {
return fmt.Errorf("failed to create broadcaster: %w", err)
}

nonce, err := l1Client.NonceAt(ctx, chainDeployer, nil)
if err != nil {
return fmt.Errorf("failed to get starting nonce: %w", err)
}

host, err := env.DefaultScriptHost(
bcaster,
lgr,
chainDeployer,
artifactsFS,
nonce,
)
if err != nil {
return fmt.Errorf("failed to create script host: %w", err)
}

var release string
if cfg.ArtifactsLocator.IsTag() {
release = cfg.ArtifactsLocator.Tag
} else {
release = "dev"
}

lgr.Info("deploying dispute game", "release", release)

dgo, err := opcm.DeployMIPS(
host,
opcm.DeployMIPSInput{
MipsVersion: cfg.MipsVersion,
PreimageOracle: cfg.PreimageOracle,
},
)
if err != nil {
return fmt.Errorf("error deploying dispute game: %w", err)
}

if _, err := bcaster.Broadcast(ctx); err != nil {
return fmt.Errorf("failed to broadcast: %w", err)
}

lgr.Info("deployed dispute game")

if err := jsonutil.WriteJSON(dgo, ioutil.ToStdOut()); err != nil {
return fmt.Errorf("failed to write output: %w", err)
}
return nil
}
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 @@ -11,7 +11,7 @@ import (
type DeployDisputeGameInput struct {
Release string
StandardVersionsToml string
MipsVersion uint8
MipsVersion uint64
MinProposalSizeBytes uint64
ChallengePeriodSeconds uint64
GameKind string
Expand Down
65 changes: 65 additions & 0 deletions op-deployer/pkg/deployer/opcm/mips.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package opcm

import (
"fmt"

"github.com/ethereum/go-ethereum/common"

"github.com/ethereum-optimism/optimism/op-chain-ops/script"
)

type DeployMIPSInput struct {
MipsVersion uint64
PreimageOracle common.Address
}

func (input *DeployMIPSInput) InputSet() bool {
return true
}

type DeployMIPSOutput struct {
MipsSingleton common.Address
}

func (output *DeployMIPSOutput) CheckOutput(input common.Address) error {
return nil
}

type DeployMIPSScript struct {
Run func(input, output common.Address) error
}

func DeployMIPS(
host *script.Host,
input DeployMIPSInput,
) (DeployMIPSOutput, error) {
var output DeployMIPSOutput
inputAddr := host.NewScriptAddress()
outputAddr := host.NewScriptAddress()

cleanupInput, err := script.WithPrecompileAtAddress[*DeployMIPSInput](host, inputAddr, &input)
if err != nil {
return output, fmt.Errorf("failed to insert DeployMIPSInput precompile: %w", err)
}
defer cleanupInput()

cleanupOutput, err := script.WithPrecompileAtAddress[*DeployMIPSOutput](host, outputAddr, &output,
script.WithFieldSetter[*DeployMIPSOutput])
if err != nil {
return output, fmt.Errorf("failed to insert DeployMIPSOutput precompile: %w", err)
}
defer cleanupOutput()

implContract := "DeployMIPS"
deployScript, cleanupDeploy, err := script.WithScript[DeployMIPSScript](host, "DeployMIPS.s.sol", implContract)
if err != nil {
return output, fmt.Errorf("failed to load %s script: %w", implContract, err)
}
defer cleanupDeploy()

if err := deployScript.Run(inputAddr, outputAddr); err != nil {
return output, fmt.Errorf("failed to run %s script: %w", implContract, err)
}

return output, nil
}
36 changes: 36 additions & 0 deletions op-deployer/pkg/deployer/opcm/mips_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package opcm

import (
"testing"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/testutil"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)

func TestDeployMIPS(t *testing.T) {
_, artifacts := testutil.LocalArtifacts(t)

host, err := env.DefaultScriptHost(
broadcaster.NoopBroadcaster(),
testlog.Logger(t, log.LevelInfo),
common.Address{'D'},
artifacts,
0,
)
require.NoError(t, err)

input := DeployMIPSInput{
MipsVersion: 1,
PreimageOracle: common.Address{0xab},
}

output, err := DeployMIPS(host, input)
require.NoError(t, err)

require.NotEmpty(t, output.MipsSingleton)
}
Loading

0 comments on commit 11843b4

Please sign in to comment.