From a2715a600a1769d08686da35e692cb8ed6ee2c09 Mon Sep 17 00:00:00 2001 From: Michael de Hoog Date: Fri, 27 Sep 2024 12:40:08 -1000 Subject: [PATCH] Limit parameterizable configuration --- enclave/client.go | 2 +- enclave/config.go | 184 ++++++++++++++------------------- enclave/rpc.go | 2 +- enclave/server.go | 13 ++- op-proposer/proposer/prover.go | 41 +++----- 5 files changed, 109 insertions(+), 133 deletions(-) diff --git a/enclave/client.go b/enclave/client.go index b17fbda..3d0ddbc 100644 --- a/enclave/client.go +++ b/enclave/client.go @@ -49,7 +49,7 @@ func (c *Client) SetSignerKey(ctx context.Context, encrypted hexutil.Bytes) erro return c.callContext(ctx, nil, "setSignerKey", encrypted) } -func (c *Client) ExecuteStateless(ctx context.Context, config *RollupConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs types.Transactions, blockHeader *types.Header, blockTxs types.Transactions, witness hexutil.Bytes, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash) (*Proposal, error) { +func (c *Client) ExecuteStateless(ctx context.Context, config *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs types.Transactions, blockHeader *types.Header, blockTxs types.Transactions, witness hexutil.Bytes, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash) (*Proposal, error) { var result Proposal return &result, c.callContext(ctx, &result, "executeStateless", config, l1Origin, l1Receipts, previousBlockTxs, blockHeader, blockTxs, witness, messageAccount, prevMessageAccountHash) } diff --git a/enclave/config.go b/enclave/config.go index cc987aa..ebaafcf 100644 --- a/enclave/config.go +++ b/enclave/config.go @@ -1,9 +1,15 @@ package enclave import ( + "math/big" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" ) @@ -14,20 +20,54 @@ const ( var uint256Type abi.Type var uint64Type abi.Type -var boolType abi.Type var addressType abi.Type var bytes32Type abi.Type +var deployConfig = state.DefaultDeployConfig() +var chainConfigTemplate params.ChainConfig + func init() { uint256Type, _ = abi.NewType("uint256", "", nil) uint64Type, _ = abi.NewType("uint64", "", nil) - boolType, _ = abi.NewType("bool", "", nil) addressType, _ = abi.NewType("address", "", nil) bytes32Type, _ = abi.NewType("bytes32", "", nil) + + deployConfig.L2ChainID = 1 + var err error + chainConfigTemplate, err = newChainConfigTemplate(&deployConfig) + if err != nil { + panic(err) + } +} + +type ChainConfig struct { + *params.ChainConfig + *PerChainConfig +} + +func newChainConfigTemplate(cfg *genesis.DeployConfig) (params.ChainConfig, error) { + l1StartHeader := &types.Header{ + Time: 1, + } + g, err := genesis.NewL2Genesis(cfg, l1StartHeader) + if err != nil { + return params.ChainConfig{}, err + } + return *g.Config, nil +} + +func NewChainConfig(cfg *PerChainConfig) *ChainConfig { + cfg.ForceDefaults() + chainConfig := chainConfigTemplate + chainConfig.ChainID = cfg.ChainID + return &ChainConfig{ + ChainConfig: &chainConfig, + PerChainConfig: cfg, + } } -type RollupConfig struct { - params.ChainConfig +type PerChainConfig struct { + ChainID *big.Int `json:"chain_id"` Genesis rollup.Genesis `json:"genesis"` BlockTime uint64 `json:"block_time"` @@ -36,129 +76,63 @@ type RollupConfig struct { L1SystemConfigAddress common.Address `json:"l1_system_config_address"` } -func (c *RollupConfig) ToRollupConfig() *rollup.Config { - return &rollup.Config{ - Genesis: c.Genesis, - BlockTime: c.BlockTime, - DepositContractAddress: c.DepositContractAddress, - L1SystemConfigAddress: c.L1SystemConfigAddress, +func FromRollupConfig(cfg *rollup.Config) *PerChainConfig { + p := &PerChainConfig{ + ChainID: cfg.L2ChainID, + Genesis: cfg.Genesis, + BlockTime: cfg.BlockTime, + DepositContractAddress: cfg.DepositContractAddress, + L1SystemConfigAddress: cfg.L1SystemConfigAddress, } + p.ForceDefaults() + return p +} + +func (p *PerChainConfig) ForceDefaults() { + p.BlockTime = 1 + p.Genesis.L2.Number = 0 + p.Genesis.SystemConfig.GasLimit = uint64(deployConfig.L2GenesisBlockGasLimit) + p.Genesis.SystemConfig.Overhead = eth.Bytes32{} + p.Genesis.SystemConfig.Scalar = deployConfig.FeeScalar() } -func (c *RollupConfig) SetRollupConfig(cfg *rollup.Config) { - c.Genesis = cfg.Genesis - c.BlockTime = cfg.BlockTime - c.DepositContractAddress = cfg.DepositContractAddress - c.L1SystemConfigAddress = cfg.L1SystemConfigAddress +func (p *PerChainConfig) ToRollupConfig() *rollup.Config { + return &rollup.Config{ + L2ChainID: p.ChainID, + Genesis: p.Genesis, + BlockTime: p.BlockTime, + DepositContractAddress: p.DepositContractAddress, + L1SystemConfigAddress: p.L1SystemConfigAddress, + } } -func (c *RollupConfig) Hash() (common.Hash, error) { - data, err := c.MarshalBinary() +func (p *PerChainConfig) Hash() (common.Hash, error) { + data, err := p.MarshalBinary() if err != nil { return common.Hash{}, err } return crypto.Keccak256Hash(data), nil } -func (c *RollupConfig) MarshalBinary() (data []byte, err error) { +func (p *PerChainConfig) MarshalBinary() (data []byte, err error) { args := abi.Arguments{ {Name: "version", Type: uint64Type}, {Name: "chainID", Type: uint256Type}, - {Name: "homesteadBlock", Type: uint256Type}, - {Name: "daoForkBlock", Type: uint256Type}, - {Name: "daoForkSupport", Type: boolType}, - {Name: "eip150Block", Type: uint256Type}, - {Name: "eip155Block", Type: uint256Type}, - {Name: "eip158Block", Type: uint256Type}, - {Name: "byzantiumBlock", Type: uint256Type}, - {Name: "constantinopleBlock", Type: uint256Type}, - {Name: "petersburgBlock", Type: uint256Type}, - {Name: "istanbulBlock", Type: uint256Type}, - {Name: "muirGlacierBlock", Type: uint256Type}, - {Name: "berlinBlock", Type: uint256Type}, - {Name: "londonBlock", Type: uint256Type}, - {Name: "arrowGlacierBlock", Type: uint256Type}, - {Name: "grayGlacierBlock", Type: uint256Type}, - {Name: "mergeNetsplitBlock", Type: uint256Type}, - {Name: "shanghaiTime", Type: uint64Type}, - {Name: "cancunTime", Type: uint64Type}, - {Name: "pragueTime", Type: uint64Type}, - {Name: "verkleTime", Type: uint64Type}, - {Name: "bedrockBlock", Type: uint256Type}, - {Name: "regolithTime", Type: uint64Type}, - {Name: "canyonTime", Type: uint64Type}, - {Name: "ecotoneTime", Type: uint64Type}, - {Name: "fjordTime", Type: uint64Type}, - {Name: "graniteTime", Type: uint64Type}, - {Name: "interopTime", Type: uint64Type}, - {Name: "terminalTotalDifficulty", Type: uint256Type}, - {Name: "terminalTotalDifficultyPassed", Type: boolType}, - {Name: "cliquePeriod", Type: uint64Type}, - {Name: "cliqueEpoch", Type: uint64Type}, - {Name: "optimismEIP1559Elasticity", Type: uint64Type}, - {Name: "optimismEIP1559Denominator", Type: uint64Type}, - {Name: "optimismEIP1559DenominatorCanyon", Type: uint64Type}, {Name: "genesisL1Hash", Type: bytes32Type}, {Name: "genesisL1Number", Type: uint64Type}, {Name: "genesisL2Hash", Type: bytes32Type}, - {Name: "genesisL2Number", Type: uint64Type}, {Name: "genesisL2Time", Type: uint64Type}, - {Name: "genesisSystemConfigBatcherAddr", Type: addressType}, - {Name: "genesisSystemConfigOverhead", Type: bytes32Type}, - {Name: "genesisSystemConfigScalar", Type: bytes32Type}, - {Name: "genesisSystemConfigGasLimit", Type: uint64Type}, - {Name: "blockTime", Type: uint64Type}, {Name: "depositContractAddress", Type: addressType}, {Name: "l1SystemConfigAddress", Type: addressType}, } return args.Pack( version0, - c.ChainID, - c.HomesteadBlock, - c.DAOForkBlock, - c.DAOForkSupport, - c.EIP150Block, - c.EIP155Block, - c.EIP158Block, - c.ByzantiumBlock, - c.ConstantinopleBlock, - c.PetersburgBlock, - c.IstanbulBlock, - c.MuirGlacierBlock, - c.BerlinBlock, - c.LondonBlock, - c.ArrowGlacierBlock, - c.GrayGlacierBlock, - c.MergeNetsplitBlock, - c.ShanghaiTime, - c.CancunTime, - c.PragueTime, - c.VerkleTime, - c.BedrockBlock, - c.RegolithTime, - c.CanyonTime, - c.EcotoneTime, - c.FjordTime, - c.GraniteTime, - c.InteropTime, - c.TerminalTotalDifficulty, - c.TerminalTotalDifficultyPassed, - c.Clique.Period, - c.Clique.Epoch, - c.Optimism.EIP1559Elasticity, - c.Optimism.EIP1559Denominator, - c.Optimism.EIP1559DenominatorCanyon, - c.Genesis.L1.Hash, - c.Genesis.L1.Number, - c.Genesis.L2.Hash, - c.Genesis.L2.Number, - c.Genesis.L2Time, - c.Genesis.SystemConfig.BatcherAddr, - c.Genesis.SystemConfig.Overhead, - c.Genesis.SystemConfig.Scalar, - c.Genesis.SystemConfig.GasLimit, - c.BlockTime, - c.DepositContractAddress, - c.L1SystemConfigAddress, + p.ChainID, + p.Genesis.L1.Hash, + p.Genesis.L1.Number, + p.Genesis.L2.Hash, + p.Genesis.L2Time, + p.DepositContractAddress, + p.L1SystemConfigAddress, ) } diff --git a/enclave/rpc.go b/enclave/rpc.go index 357b59d..0ea8b7b 100644 --- a/enclave/rpc.go +++ b/enclave/rpc.go @@ -20,7 +20,7 @@ type RPC interface { SetSignerKey(ctx context.Context, encrypted hexutil.Bytes) error ExecuteStateless( ctx context.Context, - config *RollupConfig, + config *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs types.Transactions, diff --git a/enclave/server.go b/enclave/server.go index d49c81c..123f8df 100644 --- a/enclave/server.go +++ b/enclave/server.go @@ -220,7 +220,7 @@ type Proposal struct { func (s *Server) ExecuteStateless( ctx context.Context, - config *RollupConfig, + cfg *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs types.Transactions, @@ -230,6 +230,8 @@ func (s *Server) ExecuteStateless( messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash, ) (*Proposal, error) { + config := NewChainConfig(cfg) + l1OriginHash := l1Origin.Hash() computed := types.DeriveSha(l1Receipts, trie.NewStackTrie(nil)) if computed != l1Origin.ReceiptHash { @@ -302,10 +304,17 @@ func (s *Server) ExecuteStateless( return nil, errors.New("L1 origin is too old") } + expectedRoot := blockHeader.Root block := types.NewBlockWithHeader(blockHeader).WithBody(types.Body{ Transactions: blockTxs, }) - stateRoot, _, err := core.ExecuteStateless(&config.ChainConfig, block, w) + stateRoot, _, err := core.ExecuteStateless(config.ChainConfig, block, w) + if err != nil { + return nil, fmt.Errorf("failed to execute stateless: %w", err) + } + if stateRoot != expectedRoot { + return nil, errors.New("invalid state root") + } if messageAccount.Address.Cmp(l2ToL1MessagePasserAddress) != 0 { return nil, errors.New("invalid message account address") diff --git a/op-proposer/proposer/prover.go b/op-proposer/proposer/prover.go index 025ed05..f65ed99 100644 --- a/op-proposer/proposer/prover.go +++ b/op-proposer/proposer/prover.go @@ -15,12 +15,12 @@ import ( ) type prover struct { - rollupConfig *enclave.RollupConfig - rollupConfigHash common.Hash - l1 L1Client - l2 L2Client - rollup RollupClient - enclave enclave.RPC + config *enclave.PerChainConfig + configHash common.Hash + l1 L1Client + l2 L2Client + rollup RollupClient + enclave enclave.RPC } type proposal struct { @@ -35,30 +35,23 @@ func newProver( rollup RollupClient, enclav enclave.RPC, ) (*prover, error) { - chainConfig, err := l2.ChainConfig(ctx) - if err != nil { - return nil, fmt.Errorf("failed to fetch chain config: %w", err) - } rollupConfig, err := rollup.RollupConfig(ctx) if err != nil { return nil, fmt.Errorf("failed to fetch rollup config: %w", err) } - cfg := &enclave.RollupConfig{ - ChainConfig: *chainConfig, - } - cfg.SetRollupConfig(rollupConfig) - rollupConfigHash, err := cfg.Hash() + cfg := enclave.FromRollupConfig(rollupConfig) + configHash, err := cfg.Hash() if err != nil { return nil, fmt.Errorf("failed to hash rollup config: %w", err) } return &prover{ - rollupConfig: cfg, - rollupConfigHash: rollupConfigHash, - l1: l1, - l2: l2, - rollup: rollup, - enclave: enclav, + config: cfg, + configHash: configHash, + l1: l1, + l2: l2, + rollup: rollup, + enclave: enclav, }, nil } @@ -99,7 +92,7 @@ func (o *prover) Generate(ctx context.Context, blockNumber uint64) (*proposal, b return fmt.Errorf("failed to fetch previous message account proof: %w", err) }) - blockRef, err := derive.L2BlockToBlockRef(o.rollupConfig.ToRollupConfig(), block) + blockRef, err := derive.L2BlockToBlockRef(o.config.ToRollupConfig(), block) if err != nil { return nil, false, fmt.Errorf("failed to derive block ref from L2 block: %w", err) } @@ -142,7 +135,7 @@ func (o *prover) Generate(ctx context.Context, blockNumber uint64) (*proposal, b output, err := o.enclave.ExecuteStateless( ctx, - o.rollupConfig, + o.config, l1Origin.value, l1Receipts.value, previousBlock.value.Transactions(), @@ -167,7 +160,7 @@ func (o *prover) Aggregate(ctx context.Context, prevOutputRoot common.Hash, prop for i, p := range proposals { prop[i] = p.output } - output, err := o.enclave.Aggregate(ctx, o.rollupConfigHash, prevOutputRoot, prop) + output, err := o.enclave.Aggregate(ctx, o.configHash, prevOutputRoot, prop) if err != nil { return nil, fmt.Errorf("failed to aggregate proposals: %w", err) }