Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions op-e2e/system/e2esys/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ func (cfg SystemConfig) Start(t *testing.T, startOpts ...StartOption) (*System,
},

BatchAuthenticatorAddress: cfg.DeployConfig.BatchAuthenticatorAddress,
CeloEspressoTimestamp: func() *uint64 { v := uint64(cfg.DeployConfig.L1GenesisBlockTimestamp); return &v }(),
}
}
defaultConfig := makeRollupConfig()
Expand Down
9 changes: 9 additions & 0 deletions op-node/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,14 @@ var (
Value: "0x703848f4c85f18e3acd8196c8ec91eb0b7bd0797",
Category: OperationsCategory,
}
CeloEspressoTimestamp = &cli.Uint64Flag{
Name: "celo-espresso-timestamp",
Usage: "Unix timestamp for activating Celo Espresso integration features",
EnvVars: prefixEnvVars("CELO_ESPRESSO_TIMESTAMP"),
Category: RollupCategory,
Required: false,
Destination: new(uint64),
}
)

var requiredFlags = []cli.Flag{
Expand Down Expand Up @@ -568,6 +576,7 @@ var optionalFlags = []cli.Flag{
CaffNodeHotShotUrls,
CaffNodeEspressoLightClientAddr,
CaffNodeL1EthRpc,
CeloEspressoTimestamp,
}

var DeprecatedFlags = []cli.Flag{
Expand Down
6 changes: 3 additions & 3 deletions op-node/rollup/derive/blob_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (ds *BlobDataSource) open(ctx context.Context) ([]blobOrCalldata, error) {
return nil, NewTemporaryError(fmt.Errorf("failed to open blob data source: L1 fetcher provided inconsistent number of receipts"))
}

data, hashes := dataAndHashesFromTxs(txs, receipts, &ds.dsCfg, ds.batcherAddr, ds.log)
data, hashes := dataAndHashesFromTxs(txs, receipts, &ds.dsCfg, ds.ref, ds.batcherAddr, ds.log)

if len(hashes) == 0 {
// there are no blobs to fetch so we can return immediately
Expand Down Expand Up @@ -127,14 +127,14 @@ func (ds *BlobDataSource) open(ctx context.Context) ([]blobOrCalldata, error) {
// dataAndHashesFromTxs extracts calldata and datahashes from the input transactions and returns them. It
// creates a placeholder blobOrCalldata element for each returned blob hash that must be populated
// by fillBlobPointers after blob bodies are retrieved.
func dataAndHashesFromTxs(txs types.Transactions, receipts types.Receipts, config *DataSourceConfig, batcherAddr common.Address, logger log.Logger) ([]blobOrCalldata, []eth.IndexedBlobHash) {
func dataAndHashesFromTxs(txs types.Transactions, receipts types.Receipts, config *DataSourceConfig, ref eth.L1BlockRef, batcherAddr common.Address, logger log.Logger) ([]blobOrCalldata, []eth.IndexedBlobHash) {
data := []blobOrCalldata{}
var hashes []eth.IndexedBlobHash
blobIndex := 0 // index of each blob in the block's blob sidecar
for i, tx := range txs {
receipt := receipts[i]
// skip any non-batcher transactions
if !isValidBatchTx(tx, receipt, config.l1Signer, config.batchInboxAddress, batcherAddr, logger) {
if !isValidBatchTx(tx, receipt, ref, config.l1Signer, config.batchInboxAddress, batcherAddr, logger, config.celoEspressoTimestamp) {
blobIndex += len(tx.BlobHashes())
continue
}
Expand Down
13 changes: 7 additions & 6 deletions op-node/rollup/derive/blob_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ func TestDataAndHashesFromTxs(t *testing.T) {
}
txs := types.Transactions{calldataTx}
receipts := types.Receipts{calldataReceipt}
data, blobHashes := dataAndHashesFromTxs(txs, receipts, &config, batcherAddr, logger)
testRef := eth.L1BlockRef{Time: 1000} // Use a fixed timestamp for testing
data, blobHashes := dataAndHashesFromTxs(txs, receipts, &config, testRef, batcherAddr, logger)
require.Equal(t, 1, len(data))
require.Equal(t, 0, len(blobHashes))

Expand All @@ -77,15 +78,15 @@ func TestDataAndHashesFromTxs(t *testing.T) {
}
txs = types.Transactions{blobTx}
receipts = types.Receipts{blobReceipt}
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, batcherAddr, logger)
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, testRef, batcherAddr, logger)
require.Equal(t, 1, len(data))
require.Equal(t, 1, len(blobHashes))
require.Nil(t, data[0].calldata)

// try again with both the blob & calldata transactions and make sure both are picked up
txs = types.Transactions{blobTx, calldataTx}
receipts = types.Receipts{blobReceipt, calldataReceipt}
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, batcherAddr, logger)
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, testRef, batcherAddr, logger)
require.Equal(t, 2, len(data))
require.Equal(t, 1, len(blobHashes))
require.NotNil(t, data[1].calldata)
Expand All @@ -98,7 +99,7 @@ func TestDataAndHashesFromTxs(t *testing.T) {
}
txs = types.Transactions{blobTx}
receipts = types.Receipts{blobReceipt}
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, batcherAddr, logger)
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, testRef, batcherAddr, logger)
require.Equal(t, 0, len(data))
require.Equal(t, 0, len(blobHashes))

Expand All @@ -112,7 +113,7 @@ func TestDataAndHashesFromTxs(t *testing.T) {
}
txs = types.Transactions{blobTx}
receipts = types.Receipts{blobReceipt}
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, batcherAddr, logger)
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, testRef, batcherAddr, logger)
require.Equal(t, 0, len(data))
require.Equal(t, 0, len(blobHashes))

Expand All @@ -131,7 +132,7 @@ func TestDataAndHashesFromTxs(t *testing.T) {
require.NoError(t, err)
txs = types.Transactions{setCodeTx}
receipts = types.Receipts{setCodeReceipt}
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, batcherAddr, logger)
data, blobHashes = dataAndHashesFromTxs(txs, receipts, &config, testRef, batcherAddr, logger)
require.Equal(t, 0, len(data))
require.Equal(t, 0, len(blobHashes))
}
Expand Down
8 changes: 4 additions & 4 deletions op-node/rollup/derive/calldata_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewCalldataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConf
}
return &CalldataSource{
open: true,
data: DataFromEVMTransactions(dsCfg, batcherAddr, txs, receipts, log.New("origin", ref)),
data: DataFromEVMTransactions(dsCfg, batcherAddr, txs, receipts, ref, log.New("origin", ref)),
}
}

Expand All @@ -80,7 +80,7 @@ func (ds *CalldataSource) Next(ctx context.Context) (eth.Data, error) {
return nil, NewTemporaryError(fmt.Errorf("failed to open calldata source: L1 fetcher provided inconsistent number of transactions and receipts"))
}
ds.open = true
ds.data = DataFromEVMTransactions(ds.dsCfg, ds.batcherAddr, txs, receipts, ds.log)
ds.data = DataFromEVMTransactions(ds.dsCfg, ds.batcherAddr, txs, receipts, ds.ref, ds.log)
}
if len(ds.data) == 0 {
return nil, io.EOF
Expand All @@ -94,10 +94,10 @@ func (ds *CalldataSource) Next(ctx context.Context) (eth.Data, error) {
// DataFromEVMTransactions filters all of the transactions and returns the calldata from transactions
// that are sent to the batch inbox address from the batch sender address.
// This will return an empty array if no valid transactions are found.
func DataFromEVMTransactions(dsCfg DataSourceConfig, batcherAddr common.Address, txs types.Transactions, receipts types.Receipts, log log.Logger) []eth.Data {
func DataFromEVMTransactions(dsCfg DataSourceConfig, batcherAddr common.Address, txs types.Transactions, receipts types.Receipts, ref eth.L1BlockRef, log log.Logger) []eth.Data {
out := []eth.Data{}
for i, tx := range txs {
if isValidBatchTx(tx, receipts[i], dsCfg.l1Signer, dsCfg.batchInboxAddress, batcherAddr, log) {
if isValidBatchTx(tx, receipts[i], ref, dsCfg.l1Signer, dsCfg.batchInboxAddress, batcherAddr, log, dsCfg.celoEspressoTimestamp) {
out = append(out, tx.Data())
}
}
Expand Down
3 changes: 2 additions & 1 deletion op-node/rollup/derive/calldata_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ func TestDataFromEVMTransactions(t *testing.T) {
}
}

out := DataFromEVMTransactions(DataSourceConfig{cfg.L1Signer(), cfg.BatchInboxAddress, false}, batcherAddr, txs, receipts, testlog.Logger(t, log.LevelCrit))
testRef := eth.L1BlockRef{Time: 1000} // Use a fixed timestamp for testing
out := DataFromEVMTransactions(DataSourceConfig{cfg.L1Signer(), cfg.BatchInboxAddress, false, nil}, batcherAddr, txs, receipts, testRef, testlog.Logger(t, log.LevelCrit))
require.ElementsMatch(t, expectedData, out)
}

Expand Down
29 changes: 18 additions & 11 deletions op-node/rollup/derive/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ type DataSourceFactory struct {

func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1Fetcher, blobsFetcher L1BlobsFetcher, altDAFetcher AltDAInputFetcher) *DataSourceFactory {
config := DataSourceConfig{
l1Signer: cfg.L1Signer(),
batchInboxAddress: cfg.BatchInboxAddress,
altDAEnabled: cfg.AltDAEnabled(),
l1Signer: cfg.L1Signer(),
batchInboxAddress: cfg.BatchInboxAddress,
altDAEnabled: cfg.AltDAEnabled(),
celoEspressoTimestamp: cfg.CeloEspressoTimestamp,
}
return &DataSourceFactory{
log: log,
Expand Down Expand Up @@ -86,19 +87,25 @@ func (ds *DataSourceFactory) OpenData(ctx context.Context, ref eth.L1BlockRef, b

// DataSourceConfig regroups the mandatory rollup.Config fields needed for DataFromEVMTransactions.
type DataSourceConfig struct {
l1Signer types.Signer
batchInboxAddress common.Address
altDAEnabled bool
l1Signer types.Signer
batchInboxAddress common.Address
altDAEnabled bool
celoEspressoTimestamp *uint64
}

// isValidBatchTx returns true if:
// 1. the transaction is not reverted
// isValidBatchTx validates a transaction against the given configuration
// It returns true if:
// 1. the transaction is not reverted (only checked if CeloEspresso is enabled)
// 2. the transaction type is any of Legacy, ACL, DynamicFee, Blob, or Deposit (for L3s).
// 3. the transaction has a To() address that matches the batch inbox address, and
// 4. the transaction has a valid signature from the batcher address
func isValidBatchTx(tx *types.Transaction, receipt *types.Receipt, l1Signer types.Signer, batchInboxAddr, batcherAddr common.Address, logger log.Logger) bool {
if receipt.Status != types.ReceiptStatusSuccessful {
return false
func isValidBatchTx(tx *types.Transaction, receipt *types.Receipt, l1Block eth.L1BlockRef, l1Signer types.Signer, batchInboxAddr, batcherAddr common.Address, logger log.Logger, celoEspressoTimestamp *uint64) bool {
// If CeloEspresso is activated, return false if the transaction is reverted
if celoEspressoTimestamp != nil && l1Block.Time >= uint64(*celoEspressoTimestamp) {
if receipt.Status != types.ReceiptStatusSuccessful {
logger.Info("tx is dropped since it is reverted", "hash", tx.Hash())
return false
}
}

// For now, we want to disallow the SetCodeTx type or any future types.
Expand Down
5 changes: 5 additions & 0 deletions op-node/rollup/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ type Config struct {
CaffNodeConfig CaffNodeConfig `json:"caff_node_config,omitempty"`

BatchAuthenticatorAddress common.Address `json:"batch_authenticator_address,omitempty,omitzero"`

// CeloEspressoTimestamp is the activation timestamp for Celo Espresso integration
// When this timestamp is reached, additional transaction validation rules in derivation pipeline will be enforced
// If nil, the integration is not active.
CeloEspressoTimestamp *uint64 `json:"celo_espresso_timestamp,omitempty"`
}

// CaffNodeConfig is the config for the Caff Node
Expand Down
4 changes: 4 additions & 0 deletions op-node/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,10 @@ func applyOverrides(ctx *cli.Context, rollupConfig *rollup.Config) {
interop := ctx.Uint64(opflags.InteropOverrideFlagName)
rollupConfig.InteropTime = &interop
}
if ctx.IsSet(flags.CeloEspressoTimestamp.Name) {
celoEspresso := ctx.Uint64(flags.CeloEspressoTimestamp.Name)
rollupConfig.CeloEspressoTimestamp = &celoEspresso
}
}

// applyCeloHardforks modifies the rollupConfig to apply Celo-specific hardforks.
Expand Down