Skip to content

Commit

Permalink
op-node: Add dedicated PlasmaConfig struct to rollup.Config
Browse files Browse the repository at this point in the history
This commit adds a dedicated PlasmaConfig section to the rollup
config. This collects all Plasma Mode configuration to the same place
and enables future expansion of Plasma Mode configuration to be confined
to a single location.

In the interim, the op-node can read from both the legacy fields and the
dedicated struct. If both are set, they must be consistent. The genesis
creation tooling currently only writes with the new config.
  • Loading branch information
trianglesphere committed May 10, 2024
1 parent 48393a6 commit 250575c
Show file tree
Hide file tree
Showing 12 changed files with 103 additions and 39 deletions.
13 changes: 9 additions & 4 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,14 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
if d.SystemConfigProxy == (common.Address{}) {
return nil, errors.New("SystemConfigProxy cannot be address(0)")
}
var plasma *rollup.PlasmaConfig
if d.UsePlasma {
plasma = &rollup.PlasmaConfig{
DAChallengeAddress: d.DAChallengeProxy,
DAChallengeWindow: d.DAChallengeWindow,
DAResolveWindow: d.DAResolveWindow,
}
}

return &rollup.Config{
Genesis: rollup.Genesis{
Expand Down Expand Up @@ -630,10 +638,7 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
EcotoneTime: d.EcotoneTime(l1StartBlock.Time()),
FjordTime: d.FjordTime(l1StartBlock.Time()),
InteropTime: d.InteropTime(l1StartBlock.Time()),
UsePlasma: d.UsePlasma,
DAChallengeAddress: d.DAChallengeProxy,
DAChallengeWindow: d.DAChallengeWindow,
DAResolveWindow: d.DAResolveWindow,
PlasmaConfig: plasma,
}, nil
}

Expand Down
6 changes: 3 additions & 3 deletions op-e2e/actions/plasma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func NewL2PlasmaDA(t Testing, params ...PlasmaParam) *L2PlasmaDA {
dp := e2eutils.MakeDeployParams(t, p)
sd := e2eutils.Setup(t, dp, defaultAlloc)

require.True(t, sd.RollupCfg.UsePlasma)
require.True(t, sd.RollupCfg.PlasmaEnabled())

miner := NewL1Miner(t, log, sd.L1Cfg)
l1Client := miner.EthClient()
Expand All @@ -72,7 +72,7 @@ func NewL2PlasmaDA(t Testing, params ...PlasmaParam) *L2PlasmaDA {
l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindBasic))
require.NoError(t, err)

plasmaCfg, err := sd.RollupCfg.PlasmaConfig()
plasmaCfg, err := sd.RollupCfg.GetOPPlasmaConfig()
require.NoError(t, err)

daMgr := plasma.NewPlasmaDAWithStorage(log, plasmaCfg, storage, &plasma.NoopMetrics{})
Expand All @@ -94,7 +94,7 @@ func NewL2PlasmaDA(t Testing, params ...PlasmaParam) *L2PlasmaDA {
alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b)))
alice.L2.SetUserEnv(l2UserEnv)

contract, err := bindings.NewDataAvailabilityChallenge(sd.RollupCfg.DAChallengeAddress, l1Client)
contract, err := bindings.NewDataAvailabilityChallenge(sd.RollupCfg.PlasmaConfig.DAChallengeAddress, l1Client)
require.NoError(t, err)

challengeWindow, err := contract.ChallengeWindow(nil)
Expand Down
14 changes: 10 additions & 4 deletions op-e2e/e2eutils/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
l2Genesis.Alloc[addr] = val
}

var plasma *rollup.PlasmaConfig
if deployConf.UsePlasma {
plasma = &rollup.PlasmaConfig{
DAChallengeAddress: l1Deployments.DataAvailabilityChallengeProxy,
DAChallengeWindow: deployConf.DAChallengeWindow,
DAResolveWindow: deployConf.DAResolveWindow,
}
}

rollupCfg := &rollup.Config{
Genesis: rollup.Genesis{
L1: eth.BlockID{
Expand Down Expand Up @@ -170,10 +179,7 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
EcotoneTime: deployConf.EcotoneTime(uint64(deployConf.L1GenesisBlockTimestamp)),
FjordTime: deployConf.FjordTime(uint64(deployConf.L1GenesisBlockTimestamp)),
InteropTime: deployConf.InteropTime(uint64(deployConf.L1GenesisBlockTimestamp)),
DAChallengeAddress: l1Deployments.DataAvailabilityChallengeProxy,
DAChallengeWindow: deployConf.DAChallengeWindow,
DAResolveWindow: deployConf.DAResolveWindow,
UsePlasma: deployConf.UsePlasma,
PlasmaConfig: plasma,
}

require.NoError(t, rollupCfg.Check())
Expand Down
2 changes: 1 addition & 1 deletion op-node/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger
}

// if plasma is not explicitly activated in the node CLI, the config + any error will be ignored.
rpCfg, err := cfg.Rollup.PlasmaConfig()
rpCfg, err := cfg.Rollup.GetOPPlasmaConfig()
if cfg.Plasma.Enabled && err != nil {
return fmt.Errorf("failed to get plasma config: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion op-node/rollup/chain_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var testConfig = Config{
DepositContractAddress: common.HexToAddress("0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"),
L1SystemConfigAddress: common.HexToAddress("0x229047fed2591dbec1eF1118d64F7aF3dB9EB290"),
ProtocolVersionsAddress: common.HexToAddress("0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935"),
UsePlasma: false,
PlasmaConfig: nil,
}

func TestCanyonForkActivation(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion op-node/rollup/derive/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1Fetcher,
config := DataSourceConfig{
l1Signer: cfg.L1Signer(),
batchInboxAddress: cfg.BatchInboxAddress,
plasmaEnabled: cfg.UsePlasma,
plasmaEnabled: cfg.PlasmaEnabled(),
}
return &DataSourceFactory{
log: log,
Expand Down
4 changes: 2 additions & 2 deletions op-node/rollup/derive/engine_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ const finalityDelay = 64
func calcFinalityLookback(cfg *rollup.Config) uint64 {
// in plasma mode the longest finality lookback is a commitment is challenged on the last block of
// the challenge window in which case it will be both challenge + resolve window.
if cfg.UsePlasma {
lkb := cfg.DAChallengeWindow + cfg.DAResolveWindow + 1
if cfg.PlasmaEnabled() {
lkb := cfg.PlasmaConfig.DAChallengeWindow + cfg.PlasmaConfig.DAResolveWindow + 1
// in the case only if the plasma windows are longer than the default finality lookback
if lkb > finalityLookback {
return lkb
Expand Down
9 changes: 5 additions & 4 deletions op-node/rollup/derive/engine_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1250,16 +1250,17 @@ func TestPlasmaFinalityData(t *testing.T) {
GasLimit: 20_000_000,
},
},
BlockTime: 1,
SeqWindowSize: 2,
UsePlasma: false,
BlockTime: 1,
SeqWindowSize: 2,
}
plasmaCfg := &rollup.PlasmaConfig{
DAChallengeWindow: 90,
DAResolveWindow: 90,
}
// shoud return l1 finality if plasma is not enabled
require.Equal(t, uint64(finalityLookback), calcFinalityLookback(cfg))

cfg.UsePlasma = true
cfg.PlasmaConfig = plasmaCfg
expFinalityLookback := 181
require.Equal(t, uint64(expFinalityLookback), calcFinalityLookback(cfg))

Expand Down
2 changes: 1 addition & 1 deletion op-node/rollup/derive/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (dp *DerivationPipeline) Origin() eth.L1BlockRef {
func (dp *DerivationPipeline) Finalize(l1Origin eth.L1BlockRef) {
// In plasma mode, the finalization signal is proxied through the plasma manager.
// Finality signal will come from the DA contract or L1 finality whichever is last.
if dp.rollupCfg.UsePlasma {
if dp.rollupCfg.PlasmaEnabled() {
dp.plasma.Finalize(l1Origin)
} else {
dp.eng.Finalize(l1Origin)
Expand Down
9 changes: 6 additions & 3 deletions op-node/rollup/derive/plasma_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ func TestPlasmaDataSource(t *testing.T) {
BlockTime: 1,
SeqWindowSize: 20,
BatchInboxAddress: batcherInbox,
UsePlasma: true,
PlasmaConfig: &rollup.PlasmaConfig{
DAChallengeWindow: pcfg.ChallengeWindow,
DAResolveWindow: pcfg.ResolveWindow,
},
}
// keep track of random input data to validate against
var inputs [][]byte
Expand Down Expand Up @@ -323,7 +326,7 @@ func TestPlasmaDataSourceStall(t *testing.T) {
BlockTime: 1,
SeqWindowSize: 20,
BatchInboxAddress: batcherInbox,
UsePlasma: true,
LegacyUsePlasma: true,
}

signer := cfg.L1Signer()
Expand Down Expand Up @@ -438,7 +441,7 @@ func TestPlasmaDataSourceInvalidData(t *testing.T) {
BlockTime: 1,
SeqWindowSize: 20,
BatchInboxAddress: batcherInbox,
UsePlasma: true,
LegacyUsePlasma: true,
}

signer := cfg.L1Signer()
Expand Down
3 changes: 3 additions & 0 deletions op-node/rollup/superchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) {
return nil, fmt.Errorf("unable to retrieve deposit contract address")
}

// var plasma *PlasmaConfig
// if Config.chConfig.

regolithTime := uint64(0)
cfg := &Config{
Genesis: Genesis{
Expand Down
76 changes: 61 additions & 15 deletions op-node/rollup/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ type Genesis struct {
SystemConfig eth.SystemConfig `json:"system_config"`
}

type PlasmaConfig struct {
// L1 DataAvailabilityChallenge contract proxy address
DAChallengeAddress common.Address `json:"da_challenge_contract_address,omitempty"`
// DA challenge window value set on the DAC contract. Used in plasma mode
// to compute when a commitment can no longer be challenged.
DAChallengeWindow uint64 `json:"da_challenge_window"`
// DA resolve window value set on the DAC contract. Used in plasma mode
// to compute when a challenge expires and trigger a reorg if needed.
DAResolveWindow uint64 `json:"da_resolve_window"`
}

type Config struct {
// Genesis anchor point of the rollup
Genesis Genesis `json:"genesis"`
Expand Down Expand Up @@ -109,19 +120,22 @@ type Config struct {
// L1 address that declares the protocol versions, optional (Beta feature)
ProtocolVersionsAddress common.Address `json:"protocol_versions_address,omitempty"`

// Plasma Config. We are in the process of migrating to the PlasmaConfig from these legacy top level values
PlasmaConfig *PlasmaConfig `json:"plasma_config,omitempty"`

// L1 DataAvailabilityChallenge contract proxy address
DAChallengeAddress common.Address `json:"da_challenge_contract_address,omitempty"`
LegacyDAChallengeAddress common.Address `json:"da_challenge_contract_address,omitempty"`

// DA challenge window value set on the DAC contract. Used in plasma mode
// to compute when a commitment can no longer be challenged.
DAChallengeWindow uint64 `json:"da_challenge_window"`
LegacyDAChallengeWindow uint64 `json:"da_challenge_window,omitempty"`

// DA resolve window value set on the DAC contract. Used in plasma mode
// to compute when a challenge expires and trigger a reorg if needed.
DAResolveWindow uint64 `json:"da_resolve_window"`
LegacyDAResolveWindow uint64 `json:"da_resolve_window,omitempty"`

// UsePlasma is activated when the chain is in plasma mode.
UsePlasma bool `json:"use_plasma"`
// LegacyUsePlasma is activated when the chain is in plasma mode.
LegacyUsePlasma bool `json:"use_plasma,omitempty"`
}

// ValidateL1Config checks L1 config variables for errors.
Expand Down Expand Up @@ -289,6 +303,9 @@ func (cfg *Config) Check() error {
if cfg.L2ChainID.Sign() < 1 {
return ErrL2ChainIDNotPositive
}
if err := validatePlasmaConfig(cfg); err != nil {
return err
}

if err := checkFork(cfg.RegolithTime, cfg.CanyonTime, "regolith", "canyon"); err != nil {
return err
Expand All @@ -306,6 +323,31 @@ func (cfg *Config) Check() error {
return nil
}

// validatePlasmaConfig checks the two approaches to configuring plasma mode.
// If the legacy values are set, they are copied to the new location. If both are set, they are check for consistency.
func validatePlasmaConfig(cfg *Config) error {
if cfg.LegacyUsePlasma && cfg.PlasmaConfig == nil {
// copy from top level to plasma config
cfg.PlasmaConfig = &PlasmaConfig{
DAChallengeAddress: cfg.LegacyDAChallengeAddress,
DAChallengeWindow: cfg.LegacyDAChallengeWindow,
DAResolveWindow: cfg.LegacyDAResolveWindow,
}
} else if cfg.LegacyUsePlasma && cfg.PlasmaConfig != nil {
// validate that both are the same
if cfg.LegacyDAChallengeAddress != cfg.PlasmaConfig.DAChallengeAddress {
return fmt.Errorf("LegacyDAChallengeAddress (%v) != PlasmaConfig.DAChallengeAddress (%v)", cfg.LegacyDAChallengeAddress, cfg.PlasmaConfig.DAChallengeAddress)
}
if cfg.LegacyDAChallengeWindow != cfg.PlasmaConfig.DAChallengeWindow {
return fmt.Errorf("LegacyDAChallengeWindow (%v) != PlasmaConfig.DAChallengeWindow (%v)", cfg.LegacyDAChallengeWindow, cfg.PlasmaConfig.DAChallengeWindow)
}
if cfg.LegacyDAResolveWindow != cfg.PlasmaConfig.DAResolveWindow {
return fmt.Errorf("LegacyDAResolveWindow (%v) != PlasmaConfig.DAResolveWindow (%v)", cfg.LegacyDAResolveWindow, cfg.PlasmaConfig.DAResolveWindow)
}
}
return nil
}

// checkFork checks that fork A is before or at the same time as fork B
func checkFork(a, b *uint64, aName, bName string) error {
if a == nil && b == nil {
Expand Down Expand Up @@ -405,29 +447,33 @@ func (c *Config) GetPayloadVersion(timestamp uint64) eth.EngineAPIMethod {
}
}

// PlasmaConfig validates and returns the plasma config from the rollup config.
func (c *Config) PlasmaConfig() (plasma.Config, error) {
if c.DAChallengeAddress == (common.Address{}) {
// GetOPPlasmaConfig validates and returns the plasma config from the rollup config.
func (c *Config) GetOPPlasmaConfig() (plasma.Config, error) {
if c.PlasmaConfig.DAChallengeAddress == (common.Address{}) {
return plasma.Config{}, fmt.Errorf("missing DAChallengeAddress")
}
if c.DAChallengeWindow == uint64(0) {
if c.PlasmaConfig.DAChallengeWindow == uint64(0) {
return plasma.Config{}, fmt.Errorf("missing DAChallengeWindow")
}
if c.DAResolveWindow == uint64(0) {
if c.PlasmaConfig.DAResolveWindow == uint64(0) {
return plasma.Config{}, fmt.Errorf("missing DAResolveWindow")
}
return plasma.Config{
DAChallengeContractAddress: c.DAChallengeAddress,
ChallengeWindow: c.DAChallengeWindow,
ResolveWindow: c.DAResolveWindow,
DAChallengeContractAddress: c.PlasmaConfig.DAChallengeAddress,
ChallengeWindow: c.PlasmaConfig.DAChallengeWindow,
ResolveWindow: c.PlasmaConfig.DAResolveWindow,
}, nil
}

func (c *Config) PlasmaEnabled() bool {
return c.PlasmaConfig != nil
}

// SyncLookback computes the number of blocks to walk back in order to find the correct L1 origin.
// In plasma mode longest possible window is challenge + resolve windows.
func (c *Config) SyncLookback() uint64 {
if c.UsePlasma {
if win := (c.DAChallengeWindow + c.DAResolveWindow); win > c.SeqWindowSize {
if c.PlasmaEnabled() {
if win := (c.PlasmaConfig.DAChallengeWindow + c.PlasmaConfig.DAResolveWindow); win > c.SeqWindowSize {
return win
}
}
Expand Down

0 comments on commit 250575c

Please sign in to comment.