diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 6b994ad708a2..0fc8393cc457 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -400,7 +400,8 @@ func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, que l.recordFailedTx(txdata, err) return nil } - data = comm.Encode() + // signal plasma commitment tx with TxDataVersion1 + data = comm.TxData() } candidate = l.calldataTxCandidate(data) } diff --git a/op-e2e/actions/l2_batcher.go b/op-e2e/actions/l2_batcher.go index 8427d33be862..e65a3383b459 100644 --- a/op-e2e/actions/l2_batcher.go +++ b/op-e2e/actions/l2_batcher.go @@ -253,7 +253,7 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic 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() + payload = comm.TxData() } nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) diff --git a/op-e2e/actions/plasma_test.go b/op-e2e/actions/plasma_test.go index 0c1426b48a58..d863283b23a9 100644 --- a/op-e2e/actions/plasma_test.go +++ b/op-e2e/actions/plasma_test.go @@ -159,7 +159,8 @@ func (a *L2PlasmaDA) ActNewL2Tx(t Testing) { a.batcher.ActL2BatchBuffer(t) a.batcher.ActL2ChannelClose(t) a.batcher.ActL2BatchSubmit(t, func(tx *types.DynamicFeeTx) { - a.lastComm = tx.Data + // skip txdata version byte + a.lastComm = tx.Data[1:] }) a.miner.ActL1StartBlock(3)(t) diff --git a/op-node/rollup/derive/params.go b/op-node/rollup/derive/params.go index bba78cc2dfee..35ac8667e83c 100644 --- a/op-node/rollup/derive/params.go +++ b/op-node/rollup/derive/params.go @@ -4,6 +4,8 @@ import ( "encoding/hex" "errors" "fmt" + + plasma "github.com/ethereum-optimism/optimism/op-plasma" ) // count the tagging info as 200 in terms of buffer size. @@ -19,6 +21,9 @@ func frameSize(frame Frame) uint64 { const DerivationVersion0 = 0 +// DerivationVersion1 is reserved for batcher transactions containing plasma commitments. +const DerivationVersion1 = plasma.TxDataVersion1 + // MaxSpanBatchSize is the maximum amount of bytes that will be needed // to decode every span batch field. This value cannot be larger than // MaxRLPBytesPerChannel because single batch cannot be larger than channel size. diff --git a/op-node/rollup/derive/plasma_data_source.go b/op-node/rollup/derive/plasma_data_source.go index c1b5121128bf..da311c50e0c3 100644 --- a/op-node/rollup/derive/plasma_data_source.go +++ b/op-node/rollup/derive/plasma_data_source.go @@ -45,14 +45,22 @@ func (s *PlasmaDataSource) Next(ctx context.Context) (eth.Data, error) { } if s.comm == nil { - var err error // the l1 source returns the input commitment for the batch. data, err := s.src.Next(ctx) if err != nil { return nil, err } + if len(data) == 0 { + return nil, NotEnoughData + } + // If the tx data type is not plasma, we forward it downstream to let the next + // steps validate and potentially parse it as L1 DA inputs. + if data[0] != plasma.TxDataVersion1 { + return data, nil + } + // validate batcher inbox data is a commitment. - comm, err := plasma.DecodeKeccak256(data) + comm, err := plasma.DecodeKeccak256(data[1:]) if err != nil { s.log.Warn("invalid commitment", "commitment", data, "err", err) return s.Next(ctx) diff --git a/op-node/rollup/derive/plasma_data_source_test.go b/op-node/rollup/derive/plasma_data_source_test.go index ba2e7c6f06ce..0769eb504a11 100644 --- a/op-node/rollup/derive/plasma_data_source_test.go +++ b/op-node/rollup/derive/plasma_data_source_test.go @@ -134,7 +134,7 @@ func TestPlasmaDataSource(t *testing.T) { Gas: 100_000, To: &batcherInbox, Value: big.NewInt(int64(0)), - Data: comm.Encode(), + Data: comm.TxData(), }) require.NoError(t, err) @@ -234,7 +234,7 @@ func TestPlasmaDataSource(t *testing.T) { Gas: 100_000, To: &batcherInbox, Value: big.NewInt(int64(0)), - Data: comm.Encode(), + Data: comm.TxData(), }) require.NoError(t, err) @@ -351,7 +351,7 @@ func TestPlasmaDataSourceStall(t *testing.T) { Gas: 100_000, To: &batcherInbox, Value: big.NewInt(int64(0)), - Data: comm.Encode(), + Data: comm.TxData(), }) require.NoError(t, err) @@ -466,7 +466,7 @@ func TestPlasmaDataSourceInvalidData(t *testing.T) { Gas: 100_000, To: &batcherInbox, Value: big.NewInt(int64(0)), - Data: comm.Encode(), + Data: comm.TxData(), }) require.NoError(t, err) @@ -481,11 +481,11 @@ func TestPlasmaDataSourceInvalidData(t *testing.T) { Gas: 100_000, To: &batcherInbox, Value: big.NewInt(int64(0)), - Data: comm2.Encode(), + Data: comm2.TxData(), }) require.NoError(t, err) - // invalid commitment + // regular input instead of commitment input3 := testutils.RandomData(rng, 32) tx3, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{ ChainID: signer.ChainID(), @@ -506,12 +506,16 @@ func TestPlasmaDataSourceInvalidData(t *testing.T) { src, err := factory.OpenData(ctx, ref, batcherAddr) require.NoError(t, err) - // oversized input should be skipped + // oversized input is skipped and returns input2 directly data, err := src.Next(ctx) require.NoError(t, err) require.Equal(t, hexutil.Bytes(input2), data) - // invalid commitment is skipped so should return an EOF + // regular input is passed through + data, err = src.Next(ctx) + require.NoError(t, err) + require.Equal(t, hexutil.Bytes(input3), data) + _, err = src.Next(ctx) require.ErrorIs(t, err, io.EOF) diff --git a/op-plasma/commitment.go b/op-plasma/commitment.go index e0f49e538425..6f45bd4f8429 100644 --- a/op-plasma/commitment.go +++ b/op-plasma/commitment.go @@ -27,6 +27,11 @@ func (c Keccak256Commitment) Encode() []byte { return append([]byte{byte(Keccak256CommitmentType)}, c...) } +// TxData adds an extra version byte to signal it's a commitment. +func (c Keccak256Commitment) TxData() []byte { + return append([]byte{TxDataVersion1}, c.Encode()...) +} + // Verify checks if the commitment matches the given input. func (c Keccak256Commitment) Verify(input []byte) error { if !bytes.Equal(c, crypto.Keccak256(input)) { diff --git a/op-plasma/params.go b/op-plasma/params.go index 3377d981cd00..e176c207919a 100644 --- a/op-plasma/params.go +++ b/op-plasma/params.go @@ -4,3 +4,8 @@ package plasma // challenge in the Data Availability Challenge contract. Value in number of bytes. // This value can only be changed in a hard fork. const MaxInputSize = 130672 + +// TxDataVersion1 is the version number for batcher transactions containing +// plasma commitments. It should not collide with DerivationVersion which is still +// used downstream when parsing the frames. +const TxDataVersion1 = 1