Skip to content
Open
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
c61a61c
op-service: add ChainSigner interface and eth_sign helper
QuentinI May 26, 2026
492b911
op-node: add EspressoBatch type and converters
QuentinI May 26, 2026
d6e953e
espresso: add TEE batcher CLI flags, streamer interface, and L1 adapter
QuentinI May 27, 2026
999eee7
op-batcher: add Nitro NSM attestation helper
QuentinI May 26, 2026
1c9f472
op-batcher: integrate TEE batcher and Espresso submission loop
QuentinI May 27, 2026
1d683d5
op-batcher: route TEE auth through ordered tx queue
QuentinI Jun 18, 2026
47dc77e
op-node: add EspressoBatch roundtrip test, fix derive_test vet failure
QuentinI Jun 18, 2026
776bcf4
verify batches while converting to a block
lukeiannucci Jul 6, 2026
51dec95
start throttling loop after espresso/non espresso loops
lukeiannucci Jul 6, 2026
c35d734
make use of unsafeBytesUpdated
lukeiannucci Jul 6, 2026
e15ada2
initChainSigner fallback for non espresso mode
lukeiannucci Jul 6, 2026
783a0d1
lint and make use of isBatcherActive
lukeiannucci Jul 7, 2026
b99e2e8
request to clear state from BlockLoader
lukeiannucci Jul 7, 2026
24fb92d
safety check for namespace and nil l1 deposit
lukeiannucci Jul 16, 2026
b851926
remove duplicate files between espresso streamer and upstream
lukeiannucci Jul 16, 2026
7fdb93d
address comments
lukeiannucci Jul 16, 2026
eaf1478
remove uneeded comments
lukeiannucci Jul 16, 2026
f6ea10a
update unsafe bytes every 100 blocks. matching non espresso path
lukeiannucci Jul 16, 2026
7081501
always set the prev sync status
lukeiannucci Jul 17, 2026
3160255
log at warn level if batcher isnt active
lukeiannucci Jul 20, 2026
699aea2
check the batcher address before publishing to avoid reverts
lukeiannucci Jul 21, 2026
f14d95c
copy espresso.go over from our fork
lukeiannucci Jul 28, 2026
fefb070
proper version of streamer
lukeiannucci Jul 28, 2026
3caefa6
address comment, remove uneeded methods and compile time assertion
lukeiannucci Jul 28, 2026
dc01558
use sync status interface for streamer
lukeiannucci Jul 31, 2026
9be65a6
point streamer to v2 (espresso-streamers PR 36) and adapt the batcher
philippecamacho Aug 6, 2026
f2c18bb
Check resolveTEEVerifierAddress first so that the streamer is not lef…
philippecamacho Aug 8, 2026
fd30eb5
Use LocalSafeL2 instead of SafeL2 so that Channel Manager and Streame…
philippecamacho Aug 8, 2026
4925920
Roll back running state on Espresso setup failure so that a failed st…
philippecamacho Aug 8, 2026
14ba61a
Anchor the streamer at the local-safe head during construction so tha…
philippecamacho Aug 8, 2026
a0b7798
Floor every streamer anchor and sync comparison at the caffeination p…
philippecamacho Aug 8, 2026
422a0c4
Bound every raw RPC read on the Espresso startup path with the networ…
philippecamacho Aug 8, 2026
2b0715e
Re-anchor the streamer instead of queueing batches at or below the lo…
philippecamacho Aug 8, 2026
0e6f4dd
Gate startup on the caffeination point being local-safe instead of an…
philippecamacho Aug 8, 2026
f50b0cb
Retry on zeroed sync-status fields in nextBlockRange so a transient z…
philippecamacho Aug 8, 2026
b46fecc
Skip the drain tick when the sync status is out of sync so a zeroed L…
philippecamacho Aug 8, 2026
b54e81f
Fetch the streamer re-anchor target before clearing state so a transi…
philippecamacho Aug 8, 2026
d79a805
op-batcher: bound the active-check CodeAt call with NetworkTimeout
philippecamacho Aug 13, 2026
79e4a5e
op-batcher: remove dead --espresso.batch-authenticator-addr flag
philippecamacho Aug 13, 2026
1a6e6ec
espresso: reject non-positive poll intervals in config validation
philippecamacho Aug 13, 2026
64802f0
op-batcher: bound the registration send so startup can't deadlock shu…
philippecamacho Aug 13, 2026
80d2204
op-batcher: make the verify-receipt retry delay cancellation-aware
philippecamacho Aug 13, 2026
4b822fe
op-batcher: dial --espresso.l1-url for light-client reads, drop rollu…
philippecamacho Aug 13, 2026
059809c
op-batcher: remove dead --espresso.namespace flag, namespace is the L…
philippecamacho Aug 13, 2026
eaa0e67
op-batcher: reject zeroed LocalSafeL2 as the streamer re-anchor target
philippecamacho Aug 13, 2026
5258dde
op-batcher: document the real zero semantics of --espresso.origin-hei…
philippecamacho Aug 13, 2026
6314621
espresso: drop stale references to --espresso.fallback-auth-lead-time
palango Aug 18, 2026
5c63f37
op-batcher: fix the data races in TestBatchSubmitter_ThrottlingEndpoints
palango Aug 18, 2026
666fa17
espresso: delete dead supporting code (#512)
palango Aug 19, 2026
f4aaa83
espresso: deduplicate the generated contract bindings (#513)
philippecamacho Sep 4, 2026
54da7e2
espresso: remove the txmgr seam, keep upstream's signer factory (#520)
jjeangal Sep 16, 2026
769b0fa
op-batcher: use one BatchAuthenticator reader, bound and code-checked…
shenkeyao Oct 7, 2026
099f5d5
Add enclave tools / docker building for TEE image to celo repository …
shenkeyao Oct 9, 2026
158237f
op-batcher: expose enclave Prometheus metrics via enclaver ingress (#…
jjeangal Oct 12, 2026
ccef597
op-service: make the RPC pre-flight check proxy-aware (#531)
shenkeyao Oct 14, 2026
7674c68
op-batcher: Add network timeout ctx to Espresso client (#534)
Sneh1999 Oct 21, 2026
a178aac
op-batcher: add a metric for the publish gate state (#559)
philippecamacho Oct 21, 2026
4a7cc89
op-batcher: own per-start Espresso state in a single session struct (…
philippecamacho Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .circleci/continue/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1632,6 +1632,23 @@ jobs:
path: ./fuzzdata
when: always

check-bindings:
docker:
- image: <<pipeline.parameters.c-default_docker_image>>
resource_class: medium
steps:
- utils/checkout-with-mise:
checkout-method: blobless
enable-mise-cache: true
- check-changed:
patterns: contracts-bedrock,op-service/bindings
# forge-artifacts from contracts-bedrock-build
- attach_workspace:
at: .
- run:
name: check generated bindings against the built contracts
command: op-service/bindings/check.sh

go-lint:
docker:
- image: <<pipeline.parameters.c-default_docker_image>>
Expand Down Expand Up @@ -2541,6 +2558,11 @@ workflows:
context:
- slack
- circleci-repo-readonly-authenticated-github-token
- check-bindings:
requires:
- contracts-bedrock-build
context:
- circleci-repo-readonly-authenticated-github-token
- go-lint:
requires:
- prep-superchain
Expand Down
65 changes: 65 additions & 0 deletions .github/workflows/espresso-enclave-images.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Builds and publishes the two images that EspressoSystems/tee-image-builder's
# nitro-op-poster workflow consumes to produce the TEE batch poster:
#
# ghcr.io/celo-org/optimism/op-batcher-enclave-app — wrapped into the Nitro EIF
# ghcr.io/celo-org/optimism/op-batcher-tee — enclave-tools is extracted from it

name: Build and Push Espresso Enclave Images

on:
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ghcr.io/celo-org/optimism

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
include:
- image: op-batcher-enclave-app
target: op-batcher-enclave-app
- image: op-batcher-tee
target: op-batcher-enclave-target
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}/${{ matrix.image }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=sha,prefix={{branch}}-,enable=${{ github.event_name == 'push' }}
Comment on lines +50 to +52

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Generate an image tag for tag-ref dispatches

When this workflow is manually dispatched with a tag ref—which GitHub explicitly supports for workflow_dispatch—neither the branch nor PR rule generates a Docker tag, while the SHA rule is disabled because github.event_name is workflow_dispatch, not push. The build step still enables push, so it has no named GHCR image target to publish. Add type=ref,event=tag or enable the SHA tag for manual dispatches. GitHub workflow dispatch reference metadata-action ref semantics

Useful? React with 👍 / 👎.


- name: Build and push ${{ matrix.image }}
uses: docker/build-push-action@v5
with:
context: .
file: ops/docker/op-stack-go/Dockerfile
target: ${{ matrix.target }}
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
GIT_COMMIT=${{ github.sha }}
213 changes: 213 additions & 0 deletions espresso/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package espresso

import (
"crypto/ecdsa"
"fmt"
"strings"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"

"github.com/urfave/cli/v2"
)

// espressoFlags returns the flag names for espresso
func espressoFlags(v string) string {
return "espresso." + v
}

func espressoEnvs(envprefix, v string) []string {
return []string{envprefix + "_ESPRESSO_" + v}
}

// Default values for batch submission receipt verification tuning.
// Defined here so that both the CLI flag defaults and the batcher logic
// can reference a single source of truth.
//
// Note: DefaultBatchAuthLookbackWindow lives in constants.go (mips64-clean
// build target shared with the derivation pipeline).
const (
DefaultVerifyReceiptMaxBlocks uint64 = 5
DefaultVerifyReceiptSafetyTimeout time.Duration = 5 * time.Minute
DefaultVerifyReceiptRetryDelay time.Duration = 100 * time.Millisecond
DefaultMaxInFlightRequestsToEspresso = 128
)

var (
EnabledFlagName = espressoFlags("enabled")
PollIntervalFlagName = espressoFlags("poll-interval")
QueryServiceUrlsFlagName = espressoFlags("urls")
LightClientAddrFlagName = espressoFlags("light-client-addr")
L1UrlFlagName = espressoFlags("l1-url")
TestingBatcherPrivateKeyFlagName = espressoFlags("testing-batcher-private-key")
CaffeinationHeightEspresso = espressoFlags("origin-height-espresso")
CaffeinationHeightL2 = espressoFlags("origin-height-l2")
AttestationServiceFlagName = espressoFlags("espresso-attestation-service")
VerifyReceiptMaxBlocksFlagName = espressoFlags("verify-receipt-max-blocks")
VerifyReceiptSafetyTimeoutFlagName = espressoFlags("verify-receipt-safety-timeout")
VerifyReceiptRetryDelayFlagName = espressoFlags("verify-receipt-retry-delay")
)

func CLIFlags(envPrefix string, category string) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: EnabledFlagName,
Usage: "Enable Espresso mode",
Value: false,
EnvVars: espressoEnvs(envPrefix, "ENABLED"),
Category: category,
},
&cli.DurationFlag{
Name: PollIntervalFlagName,
Usage: "Polling interval for Espresso queries",
Value: 250 * time.Millisecond,
EnvVars: espressoEnvs(envPrefix, "POLL_INTERVAL"),
Category: category,
},
&cli.StringSliceFlag{
Name: QueryServiceUrlsFlagName,
Usage: "Comma-separated list of Espresso query service URLs",
EnvVars: espressoEnvs(envPrefix, "URLS"),
Category: category,
},
&cli.StringFlag{
Name: LightClientAddrFlagName,
Usage: "Address of the Espresso light client",
EnvVars: espressoEnvs(envPrefix, "LIGHT_CLIENT_ADDR"),
Category: category,
},
&cli.StringFlag{
Name: L1UrlFlagName,
Usage: "L1 RPC URL the Espresso light client is deployed on; defaults to the batcher's L1 RPC when unset",
EnvVars: espressoEnvs(envPrefix, "L1_URL"),
Category: category,
},
&cli.StringFlag{
Name: TestingBatcherPrivateKeyFlagName,
Usage: "Pre-approved batcher ephemeral key (testing only)",
EnvVars: espressoEnvs(envPrefix, "TESTING_BATCHER_PRIVATE_KEY"),
Category: category,
},
&cli.Uint64Flag{
Name: CaffeinationHeightEspresso,
Usage: "Espresso transactions below this height will not be considered",
EnvVars: espressoEnvs(envPrefix, "ORIGIN_HEIGHT_ESPRESSO"),
Category: category,
},
&cli.Uint64Flag{
Name: CaffeinationHeightL2,
Usage: "L2 batch position at which the Espresso streamer starts emitting batches. " +
"Operational parameter for restarting batchers mid-chain; set it explicitly when " +
"taking over from the fallback batcher. " +
"When zero, no floor is enforced and the streamer anchors at the current local-safe head. " +
"Independent of the EspressoTime hardfork, which gates derivation semantics.",
Value: 0,
EnvVars: espressoEnvs(envPrefix, "ORIGIN_HEIGHT_L2"),
Category: category,
},
&cli.StringFlag{
Name: AttestationServiceFlagName,
Usage: "URL of the Espresso attestation service",
EnvVars: espressoEnvs(envPrefix, "ESPRESSO_ATTESTATION_SERVICE"),
Category: category,
},
&cli.Uint64Flag{
Name: VerifyReceiptMaxBlocksFlagName,
Usage: "Number of HotShot blocks to wait for a submitted transaction to become queryable before re-submitting",
Value: DefaultVerifyReceiptMaxBlocks,
EnvVars: espressoEnvs(envPrefix, "VERIFY_RECEIPT_MAX_BLOCKS"),
Category: category,
},
&cli.DurationFlag{
Name: VerifyReceiptSafetyTimeoutFlagName,
Usage: "Wall-clock backstop for receipt verification; re-submits the transaction if this duration is exceeded",
Value: DefaultVerifyReceiptSafetyTimeout,
EnvVars: espressoEnvs(envPrefix, "VERIFY_RECEIPT_SAFETY_TIMEOUT"),
Category: category,
},
&cli.DurationFlag{
Name: VerifyReceiptRetryDelayFlagName,
Usage: "Delay between receipt verification retries",
Value: DefaultVerifyReceiptRetryDelay,
EnvVars: espressoEnvs(envPrefix, "VERIFY_RECEIPT_RETRY_DELAY"),
Category: category,
},
}
}

type CLIConfig struct {
Enabled bool
PollInterval time.Duration
QueryServiceURLs []string
LightClientAddr common.Address
L1URL string
TestingBatcherPrivateKey *ecdsa.PrivateKey
CaffeinationHeightEspresso uint64
CaffeinationHeightL2 uint64
EspressoAttestationService string

// Batch submission receipt verification tuning
VerifyReceiptMaxBlocks uint64
VerifyReceiptSafetyTimeout time.Duration
VerifyReceiptRetryDelay time.Duration
}

func (c CLIConfig) Check() error {
if c.Enabled {
Comment thread
piersy marked this conversation as resolved.
Comment thread
philippecamacho marked this conversation as resolved.
// Check required fields when Espresso is enabled
if len(c.QueryServiceURLs) == 0 {
return fmt.Errorf("query service URLs are required when Espresso is enabled")
}
if c.LightClientAddr == (common.Address{}) {
return fmt.Errorf("light client address is required when Espresso is enabled")
}
if c.L1URL == "" {
return fmt.Errorf("L1 URL is required when Espresso is enabled")
}
if c.EspressoAttestationService == "" {
return fmt.Errorf("attestation service URL is required when Espresso is enabled")
}
Comment on lines +168 to +170

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Allow pre-approved test keys without an attestation URL

When Espresso runs outside Nitro with --espresso.testing-batcher-private-key, initEspresso deliberately selects the pre-approved key and leaves Attestation empty, and registerBatcher consequently skips both proof generation and registration before ever using the service URL. Requiring the URL unconditionally here therefore rejects an otherwise supported devnet/test configuration unless operators provide a meaningless dummy endpoint; make this requirement conditional on the enclave-attestation path.

Useful? React with 👍 / 👎.

if c.PollInterval <= 0 {
return fmt.Errorf("poll interval must be > 0")
}
if c.VerifyReceiptMaxBlocks == 0 {
return fmt.Errorf("verify-receipt-max-blocks must be > 0")
}
if c.VerifyReceiptSafetyTimeout <= 0 {
return fmt.Errorf("verify-receipt-safety-timeout must be > 0")
}
if c.VerifyReceiptRetryDelay <= 0 {
return fmt.Errorf("verify-receipt-retry-delay must be > 0")
}
}
return nil
}

func ReadCLIConfig(c *cli.Context) CLIConfig {
config := CLIConfig{
Enabled: c.Bool(EnabledFlagName),
PollInterval: c.Duration(PollIntervalFlagName),
L1URL: c.String(L1UrlFlagName),
CaffeinationHeightEspresso: c.Uint64(CaffeinationHeightEspresso),
CaffeinationHeightL2: c.Uint64(CaffeinationHeightL2),
EspressoAttestationService: c.String(AttestationServiceFlagName),
VerifyReceiptMaxBlocks: c.Uint64(VerifyReceiptMaxBlocksFlagName),
VerifyReceiptSafetyTimeout: c.Duration(VerifyReceiptSafetyTimeoutFlagName),
VerifyReceiptRetryDelay: c.Duration(VerifyReceiptRetryDelayFlagName),
}

config.QueryServiceURLs = c.StringSlice(QueryServiceUrlsFlagName)

addrStr := c.String(LightClientAddrFlagName)
config.LightClientAddr = common.HexToAddress(addrStr)

pkStr := c.String(TestingBatcherPrivateKeyFlagName)
pkStr = strings.TrimPrefix(pkStr, "0x")
pk, err := crypto.HexToECDSA(pkStr)
if err == nil {
config.TestingBatcherPrivateKey = pk
}

return config
}
17 changes: 13 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ go 1.26.4

require (
github.com/BurntSushi/toml v1.5.0
github.com/EspressoSystems/espresso-network/sdks/go v0.3.5-0.20260410134522-1a819609a513
github.com/EspressoSystems/espresso-streamers v1.3.1-0.20260731024110-22c396aa0934
github.com/Masterminds/semver/v3 v3.3.1
github.com/andybalholm/brotli v1.1.0
github.com/base/go-bip39 v1.1.0
Expand All @@ -19,7 +21,7 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.4-0.20251001155152-4eb15ccedf7e
github.com/ethereum-optimism/superchain-registry/validation v0.0.0-20260115192958-fb86a23cd30e
github.com/ethereum/go-ethereum v1.17.0
github.com/ethereum/go-ethereum v1.17.1
github.com/fsnotify/fsnotify v1.9.0
github.com/golang/snappy v1.0.0
github.com/google/go-cmp v0.7.0
Expand All @@ -30,6 +32,8 @@ require (
github.com/hashicorp/raft v1.7.3
github.com/hashicorp/raft-boltdb/v2 v2.3.1
github.com/hashicorp/raft-wal v0.4.2
github.com/hf/nitrite v0.0.0-20241225144000-c2d5d3c4f303
github.com/hf/nsm v0.0.0-20220930140112-cd181bd646b9
github.com/holiman/uint256 v1.3.2
github.com/ipfs/go-datastore v0.6.0
github.com/ipfs/go-ds-leveldb v0.5.0
Expand Down Expand Up @@ -67,18 +71,23 @@ require (
gopkg.in/yaml.v3 v3.0.1
)

require github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect
require (
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect
github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f // indirect
)

require (
github.com/benbjohnson/immutable v0.4.0 // indirect
github.com/coreos/etcd v3.3.27+incompatible // indirect
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fxamacker/cbor/v2 v2.2.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/grafana/pyroscope-go v1.2.7 // indirect
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
golang.org/x/telemetry v0.0.0-20260625142307-59b4966ccb57 // indirect
)
Expand Down Expand Up @@ -111,7 +120,7 @@ require (
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/dchest/siphash v1.2.3 // indirect
Expand Down Expand Up @@ -277,7 +286,7 @@ require (
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v2 v2.4.0
lukechampine.com/blake3 v1.3.0 // indirect
)

Expand Down
Loading
Loading