Skip to content

Commit

Permalink
handle Holocene l1 attributes in l1 data fee computation
Browse files Browse the repository at this point in the history
  • Loading branch information
roberto-bayardo committed Sep 22, 2024
1 parent 5f7ebba commit 99df6a5
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 6 deletions.
19 changes: 14 additions & 5 deletions core/types/rollup_cost.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ var (
BedrockL1AttributesSelector = []byte{0x01, 0x5d, 0x8e, 0xb9}
// EcotoneL1AttributesSelector is the selector indicating Ecotone style L1 gas attributes.
EcotoneL1AttributesSelector = []byte{0x44, 0x0a, 0x5e, 0x20}
// HoloceneL1AttributesSelector is the selector indicating Holocene style L1 gas attributes.
HoloceneL1AttributesSelector = []byte{0xd1, 0xfb, 0xe1, 0x5b}

// L1BlockAddr is the address of the L1Block contract which stores the L1 gas attributes.
L1BlockAddr = common.HexToAddress("0x4200000000000000000000000000000000000015")
Expand Down Expand Up @@ -264,7 +266,7 @@ func extractL1GasParams(config *params.ChainConfig, time uint64, data []byte) (g
// If so, fall through to the pre-ecotone format
// Both Ecotone and Fjord use the same function selector
if config.IsEcotone(time) && len(data) >= 4 && !bytes.Equal(data[0:4], BedrockL1AttributesSelector) {
p, err := extractL1GasParamsPostEcotone(data)
p, err := extractL1GasParamsPostEcotone(config.IsHolocene(time), data)
if err != nil {
return gasParams{}, err
}
Expand Down Expand Up @@ -309,13 +311,16 @@ func extractL1GasParamsPreEcotone(config *params.ChainConfig, time uint64, data
}

// extractL1GasParamsPostEcotone extracts the gas parameters necessary to compute gas from L1 attribute
// info calldata after the Ecotone upgrade, but not for the very first Ecotone block.
func extractL1GasParamsPostEcotone(data []byte) (gasParams, error) {
if len(data) != 164 {
// info calldata after the Ecotone upgrade, other than the very first Ecotone block.
func extractL1GasParamsPostEcotone(isHolocene bool, data []byte) (gasParams, error) {
if isHolocene && len(data) >= 4 && bytes.Equal(data[0:4], HoloceneL1AttributesSelector) {
if len(data) != 180 {
return gasParams{}, fmt.Errorf("expected 180 L1 info bytes, got %d", len(data))
}
} else if len(data) != 164 {
return gasParams{}, fmt.Errorf("expected 164 L1 info bytes, got %d", len(data))
}
// data layout assumed for Ecotone:
// offset type varname
// 0 <selector>
// 4 uint32 _basefeeScalar
// 8 uint32 _blobBaseFeeScalar
Expand All @@ -326,6 +331,10 @@ func extractL1GasParamsPostEcotone(data []byte) (gasParams, error) {
// 68 uint256 _blobBaseFee,
// 100 bytes32 _hash,
// 132 bytes32 _batcherHash,
//
// added by Holocene:
// 164 uint64 _eip1559Denominator,
// 172 uint64 _eip1559Elasticity,
l1BaseFee := new(big.Int).SetBytes(data[36:68])
l1BlobBaseFee := new(big.Int).SetBytes(data[68:100])
l1BaseFeeScalar := binary.BigEndian.Uint32(data[4:8])
Expand Down
71 changes: 70 additions & 1 deletion core/types/rollup_cost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,69 @@ func TestExtractEcotoneGasParams(t *testing.T) {

// make sure wrong amont of data results in error
data = append(data, 0x00) // tack on garbage byte
_, err = extractL1GasParamsPostEcotone(data)
_, err = extractL1GasParamsPostEcotone(false, data)
require.Error(t, err)

// make sure holocene attributes result in error prior to Holocene activation
data = getHoloceneL1Attributes(
baseFee,
blobBaseFee,
baseFeeScalar,
blobBaseFeeScalar,
)
gasparams, err = extractL1GasParams(config, zeroTime, data)
require.Error(t, err)
}

func TestExtractHoloceneGasParams(t *testing.T) {
zeroTime := uint64(0)
// create a config where holocene upgrade is active
config := &params.ChainConfig{
Optimism: params.OptimismTestConfig.Optimism,
RegolithTime: &zeroTime,
EcotoneTime: &zeroTime,
HoloceneTime: &zeroTime,
}
require.True(t, config.IsOptimismEcotone(zeroTime))
require.True(t, config.IsOptimismHolocene(zeroTime))

// make sure empty attributes returns error
data := []byte{}
_, err := extractL1GasParamsPostEcotone(true, data)
require.Error(t, err)

// Check that we still allow Ecotone-style L1 attributes post-Holocene, since the very first Holocene block will
// have Ecotone attributes.
data = getEcotoneL1Attributes(
baseFee,
blobBaseFee,
baseFeeScalar,
blobBaseFeeScalar,
)
gasparams, err := extractL1GasParams(config, zeroTime, data)
require.NoError(t, err)
costFunc := gasparams.costFunc
c, g := costFunc(emptyTx.RollupCostData())
require.Equal(t, ecotoneGas, g)
require.Equal(t, ecotoneFee, c)

// Now confirm Holocene-style L1 attributes work.
data = getHoloceneL1Attributes(
baseFee,
blobBaseFee,
baseFeeScalar,
blobBaseFeeScalar,
)
gasparams, err = extractL1GasParams(config, zeroTime, data)
require.NoError(t, err)
costFunc = gasparams.costFunc
c, g = costFunc(emptyTx.RollupCostData())
require.Equal(t, ecotoneGas, g)
require.Equal(t, ecotoneFee, c)

// make sure wrong amont of data results in error
data = append(data, 0x00) // tack on garbage byte
_, err = extractL1GasParamsPostEcotone(true, data)
require.Error(t, err)
}

Expand Down Expand Up @@ -263,6 +325,13 @@ func getEcotoneL1Attributes(baseFee, blobBaseFee, baseFeeScalar, blobBaseFeeScal
return data
}

func getHoloceneL1Attributes(baseFee, blobBaseFee, baseFeeScalar, blobBaseFeeScalar *big.Int) []byte {
data := getEcotoneL1Attributes(baseFee, blobBaseFee, baseFeeScalar, blobBaseFeeScalar)
copy(data, HoloceneL1AttributesSelector)
data = append(data, make([]byte, 16)...) // add 0 values for the two new attributes
return data
}

type testStateGetter struct {
baseFee, blobBaseFee, overhead, scalar *big.Int
baseFeeScalar, blobBaseFeeScalar uint32
Expand Down

0 comments on commit 99df6a5

Please sign in to comment.