just remember this
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
package derive
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/ethereum-optimism/optimism/op-node/rollup"
|
||||
"github.com/ethereum-optimism/optimism/op-service/eth"
|
||||
"github.com/ethereum-optimism/optimism/op-service/solabi"
|
||||
)
|
||||
|
||||
var (
|
||||
SystemConfigUpdateBatcher = common.Hash{31: 0}
|
||||
SystemConfigUpdateGasConfig = common.Hash{31: 1}
|
||||
SystemConfigUpdateGasLimit = common.Hash{31: 2}
|
||||
SystemConfigUpdateUnsafeBlockSigner = common.Hash{31: 3}
|
||||
SystemConfigUpdateGasConfigEcotone = common.Hash{31: 4}
|
||||
)
|
||||
|
||||
var (
|
||||
ConfigUpdateEventABI = "ConfigUpdate(uint256,uint8,bytes)"
|
||||
ConfigUpdateEventABIHash = crypto.Keccak256Hash([]byte(ConfigUpdateEventABI))
|
||||
ConfigUpdateEventVersion0 = common.Hash{}
|
||||
)
|
||||
|
||||
// UpdateSystemConfigWithL1Receipts filters all L1 receipts to find config updates and applies the config updates to the given sysCfg
|
||||
func UpdateSystemConfigWithL1Receipts(sysCfg *eth.SystemConfig, receipts []*types.Receipt, cfg *rollup.Config, l1Time uint64) error {
|
||||
var result error
|
||||
for i, rec := range receipts {
|
||||
if rec.Status != types.ReceiptStatusSuccessful {
|
||||
continue
|
||||
}
|
||||
for j, log := range rec.Logs {
|
||||
if log.Address == cfg.L1SystemConfigAddress && len(log.Topics) > 0 && log.Topics[0] == ConfigUpdateEventABIHash {
|
||||
if err := ProcessSystemConfigUpdateLogEvent(sysCfg, log, cfg, l1Time); err != nil {
|
||||
result = multierror.Append(result, fmt.Errorf("malformatted L1 system sysCfg log in receipt %d, log %d: %w", i, j, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ProcessSystemConfigUpdateLogEvent decodes an EVM log entry emitted by the system config contract and applies it as a system config change.
|
||||
//
|
||||
// parse log data for:
|
||||
//
|
||||
// event ConfigUpdate(
|
||||
// uint256 indexed version,
|
||||
// UpdateType indexed updateType,
|
||||
// bytes data
|
||||
// );
|
||||
func ProcessSystemConfigUpdateLogEvent(destSysCfg *eth.SystemConfig, ev *types.Log, rollupCfg *rollup.Config, l1Time uint64) error {
|
||||
if len(ev.Topics) != 3 {
|
||||
return fmt.Errorf("expected 3 event topics (event identity, indexed version, indexed updateType), got %d", len(ev.Topics))
|
||||
}
|
||||
if ev.Topics[0] != ConfigUpdateEventABIHash {
|
||||
return fmt.Errorf("invalid SystemConfig update event: %s, expected %s", ev.Topics[0], ConfigUpdateEventABIHash)
|
||||
}
|
||||
|
||||
// indexed 0
|
||||
version := ev.Topics[1]
|
||||
if version != ConfigUpdateEventVersion0 {
|
||||
return fmt.Errorf("unrecognized SystemConfig update event version: %s", version)
|
||||
}
|
||||
// indexed 1
|
||||
updateType := ev.Topics[2]
|
||||
|
||||
// Create a reader of the unindexed data
|
||||
reader := bytes.NewReader(ev.Data)
|
||||
|
||||
// Attempt to read unindexed data
|
||||
switch updateType {
|
||||
case SystemConfigUpdateBatcher:
|
||||
if pointer, err := solabi.ReadUint64(reader); err != nil || pointer != 32 {
|
||||
return NewCriticalError(errors.New("invalid pointer field"))
|
||||
}
|
||||
if length, err := solabi.ReadUint64(reader); err != nil || length != 32 {
|
||||
return NewCriticalError(errors.New("invalid length field"))
|
||||
}
|
||||
address, err := solabi.ReadAddress(reader)
|
||||
if err != nil {
|
||||
return NewCriticalError(errors.New("could not read address"))
|
||||
}
|
||||
if !solabi.EmptyReader(reader) {
|
||||
return NewCriticalError(errors.New("too many bytes"))
|
||||
}
|
||||
destSysCfg.BatcherAddr = address
|
||||
return nil
|
||||
case SystemConfigUpdateGasConfig:
|
||||
if pointer, err := solabi.ReadUint64(reader); err != nil || pointer != 32 {
|
||||
return NewCriticalError(errors.New("invalid pointer field"))
|
||||
}
|
||||
if length, err := solabi.ReadUint64(reader); err != nil || length != 64 {
|
||||
return NewCriticalError(errors.New("invalid length field"))
|
||||
}
|
||||
overhead, err := solabi.ReadEthBytes32(reader)
|
||||
if err != nil {
|
||||
return NewCriticalError(errors.New("could not read overhead"))
|
||||
}
|
||||
scalar, err := solabi.ReadEthBytes32(reader)
|
||||
if err != nil {
|
||||
return NewCriticalError(errors.New("could not read scalar"))
|
||||
}
|
||||
if !solabi.EmptyReader(reader) {
|
||||
return NewCriticalError(errors.New("too many bytes"))
|
||||
}
|
||||
if rollupCfg.IsEcotone(l1Time) {
|
||||
if err := eth.CheckEcotoneL1SystemConfigScalar(scalar); err != nil {
|
||||
return nil // ignore invalid scalars, retain the old system-config scalar
|
||||
}
|
||||
// retain the scalar data in encoded form
|
||||
destSysCfg.Scalar = scalar
|
||||
// zero out the overhead, it will not affect the state-transition after Ecotone
|
||||
destSysCfg.Overhead = eth.Bytes32{}
|
||||
} else {
|
||||
destSysCfg.Overhead = overhead
|
||||
destSysCfg.Scalar = scalar
|
||||
}
|
||||
return nil
|
||||
case SystemConfigUpdateGasLimit:
|
||||
if pointer, err := solabi.ReadUint64(reader); err != nil || pointer != 32 {
|
||||
return NewCriticalError(errors.New("invalid pointer field"))
|
||||
}
|
||||
if length, err := solabi.ReadUint64(reader); err != nil || length != 32 {
|
||||
return NewCriticalError(errors.New("invalid length field"))
|
||||
}
|
||||
gasLimit, err := solabi.ReadUint64(reader)
|
||||
if err != nil {
|
||||
return NewCriticalError(errors.New("could not read gas limit"))
|
||||
}
|
||||
if !solabi.EmptyReader(reader) {
|
||||
return NewCriticalError(errors.New("too many bytes"))
|
||||
}
|
||||
destSysCfg.GasLimit = gasLimit
|
||||
return nil
|
||||
case SystemConfigUpdateUnsafeBlockSigner:
|
||||
// Ignored in derivation. This configurable applies to runtime configuration outside of the derivation.
|
||||
return nil
|
||||
case SystemConfigUpdateGasConfigEcotone:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unrecognized L1 sysCfg update type: %s", updateType)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user