Skip to content

Commit

Permalink
op-chain-ops: multi L2 deploy progress
Browse files Browse the repository at this point in the history
  • Loading branch information
protolambda committed Aug 19, 2024
1 parent b1ccf4d commit b97758d
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 51 deletions.
20 changes: 10 additions & 10 deletions op-chain-ops/genz/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func createL2(logger log.Logger, fa *foundry.ArtifactsFS, l2Cfg *L2Config, genes
func initialL1(l1Host *script.Host) (*L1Deployment, error) {
// TODO set deployer
// Init L2Genesis script. Yes, this is L1. Hack to deploy all preinstalls.
l2GenesisScript, cleanupL2Genesis, err := WithScript[L2GenesisScript](l1Host, "L2Genesis.s.sol")
l2GenesisScript, cleanupL2Genesis, err := script.WithScript[L2GenesisScript](l1Host, "L2Genesis.s.sol", "L2Genesis")
if err != nil {
return nil, fmt.Errorf("failed to load L2Genesis script for L1 preinstalls work: %w", err)
}
Expand All @@ -136,14 +136,14 @@ func deploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup
deploymentRegistry := &DeploymentRegistryPrecompile{
Deployments: map[string]common.Address{},
}
cleanupDeploymentRegistry, err := WithPrecompileAtAddress[*DeploymentRegistryPrecompile](
cleanupDeploymentRegistry, err := script.WithPrecompileAtAddress[*DeploymentRegistryPrecompile](
l1Host, deploymentRegistryAddr, deploymentRegistry)
if err != nil {
return nil, fmt.Errorf("failed to insert DeploymentRegistry precompile: %w", err)
}
defer cleanupDeploymentRegistry()

l1DeployScript, cleanupL1Deploy, err := WithScript[DeployScript](l1Host, "Deploy.s.sol")
l1DeployScript, cleanupL1Deploy, err := script.WithScript[DeployScript](l1Host, "Deploy.s.sol", "Deploy")
if err != nil {
return nil, fmt.Errorf("failed to load Deploy script: %w", err)
}
Expand All @@ -152,7 +152,7 @@ func deploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup
deployConfig := &genesis.DeployConfig{}
deployConfig.ProxyAdminOwner = superCfg.ProxyAdminOwner
deployConfig.SuperchainL1DeployConfig = superCfg.SuperchainL1DeployConfig
cleanupDeployConfig, err := WithPrecompileAtAddress[*genesis.DeployConfig](l1Host, deployConfigAddr, deployConfig)
cleanupDeployConfig, err := script.WithPrecompileAtAddress[*genesis.DeployConfig](l1Host, deployConfigAddr, deployConfig)
if err != nil {
return nil, fmt.Errorf("failed to insert DeployConfig precompile: %w", err)
}
Expand Down Expand Up @@ -215,14 +215,14 @@ func deployL2ToL1(l1Host *script.Host, superDeployment *SuperchainDeployment, cf
"DisputeGameFactory": superDeployment.DisputeGameFactory,
},
}
cleanupDeploymentRegistry, err := WithPrecompileAtAddress[*DeploymentRegistryPrecompile](
cleanupDeploymentRegistry, err := script.WithPrecompileAtAddress[*DeploymentRegistryPrecompile](
l1Host, deploymentRegistryAddr, deploymentRegistry)
if err != nil {
return nil, fmt.Errorf("failed to insert DeploymentRegistry precompile: %w", err)
}
defer cleanupDeploymentRegistry()

l1DeployScript, cleanupL1Deploy, err := WithScript[DeployScript](l1Host, "Deploy.s.sol")
l1DeployScript, cleanupL1Deploy, err := script.WithScript[DeployScript](l1Host, "Deploy.s.sol", "Deploy")
if err != nil {
return nil, fmt.Errorf("failed to load Deploy script: %w", err)
}
Expand All @@ -233,7 +233,7 @@ func deployL2ToL1(l1Host *script.Host, superDeployment *SuperchainDeployment, cf
OutputOracleDeployConfig: cfg.OutputOracleDeployConfig,
FaultProofDeployConfig: cfg.FaultProofDeployConfig,
}
cleanupDeployConfig, err := WithPrecompileAtAddress[*genesis.DeployConfig](l1Host, deployConfigAddr, deployConfig)
cleanupDeployConfig, err := script.WithPrecompileAtAddress[*genesis.DeployConfig](l1Host, deployConfigAddr, deployConfig)
if err != nil {
return nil, fmt.Errorf("failed to insert DeployConfig precompile: %w", err)
}
Expand Down Expand Up @@ -273,7 +273,7 @@ func genesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment) err
"L1ERC721BridgeProxy": deployment.L1ERC721BridgeProxy,
},
}
cleanupDeploymentRegistry, err := WithPrecompileAtAddress[*DeploymentRegistryPrecompile](
cleanupDeploymentRegistry, err := script.WithPrecompileAtAddress[*DeploymentRegistryPrecompile](
l2Host, deploymentRegistryAddr, deploymentRegistry)
if err != nil {
return fmt.Errorf("failed to insert DeploymentRegistry precompile: %w", err)
Expand All @@ -283,13 +283,13 @@ func genesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment) err
deployConfig := &genesis.DeployConfig{
L2InitializationConfig: cfg.L2InitializationConfig,
}
cleanupDeployConfig, err := WithPrecompileAtAddress[*genesis.DeployConfig](l2Host, deployConfigAddr, deployConfig)
cleanupDeployConfig, err := script.WithPrecompileAtAddress[*genesis.DeployConfig](l2Host, deployConfigAddr, deployConfig)
if err != nil {
return fmt.Errorf("failed to insert DeployConfig precompile: %w", err)
}
defer cleanupDeployConfig()

l2GenesisScript, cleanupL2Genesis, err := WithScript[L2GenesisScript](l2Host, "L2Genesis.s.sol")
l2GenesisScript, cleanupL2Genesis, err := script.WithScript[L2GenesisScript](l2Host, "L2Genesis.s.sol", "L2Genesis")
if err != nil {
return fmt.Errorf("failed to load L2Genesis script: %w", err)
}
Expand Down
22 changes: 0 additions & 22 deletions op-chain-ops/genz/precompiles.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,9 @@
package genz

import (
"fmt"

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

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

var deployConfigAddr = common.Address(crypto.Keccak256([]byte("optimism.deployconfig"))[12:])
var deploymentRegistryAddr = common.Address(crypto.Keccak256([]byte("optimism.deploymentregistry"))[12:])

func WithPrecompileAtAddress[E any](h *script.Host, addr common.Address, elem E) (cleanup func(), err error) {
precompile, err := script.NewPrecompile[E](elem)
if err != nil {
return nil, fmt.Errorf("failed to construct precompile: %w", err)
}
_ = precompile
// set code to []byte{0}
// override precompile
return // TODO
}

func WithPrecompile(h *script.Host, precompile any) (addr common.Address, cleanup func()) {
// create tmp addr
// set code to []byte{0}
// override precompile
return // TODO
}
18 changes: 0 additions & 18 deletions op-chain-ops/genz/scripts.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package genz

import (
"errors"

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

type DeployScript struct {
DeploySafe func(name string)

Expand Down Expand Up @@ -38,15 +32,3 @@ type L2GenesisScript struct {
RunWithAllUpgrades func() error
SetPreinstalls func() error
}

func WithScript[B any](h *script.Host, name string) (b *B, cleanup func(), err error) {
// TODO
// load contract artifact
// init bindings (with ABI check)
// create tmp addr
// set tmp addr to script bytecode
// run setUp of script
// fn(bindingS)
// remove script
return nil, nil, errors.New("TODO")
}
48 changes: 47 additions & 1 deletion op-chain-ops/script/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ type Host struct {
cheatcodes *Precompile[*CheatCodesPrecompile]
console *Precompile[*ConsolePrecompile]

precompiles map[common.Address]vm.PrecompiledContract

callStack []CallFrame

// serializerStates are in-progress JSON payloads by name,
Expand Down Expand Up @@ -251,10 +253,38 @@ func (h *Host) getPrecompile(rules params.Rules, original vm.PrecompiledContract
case ConsoleAddr:
return h.console // nil if cheats are not enabled
default:
if p, ok := h.precompiles[addr]; ok {
return p
}
return original
}
}

// SetPrecompile inserts a precompile at the given address.
// If the precompile is nil, it removes the precompile override from that address, if any.
func (h *Host) SetPrecompile(addr common.Address, precompile vm.PrecompiledContract) {
if precompile == nil {
delete(h.precompiles, addr)
h.state.SelfDestruct(addr)
return
}
h.precompiles[addr] = precompile
// insert non-empty placeholder bytecode, so EXTCODESIZE checks pass
h.state.SetCode(addr, []byte{0})
}

func (h *Host) HasPrecompileOverride(addr common.Address) bool {
switch addr {
case VMAddr:
return h.cheatcodes != nil
case ConsoleAddr:
return h.console != nil
default:
_, ok := h.precompiles[addr]
return ok
}
}

// onExit is a trace-hook, which we use to maintain an accurate view of functions, and log any revert warnings.
func (h *Host) onExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
// Note: onExit runs also when going deeper, exiting the context into a nested context.
Expand Down Expand Up @@ -313,7 +343,7 @@ func (h *Host) onOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpCo
// apply prank, if parent call-frame set up a prank
if len(h.callStack) > 1 {
parentCallFrame := h.callStack[len(h.callStack)-2]
if parentCallFrame.Prank != nil {
if parentCallFrame.Prank != nil && scope.Address() != VMAddr { // pranks do not apply to the cheatcode precompile
if parentCallFrame.Prank.Sender != nil {
scopeCtx.Contract.CallerAddress = *parentCallFrame.Prank.Sender
}
Expand Down Expand Up @@ -490,5 +520,21 @@ func (h *Host) StateDump() (*foundry.ForgeAllocs, error) {
// because solidity checks if the code exists prior to regular EVM-calls to it.
delete(allocs.Accounts, VMAddr)

// Precompile overrides come with temporary state account placeholders. Ignore those.
for addr := range h.precompiles {
delete(allocs.Accounts, addr)
}

return &allocs, nil
}

func (h *Host) SetTxOrigin(addr common.Address) {
h.env.TxContext.Origin = addr
}

func (h *Host) ScriptBackendFn(to common.Address) CallBackendFn {
return func(data []byte) ([]byte, error) {
ret, _, err := h.Call(h.env.TxContext.Origin, to, data, DefaultFoundryGasLimit, uint256.NewInt(0))
return ret, err
}
}
59 changes: 59 additions & 0 deletions op-chain-ops/script/with.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package script

import (
"errors"
"fmt"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)

func checkABI(abiData *abi.ABI, methodSignature string) bool {
for _, m := range abiData.Methods {
if m.Sig == methodSignature {
return true
}
}
return false
}

func WithScript[B any](h *Host, name string, contract string) (b *B, cleanup func(), err error) {
// load contract artifact
artifact, err := h.af.ReadArtifact(name, contract)
if err != nil {
return nil, nil, fmt.Errorf("could not load script artifact: %w", err)
}

// TODO compute address of script contract to be deployed
addr := common.Address{}

// init bindings (with ABI check)
bindings, err := MakeBindings[B](h.ScriptBackendFn(addr), func(abiDef string) bool {
return checkABI(&artifact.ABI, abiDef)
})
if err != nil {
return nil, nil, fmt.Errorf("failed to make bindings: %w", err)
}

// TODO deploy the script contract

// TODO cleanup func to remove script contract
return bindings, nil, errors.New("TODO")
}

// WithPrecompileAtAddress turns a struct into a precompile,
// and inserts it as override at the given address in the host.
// A cleanup function is returned, to remove the precompile override again.
func WithPrecompileAtAddress[E any](h *Host, addr common.Address, elem E) (cleanup func(), err error) {
if h.HasPrecompileOverride(addr) {
return nil, fmt.Errorf("already have existing precompile override at %s", addr)
}
precompile, err := NewPrecompile[E](elem)
if err != nil {
return nil, fmt.Errorf("failed to construct precompile: %w", err)
}
h.SetPrecompile(addr, precompile)
return func() {
h.SetPrecompile(addr, nil)
}, nil
}

0 comments on commit b97758d

Please sign in to comment.