Skip to content

Espresso 2: derivation pipeline#445

Closed
QuentinI wants to merge 42 commits into
celo-org:celo-rebase-18from
EspressoSystems:ag/derivation-pipeline
Closed

Espresso 2: derivation pipeline#445
QuentinI wants to merge 42 commits into
celo-org:celo-rebase-18from
EspressoSystems:ag/derivation-pipeline

Conversation

@QuentinI

Copy link
Copy Markdown
Collaborator

This PR introduces the op-node changes of Espresso integration: batch authentication and caff node. As I can't push branches to this PR I can't create a clean stacked PR; relevant changes over #443 are in commit 08a9056

Batch authentication: derivation pipeline now reads BatchAuthenticated events emitted by the BatchAuthenticator contract introduced by #443, gated by EspressoEnforcementTime hardfork timestamp.

Caff node: op-node gains Caff mode support. When a node is configured as a Caff node (CaffNodeConfig.Enabled) and the parent L2 block has reached the configured caffeination height (and the Espresso enforcement hardfork is active), derivation pulls batches directly from the Espresso sequencer via Espresso Streamer

The PR includes unit tests for the batch-authenticator event scanner, Espresso batch RLP round-trip, and the new event-based authorization path across the calldata, blob, and altDA data sources. e2e testing involving actual Espresso instance is not part of this PR because it requires batcher changes as well.

Comment thread op-service/sources/eth_client.go Outdated
Comment thread op-node/rollup/types.go Outdated
Comment thread espresso/cli.go Outdated
@piersy

piersy commented May 21, 2026

Copy link
Copy Markdown

Hi @QuentinI, wondering why there are these "CaffNode" changes:

Caff node: op-node gains Caff mode support

I thought this was being handled by the espresso-rollup-node-proxy?

@QuentinI

Copy link
Copy Markdown
Collaborator Author

@piersy you are right, I was out of date on how the proxy works. I'll strip the Caff node out of this PR, we are not going to need it.

@QuentinI QuentinI force-pushed the ag/derivation-pipeline branch from 08a9056 to 51888e5 Compare May 25, 2026 14:05
@QuentinI

Copy link
Copy Markdown
Collaborator Author

Rebased and dropped caff-node changes.

QuentinI added a commit to EspressoSystems/optimism-espresso-integration that referenced this pull request May 25, 2026
Matches upstream Optimism hardfork naming convention (RegolithTime,
EcotoneTime, IsthmusTime, ...). All hardforks enforce a new set of
rules, so the "Enforcement" qualifier was redundant.

Renames:
  EspressoEnforcementTime    -> EspressoTime    (rollup.Config field)
  IsEspressoEnforcement      -> IsEspresso      (rollup.Config method)
  espressoEnforcementTime    -> espressoTime    (DataSourceConfig field)
  isEspressoEnforcement      -> isEspresso      (DataSourceConfig method)
  espresso_enforcement_time  -> espresso_time   (JSON tag, forEachFork log key)
  "Espresso Enforcement"     -> "Espresso"      (forEachFork display name)

Also rewords prose docstrings: "EspressoEnforcement" -> "Espresso",
"Pre/Post-EspressoEnforcement" -> "Pre/Post-Espresso".

Addresses PR feedback: celo-org#445 (comment)

Co-authored-by: OpenCode <noreply@opencode.ai>
@jcortejoso

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d55b56e12a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/contracts-bedrock/scripts/deploy/DeployEspresso.s.sol Outdated
Comment thread op-node/rollup/types.go Outdated
Comment thread op-node/rollup/types.go

// BatchAuthenticatorAddress is the L1 address of the BatchAuthenticator contract whose
// BatchInfoAuthenticated(bytes32) events the derivation pipeline scans post-Espresso.
BatchAuthenticatorAddress common.Address `json:"batch_authenticator_address,omitempty,omitzero"`

@palango palango May 27, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EspressoTime makes BatchInfoAuthenticated events mandatory post-fork, but the rollup config does not appear to require a non-zero BatchAuthenticatorAddress when the fork is configured.

There should be a check added that checks BatchAuthenticatorAddress is set when EspressoTime is non-nil.

Then test should be added:

  • A rollup config validation test that fails when EspressoTime != nil and BatchAuthenticatorAddress == common.Address{}.
  • A rollup config validation test that passes when both EspressoTime and a non-zero BatchAuthenticatorAddress are configured.

@QuentinI QuentinI Jun 2, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! Implemented in 1c566cd

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we decide not to hardcode BatchAuthLookbackWindow then we probably would like to include that in the check as well.

@palango

palango commented May 27, 2026

Copy link
Copy Markdown

@QuentinI Will the derivation changes for kona also be submitted in this PR or in a stacked one?

@QuentinI

Copy link
Copy Markdown
Collaborator Author

@palango kona counterpart available at #449

Comment thread op-node/rollup/derive/data_source.go Outdated
Comment thread espresso/constants.go Outdated
Comment thread op-node/rollup/derive/batch_authenticator.go Outdated
Comment thread op-node/rollup/espresso_types.go
QuentinI added a commit to EspressoSystems/celo-kona that referenced this pull request Jun 4, 2026
Add the `celo-derive` crate implementing the Rust (kona) companion to the
op-node Espresso batch-authentication changes (celo-org/optimism#445),
relocated from the vendored-kona PR celo-org/optimism#449 to follow
celo-kona's wrap/duplicate-don't-patch model.

Post-fork, batches are authorized by scanning L1 receipts for
`BatchInfoAuthenticated` events from the configured `BatchAuthenticator`
contract within a lookback window, instead of by transaction sender.
Pre-fork (or when the fork is not yet active) derivation is byte-identical
to upstream OP Stack.

- `CeloEthereumDataSource` / `CeloCalldataSource` / `CeloBlobSource`:
  duplicates of kona's data sources with the auth branch folded in
  (kona's `CalldataSource`/`BlobSource`/`BlobData` internals are
  `pub(crate)` and cannot be wrapped).
- `BatchAuthConfig` bundles the authenticator address, fork time and
  lookback window so the "fork scheduled but no authenticator" state is
  unrepresentable; `CeloRollupConfig::batch_auth_params` validates it and
  hard-errors on misconfiguration (otherwise derivation would silently
  stall at the fork boundary).
- `CeloRollupConfig` gains the Espresso settings (parsed from the same
  rollup.json) and `CeloBootInfo` carries them through boot.
- Point the hokulea git dep at celo-org/hokulea fccc98c (celo-org/hokulea#2),
  which generalizes `EigenDADataSource` over `DataAvailabilityProvider` so
  the eigenda path can wrap `CeloEthereumDataSource`.

Co-authored-by: OpenCode <noreply@opencode.ai>
QuentinI added a commit to EspressoSystems/optimism-espresso-integration that referenced this pull request Jun 8, 2026
Matches upstream Optimism hardfork naming convention (RegolithTime,
EcotoneTime, IsthmusTime, ...). All hardforks enforce a new set of
rules, so the "Enforcement" qualifier was redundant.

Renames:
  EspressoEnforcementTime    -> EspressoTime    (rollup.Config field)
  IsEspressoEnforcement      -> IsEspresso      (rollup.Config method)
  espressoEnforcementTime    -> espressoTime    (DataSourceConfig field)
  isEspressoEnforcement      -> isEspresso      (DataSourceConfig method)
  espresso_enforcement_time  -> espresso_time   (JSON tag, forEachFork log key)
  "Espresso Enforcement"     -> "Espresso"      (forEachFork display name)

Also rewords prose docstrings: "EspressoEnforcement" -> "Espresso",
"Pre/Post-EspressoEnforcement" -> "Pre/Post-Espresso".

Addresses PR feedback: celo-org#445 (comment)

Co-authored-by: OpenCode <noreply@opencode.ai>
@QuentinI QuentinI force-pushed the ag/derivation-pipeline branch from cfc8950 to 6b21ccb Compare June 8, 2026 13:39
QuentinI added a commit to EspressoSystems/optimism-espresso-integration that referenced this pull request Jun 8, 2026
Matches upstream Optimism hardfork naming convention (RegolithTime,
EcotoneTime, IsthmusTime, ...). All hardforks enforce a new set of
rules, so the "Enforcement" qualifier was redundant.

Renames:
  EspressoEnforcementTime    -> EspressoTime    (rollup.Config field)
  IsEspressoEnforcement      -> IsEspresso      (rollup.Config method)
  espressoEnforcementTime    -> espressoTime    (DataSourceConfig field)
  isEspressoEnforcement      -> isEspresso      (DataSourceConfig method)
  espresso_enforcement_time  -> espresso_time   (JSON tag, forEachFork log key)
  "Espresso Enforcement"     -> "Espresso"      (forEachFork display name)

Also rewords prose docstrings: "EspressoEnforcement" -> "Espresso",
"Pre/Post-EspressoEnforcement" -> "Pre/Post-Espresso".

Addresses PR feedback: celo-org#445 (comment)

Co-authored-by: OpenCode <noreply@opencode.ai>
@QuentinI QuentinI force-pushed the ag/derivation-pipeline branch 2 times, most recently from d6ae34f to 47d6742 Compare June 8, 2026 16:25
QuentinI and others added 10 commits June 12, 2026 11:40
Resolve the 16 findings flagged by the contracts-bedrock-checks-fast
semgrep job:

- sol-safety-use-deployutils-getcode: replace vm.getCode(...) with
  DeployUtils.getCode(...) in DeployBatchAuthenticator, DeployEspresso,
  DeployPeriphery, BatchAuthenticator.t, and FeesDepositor.t (add the
  DeployUtils import where missing).
- sol-style-use-abi-encodecall: add a justified nosemgrep on the
  EspressoTEEVerifier initialize encoding in DeployEspresso; encodeCall
  would pull the EspressoTEEVerifier impl closure into OP's compile group,
  which deploying from the submodule artifact is meant to avoid.
- sol-style-input-arg-fmt / sol-style-return-arg-fmt: rename interface and
  contract args (index -> _index, l1Block -> _l1Block) and name returns
  (batcher_, fromBlock_) on BatchAuthenticator and IBatchAuthenticator.

forge build, the semgrep scan (0 blocking findings), and the
BatchAuthenticator/FeesDepositor test suites all pass.

Co-authored-by: OpenCode <noreply@opencode.ai>
Adds derivation-pipeline support for the BatchAuthenticator contract
introduced in the previous PR. Stacks on the contracts PR.

Introduces an L2-timestamp hardfork (EspressoEnforcementTime) gating all
post-fork derivation semantics. Pre-fork, derivation behaves exactly as
upstream Optimism: batches are accepted based on the L1 transaction
sender matching the SystemConfig batcher address. Post-fork, batches are
authenticated via BatchInfoAuthenticated(bytes32) events emitted by the
BatchAuthenticator contract, and sender-based authorization is rejected.

Adds CollectAuthenticatedBatches which scans L1 receipts over a
configurable lookback window (default 100 blocks) to build the set of
authenticated batch commitment hashes for each L1 block being derived.
Results are cached in two reorg-safe (block-hash-keyed) LRU caches: one
for receipt-derived event sets, one for L1BlockRef resolution. For
consecutive L1 blocks the lookback windows overlap by ~99 blocks, so
only one new block's receipts need to be fetched on each call.

Adds rollup.Config fields: EspressoEnforcementTime *uint64,
BatchAuthenticatorAddress, BatchAuthLookbackWindow.

Adds unit tests for batch authentication across calldata, blob, and
altda data sources.

Co-authored-by: OpenCode <noreply@opencode.ai>
Matches upstream Optimism hardfork naming convention (RegolithTime,
EcotoneTime, IsthmusTime, ...). All hardforks enforce a new set of
rules, so the "Enforcement" qualifier was redundant.

Renames:
  EspressoEnforcementTime    -> EspressoTime    (rollup.Config field)
  IsEspressoEnforcement      -> IsEspresso      (rollup.Config method)
  espressoEnforcementTime    -> espressoTime    (DataSourceConfig field)
  isEspressoEnforcement      -> isEspresso      (DataSourceConfig method)
  espresso_enforcement_time  -> espresso_time   (JSON tag, forEachFork log key)
  "Espresso Enforcement"     -> "Espresso"      (forEachFork display name)

Also rewords prose docstrings: "EspressoEnforcement" -> "Espresso",
"Pre/Post-EspressoEnforcement" -> "Pre/Post-Espresso".

Addresses PR feedback: celo-org#445 (comment)

Co-authored-by: OpenCode <noreply@opencode.ai>
Co-authored-by: OpenCode <noreply@opencode.ai>
EspressoTime is a conceptually L2-timestamp fork activation time, but the
derivation pipeline gates on it by comparing against the L1 origin time of
the enclosing L1 block. Update the doc comments to reflect this, consistent
with the existing blob_data_source.go/calldata_source.go comments.

Co-authored-by: OpenCode <noreply@opencode.ai>
Adapts the derivation pipeline to PR ethereum-optimism#443's updated BatchAuthenticator
event and enforces that a batch is submitted by the same address that
authenticated it.

The contract event changed from BatchInfoAuthenticated(bytes32 indexed
commitment) to BatchInfoAuthenticated(bytes32 commitment, address indexed
caller): the signature hash (Topics[0]) changes, the commitment moves into
the unindexed log data, and the caller becomes the indexed Topics[1]. The
event scanner is updated accordingly (new ABI string, commitment read from
Data[:32], with a length guard).

CollectAuthenticatedBatches and collectAuthEventsFromReceipts now return
map[commitment]caller instead of a commitment set. Post-fork,
isBatchTxAuthorized recovers the batch transaction's L1 sender and accepts
the batch only if it equals the caller that emitted the auth event. This
binds each batch to the address that authenticated it, so a batch
authenticated by one batcher cannot be submitted by another. When the same
commitment is authenticated in more than one block within the lookback
window, the newest event's caller is retained.

Removes FindBatchAuthEvent and its test: it had no production caller (the
pipeline uses CollectAuthenticatedBatches) and, lacking a caller check,
diverged from the enforced sender-equals-caller semantics.

Updates the data-source tests to set the auth event caller to the batch
tx sender, and adds cases covering acceptance for a non-batcher sender
matching its caller, rejection when the sender differs from the caller,
and newest-caller-wins on duplicate authentication.

Co-authored-by: OpenCode <noreply@opencode.ai>
…stances

Remove package-level singleton LRU caches and sync.Once from
batch_authenticator.go. Instead, BatchAuthCaches are constructed in
NewDataSourceFactory and threaded through DataSourceConfig to
CollectAuthenticatedBatches. This eliminates the global mutable state,
the cache-size-locked-by-first-caller problem, and the data race in
resetBatchAuthCaches. Tests now construct their own caches and are safe
for t.Parallel().
Two follow-ups required after cherry-picking the batch-auth cache
dependency-injection and rollup.Config-in-DataSourceConfig changes:

- batch_authenticator_test.go: thread the BatchAuthCaches argument
  through the duplicate-authentication caller test, which post-dates the
  cache-DI change and so was not updated by it.
- IsEspresso: guard against a nil Config receiver. Holding the
  rollup.Config in DataSourceConfig means IsEspresso is now reached via
  DataSourceConfig.rollupCfg, which is nil for non-Espresso data-source
  tests; the previous DataSourceConfig.isEspresso method was nil-safe.

Co-authored-by: OpenCode <noreply@opencode.ai>
@QuentinI QuentinI force-pushed the ag/derivation-pipeline branch from 47d6742 to 931a7dd Compare June 12, 2026 10:03
@QuentinI QuentinI changed the base branch from celo-rebase-17 to celo-rebase-18 June 12, 2026 11:04
@piersy

piersy commented Jun 15, 2026

Copy link
Copy Markdown

Hi @QuentinI I made a pr into this (EspressoSystems#440) that adds some test cases, tightens some assertions and moves the additional espresso tests to their own files, to lessen the chance of conflicts when updating.

piersy and others added 5 commits June 16, 2026 15:11
Adds derivation tests that close two gaps in the Espresso batch-auth
coverage. Both data sources gate event-based authentication on
IsEspresso(ref.Time), and each implements that gate separately, but no
test exercised the gate flipping across activation or verified that
multiple batches are matched to their own commitments.

Fork-boundary tests (TestDataFromEVMTransactionsForkBoundary for the
calldata source, TestDataAndHashesFromTxsForkBoundary for the blob
source) reuse a single DataSourceConfig with EspressoTime set and vary
only ref.Time across the activation boundary:

  - pre-fork (ref.Time < EspressoTime): the batcher tx is accepted via
    upstream sender-based auth, and an empty L1 mock asserts that zero
    receipt scanning occurs;
  - non-batcher senders remain rejected pre-fork;
  - activation block (ref.Time == EspressoTime): the same batcher tx is
    rejected without a BatchInfoAuthenticated event and accepted with one.

This pins the ">=" gate in both directions: a regression to ">" makes the
activation block either accept an unauthenticated batch or skip the event
scan, failing the test. The blob-source copy drives a type-2 calldata tx,
the shape an Ecotone-active, calldata-batching chain (e.g. Celo) submits
through the blob source.

TestDataFromEVMTransactionsEventAuth gains a "multiple authenticated txs
each accepted for their own commitment" case: two distinct batches, each
authenticated by its own commitment, must both be accepted in order and
mapped to their own data, verifying each tx is matched against its own
commitment rather than to "some" authenticated entry.

Test-only change; no production code is modified.
Moves the Espresso batch-auth tests out of the upstream calldata/blob
data-source test files into new espresso_calldata_source_test.go and
espresso_blob_data_source_test.go, and renames batch_authenticator_test.go
to espresso_batch_authenticator_test.go.

Pure test relocation: no production code and no test logic, names,
comments, or assertions change. The goal is to keep all Espresso-specific
tests in espresso_-prefixed files so upstream changes to the shared
data-source test files cannot conflict with them on rebase.

Moved into espresso_calldata_source_test.go (from calldata_source_test.go):
the mockAuthEvents helper, TestDataFromEVMTransactionsEventAuth (including
the "multiple authenticated txs each accepted for their own commitment"
subtest), and TestDataFromEVMTransactionsForkBoundary.

Moved into espresso_blob_data_source_test.go (from blob_data_source_test.go):
TestDataAndHashesFromTxsEventAuth and TestDataAndHashesFromTxsForkBoundary.

The upstream tests (TestDataFromEVMTransactions, TestDataAndHashesFromTxs,
TestFillBlobPointers, TestBlobDataSourceL1FetcherErrors) stay in their
original files. The only import adjustment is dropping io, common/hexutil,
and op-service/txmgr from the new blob file (used only by the kept
TestBlobDataSourceL1FetcherErrors); both original import blocks are
unchanged.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
QuentinI added a commit to EspressoSystems/celo-kona that referenced this pull request Jun 16, 2026
Add the `celo-derive` crate implementing the Rust (kona) companion to the
op-node Espresso batch-authentication changes (celo-org/optimism#445),
relocated from the vendored-kona PR celo-org/optimism#449 to follow
celo-kona's wrap/duplicate-don't-patch model.

Post-fork, batches are authorized by scanning L1 receipts for
`BatchInfoAuthenticated` events from the configured `BatchAuthenticator`
contract within a lookback window, instead of by transaction sender.
Pre-fork (or when the fork is not yet active) derivation is byte-identical
to upstream OP Stack.

- `CeloEthereumDataSource` / `CeloCalldataSource` / `CeloBlobSource`:
  duplicates of kona's data sources with the auth branch folded in
  (kona's `CalldataSource`/`BlobSource`/`BlobData` internals are
  `pub(crate)` and cannot be wrapped).
- `BatchAuthConfig` bundles the authenticator address, fork time and
  lookback window so the "fork scheduled but no authenticator" state is
  unrepresentable; `CeloRollupConfig::batch_auth_params` validates it and
  hard-errors on misconfiguration (otherwise derivation would silently
  stall at the fork boundary).
- `CeloRollupConfig` gains the Espresso settings (parsed from the same
  rollup.json) and `CeloBootInfo` carries them through boot.
- Point the hokulea git dep at celo-org/hokulea fccc98c (celo-org/hokulea#2),
  which generalizes `EigenDADataSource` over `DataAvailabilityProvider` so
  the eigenda path can wrap `CeloEthereumDataSource`.

Co-authored-by: OpenCode <noreply@opencode.ai>

// NewBatchAuthCaches creates caches sized for the BatchAuthLookbackWindow.
func NewBatchAuthCaches() *BatchAuthCaches {
// BatchAuthLookbackWindow past blocks + 1 current block + 1 LRU overhead.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expanding this comment to explain why +2 is the minimum rather than arbitrary headroom. The traversal reads newest-to-oldest, so the ref block becomes the LRU entry; with exactly +1 (101 slots) inserting the next block's ref evicts the very parent we're about to read, cascading evict-and-refetch through the whole window. The extra slot holds the one stale (out-of-window) entry that gets evicted instead.

Suggested change
// BatchAuthLookbackWindow past blocks + 1 current block + 1 LRU overhead.
// The lookback window covers 101 blocks (the ref block plus 100 ancestors),
// so 101 entries are live during any single traversal. We add +2 (not +1)
// because the traversal reads newest-to-oldest: the ref block is touched
// first and so becomes the LRU entry. With exactly 101 slots, inserting the
// next block's ref would evict the previous ref (its parent) — the very block
// we're about to read — triggering a cascade of evict-and-refetch through the
// whole window. The extra slot leaves room for the 101 new window entries plus
// one stale entry (the block that just fell out of the lookback window). That
// stale entry, untouched in the current traversal, is the LRU and gets evicted
// instead, so no cascade occurs.

@QuentinI

Copy link
Copy Markdown
Collaborator Author

Superseded by #457, re-hosted on an in-repo branch (now properly stacked). Closing in favor of that.

@QuentinI QuentinI closed this Jun 17, 2026
QuentinI added a commit that referenced this pull request Jun 17, 2026
Matches upstream Optimism hardfork naming convention (RegolithTime,
EcotoneTime, IsthmusTime, ...). All hardforks enforce a new set of
rules, so the "Enforcement" qualifier was redundant.

Renames:
  EspressoEnforcementTime    -> EspressoTime    (rollup.Config field)
  IsEspressoEnforcement      -> IsEspresso      (rollup.Config method)
  espressoEnforcementTime    -> espressoTime    (DataSourceConfig field)
  isEspressoEnforcement      -> isEspresso      (DataSourceConfig method)
  espresso_enforcement_time  -> espresso_time   (JSON tag, forEachFork log key)
  "Espresso Enforcement"     -> "Espresso"      (forEachFork display name)

Also rewords prose docstrings: "EspressoEnforcement" -> "Espresso",
"Pre/Post-EspressoEnforcement" -> "Pre/Post-Espresso".

Addresses PR feedback: #445 (comment)

Co-authored-by: OpenCode <noreply@opencode.ai>
QuentinI added a commit that referenced this pull request Jun 17, 2026
Add the fallback (non-TEE) batcher's BatchAuthenticator integration:

- op-batcher/batcher/fallback_auth.go: sendTxWithFallbackAuth path that
  posts authenticateBatchInfo before the batch tx, with a deadline check
  against the batch's L1 inclusion window. Computes the batch commitment
  hash from either calldata or concatenated blob versioned hashes.
- op-batcher/batcher/espresso_active.go: hasBatchAuthenticator (does
  this rollup use BatchAuthenticator at all?) and isFallbackAuthRequired
  (gates fallback authentication on Config.IsEspresso(tip.Time + lead)).
  The Espresso hardfork predicate is consulted with the configured
  FallbackAuthLeadTime added to the L1 tip, so the batcher starts
  authenticating slightly before the verifier requires it. This absorbs
  worst-case L1 inclusion delay between the batcher's decision time
  (L1 tip) and the verifier's evaluation time (containing L1 block).
- op-batcher/batcher/espresso_driver.go: the authGroup bookkeeping
  (initAuthGroup, waitForAuthGroup, fallbackAuthGroupLimit) and the
  dispatchAuthenticatedSendTx fan-out used by driver.go sendTx.

Small wiring edits to upstream files:

- op-batcher/flags/flags.go: register --espresso.fallback-auth-lead-time
  (default 5m).
- op-batcher/batcher/config.go: thread the FallbackAuthLeadTime through
  CLIConfig.
- op-batcher/batcher/service.go: BatcherConfig.FallbackAuthLeadTime
  field, propagated from CLIConfig in initFromCLIConfig.
- op-batcher/batcher/driver.go: extend L1Client to embed
  bind.ContractBackend (required by the BatchAuthenticator binding), add
  authGroup field to BatchSubmitter, call initAuthGroup in
  NewBatchSubmitter, call dispatchAuthenticatedSendTx in sendTx, call
  waitForAuthGroup in publishingLoop's shutdown drain.
- op-batcher/batcher/driver_test.go: embed bind.ContractBackend in
  fakeL1Client so the AltDA tests still satisfy L1Client.

The fallback batcher does nothing when the rollup config has no
BatchAuthenticator address, and it falls through to the upstream
queue.Send path pre-EspressoTime. Cancel transactions always take the
upstream path. No new external dependencies are added; the only third-
party Go modules needed are already in PR #445.

The TEE batcher is a separate PR stacked on top.

Co-authored-by: OpenCode <noreply@opencode.ai>
QuentinI added a commit that referenced this pull request Jun 17, 2026
Matches upstream Optimism hardfork naming convention (RegolithTime,
EcotoneTime, IsthmusTime, ...). All hardforks enforce a new set of
rules, so the "Enforcement" qualifier was redundant.

Renames:
  EspressoEnforcementTime    -> EspressoTime    (rollup.Config field)
  IsEspressoEnforcement      -> IsEspresso      (rollup.Config method)
  espressoEnforcementTime    -> espressoTime    (DataSourceConfig field)
  isEspressoEnforcement      -> isEspresso      (DataSourceConfig method)
  espresso_enforcement_time  -> espresso_time   (JSON tag, forEachFork log key)
  "Espresso Enforcement"     -> "Espresso"      (forEachFork display name)

Also rewords prose docstrings: "EspressoEnforcement" -> "Espresso",
"Pre/Post-EspressoEnforcement" -> "Pre/Post-Espresso".

Addresses PR feedback: #445 (comment)

Co-authored-by: OpenCode <noreply@opencode.ai>
QuentinI added a commit that referenced this pull request Jun 17, 2026
Add the fallback (non-TEE) batcher's BatchAuthenticator integration:

- op-batcher/batcher/fallback_auth.go: sendTxWithFallbackAuth path that
  posts authenticateBatchInfo before the batch tx, with a deadline check
  against the batch's L1 inclusion window. Computes the batch commitment
  hash from either calldata or concatenated blob versioned hashes.
- op-batcher/batcher/espresso_active.go: hasBatchAuthenticator (does
  this rollup use BatchAuthenticator at all?) and isFallbackAuthRequired
  (gates fallback authentication on Config.IsEspresso(tip.Time + lead)).
  The Espresso hardfork predicate is consulted with the configured
  FallbackAuthLeadTime added to the L1 tip, so the batcher starts
  authenticating slightly before the verifier requires it. This absorbs
  worst-case L1 inclusion delay between the batcher's decision time
  (L1 tip) and the verifier's evaluation time (containing L1 block).
- op-batcher/batcher/espresso_driver.go: the authGroup bookkeeping
  (initAuthGroup, waitForAuthGroup, fallbackAuthGroupLimit) and the
  dispatchAuthenticatedSendTx fan-out used by driver.go sendTx.

Small wiring edits to upstream files:

- op-batcher/flags/flags.go: register --espresso.fallback-auth-lead-time
  (default 5m).
- op-batcher/batcher/config.go: thread the FallbackAuthLeadTime through
  CLIConfig.
- op-batcher/batcher/service.go: BatcherConfig.FallbackAuthLeadTime
  field, propagated from CLIConfig in initFromCLIConfig.
- op-batcher/batcher/driver.go: extend L1Client to embed
  bind.ContractBackend (required by the BatchAuthenticator binding), add
  authGroup field to BatchSubmitter, call initAuthGroup in
  NewBatchSubmitter, call dispatchAuthenticatedSendTx in sendTx, call
  waitForAuthGroup in publishingLoop's shutdown drain.
- op-batcher/batcher/driver_test.go: embed bind.ContractBackend in
  fakeL1Client so the AltDA tests still satisfy L1Client.

The fallback batcher does nothing when the rollup config has no
BatchAuthenticator address, and it falls through to the upstream
queue.Send path pre-EspressoTime. Cancel transactions always take the
upstream path. No new external dependencies are added; the only third-
party Go modules needed are already in PR #445.

The TEE batcher is a separate PR stacked on top.

Co-authored-by: OpenCode <noreply@opencode.ai>
QuentinI added a commit that referenced this pull request Jun 18, 2026
Matches upstream Optimism hardfork naming convention (RegolithTime,
EcotoneTime, IsthmusTime, ...). All hardforks enforce a new set of
rules, so the "Enforcement" qualifier was redundant.

Renames:
  EspressoEnforcementTime    -> EspressoTime    (rollup.Config field)
  IsEspressoEnforcement      -> IsEspresso      (rollup.Config method)
  espressoEnforcementTime    -> espressoTime    (DataSourceConfig field)
  isEspressoEnforcement      -> isEspresso      (DataSourceConfig method)
  espresso_enforcement_time  -> espresso_time   (JSON tag, forEachFork log key)
  "Espresso Enforcement"     -> "Espresso"      (forEachFork display name)

Also rewords prose docstrings: "EspressoEnforcement" -> "Espresso",
"Pre/Post-EspressoEnforcement" -> "Pre/Post-Espresso".

Addresses PR feedback: #445 (comment)

Co-authored-by: OpenCode <noreply@opencode.ai>
QuentinI added a commit that referenced this pull request Jun 18, 2026
Add the fallback (non-TEE) batcher's BatchAuthenticator integration:

- op-batcher/batcher/fallback_auth.go: sendTxWithFallbackAuth path that
  posts authenticateBatchInfo before the batch tx, with a deadline check
  against the batch's L1 inclusion window. Computes the batch commitment
  hash from either calldata or concatenated blob versioned hashes.
- op-batcher/batcher/espresso_active.go: hasBatchAuthenticator (does
  this rollup use BatchAuthenticator at all?) and isFallbackAuthRequired
  (gates fallback authentication on Config.IsEspresso(tip.Time + lead)).
  The Espresso hardfork predicate is consulted with the configured
  FallbackAuthLeadTime added to the L1 tip, so the batcher starts
  authenticating slightly before the verifier requires it. This absorbs
  worst-case L1 inclusion delay between the batcher's decision time
  (L1 tip) and the verifier's evaluation time (containing L1 block).
- op-batcher/batcher/espresso_driver.go: the authGroup bookkeeping
  (initAuthGroup, waitForAuthGroup, fallbackAuthGroupLimit) and the
  dispatchAuthenticatedSendTx fan-out used by driver.go sendTx.

Small wiring edits to upstream files:

- op-batcher/flags/flags.go: register --espresso.fallback-auth-lead-time
  (default 5m).
- op-batcher/batcher/config.go: thread the FallbackAuthLeadTime through
  CLIConfig.
- op-batcher/batcher/service.go: BatcherConfig.FallbackAuthLeadTime
  field, propagated from CLIConfig in initFromCLIConfig.
- op-batcher/batcher/driver.go: extend L1Client to embed
  bind.ContractBackend (required by the BatchAuthenticator binding), add
  authGroup field to BatchSubmitter, call initAuthGroup in
  NewBatchSubmitter, call dispatchAuthenticatedSendTx in sendTx, call
  waitForAuthGroup in publishingLoop's shutdown drain.
- op-batcher/batcher/driver_test.go: embed bind.ContractBackend in
  fakeL1Client so the AltDA tests still satisfy L1Client.

The fallback batcher does nothing when the rollup config has no
BatchAuthenticator address, and it falls through to the upstream
queue.Send path pre-EspressoTime. Cancel transactions always take the
upstream path. No new external dependencies are added; the only third-
party Go modules needed are already in PR #445.

The TEE batcher is a separate PR stacked on top.

Co-authored-by: OpenCode <noreply@opencode.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants