Skip to content

Commit

Permalink
op-plasma: sync derivation with DA challenge contract state (#9682)
Browse files Browse the repository at this point in the history
* feat: plasma e2e

* feat: skip oversized inputs

* fix: bring back metrics

* feat: set usePlasma in e2e test params

* fix: lint

* fix: activate plasma flag in data source test

* fix: add DA contract proxy to deploy config

* more tests, fix leaky abstraction and refactor loadChallenges

* fix: cleanup type assertion

* support for l1 reorgs, proxy l1 finality signal and tests

* fix: plasma disabled

* add plasma specific e2e test run

* strongly typed commitment

* fix test

* fix sync lookback

* finalize with l1 signal events instead of derivation

* adjust pipeline errors

* fix batcher commitment encoding and invalid comm logging

* fix: adjust plasma state pruning and use bool for DA resetting flag

* fix: use l1 fetcher and check pq length
  • Loading branch information
tchardin committed Mar 12, 2024
1 parent 25985c1 commit 802c283
Show file tree
Hide file tree
Showing 35 changed files with 2,262 additions and 98 deletions.
17 changes: 16 additions & 1 deletion .circleci/config.yml
Expand Up @@ -203,6 +203,12 @@ jobs:
- run:
name: Copy FPAC allocs to .devnet-fpac
command: cp -r .devnet/ .devnet-fault-proofs/
- run:
name: Generate Plasma allocs
command: DEVNET_PLASMA="true" make devnet-allocs
- run:
name: Copy Plasma allocs to .devnet-plasma
command: cp -r .devnet/ .devnet-plasma/
- run:
name: Generate non-FPAC allocs
command: make devnet-allocs
Expand All @@ -219,6 +225,8 @@ jobs:
- ".devnet/addresses.json"
- ".devnet-fault-proofs/allocs-l1.json"
- ".devnet-fault-proofs/addresses.json"
- ".devnet-plasma/allocs-l1.json"
- ".devnet-plasma/addresses.json"
- "packages/contracts-bedrock/deploy-config/devnetL1.json"
- "packages/contracts-bedrock/deployments/devnetL1"

Expand Down Expand Up @@ -896,6 +904,13 @@ jobs:
- run:
name: Set OP_E2E_USE_FPAC = true
command: echo 'export OP_E2E_USE_FPAC=true' >> $BASH_ENV
- when:
condition:
equal: ['-plasma', <<parameters.fpac>>]
steps:
- run:
name: Set OP_E2E_USE_PLASMA = true
command: echo 'export OP_E2E_USE_PLASMA=true' >> $BASH_ENV
- check-changed:
patterns: op-(.+),cannon,contracts-bedrock
- run:
Expand Down Expand Up @@ -1636,7 +1651,7 @@ workflows:
name: op-e2e-action-tests<< matrix.fpac >>
matrix:
parameters:
fpac: ["", "-fault-proofs"]
fpac: ["", "-fault-proofs", "-plasma"]
module: op-e2e
target: test-actions
parallelism: 1
Expand Down
3 changes: 3 additions & 0 deletions bedrock-devnet/devnet/__init__.py
Expand Up @@ -29,6 +29,7 @@
# Global environment variables
DEVNET_NO_BUILD = os.getenv('DEVNET_NO_BUILD') == "true"
DEVNET_FPAC = os.getenv('DEVNET_FPAC') == "true"
DEVNET_PLASMA = os.getenv('DEVNET_PLASMA') == "true"

class Bunch:
def __init__(self, **kwds):
Expand Down Expand Up @@ -130,6 +131,8 @@ def init_devnet_l1_deploy_config(paths, update_timestamp=False):
if DEVNET_FPAC:
deploy_config['useFaultProofs'] = True
deploy_config['faultGameMaxDuration'] = 10
if DEVNET_PLASMA:
deploy_config['usePlasma'] = True
write_json(paths.devnet_config_path, deploy_config)

def devnet_l1_genesis(paths):
Expand Down
3 changes: 2 additions & 1 deletion op-batcher/batcher/driver.go
Expand Up @@ -393,13 +393,14 @@ func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, que
data := txdata.CallData()
// if plasma DA is enabled we post the txdata to the DA Provider and replace it with the commitment.
if l.Config.UsePlasma {
data, err = l.PlasmaDA.SetInput(ctx, data)
comm, err := l.PlasmaDA.SetInput(ctx, data)
if err != nil {
l.Log.Error("Failed to post input to Plasma DA", "error", err)
// requeue frame if we fail to post to the DA Provider so it can be retried
l.recordFailedTx(txdata, err)
return nil
}
data = comm.Encode()
}
candidate = l.calldataTxCandidate(data)
}
Expand Down
5 changes: 5 additions & 0 deletions op-batcher/batcher/service.go
Expand Up @@ -209,6 +209,11 @@ func (bs *BatcherService) initChannelConfig(cfg *CLIConfig) error {
default:
return fmt.Errorf("unknown data availability type: %v", cfg.DataAvailabilityType)
}

if bs.UsePlasma && bs.ChannelConfig.MaxFrameSize > plasma.MaxInputSize {
return fmt.Errorf("max frame size %d exceeds plasma max input size %d", bs.ChannelConfig.MaxFrameSize, plasma.MaxInputSize)
}

bs.ChannelConfig.MaxFrameSize-- // subtract 1 byte for version

if bs.ChannelConfig.CompressorConfig.Kind == compressor.ShadowKind {
Expand Down
35 changes: 27 additions & 8 deletions op-chain-ops/genesis/config.go
Expand Up @@ -243,15 +243,18 @@ type DeployConfig struct {

// UsePlasma is a flag that indicates if the system is using op-plasma
UsePlasma bool `json:"usePlasma"`
// DaChallengeWindow represents the block interval during which the availability of a data commitment can be challenged.
DaChallengeWindow uint64 `json:"daChallengeWindow"`
// DaResolveWindow represents the block interval during which a data availability challenge can be resolved.
DaResolveWindow uint64 `json:"daResolveWindow"`
// DaBondSize represents the required bond size to initiate a data availability challenge.
DaBondSize uint64 `json:"daBondSize"`
// DaResolverRefundPercentage represents the percentage of the resolving cost to be refunded to the resolver
// DAChallengeWindow represents the block interval during which the availability of a data commitment can be challenged.
DAChallengeWindow uint64 `json:"daChallengeWindow"`
// DAResolveWindow represents the block interval during which a data availability challenge can be resolved.
DAResolveWindow uint64 `json:"daResolveWindow"`
// DABondSize represents the required bond size to initiate a data availability challenge.
DABondSize uint64 `json:"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"`

// DAChallengeProxy represents the L1 address of the DataAvailabilityChallenge contract.
DAChallengeProxy common.Address `json:"daChallengeProxy"`

// When Cancun activates. Relative to L1 genesis.
L1CancunTimeOffset *hexutil.Uint64 `json:"l1CancunTimeOffset,omitempty"`
Expand Down Expand Up @@ -402,6 +405,17 @@ func (d *DeployConfig) Check() error {
if d.DisputeGameFinalityDelaySeconds == 0 {
log.Warn("DisputeGameFinalityDelaySeconds is 0")
}
if d.UsePlasma {
if d.DAChallengeWindow == 0 {
return fmt.Errorf("%w: DAChallengeWindow cannot be 0 when using plasma mode", ErrInvalidDeployConfig)
}
if d.DAResolveWindow == 0 {
return fmt.Errorf("%w: DAResolveWindow cannot be 0 when using plasma mode", ErrInvalidDeployConfig)
}
if d.DAChallengeProxy == (common.Address{}) {
return fmt.Errorf("%w: DAChallengeContract cannot be empty when using plasma mode", ErrInvalidDeployConfig)
}
}
// checkFork checks that fork A is before or at the same time as fork B
checkFork := func(a, b *hexutil.Uint64, aName, bName string) error {
if a == nil && b == nil {
Expand Down Expand Up @@ -463,6 +477,7 @@ func (d *DeployConfig) SetDeployments(deployments *L1Deployments) {
d.L1ERC721BridgeProxy = deployments.L1ERC721BridgeProxy
d.SystemConfigProxy = deployments.SystemConfigProxy
d.OptimismPortalProxy = deployments.OptimismPortalProxy
d.DAChallengeProxy = deployments.DataAvailabilityChallengeProxy
}

func (d *DeployConfig) GovernanceEnabled() bool {
Expand Down Expand Up @@ -577,6 +592,10 @@ 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,
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions op-chain-ops/genesis/testdata/test-deploy-config-full.json
Expand Up @@ -83,6 +83,7 @@
"useFaultProofs": false,
"usePlasma": false,
"daBondSize": 0,
"daChallengeProxy": "0x0000000000000000000000000000000000000000",
"daChallengeWindow": 0,
"daResolveWindow": 0,
"daResolverRefundPercentage": 0
Expand Down
29 changes: 27 additions & 2 deletions op-e2e/actions/l2_batcher.go
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
plasma "github.com/ethereum-optimism/optimism/op-plasma"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
)
Expand All @@ -42,6 +43,10 @@ type L1TxAPI interface {
SendTransaction(ctx context.Context, tx *types.Transaction) error
}

type PlasmaInputSetter interface {
SetInput(ctx context.Context, img []byte) (plasma.Keccak256Commitment, error)
}

type BatcherCfg struct {
// Limit the size of txs
MinL1TxSize uint64
Expand All @@ -53,8 +58,10 @@ type BatcherCfg struct {

ForceSubmitSingularBatch bool
ForceSubmitSpanBatch bool
UsePlasma bool

DataAvailabilityType batcherFlags.DataAvailabilityType
PlasmaDA PlasmaInputSetter
}

func DefaultBatcherCfg(dp *e2eutils.DeployParams) *BatcherCfg {
Expand All @@ -66,6 +73,17 @@ func DefaultBatcherCfg(dp *e2eutils.DeployParams) *BatcherCfg {
}
}

func PlasmaBatcherCfg(dp *e2eutils.DeployParams, plasmaDa PlasmaInputSetter) *BatcherCfg {
return &BatcherCfg{
MinL1TxSize: 0,
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
DataAvailabilityType: batcherFlags.CalldataType,
PlasmaDA: plasmaDa,
UsePlasma: true,
}
}

type L2BlockRefs interface {
L2BlockRefByHash(ctx context.Context, hash common.Hash) (eth.L2BlockRef, error)
}
Expand Down Expand Up @@ -231,6 +249,13 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic
t.Fatalf("failed to output channel data to frame: %v", err)
}

payload := data.Bytes()
if s.l2BatcherCfg.UsePlasma {
comm, err := s.l2BatcherCfg.PlasmaDA.SetInput(t.Ctx(), payload)
require.NoError(t, err, "failed to set input for plasma")
payload = comm.Encode()
}

nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr)
require.NoError(t, err, "need batcher nonce")

Expand All @@ -247,7 +272,7 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic
To: &s.rollupCfg.BatchInboxAddress,
GasTipCap: gasTipCap,
GasFeeCap: gasFeeCap,
Data: data.Bytes(),
Data: payload,
}
for _, opt := range txOpts {
opt(rawTx)
Expand All @@ -259,7 +284,7 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic
txData = rawTx
} else if s.l2BatcherCfg.DataAvailabilityType == batcherFlags.BlobsType {
var b eth.Blob
require.NoError(t, b.FromData(data.Bytes()), "must turn data into blob")
require.NoError(t, b.FromData(payload), "must turn data into blob")
sidecar, blobHashes, err := txmgr.MakeSidecar([]*eth.Blob{&b})
require.NoError(t, err)
require.NotNil(t, pendingHeader.ExcessBlobGas, "need L1 header with 4844 properties")
Expand Down
4 changes: 2 additions & 2 deletions op-e2e/actions/l2_sequencer.go
Expand Up @@ -44,8 +44,8 @@ type L2Sequencer struct {
}

func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, blobSrc derive.L1BlobsFetcher,
eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer {
ver := NewL2Verifier(t, log, l1, blobSrc, eng, cfg, &sync.Config{}, safedb.Disabled)
plasmaSrc derive.PlasmaInputFetcher, eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer {
ver := NewL2Verifier(t, log, l1, blobSrc, plasmaSrc, eng, cfg, &sync.Config{}, safedb.Disabled)
attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, eng)
seqConfDepthL1 := driver.NewConfDepth(seqConfDepth, ver.l1State.L1Head, l1)
l1OriginSelector := &MockL1OriginSelector{
Expand Down
3 changes: 2 additions & 1 deletion op-e2e/actions/l2_sequencer_test.go
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
plasma "github.com/ethereum-optimism/optimism/op-plasma"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
Expand Down Expand Up @@ -47,7 +48,7 @@ func setupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1M
l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg))
require.NoError(t, err)

sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), l2Cl, sd.RollupCfg, 0)
sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), plasma.Disabled, l2Cl, sd.RollupCfg, 0)
return miner, engine, sequencer
}

Expand Down
4 changes: 2 additions & 2 deletions op-e2e/actions/l2_verifier.go
Expand Up @@ -63,10 +63,10 @@ type safeDB interface {
node.SafeDBReader
}

func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB) *L2Verifier {
func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, plasmaSrc derive.PlasmaInputFetcher, eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB) *L2Verifier {
metrics := &testutils.TestDerivationMetrics{}
engine := derive.NewEngineController(eng, log, metrics, cfg, syncCfg.SyncMode)
pipeline := derive.NewDerivationPipeline(log, cfg, l1, blobsSrc, nil, eng, engine, metrics, syncCfg, safeHeadListener)
pipeline := derive.NewDerivationPipeline(log, cfg, l1, blobsSrc, plasmaSrc, eng, engine, metrics, syncCfg, safeHeadListener)
pipeline.Reset()

rollupNode := &L2Verifier{
Expand Down
3 changes: 2 additions & 1 deletion op-e2e/actions/l2_verifier_test.go
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/ethereum-optimism/optimism/op-node/node/safedb"
plasma "github.com/ethereum-optimism/optimism/op-plasma"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -40,7 +41,7 @@ func setupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, l1F derive
jwtPath := e2eutils.WriteDefaultJWT(t)
engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P())
engCl := engine.EngineClient(t, sd.RollupCfg)
verifier := NewL2Verifier(t, log, l1F, blobSrc, engCl, sd.RollupCfg, syncCfg, cfg.safeHeadListener)
verifier := NewL2Verifier(t, log, l1F, blobSrc, plasma.Disabled, engCl, sd.RollupCfg, syncCfg, cfg.safeHeadListener)
return engine, verifier
}

Expand Down

0 comments on commit 802c283

Please sign in to comment.