Sitelet https://github.com/ethereum-optimism/optimism/commit/a864f6fbfbfc8b358a39d617a9f7471609d47075
Skip to content

Commit a864f6f

Browse files
authored
op-alt-da: make input size limit configurable (#22496)
1 parent cd39278 commit a864f6f

8 files changed

Lines changed: 94 additions & 33 deletions

File tree

‎op-alt-da/params.go‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package altda
22

3-
// MaxInputSize ensures the canonical chain cannot include input batches too large to
4-
// challenge in the Data Availability Challenge contract. Value in number of bytes.
5-
// This value can only be changed in a hard fork.
3+
// MaxInputSize is the default maximum input size in bytes. It ensures the canonical
4+
// chain cannot include input batches too large to challenge in the Data Availability
5+
// Challenge contract.
66
const MaxInputSize = 130672

‎op-batcher/batcher/service.go‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,9 @@ func (bs *BatcherService) initChannelConfig(cfg *CLIConfig) error {
288288
return fmt.Errorf("cannot use data availability type blobs or auto with Alt-DA")
289289
}
290290

291-
if bs.UseAltDA && !bs.GenericDA && cc.MaxFrameSize > altda.MaxInputSize {
292-
return fmt.Errorf("max frame size %d exceeds altDA max input size %d", cc.MaxFrameSize, altda.MaxInputSize)
291+
maxInputSize := bs.RollupConfig.AltDAConfig.MaxInputSizeOrDefault()
292+
if bs.UseAltDA && !bs.GenericDA && cc.MaxFrameSize > maxInputSize {
293+
return fmt.Errorf("max frame size %d exceeds altDA max input size %d", cc.MaxFrameSize, maxInputSize)
293294
}
294295

295296
cc.InitCompressorConfig(cfg.ApproxComprRatio, cfg.Compressor, cfg.CompressionAlgo)

‎op-node/rollup/derive/altda_data_source.go‎

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,24 @@ import (
1414
// AltDADataSource is a data source that fetches inputs from a AltDA provider given
1515
// their onchain commitments. Same as CalldataSource it will keep attempting to fetch.
1616
type AltDADataSource struct {
17-
log log.Logger
18-
src DataIter
19-
fetcher AltDAInputFetcher
20-
l1 L1Fetcher
21-
id eth.L1BlockRef
17+
log log.Logger
18+
src DataIter
19+
fetcher AltDAInputFetcher
20+
l1 L1Fetcher
21+
id eth.L1BlockRef
22+
maxInputSize uint64
2223
// keep track of a pending commitment so we can keep trying to fetch the input.
2324
comm altda.CommitmentData
2425
}
2526

26-
func NewAltDADataSource(log log.Logger, src DataIter, l1 L1Fetcher, fetcher AltDAInputFetcher, id eth.L1BlockRef) *AltDADataSource {
27+
func NewAltDADataSource(log log.Logger, src DataIter, l1 L1Fetcher, fetcher AltDAInputFetcher, maxInputSize uint64, id eth.L1BlockRef) *AltDADataSource {
2728
return &AltDADataSource{
28-
log: log,
29-
src: src,
30-
fetcher: fetcher,
31-
l1: l1,
32-
id: id,
29+
log: log,
30+
src: src,
31+
fetcher: fetcher,
32+
l1: l1,
33+
id: id,
34+
maxInputSize: maxInputSize,
3335
}
3436
}
3537

@@ -99,8 +101,8 @@ func (s *AltDADataSource) Next(ctx context.Context) (eth.Data, error) {
99101
return nil, NewTemporaryError(fmt.Errorf("failed to fetch input data with comm %s from da service: %w", s.comm, err))
100102
}
101103
// inputs are limited to a max size to ensure they can be challenged in the DA contract.
102-
if s.comm.CommitmentType() == altda.Keccak256CommitmentType && len(data) > altda.MaxInputSize {
103-
s.log.Warn("input data exceeds max size", "size", len(data), "max", altda.MaxInputSize)
104+
if s.comm.CommitmentType() == altda.Keccak256CommitmentType && uint64(len(data)) > s.maxInputSize {
105+
s.log.Warn("input data exceeds max size", "size", len(data), "max", s.maxInputSize)
104106
s.comm = nil
105107
return s.Next(ctx)
106108
}

‎op-node/rollup/derive/altda_data_source_test.go‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ func TestAltDADataSourceInvalidData(t *testing.T) {
447447
batcherPriv := testutils.RandomKey()
448448
batcherAddr := crypto.PubkeyToAddress(batcherPriv.PublicKey)
449449
batcherInbox := common.Address{42}
450+
maxInputSize := uint64(3_000)
450451
cfg := &rollup.Config{
451452
L1ChainID: big.NewInt(42), // any, for L1Signer
452453
Genesis: rollup.Genesis{
@@ -461,6 +462,7 @@ func TestAltDADataSourceInvalidData(t *testing.T) {
461462
DAChallengeWindow: pcfg.ChallengeWindow,
462463
DAResolveWindow: pcfg.ResolveWindow,
463464
CommitmentType: altda.KeccakCommitmentString,
465+
MaxInputSize: &maxInputSize,
464466
},
465467
}
466468

@@ -478,7 +480,7 @@ func TestAltDADataSourceInvalidData(t *testing.T) {
478480
}
479481
l1F.ExpectFetchReceipts(ref.Hash, nil, optypes.Receipts{}, nil)
480482
// mock input commitments in l1 transactions with an oversized input
481-
input := testutils.RandomData(rng, altda.MaxInputSize+1)
483+
input := testutils.RandomData(rng, int(maxInputSize)+1)
482484
comm, _ := storage.SetInput(ctx, input)
483485

484486
tx1, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{

‎op-node/rollup/derive/data_source.go‎

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ type AltDAInputFetcher interface {
4040
// batch submitter transactions.
4141
// This is not a stage in the pipeline, but a wrapper for another stage in the pipeline
4242
type DataSourceFactory struct {
43-
log log.Logger
44-
dsCfg DataSourceConfig
45-
fetcher L1Fetcher
46-
blobsFetcher L1BlobsFetcher
47-
altDAFetcher AltDAInputFetcher
48-
ecotoneTime *uint64
43+
log log.Logger
44+
dsCfg DataSourceConfig
45+
fetcher L1Fetcher
46+
blobsFetcher L1BlobsFetcher
47+
altDAFetcher AltDAInputFetcher
48+
altDAMaxInputSize uint64
49+
ecotoneTime *uint64
4950
}
5051

5152
func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1Fetcher, blobsFetcher L1BlobsFetcher, altDAFetcher AltDAInputFetcher) *DataSourceFactory {
@@ -55,12 +56,13 @@ func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1Fetcher,
5556
altDAEnabled: cfg.AltDAEnabled(),
5657
}
5758
return &DataSourceFactory{
58-
log: log,
59-
dsCfg: config,
60-
fetcher: fetcher,
61-
blobsFetcher: blobsFetcher,
62-
altDAFetcher: altDAFetcher,
63-
ecotoneTime: cfg.EcotoneTime,
59+
log: log,
60+
dsCfg: config,
61+
fetcher: fetcher,
62+
blobsFetcher: blobsFetcher,
63+
altDAFetcher: altDAFetcher,
64+
altDAMaxInputSize: cfg.AltDAConfig.MaxInputSizeOrDefault(),
65+
ecotoneTime: cfg.EcotoneTime,
6466
}
6567
}
6668

@@ -79,7 +81,7 @@ func (ds *DataSourceFactory) OpenData(ctx context.Context, ref eth.L1BlockRef, b
7981
}
8082
if ds.dsCfg.altDAEnabled {
8183
// altDA([calldata | blobdata](l1Ref)) -> data
82-
return NewAltDADataSource(ds.log, src, ds.fetcher, ds.altDAFetcher, ref), nil
84+
return NewAltDADataSource(ds.log, src, ds.fetcher, ds.altDAFetcher, ds.altDAMaxInputSize, ref), nil
8385
}
8486
return src, nil
8587
}

‎op-node/rollup/types.go‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ type AltDAConfig struct {
6565
DAChallengeAddress common.Address `json:"da_challenge_contract_address,omitempty"`
6666
// CommitmentType specifies which commitment type can be used. Defaults to Keccak (type 0) if not present
6767
CommitmentType string `json:"da_commitment_type"`
68+
// MaxInputSize is the maximum byte size accepted for Keccak commitments.
69+
// It defaults to the protocol limit when omitted.
70+
MaxInputSize *uint64 `json:"da_max_input_size,omitempty"`
6871
// DA challenge window value set on the DAC contract. Used in alt-da mode
6972
// to compute when a commitment can no longer be challenged.
7073
DAChallengeWindow uint64 `json:"da_challenge_window"`
@@ -73,6 +76,14 @@ type AltDAConfig struct {
7376
DAResolveWindow uint64 `json:"da_resolve_window"`
7477
}
7578

79+
// MaxInputSizeOrDefault returns the configured maximum input size or the protocol default.
80+
func (c *AltDAConfig) MaxInputSizeOrDefault() uint64 {
81+
if c == nil || c.MaxInputSize == nil {
82+
return altda.MaxInputSize
83+
}
84+
return *c.MaxInputSize
85+
}
86+
7687
type Config struct {
7788
// Genesis anchor point of the rollup
7889
Genesis Genesis `json:"genesis"`
@@ -433,6 +444,12 @@ func (cfg *Config) ProbablyMissingPectraBlobSchedule() bool {
433444
// If the legacy values are set, they are copied to the new location. If both are set, they are check for consistency.
434445
func validateAltDAConfig(cfg *Config) error {
435446
if cfg.AltDAConfig != nil {
447+
if cfg.AltDAConfig.CommitmentType == altda.GenericCommitmentString && cfg.AltDAConfig.MaxInputSize != nil {
448+
return errors.New("altDA max input size must be omitted for generic commitments")
449+
}
450+
if cfg.AltDAConfig.MaxInputSize != nil && *cfg.AltDAConfig.MaxInputSize == 0 {
451+
return errors.New("altDA max input size must be greater than zero")
452+
}
436453
if !(cfg.AltDAConfig.CommitmentType == altda.KeccakCommitmentString || cfg.AltDAConfig.CommitmentType == altda.GenericCommitmentString) {
437454
return fmt.Errorf("invalid commitment type: %v", cfg.AltDAConfig.CommitmentType)
438455
}

‎op-node/rollup/types_test.go‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/ethereum/go-ethereum/log"
2121
"github.com/ethereum/go-ethereum/params"
2222

23+
altda "github.com/ethereum-optimism/optimism/op-alt-da"
2324
"github.com/ethereum-optimism/optimism/op-core/forks"
2425
opparams "github.com/ethereum-optimism/optimism/op-core/params"
2526
"github.com/ethereum-optimism/optimism/op-service/eth"
@@ -75,6 +76,31 @@ func TestConfigJSON(t *testing.T) {
7576
assert.Equal(t, &roundTripped, config)
7677
}
7778

79+
func TestAltDAConfigMaxInputSize(t *testing.T) {
80+
custom := uint64(1_000_000)
81+
82+
require.Equal(t, uint64(altda.MaxInputSize), (*AltDAConfig)(nil).MaxInputSizeOrDefault())
83+
require.Equal(t, uint64(altda.MaxInputSize), (&AltDAConfig{}).MaxInputSizeOrDefault())
84+
require.Equal(t, custom, (&AltDAConfig{MaxInputSize: &custom}).MaxInputSizeOrDefault())
85+
86+
cfg := randConfig()
87+
cfg.AltDAConfig = &AltDAConfig{
88+
DAChallengeAddress: common.Address{1},
89+
CommitmentType: altda.KeccakCommitmentString,
90+
MaxInputSize: ptr.Zero64,
91+
}
92+
require.EqualError(t, cfg.Check(), "altDA max input size must be greater than zero")
93+
94+
cfg.AltDAConfig = &AltDAConfig{
95+
CommitmentType: altda.GenericCommitmentString,
96+
MaxInputSize: &custom,
97+
}
98+
require.EqualError(t, cfg.Check(), "altDA max input size must be omitted for generic commitments")
99+
100+
cfg.AltDAConfig.MaxInputSize = nil
101+
require.NoError(t, cfg.Check())
102+
}
103+
78104
// TestConfigChainOpConfigJSONWireFormat pins the on-the-wire serialization of the
79105
// ChainOpConfig field. Its type moved from op-geth's params.OptimismConfig to
80106
// op-core/params.OptimismConfig; the JSON must remain byte-for-byte identical.

‎rust/kona/crates/protocol/genesis/src/chain/altda.rs‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub struct AltDAConfig {
2020
pub da_resolve_window: Option<u64>,
2121
/// `AltDA` commitment type
2222
pub da_commitment_type: Option<String>,
23+
/// Maximum input size for Keccak commitments.
24+
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
25+
pub da_max_input_size: Option<u64>,
2326
}
2427

2528
#[cfg(test)]
@@ -36,7 +39,8 @@ mod tests {
3639
"da_challenge_address": "0x12c6a7db25b20347ca6f5d47e56d5e8219871c6d",
3740
"da_challenge_window": 1,
3841
"da_resolve_window": 1,
39-
"da_commitment_type": "KeccakCommitment"
42+
"da_commitment_type": "KeccakCommitment",
43+
"da_max_input_size": 1000000
4044
}
4145
"#;
4246

@@ -45,6 +49,7 @@ mod tests {
4549
da_challenge_window: Some(1),
4650
da_resolve_window: Some(1),
4751
da_commitment_type: Some("KeccakCommitment".to_string()),
52+
da_max_input_size: Some(1_000_000),
4853
};
4954

5055
let deserialized: AltDAConfig = serde_json::from_str(raw).unwrap();
@@ -66,4 +71,10 @@ mod tests {
6671
let err = serde_json::from_str::<AltDAConfig>(raw).unwrap_err();
6772
assert_eq!(err.classify(), serde_json::error::Category::Data);
6873
}
74+
75+
#[test]
76+
fn test_altda_serialize_omits_unset_max_input_size() {
77+
let serialized = serde_json::to_value(AltDAConfig::default()).unwrap();
78+
assert!(serialized.get("da_max_input_size").is_none());
79+
}
6980
}

0 commit comments

Comments
 (0)