Skip to content

Espresso 4: e2e tests#465

Draft
QuentinI wants to merge 70 commits into
espresso/batcherfrom
espresso/e2e-tests
Draft

Espresso 4: e2e tests#465
QuentinI wants to merge 70 commits into
espresso/batcherfrom
espresso/e2e-tests

Conversation

@QuentinI

@QuentinI QuentinI commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Not ready for review

QuentinI and others added 30 commits June 17, 2026 18:20
Adds the Espresso-introduced contracts and the minimum supporting changes
required for them to compile, test, and pass the contract checks.

New contracts and scripts:

- src/L1/BatchAuthenticator.sol and interfaces/L1/IBatchAuthenticator.sol
  (upgradeable contract that authenticates batch transactions, with switching
  between Espresso and fallback batchers)
- scripts/deploy/DeployBatchAuthenticator.s.sol and
  scripts/deploy/DeployEspresso.s.sol
- test/L1/BatchAuthenticator.t.sol and test/mocks/MockEspressoTEEVerifiers.sol
- snapshots/{abi,storageLayout}/BatchAuthenticator.json
- snapshots/semver-lock.json entry for BatchAuthenticator

New submodules:

- lib/espresso-tee-contracts (interfaces required by BatchAuthenticator)
- lib/openzeppelin-contracts-upgradeable-v5 (OZ v5 used by BatchAuthenticator
  via OwnableUpgradeable)

Supporting changes (Espresso-driven):

- foundry.toml: remappings for OZ v5 and espresso-tee-contracts; ignored
  warning codes for vendored libs; OOM-safe jobs settings; via-ir profile.
- justfile: fix-proxy-artifact recipe to handle OZ v5 shadowing Proxy/ProxyAdmin
  artifacts; build/coverage hooks.
- src/universal/Proxy.sol, src/universal/ProxyAdmin.sol: pin pragma to exact
  0.8.15 so they stay in their own compilation group and never emit PUSH0.
- src/universal/ReinitializableBase.sol: loosen pragma to ^0.8.15 so
  BatchAuthenticator (compiled with OZ v5) can import it.
- scripts/* and test/*: disambiguate Proxy artifact lookups to
  src/universal/Proxy.sol:Proxy (avoids OZ v5 proxy/Proxy.sol shadow).
- scripts/checks: bypass interface checks for artifacts originating from lib/;
  add Espresso-related contract names to exclude lists; pragma exclusions for
  Proxy/ProxyAdmin/BatchAuthenticator.
- test/vendor/Initializable.t.sol: exclude BatchAuthenticator (deployed by a
  separate Espresso script).

Co-authored-by: OpenCode <noreply@opencode.ai>
Co-authored-by: piersy <pierspowlesland@gmail.com>
- strict-pragma: remove unneeded exclusions for src/universal/Proxy.sol
  and src/universal/ProxyAdmin.sol — both already use strict
  'pragma solidity 0.8.15;', so the entries (and their misleading
  comment claiming '^') were dead.
- interfaces: move the Espresso excludeContracts block out of the
  upstream-shared area and down next to the Celo block, with one
  entry per line to match the surrounding style. Localizes future
  rebase deltas.

Co-authored-by: OpenCode <noreply@opencode.ai>
Inline the EspressoTEEVerifier deployment in DeployEspresso.s.sol so it
no longer imports lib/espresso-tee-contracts/scripts/DeployTEEVerifier.s.sol
or DeployNitroTEEVerifier.s.sol. The upstream scripts pulled OZ v5's
TransparentUpgradeableProxy (and its auto-deployed ProxyAdmin) into the
OP artifact tree, shadowing src/universal/ProxyAdmin.sol and forcing a
~90-line fix-proxy-artifact justfile recipe.

The TEEVerifier is now deployed behind src/universal/Proxy.sol +
src/universal/ProxyAdmin.sol, matching how BatchAuthenticator is
deployed in the same script. ERC-1967 slots are unchanged, so external
callers see no difference.

The raw vm.getCode("ProxyAdmin") lookups in the deploy scripts and
BatchAuthenticator tests are switched to the explicit artifact path
vm.getCode("forge-artifacts/ProxyAdmin.sol/ProxyAdmin.json") to
deterministically resolve the default compilation profile's bytecode
(the dispute profile transitively compiles ProxyAdmin at optimizer_runs=5000,
creating a second artifact that broke unqualified lookups).

The fix-proxy-artifact recipe and its 5 callsites are removed.
Cherry-picked from piersy's commit 5d0a803 on PR #443.

Walks the dual-batcher state machine: Espresso path → switchBatcher →
fallback path → switchBatcher → Espresso path. Asserts every transition
emits the expected event, that signer registration survives the
round-trip, and that re-issuing the same call after a mode flip changes
the outcome (the previously-valid Espresso signature is no longer
consulted on the fallback path).

Co-authored-by: Piers Powlesland <pierspowlesland@gmail.com>
Co-authored-by: OpenCode <noreply@opencode.ai>
Replace the hand-rolled `EspressoBatcherEntry[]` history + binary search
with OpenZeppelin's `Checkpoints.Trace160` (`(uint96 key, uint160 value)`).
`uint160` is exactly an address with no waste, and `uint96` easily covers
L1 block numbers. `upperLookupRecent` replaces the custom binary search
and the same-block-overwrite branch is now handled inside `_insert`.

Co-authored-by: OpenCode <noreply@opencode.ai>
…sed warning codes

Drop the two impl imports (EspressoTEEVerifier, EspressoNitroTEEVerifier) from
DeployEspresso.s.sol and replace direct instantiation with vm.getCode + assembly
create, reading bytecode from the submodule's own out/ directory.

This removes the impl closure (TEEHelper, JournalValidation, and the
aws-nitro-enclave-attestation chain) from OP's solc invocations. The impls
are still parsed/ABI-checked by forge via libs=['lib'], but they no longer
require bytecode emission or the optimizer backend.

Since OP's build no longer compiles the submodule's impl files, the three
error codes those files triggered (6321 unnamed return, 5667 unused param,
1878 missing SPDX) can be removed from ignored_error_codes. OP's own code
does not trigger any of them. The lint_on_build=false workaround is also
removed for the same reason — with the impl closure gone, forge lint reports
283 warnings (all from OP's own code), none of which cause a build failure.

Adds fs_permissions read access for lib/espresso-tee-contracts/out/ so
vm.getCode can locate the pre-built artifacts. The submodule must be built
(forge build --root lib/espresso-tee-contracts) before OP's main build.

Co-authored-by: OpenCode <noreply@opencode.ai>
Deploy the BatchAuthenticator and TEEVerifier proxies behind the existing
OP Stack ProxyAdmin instead of dedicated ones (#443).
Both proxies use the deployer as a transient admin to initialize directly,
then changeAdmin to the shared ProxyAdmin (DeployAltDA/DeployFeesDepositor
pattern). Reorder TEE deploy so the Nitro verifier is wired via initialize,
removing the post-init onlyOwner call and ownership-transfer dance. Rename
inputs to espressoOwner/sharedProxyAdmin and drop the teeVerifierProxyAdmin
output.

Co-authored-by: OpenCode <noreply@opencode.ai>
Co-authored-by: OpenCode <noreply@opencode.ai>
The Go script host's getArtifact translated a fully-qualified Foundry
name like "src/universal/Proxy.sol:Proxy" into the artifact path
"src/universal/Proxy.sol/Proxy.json", which does not exist because the
artifacts FS is keyed by the source-file basename. Reduce any
directory-qualified path to its basename before ReadArtifact so that
both "File.sol:Contract" and "path/to/File.sol:Contract" resolve to the
same artifact.

This unblocks the deploy scripts that use
getCode("src/universal/Proxy.sol:Proxy") to disambiguate from the
OpenZeppelin v5 proxy/Proxy.sol artifact, fixing TestNewDeployAltDAScript,
TestNewDeployImplementationsScript, TestNewDeploySuperchainScript and the
op-e2e proofs actions that hit the same DeploySuperchain code path.

Co-authored-by: OpenCode <noreply@opencode.ai>
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>
The espressoBatcher history is an OZ Checkpoints.Trace160 keyed by block
number. OZ's push overwrites (not appends) when the key equals the latest
entry's key, so two setEspressoBatcher calls in the same block — or one in
the same block as the initialize seed — silently destroyed the prior record.

setEspressoBatcher now reverts with BatcherChangedThisBlock if a history
entry already exists for the current block.

Co-authored-by: OpenCode <noreply@opencode.ai>
piersy and others added 29 commits June 18, 2026 15:45
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>
Regenerated against PR #443's BatchAuthenticator.sol via forge build +
abigen. Includes the new history-based API (espressoBatcherAt,
espressoBatcherAtBlock, espressoBatcherHistoryLength, setEspressoBatcher)
and the EspressoBatcherUpdated(address,address,uint64) event with the
fromBlock parameter; drops the removed paused() function.

Consumed by the fallback batcher (next commit) to read activeIsEspresso
and pack authenticateBatchInfo calldata. The TEE batcher in a follow-up
PR will use the same binding.

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>
The Espresso fallback-auth path previously dispatched each auth+batch pair to a
separate errgroup and called Txmgr.Send directly, bypassing the operator's
MaxPendingTransactions bound and assigning nonces in a nondeterministic order.
Under Holocene the frame queue drops out-of-order frames instead of buffering
them, so the batcher's L1 txs must land in submission order.

Submit the authenticateBatchInfo tx and the batch inbox tx through the same
ordered queue.Send path as the non-fallback batcher, in submission order, so
the auth tx takes the lower nonce and is mined first, and both txs stay under
MaxPendingTransactions. A watcher goroutine (tracked by authGroup so the
publishing loop drains it before closing receiptsCh) collects both receipts on
private channels, fails the pair if the auth tx reverted (a reverted
authenticateBatchInfo emits no event, so the verifier would silently drop the
batch), runs the lookback-window check, and emits a single synthetic receipt
for the batch txData.

Co-authored-by: OpenCode <noreply@opencode.ai>
Bring in op-service/crypto/espresso.go (ChainSigner interface unifying
SignTransaction and arbitrary-data signing) and op-service/signer/espresso.go
(SignerClient.Sign wrapper around eth_sign).

Required by the Espresso batcher to sign batch-authentication payloads with
either a remote signer or a local private key, in addition to the existing
transaction-signing path.

Co-authored-by: OpenCode <noreply@opencode.ai>
Introduce op-node/rollup/derive/espresso_batch.go defining EspressoBatch
(a SingularBatch with block number, L1 info deposit transaction, and
signer address attached), along with BlockToEspressoBatch and the
unmarshaler used by the streamer.

Also pulls in the github.com/EspressoSystems/espresso-network/sdks/go
dependency, which provides the Espresso transaction and namespace types.

Consumed by the Espresso batcher (next commits) to convert L2 blocks into
batches submitted to Espresso, and to round-trip those batches back through
the streamer.

Co-authored-by: OpenCode <noreply@opencode.ai>
Bring in the parts of the espresso/ shared package that are TEE-only:

- espresso/cli.go: full CLI flag set for --espresso.enabled, query
  service URLs, light-client/L1 endpoints, batch-authenticator address,
  receipt-verification tuning, namespace/origin-height parameters used
  to construct the espresso-streamer. (The --espresso.fallback-auth-lead-time
  flag lives in op-batcher/flags/flags.go and was added by the fallback PR.)
- espresso/interface.go: EspressoStreamer[B] interface that wraps
  github.com/EspressoSystems/espresso-streamers/op.BatchStreamer.
- espresso/ethclient.go: AdaptL1BlockRefClient adapter (used by cli.go to
  construct the streamer) and FetchEspressoBatcherAddress helper.

Also adds the EspressoSystems/espresso-network/sdks/go and
EspressoSystems/espresso-streamers Go module dependencies.

The regenerated BatchAuthenticator bindings already live in the
fallback PR's espresso/bindings/.

Co-authored-by: OpenCode <noreply@opencode.ai>
Bring in op-batcher/enclave/attestation.go: a thin wrapper around the
hf/nsm library that obtains an AWS Nitro NSM attestation document over
a given public key. Used by the Espresso batcher (next commit) to attach
a TEE attestation to its registration with the BatchAuthenticator.

Adds the github.com/hf/nsm dependency. Builds on all platforms; NSM
device access is only attempted at runtime when invoked from inside
a Nitro enclave.

Co-authored-by: OpenCode <noreply@opencode.ai>
Add the Espresso TEE batcher write-path on top of the fallback batcher:

- op-batcher/batcher/espresso.go: Espresso submission loop (peeks the
  channel manager, converts each L2 block to an EspressoBatch, submits
  it to Espresso, waits for inclusion, and then posts the batch txs to
  L1 with TEE-attested BatchAuthenticator.authenticateBatchInfo calls).
- op-batcher/batcher/espresso_service.go: EspressoBatcherConfig,
  initEspresso (Espresso client / light-client construction, optional
  TEE attestation gathering), and the initChainSigner hook that wraps
  the txmgr into a opcrypto.ChainSigner.
- op-batcher/batcher/espresso_helpers_test.go and
  espresso_transaction_submitter_test.go: unit tests for the helpers and
  the TEE transaction submitter.

Extends the existing fallback wiring:

- op-batcher/batcher/espresso_driver.go: adds EspressoDriverSetup
  fields (Client/LightClient/ChainSigner/SequencerAddress/Attestation),
  batcherL1Adapter, setupEspressoStreamer, startEspressoLoops,
  resetEspressoStreamer; extends dispatchAuthenticatedSendTx with the
  TEE branch (always authenticates when Espresso.Enabled).
- op-batcher/batcher/espresso_active.go: adds isBatcherActive
  (queries BatchAuthenticator.activeIsEspresso to gate publishing
  against this batcher's role).
- op-batcher/batcher/driver.go: extends DriverSetup with the Espresso
  EspressoDriverSetup field; adds espressoSubmitter / espressoStreamer /
  teeVerifierAddress / degradedLog fields on BatchSubmitter; calls
  setupEspressoStreamer in NewBatchSubmitter; branches
  StartBatchSubmitting on Espresso.Enabled to call startEspressoLoops;
  calls resetEspressoStreamer in clearState.
- op-batcher/batcher/service.go: BatcherConfig.Espresso field;
  EspressoClient / EspressoLightClient / ChainSigner / Attestation
  runtime fields; initEspresso / initChainSigner /
  applyEspressoDriverSetup call-outs.
- op-batcher/batcher/config.go: thread Espresso espresso.CLIConfig
  through CLIConfig.
- op-batcher/flags/flags.go: register espresso.CLIFlags (TEE-only
  flags; the --espresso.fallback-auth-lead-time flag added by the
  fallback PR continues to live in op-batcher/flags/flags.go).

Also adds op-service/log/repeat_state.go (RepeatStateLogger) and its
test, used by the Espresso submission loop's tick-driven warnings.
A safeTestRecorder helper is inlined into the test to avoid pulling
in the unrelated debouncer.

Adds the github.com/hf/nitrite dependency (transitively required by
hf/nsm for attestation document parsing).

Co-authored-by: OpenCode <noreply@opencode.ai>
The TEE batcher's Espresso submission path called Txmgr.Send directly for both
the authenticateBatchInfo tx and the batch inbox tx, and ran inside authGroup,
so it bypassed MaxPendingTransactions, assigned nonces nondeterministically
(violating Holocene's in-order L1 inclusion requirement), and never checked
whether the auth tx reverted — a reverted authenticateBatchInfo emits no event,
so the verifier would silently drop the batch.

Submit both txs through the ordered queue.Send path on the publishing-loop
goroutine (auth first, batch second) so the auth tx takes the lower nonce and is
mined first, and both stay under MaxPendingTransactions. A watcher goroutine
(tracked by authGroup) collects both receipts, fails the pair if the auth tx
reverted, runs the lookback-window check, and emits a single synthetic receipt.

This is the same fix already applied to the fallback path; extract the shared
submission + receipt-watching flow into submitAuthenticatedBatch /
watchAuthReceipts so both paths reuse it and differ only in how the
authenticateBatchInfo calldata is built (TEE-attested signature vs empty
signature). Rename fallback_auth.go to espresso_auth.go to reflect the shared
scope, and restructure the tests: one suite drives the shared flow directly,
plus per-path tests asserting the distinguishing auth calldata (empty sig vs a
recoverable EIP-712 signature).

Co-authored-by: OpenCode <noreply@opencode.ai>
Port TestBatchRoundtrip from the integration branch and fold it into
espresso_batch_test.go. It is the only test covering ToEspressoTransaction
and the batcher->derivation serialization path; it asserts the decoded batch
matches the original and that the recovered signer is the batcher.

Also drop the decodedBlock.ExecutionWitness() comparison in
TestEspressoBatchConversion: that method does not exist on the op-geth
types.Block pinned in the rebase-18 base, so go vet of the derive_test
package failed to build. EspressoBatch/ToBlock carries no execution witness.

Co-authored-by: OpenCode <noreply@opencode.ai>
The Espresso batcher's initChainSigner casts its TxManager to
opcrypto.ChainSigner to sign batch-authentication payloads, but the
SimpleTxManager never implemented it. Build the ChainSigner from the
signer factory in NewConfig (storing it on Config.ChainSigner) and add
SignTransaction/Sign methods so both Config and SimpleTxManager satisfy
opcrypto.ChainSigner.

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

Add the optional L2GenesisEspressoTimeOffset deploy-config field and its
EspressoTime() accessor, plus a BatchAuthenticatorAddress L1 dependency,
and wire both into DeployConfig.RollupConfig so generated rollup configs
carry the Espresso fork time and the BatchAuthenticator address used by
event-based derivation. Espresso is not a core OP Stack fork, so it is
excluded from the ForkTimeOffset/SetForkTimeOffset fork-iteration helpers.

Co-authored-by: OpenCode <noreply@opencode.ai>
Add a deploy-espresso pipeline stage that runs the (PR #455) redesigned
scripts/deploy/DeployEspresso.s.sol for chains whose intent has
EspressoEnabled, deploying the BatchAuthenticator + TEE verifier (mock
verifiers when NITRO_ENCLAVE_VERIFIER_ADDRESS is unset). The opcm wrapper
matches the redesigned script's inputs (espressoOwner + sharedProxyAdmin,
the latter taken from the chain's shared OP Stack ProxyAdmin) and outputs
(batchAuthenticator, teeVerifierProxy, nitroTEEVerifier).

Adds ChainIntent.EspressoEnabled/EspressoBatcher,
ChainState.BatchAuthenticatorAddress, and activates Espresso at genesis
for Espresso-enabled chains in CombineDeployConfig.

Co-authored-by: OpenCode <noreply@opencode.ai>
Add the espresso-enclave / espresso-no-enclave alloc types (config/init.go)
with graceful skip when the mock TEE contracts are unavailable, wire the
Espresso + fallback batchers, System.L1, SystemConfig.L1Allocs and the
EspressoTime/BatchAuthenticatorAddress rollup fields into e2esys, give
StartOption.BatcherMod access to the System, add GethInstance.Fork (and
System.ForkL1) for L1 reorg tests, and add
GetFaultDisputeSystemConfigForEspresso.

Co-authored-by: OpenCode <noreply@opencode.ai>
Generated binding for the EspressoTEEVerifier contract (espresso-tee-contracts
submodule), used by the e2e enclave helpers to register enclave PCR0 hashes.

Co-authored-by: OpenCode <noreply@opencode.ai>
Port the non-Caff Espresso end-to-end tests from
celo-integration-rebase-17 onto the upstreaming stack: liveness, batch
authentication, batch inbox, stateless batcher, L1 reorgs, pipeline
enhancement, soft-confirmation integrity, forced transactions, dispute
game, batcher fallback, the Espresso enforcement hardfork transition, and
the dev-node simple-transaction tests, plus their docker dev-node /
attestation-verifier helpers.

Caff-node tests and helpers are dropped (the Caff node is handled out of
band by espresso-rollup-node-proxy). Adapted to the stack's renames:
EspressoEnforcementTime -> EspressoTime, SwitchBatcher() ->
SetActiveIsEspresso(bool), and the single-sourced FallbackAuthLeadTime.

These tests still launch a real dockerized espresso-dev-node; a mock is a
follow-up.

Co-authored-by: OpenCode <noreply@opencode.ai>
Widen BatcherService.EspressoClient and EspressoDriverSetup.Client from the
concrete *MultipleNodesClient to the SDK's client.EspressoClient interface, and
add the WithEspressoClientOverride DriverSetupOption so tests can inject an
in-memory Espresso fake in place of a real espresso-dev-node. Production code
never sets the override.

Co-authored-by: OpenCode <noreply@opencode.ai>
Add MockEspressoClient, an in-memory implementation of the SDK's
client.EspressoClient interface for e2e tests. It models a HotShot chain as
append-only blocks: SubmitTransaction appends to the pending block, a background
ticker seals a block every tick so the height advances continuously (as the
batcher's verification logic expects), and FetchNamespaceTransactionsInRange /
FetchTransactionByHash / FetchLatestBlockHeight round-trip the payloads. The
streamer performs no cryptographic verification of HotShot data, so the unused
query methods are stubbed.

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

Replace the dockerized espresso-dev-node with the in-memory MockEspressoClient.
e2esys.System now owns a single shared mock (System.EspressoClient) for Espresso
alloc types, injected into the primary and fallback batchers via
WithEspressoClientOverride and stopped on System.Close. The launcher no longer
starts Docker; EspressoDevNode is backed by mockEspressoDevNode exposing the
shared client via Client(). A fixed dummy light-client address is used when
ESPRESSO_SEQUENCER_LIGHT_CLIENT_PROXY_ADDRESS is unset (the streamer tolerates
the resulting no-contract error).

Tests that built their own client from EspressoUrls() now use
espressoDevNode.Client(). The dead dev-node-docker code (container-info types,
container-launch helpers, EspressoLightClientAddr, the docker smoke test) is
removed; the shared DockerCli infra used by the attestation-verifier and EigenDA
helpers is kept.

Co-authored-by: OpenCode <noreply@opencode.ai>
The in-memory mock Espresso client replaced the dockerized espresso-dev-node,
so the tests and helpers that depend on external Docker services no longer have
a backing service:

- Remove TestE2eDevnetWithInvalidAttestation / TestE2eDevnetWithUnattestedBatcherKey
  (5_batch_authentication_test.go): both gate on the SP1 zk attestation-verifier
  Docker container, which the mock does not emulate.
- Remove attestation_verifier_service_helpers.go (only consumed by those tests)
  and enclave_helpers.go (its sole live dependency was the attestation helper;
  the enclave tests were never ported).
- Remove espresso_docker_helpers.go and the now-unused EigenDA / Docker helpers
  in optitmism_espresso_test_helpers.go (StartEigenDA, StopDockerContainer,
  EIGENDA_* consts, getContainerRemappedHostPort, determineDockerNetworkMode,
  FailedToLaunchDockerContainer, determineFreePort, and the net import).
- TestE2eDevnetWithEspressoAndAltDaSimpleTransactions no longer starts an EigenDA
  proxy container: WithAltDa enables UseAltDA, which wires the system to the
  in-process altda.FakeDAServer, so the proxy was never actually contacted.

Co-authored-by: OpenCode <noreply@opencode.ai>
When restarting a TEE batcher mid-chain, CaffeinationHeightEspresso was set to
espHeight (FetchLatestBlockHeight, i.e. the chain height / block count). The
streamer treats that value as already processed and begins reading from the next
height, so it skipped the HotShot block at espHeight where the restarted batcher
re-submits its batches; safe L2 never advanced and the verifier stalled. Set it
to espHeight-1 (the last already-sealed block) so the streamer reads from
espHeight inclusive. Fixes TestBatcherSwitching and TestEspressoEnforcementHardfork.

Co-authored-by: OpenCode <noreply@opencode.ai>
RunSimpleL2BurnWithTimeout accepted a timeout but routed through
helpers.SendL2TxWithID, which ignores the caller's context and imposes its own
fixed 30s deadline on the verifier receipt wait. After a batcher switch (or with
the fallback batcher posting plain calldata in multi-frame channels) the verifier
can take well over 30s to re-derive, so the wait timed out and
TestBatcherSwitching, TestEspressoEnforcementHardfork, and
TestFallbackMechanismIntegrationTestChannelNotClosed failed.

Add an Espresso-local sendL2TxAndVerify that honours the supplied ctx (otherwise
identical to SendL2TxWithID) and use it from RunSimpleL2BurnWithTimeout, leaving
the shared op-e2e helper untouched.

Co-authored-by: OpenCode <noreply@opencode.ai>
- Inject the in-memory mock Espresso client into the batchers these tests start
  by hand mid-run (WithEspressoClientOverride); without it the restarted/extra
  batcher has no Espresso client and never produces batches.
- Set MaxPendingTransactions=0 (unbounded) for the batchers in these tests so the
  Espresso auth+batch tx pairs (routed through the ordered txmgr queue) publish
  concurrently instead of one-per-L1-block; otherwise L1 data availability lags
  and the verifier cannot derive recent blocks within the tests' windows.
- Make GetBatcherConfig a pure snapshot of the batcher CLIConfig and move the
  channel-tuning (small frames + long channel duration, which force multi-frame
  channels split across L1 blocks) to explicit WithBatcher* options at the call
  sites, so the config mutation is visible and GetBatcherConfig does only what
  its name implies.

Co-authored-by: OpenCode <noreply@opencode.ai>
The test was skipped ("takes a long time to run") but was actually broken: the
hardcoded TEST_ESPRESSO_TRANSACTION fixture was RLP-encoded against an older
3-field EspressoBatch layout, so UnmarshalBatch failed with "rlp: too few
elements" once the SignerAddress field was added. Its final step also waited for
the fixture's L1-info deposit to land on the verifier, which can never happen: a
fixed genesis-era batch is not the next expected batch on a freshly-started
chain, so the batcher never derives it (the source of the long run / timeout).

- Regenerate TEST_ESPRESSO_TRANSACTION in the current 4-field layout (adds the
  trailing SignerAddress element; otherwise byte-identical). Also used by the
  already-passing TestDeterministicDerivationExecutionStateWithInvalidTransaction.
- Replace the impossible deposit-on-verifier assertion with the test's actual
  purpose: the batcher streamer unmarshals the tx and recovers the real batcher
  address from the prepended signature, and the batch carries an L1-info deposit.
- Remove the now-unused espressoTransactionDataSkippingUnmarshal helper and unskip.

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.

4 participants