Espresso 2: derivation pipeline#445
Conversation
|
Hi @QuentinI, wondering why there are these "CaffNode" changes:
I thought this was being handled by the espresso-rollup-node-proxy? |
|
@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. |
08a9056 to
51888e5
Compare
|
Rebased and dropped caff-node changes. |
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>
|
@codex review |
There was a problem hiding this comment.
💡 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".
|
|
||
| // 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"` |
There was a problem hiding this comment.
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 != nilandBatchAuthenticatorAddress == common.Address{}. - A rollup config validation test that passes when both
EspressoTimeand a non-zeroBatchAuthenticatorAddressare configured.
There was a problem hiding this comment.
If we decide not to hardcode BatchAuthLookbackWindow then we probably would like to include that in the check as well.
|
@QuentinI Will the derivation changes for kona also be submitted in this PR or in a stacked one? |
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>
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>
cfc8950 to
6b21ccb
Compare
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>
d6ae34f to
47d6742
Compare
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>
47d6742 to
931a7dd
Compare
|
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. |
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>
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. |
There was a problem hiding this comment.
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.
| // 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. |
|
Superseded by #457, re-hosted on an in-repo branch (now properly stacked). Closing in favor of that. |
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>
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>
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>
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>
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>
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>
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
BatchAuthenticatedevents emitted by theBatchAuthenticatorcontract introduced by #443, gated byEspressoEnforcementTimehardfork 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 StreamerThe 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.