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 alt-DA deployments #12798

Merged
merged 5 commits into from
Nov 5, 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
12 changes: 6 additions & 6 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,18 +597,18 @@ func (d *L2CoreDeployConfig) Check(log log.Logger) error {
// AltDADeployConfig configures optional AltDA functionality.
type AltDADeployConfig struct {
// UseAltDA is a flag that indicates if the system is using op-alt-da
UseAltDA bool `json:"useAltDA"`
UseAltDA bool `json:"useAltDA" toml:"useAltDA"`
// DACommitmentType specifies the allowed commitment
DACommitmentType string `json:"daCommitmentType"`
DACommitmentType string `json:"daCommitmentType" toml:"daCommitmentType"`
// DAChallengeWindow represents the block interval during which the availability of a data commitment can be challenged.
DAChallengeWindow uint64 `json:"daChallengeWindow"`
DAChallengeWindow uint64 `json:"daChallengeWindow" toml:"daChallengeWindow"`
// DAResolveWindow represents the block interval during which a data availability challenge can be resolved.
DAResolveWindow uint64 `json:"daResolveWindow"`
DAResolveWindow uint64 `json:"daResolveWindow" toml:"daResolveWindow"`
// DABondSize represents the required bond size to initiate a data availability challenge.
DABondSize uint64 `json:"daBondSize"`
DABondSize uint64 `json:"daBondSize" toml:"daBondSize"`
// DAResolverRefundPercentage represents the percentage of the resolving cost to be refunded to the resolver
// such as 100 means 100% refund.
DAResolverRefundPercentage uint64 `json:"daResolverRefundPercentage"`
DAResolverRefundPercentage uint64 `json:"daResolverRefundPercentage" toml:"daResolverRefundPercentage"`
}

var _ ConfigChecker = (*AltDADeployConfig)(nil)
Expand Down
11 changes: 11 additions & 0 deletions op-chain-ops/script/cheatcodes_utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,17 @@ func (c *CheatCodesPrecompile) ParseTomlAddress_65e7c844(tomlStr string, key str
panic("should never get here")
}

func (c *CheatCodesPrecompile) ComputeCreate2Address_890c283b(salt, codeHash [32]byte) (common.Address, error) {
mslipper marked this conversation as resolved.
Show resolved Hide resolved
data := make([]byte, 1+20+32+32)
data[0] = 0xff
copy(data[1:], DeterministicDeployerAddress.Bytes())
copy(data[1+20:], salt[:])
copy(data[1+20+32:], codeHash[:])
finalHash := crypto.Keccak256(data)
// Take the last 20 bytes of the hash to get the address
return common.BytesToAddress(finalHash[12:]), nil
}

// unsupported
//func (c *CheatCodesPrecompile) CreateWallet() {}

Expand Down
11 changes: 11 additions & 0 deletions op-chain-ops/script/cheatcodes_utilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,14 @@ func TestParseTomlAddress(t *testing.T) {
require.NoError(t, err)
require.Equal(t, common.HexToAddress("0xff4ce7b6a91a35c31d7d62b327d19617c8da6f23"), addr)
}

func TestComputeCreate2Address(t *testing.T) {
c := &CheatCodesPrecompile{}
var salt [32]byte
salt[31] = 'S'
var codeHash [32]byte
codeHash[31] = 'C'
addr, err := c.ComputeCreate2Address_890c283b(salt, codeHash)
require.NoError(t, err)
require.EqualValues(t, common.HexToAddress("0x2f29AF1b5a7083bf98C4A89976c2f17FF980735f"), addr)
}
5 changes: 5 additions & 0 deletions op-deployer/pkg/deployer/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ func ApplyPipeline(
return pipeline.DeployOPChainGenesisStrategy(env, intent, st, chainID)
}
},
}, pipelineStage{
fmt.Sprintf("deploy-alt-da-%s", chainID.Hex()),
func() error {
return pipeline.DeployAltDA(env, intent, st, chainID)
},
}, pipelineStage{
fmt.Sprintf("generate-l2-genesis-%s", chainID.Hex()),
func() error {
Expand Down
43 changes: 43 additions & 0 deletions op-deployer/pkg/deployer/integration_test/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import (
"testing"
"time"

altda "github.com/ethereum-optimism/optimism/op-alt-da"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/inspect"
"github.com/ethereum-optimism/optimism/op-node/rollup"

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

"github.com/ethereum-optimism/optimism/op-chain-ops/script"
Expand Down Expand Up @@ -404,6 +408,45 @@ func TestInteropDeployment(t *testing.T) {
checkStorageSlot(t, st.L1StateDump.Data.Accounts, chainState.SystemConfigProxyAddress, depManagerSlot, proxyAdminOwnerHash)
}

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

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

env, bundle, intent, st := setupGenesisChain(t)
altDACfg := genesis.AltDADeployConfig{
UseAltDA: true,
DACommitmentType: altda.KeccakCommitmentString,
DAChallengeWindow: 10,
DAResolveWindow: 10,
DABondSize: 100,
DAResolverRefundPercentage: 50,
}
intent.Chains[0].DangerousAltDAConfig = altDACfg

require.NoError(t, deployer.ApplyPipeline(
ctx,
env,
bundle,
intent,
st,
))

chainState := st.Chains[0]
require.NotEmpty(t, chainState.DataAvailabilityChallengeProxyAddress)
require.NotEmpty(t, chainState.DataAvailabilityChallengeImplAddress)

_, rollupCfg, err := inspect.GenesisAndRollup(st, chainState.ID)
require.NoError(t, err)
require.EqualValues(t, &rollup.AltDAConfig{
CommitmentType: altda.KeccakCommitmentString,
DAChallengeWindow: altDACfg.DAChallengeWindow,
DAChallengeAddress: chainState.DataAvailabilityChallengeProxyAddress,
DAResolveWindow: altDACfg.DAResolveWindow,
}, rollupCfg.AltDAConfig)
}

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

Expand Down
63 changes: 63 additions & 0 deletions op-deployer/pkg/deployer/opcm/alt_da.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package opcm

import (
"fmt"
"math/big"

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

type DeployAltDAInput struct {
Salt common.Hash
ProxyAdmin common.Address
ChallengeContractOwner common.Address
ChallengeWindow *big.Int
ResolveWindow *big.Int
BondSize *big.Int
ResolverRefundPercentage *big.Int
}

type DeployAltDAOutput struct {
DataAvailabilityChallengeProxy common.Address
DataAvailabilityChallengeImpl common.Address
}

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

func DeployAltDA(
host *script.Host,
input DeployAltDAInput,
) (DeployAltDAOutput, error) {
var output DeployAltDAOutput
inputAddr := host.NewScriptAddress()
outputAddr := host.NewScriptAddress()

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

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

implContract := "DeployAltDA"
deployScript, cleanupDeploy, err := script.WithScript[DeployAltDAScript](host, "DeployAltDA.s.sol", implContract)
if err != nil {
return output, fmt.Errorf("failed to laod %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
}
43 changes: 43 additions & 0 deletions op-deployer/pkg/deployer/opcm/alt_da_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package opcm

import (
"math/big"
"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 TestDeployAltDA(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 := DeployAltDAInput{
Salt: common.HexToHash("0x1234"),
ProxyAdmin: common.Address{'P'},
ChallengeContractOwner: common.Address{'O'},
ChallengeWindow: big.NewInt(100),
ResolveWindow: big.NewInt(200),
BondSize: big.NewInt(300),
ResolverRefundPercentage: big.NewInt(50), // must be < 100
}

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

require.NotEmpty(t, output.DataAvailabilityChallengeProxy)
require.NotEmpty(t, output.DataAvailabilityChallengeImpl)
}
56 changes: 56 additions & 0 deletions op-deployer/pkg/deployer/pipeline/alt_da.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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/state"
"github.com/ethereum/go-ethereum/common"
)

func DeployAltDA(env *Env, intent *state.Intent, st *state.State, chainID common.Hash) error {
lgr := env.Logger.New("stage", "deploy-alt-da")

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

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

if !shouldDeployAltDA(chainIntent, chainState) {
lgr.Info("alt-da deployment not needed")
return nil
}

var dao opcm.DeployAltDAOutput
lgr.Info("deploying alt-da contracts")
dao, err = opcm.DeployAltDA(env.L1ScriptHost, opcm.DeployAltDAInput{
Salt: st.Create2Salt,
ProxyAdmin: st.ImplementationsDeployment.OpcmProxyAddress,
ChallengeContractOwner: chainIntent.Roles.L1ProxyAdminOwner,
ChallengeWindow: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DAChallengeWindow),
ResolveWindow: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DAResolveWindow),
BondSize: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DABondSize),
ResolverRefundPercentage: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DAResolverRefundPercentage),
})
if err != nil {
return fmt.Errorf("failed to deploy alt-da contracts: %w", err)
}

chainState.DataAvailabilityChallengeProxyAddress = dao.DataAvailabilityChallengeProxy
chainState.DataAvailabilityChallengeImplAddress = dao.DataAvailabilityChallengeImpl
mslipper marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

func shouldDeployAltDA(chainIntent *state.ChainIntent, chainState *state.ChainState) bool {
if !chainIntent.DangerousAltDAConfig.UseAltDA {
return false
}

return chainState.DataAvailabilityChallengeImplAddress == common.Address{}
}
5 changes: 5 additions & 0 deletions op-deployer/pkg/deployer/state/deploy_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
}
}

if chainIntent.DangerousAltDAConfig.UseAltDA {
cfg.AltDADeployConfig = chainIntent.DangerousAltDAConfig
cfg.L1DependenciesConfig.DAChallengeProxy = chainState.DataAvailabilityChallengeProxyAddress
}

// The below dummy variables are set in order to allow the deploy
// config to pass validation. The validation checks are useful to
// ensure that the L2 is properly configured. They are not used by
Expand Down
8 changes: 8 additions & 0 deletions op-deployer/pkg/deployer/state/intent.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"math/big"

"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"

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

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
Expand Down Expand Up @@ -163,6 +165,8 @@ 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"`
}

type ChainRoles struct {
Expand Down Expand Up @@ -207,5 +211,9 @@ func (c *ChainIntent) Check() error {
return fmt.Errorf("batcher must be set")
}

if c.DangerousAltDAConfig.UseAltDA {
return c.DangerousAltDAConfig.Check(nil)
}

return nil
}
2 changes: 2 additions & 0 deletions op-deployer/pkg/deployer/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ type ChainState struct {
PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"`
DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"`
DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"`
DataAvailabilityChallengeProxyAddress common.Address `json:"dataAvailabilityChallengeProxyAddress"`
DataAvailabilityChallengeImplAddress common.Address `json:"dataAvailabilityChallengeImplAddress"`

Allocs *GzipData[foundry.ForgeAllocs] `json:"allocs"`

Expand Down
Loading