diff --git a/.github/workflows/docker-images.yml b/.github/workflows/docker-images.yml index 4f98d2fe69e..d7b05e15079 100644 --- a/.github/workflows/docker-images.yml +++ b/.github/workflows/docker-images.yml @@ -14,6 +14,7 @@ env: jobs: prepare-deployment: runs-on: ubuntu-latest + timeout-minutes: 30 outputs: deployment-hash: ${{ steps.hash.outputs.hash }} steps: @@ -48,7 +49,10 @@ jobs: echo "$(pwd)/bin" >> $GITHUB_PATH - name: Compile contracts - run: cd packages/contracts-bedrock && just build + env: + FOUNDRY_DISABLE_NIGHTLY_WARNING: 1 + run: cd packages/contracts-bedrock && just build-no-tests + timeout-minutes: 25 - name: Fix Proxy artifact bytecode run: cd packages/contracts-bedrock && just fix-proxy-artifact diff --git a/espresso/docker/op-geth/Dockerfile b/espresso/docker/op-geth/Dockerfile index 37b6ac72dc7..a7dc4aac7c0 100644 --- a/espresso/docker/op-geth/Dockerfile +++ b/espresso/docker/op-geth/Dockerfile @@ -7,7 +7,7 @@ ARG GIT_COMMIT ARG GIT_DATE # CGO builder for components that need Espresso crypto linking -FROM golang:1.23.8-alpine3.20 AS op-cgo-builder +FROM golang:1.24-alpine AS op-cgo-builder # Install dependencies RUN apk add musl-dev gcc g++ curl tar gzip make linux-headers git jq bash yq # Install just from mise diff --git a/espresso/docker/op-stack/Dockerfile b/espresso/docker/op-stack/Dockerfile index 08f578d8eb0..9060e5be68a 100644 --- a/espresso/docker/op-stack/Dockerfile +++ b/espresso/docker/op-stack/Dockerfile @@ -6,7 +6,7 @@ ARG TARGETOS ARG TARGETARCH # Base builder image -FROM golang:1.23.8-alpine3.20 AS builder +FROM golang:1.24-alpine AS builder RUN apk add --no-cache \ curl netcat-openbsd tar gzip make gcc g++ musl-dev \ @@ -32,10 +32,18 @@ RUN case "$TARGETARCH" in \ chmod +x /usr/local/bin/cast && \ chmod +x /usr/local/bin/forge -# Install versioned toolchain -COPY ./mise.toml . -RUN mise trust && mise install -v -y just && cp $(mise which just) /usr/local/bin/just && just --version +# Install just (direct binary to avoid mise trust issues) +ARG TARGETARCH +RUN case "$TARGETARCH" in \ + "amd64") JUST_ARCH="x86_64-unknown-linux-musl" ;; \ + "arm64") JUST_ARCH="aarch64-unknown-linux-musl" ;; \ + *) echo "Unsupported architecture for just: $TARGETARCH" >&2; exit 1 ;; \ + esac && \ + wget -q "https://github.com/casey/just/releases/download/1.37.0/just-1.37.0-${JUST_ARCH}.tar.gz" -O /tmp/just.tar.gz && \ + tar -xzf /tmp/just.tar.gz -C /usr/local/bin just && rm /tmp/just.tar.gz && just --version +# Ensure just and other tools are on PATH for all FROM builder stages +ENV PATH="/usr/local/bin:$PATH" # Copy and download Go dependencies COPY ./go.mod /app/go.mod @@ -52,45 +60,64 @@ ARG GIT_DATE # Build op-node FROM builder AS op-node-builder +ARG TARGETOS +ARG TARGETARCH +ARG GIT_COMMIT +ARG GIT_DATE ARG OP_NODE_VERSION=v0.0.0 -RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-node && \ - CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ - go build -a -ldflags '-extldflags "-static"' \ - -o bin/op-node ./cmd/main.go +ENV GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_NODE_VERSION" +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ + cd /app/op-node && mkdir -p bin && go build -v -ldflags "-X main.GitCommit=$GITCOMMIT -X main.GitDate=$GITDATE -X github.com/ethereum-optimism/optimism/op-node/version.Version=$VERSION -X github.com/ethereum-optimism/optimism/op-node/version.Meta=" -o ./bin/op-node ./cmd # Build op-batcher FROM builder AS op-batcher-builder +ARG TARGETOS +ARG TARGETARCH +ARG GIT_COMMIT +ARG GIT_DATE ARG OP_BATCHER_VERSION=v0.0.0 -WORKDIR /app/op-batcher ENV GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_BATCHER_VERSION" -RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build just op-batcher +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ + cd /app/op-batcher && mkdir -p bin && go build -v -ldflags "-X main.GitCommit=$GITCOMMIT -X main.GitDate=$GITDATE -X main.Version=$VERSION" -o ./bin/op-batcher ./cmd # Build enclave-tools FROM builder AS enclave-tools-builder +ARG TARGETOS +ARG TARGETARCH +ARG GIT_COMMIT +ARG GIT_DATE ARG ENCLAVE_TOOLS_VERSION=v0.0.0 -WORKDIR /app/op-batcher ENV GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$ENCLAVE_TOOLS_VERSION" -RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build just enclave-tools +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ + cd /app/op-batcher && mkdir -p bin && go build -v -o ./bin/enclave-tools ./enclave-tools/cmd # Build op-proposer FROM builder AS op-proposer-builder +ARG TARGETOS +ARG TARGETARCH +ARG GIT_COMMIT +ARG GIT_DATE ARG OP_PROPOSER_VERSION=v0.0.0 -RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-proposer && make op-proposer \ - GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROPOSER_VERSION" -RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-challenger && make op-challenger \ - GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROPOSER_VERSION" +ENV GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROPOSER_VERSION" +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd /app/op-proposer && make op-proposer +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd /app/op-challenger && make op-challenger # Build op-deployer FROM builder AS op-deployer-builder -ARG OP_DEPLOER_VERSION=v0.0.0 -RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-deployer && \ - GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_DEPLOYER_VERSION" just +ARG TARGETOS +ARG TARGETARCH +ARG GIT_COMMIT +ARG GIT_DATE +ARG OP_DEPLOYER_VERSION=v0.0.0 +ENV GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_DEPLOYER_VERSION" +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ + cd /app/op-deployer && just build-go # Final runtime images FROM $TARGET_BASE_IMAGE AS op-node-target RUN apk add gcc -ENV AZTEC_SRS_PATH /aztec/kzg10-aztec20-srs-1048584.bin +ENV AZTEC_SRS_PATH=/aztec/kzg10-aztec20-srs-1048584.bin ADD "https://github.com/EspressoSystems/ark-srs/releases/download/v0.2.0/kzg10-aztec20-srs-1048584.bin" /aztec/kzg10-aztec20-srs-1048584.bin COPY --from=op-node-builder /app/op-node/bin/op-node /usr/local/bin/ @@ -104,7 +131,7 @@ CMD ["op-node"] FROM $TARGET_BASE_IMAGE AS op-batcher-target RUN apk add gcc -ENV AZTEC_SRS_PATH /aztec/kzg10-aztec20-srs-1048584.bin +ENV AZTEC_SRS_PATH=/aztec/kzg10-aztec20-srs-1048584.bin ADD "https://github.com/EspressoSystems/ark-srs/releases/download/v0.2.0/kzg10-aztec20-srs-1048584.bin" /aztec/kzg10-aztec20-srs-1048584.bin COPY --from=op-batcher-builder /app/op-batcher/bin/op-batcher /usr/local/bin/ CMD ["op-batcher"] @@ -121,7 +148,7 @@ COPY espresso/deployment/ /source/espresso/deployment/ # Copy the run-enclave.sh script COPY espresso/docker/op-batcher-tee/run-enclave.sh ./espresso/docker/op-batcher-tee/run-enclave.sh RUN chmod +x ./espresso/docker/op-batcher-tee/run-enclave.sh -ENV AZTEC_SRS_PATH /aztec/kzg10-aztec20-srs-1048584.bin +ENV AZTEC_SRS_PATH=/aztec/kzg10-aztec20-srs-1048584.bin ADD "https://github.com/EspressoSystems/ark-srs/releases/download/v0.2.0/kzg10-aztec20-srs-1048584.bin" /aztec/kzg10-aztec20-srs-1048584.bin COPY --from=enclave-tools-builder /app/op-batcher/bin/enclave-tools /usr/local/bin/ CMD ["enclave-tools"] @@ -132,7 +159,7 @@ COPY espresso/docker/op-stack/entrypoint.sh /bin/entrypoint.sh RUN chmod +x /bin/entrypoint.sh COPY --from=op-proposer-builder /app/op-proposer/bin/op-proposer /usr/local/bin/ COPY --from=op-proposer-builder /app/espresso/deployment/deployer /deployer -ENV ENV_PREFIX OP_PROPOSER +ENV ENV_PREFIX=OP_PROPOSER ENTRYPOINT [ "/bin/entrypoint.sh" ] CMD ["op-proposer"] @@ -150,7 +177,7 @@ COPY --from=op-proposer-builder /app/op-challenger/bin/op-challenger /usr/local/ # ENV OP_CHALLENGER_CANNON_BIN /usr/local/bin/cannon # ENV OP_CHALLENGER_CANNON_SERVER /usr/local/bin/op-program # ENV OP_CHALLENGER_CANNON_PRESTATE /app/prestate-proof.json -ENV ENV_PREFIX OP_CHALLENGER +ENV ENV_PREFIX=OP_CHALLENGER ENTRYPOINT [ "/bin/entrypoint.sh" ] CMD ["op-challenger"] diff --git a/espresso/environment/enclave_helpers.go b/espresso/environment/enclave_helpers.go index 1ab4debac92..deed81fa034 100644 --- a/espresso/environment/enclave_helpers.go +++ b/espresso/environment/enclave_helpers.go @@ -145,13 +145,16 @@ func LaunchBatcherInEnclave() E2eDevnetLauncherOption { appendArg(&args, flags.MaxL1TxSizeBytesFlag.Name, c.MaxL1TxSize) appendArg(&args, flags.MaxPendingTransactionsFlag.Name, c.MaxPendingTransactions) appendArg(&args, flags.PollIntervalFlag.Name, c.PollInterval) - appendArg(&args, flags.AdditionalThrottlingEndpointsFlag.Name, c.AdditionalThrottlingEndpoints) + appendArg(&args, flags.AdditionalThrottlingEndpointsFlag.Name, strings.Join(c.ThrottleConfig.AdditionalEndpoints, ",")) appendArg(&args, flags.SubSafetyMarginFlag.Name, c.SubSafetyMargin) appendArg(&args, flags.TargetNumFramesFlag.Name, c.TargetNumFrames) - appendArg(&args, flags.ThrottleAlwaysBlockSizeFlag.Name, c.ThrottleAlwaysBlockSize) - appendArg(&args, flags.ThrottleBlockSizeFlag.Name, c.ThrottleBlockSize) - appendArg(&args, flags.ThrottleThresholdFlag.Name, c.ThrottleThreshold) - appendArg(&args, flags.ThrottleTxSizeFlag.Name, c.ThrottleTxSize) + appendArg(&args, flags.ThrottleBlockSizeLowerLimitFlag.Name, c.ThrottleConfig.BlockSizeLowerLimit) + appendArg(&args, flags.ThrottleBlockSizeUpperLimitFlag.Name, c.ThrottleConfig.BlockSizeUpperLimit) + appendArg(&args, flags.ThrottleUsafeDABytesLowerThresholdFlag.Name, c.ThrottleConfig.LowerThreshold) + appendArg(&args, flags.ThrottleUsafeDABytesUpperThresholdFlag.Name, c.ThrottleConfig.UpperThreshold) + appendArg(&args, flags.ThrottleTxSizeLowerLimitFlag.Name, c.ThrottleConfig.TxSizeLowerLimit) + appendArg(&args, flags.ThrottleTxSizeUpperLimitFlag.Name, c.ThrottleConfig.TxSizeUpperLimit) + appendArg(&args, flags.ThrottleControllerTypeFlag.Name, string(c.ThrottleConfig.ControllerType)) appendArg(&args, flags.WaitNodeSyncFlag.Name, c.WaitNodeSync) // TxMgr flags diff --git a/espresso/environment/espresso_caff_node.go b/espresso/environment/espresso_caff_node.go index 40adfbc91fb..9ef6ec84f6f 100644 --- a/espresso/environment/espresso_caff_node.go +++ b/espresso/environment/espresso_caff_node.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/config" + "github.com/ethereum-optimism/optimism/op-service/clock" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" ) @@ -138,7 +139,7 @@ func LaunchCaffNode(t *testing.T, system *e2esys.System, espressoDevNode Espress l := system.Cfg.Loggers[RoleCaffNode] var opNodeError error - caffNode, err := opnode.NewOpnode(l, &caffNodeConfig, func(e error) { + caffNode, err := opnode.NewOpnode(l, &caffNodeConfig, clock.SystemClock, func(e error) { opNodeError = e }) if have, want := err, error(nil); have != want { diff --git a/espresso/scripts/prepare-allocs.sh b/espresso/scripts/prepare-allocs.sh index 891ad04cc11..73b3dfb5b42 100755 --- a/espresso/scripts/prepare-allocs.sh +++ b/espresso/scripts/prepare-allocs.sh @@ -40,12 +40,6 @@ sleep 1 cast rpc anvil_setBalance "${OPERATOR_ADDRESS}" 0x100000000000000000000000000000000000 --rpc-url "${ANVIL_URL}" cast rpc anvil_setBalance "${PROPOSER_ADDRESS}" 0x100000000000000000000000000000000000 --rpc-url "${ANVIL_URL}" -op-deployer bootstrap proxy \ - --l1-rpc-url="${ANVIL_URL}" \ - --private-key="${OPERATOR_PRIVATE_KEY}" \ - --artifacts-locator="${ARTIFACTS_DIR}" \ - --proxy-owner="${OPERATOR_ADDRESS}" - export LOG_LEVEL=debug op-deployer bootstrap superchain \ @@ -97,6 +91,8 @@ dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .globalDeployOverrides.disputeGame dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].baseFeeVaultRecipient -v "${OPERATOR_ADDRESS}" dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].l1FeeVaultRecipient -v "${OPERATOR_ADDRESS}" dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].sequencerFeeVaultRecipient -v "${OPERATOR_ADDRESS}" +dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].operatorFeeVaultRecipient -v "${OPERATOR_ADDRESS}" +dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].chainFeesRecipient -v "${OPERATOR_ADDRESS}" dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].roles.systemConfigOwner -v "${OPERATOR_ADDRESS}" dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].roles.unsafeBlockSigner -v "${OPERATOR_ADDRESS}" dasel put -f "${DEPLOYER_DIR}/intent.toml" -s .chains.[0].roles.batcher -v "${OPERATOR_ADDRESS}" diff --git a/go.mod b/go.mod index 0918a4227b2..14cd1455274 100644 --- a/go.mod +++ b/go.mod @@ -113,7 +113,6 @@ require ( github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/consensys/bavard v0.1.27 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -172,7 +171,6 @@ require ( github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/golang-lru/arc/v2 v2.0.7 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e // indirect - github.com/hf/nitrite v0.0.0-20241225144000-c2d5d3c4f303 // indirect github.com/holiman/billy v0.0.0-20250707135307-f2f9b9aae7db // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.3.0 // indirect diff --git a/kurtosis-devnet/enclaver/Dockerfile b/kurtosis-devnet/enclaver/Dockerfile index 1769009d374..49bfdae3eff 100644 --- a/kurtosis-devnet/enclaver/Dockerfile +++ b/kurtosis-devnet/enclaver/Dockerfile @@ -17,7 +17,7 @@ ARG UBUNTU_TARGET_BASE_IMAGE=ubuntu:22.04 ARG KONA_VERSION="kona-client-v0.1.0-beta.5" # We may be cross-building for another platform. Specify which platform we need as builder. -FROM --platform=$BUILDPLATFORM golang:1.23.8-alpine3.20 AS builder +FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder RUN apk add --no-cache curl tar gzip make gcc musl-dev linux-headers git jq bash @@ -77,7 +77,7 @@ RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache # We don't use the golang image for batcher because it doesn't play well with CGO -FROM --platform=$BUILDPLATFORM golang:1.23.8-alpine3.20 AS op-batcher-builder +FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS op-batcher-builder ARG OP_BATCHER_VERSION=v0.0.0 # Install dependencies RUN apk add musl-dev gcc g++ curl tar gzip make linux-headers git jq bash yq diff --git a/kurtosis-devnet/enclaver/Dockerfile.nonEnclave b/kurtosis-devnet/enclaver/Dockerfile.nonEnclave index cda5905e77a..825dc5de049 100644 --- a/kurtosis-devnet/enclaver/Dockerfile.nonEnclave +++ b/kurtosis-devnet/enclaver/Dockerfile.nonEnclave @@ -17,7 +17,7 @@ ARG UBUNTU_TARGET_BASE_IMAGE=ubuntu:22.04 ARG KONA_VERSION="kona-client-v0.1.0-beta.5" # We may be cross-building for another platform. Specify which platform we need as builder. -FROM --platform=$BUILDPLATFORM golang:1.23.8-alpine3.20 AS builder +FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder RUN apk add --no-cache curl tar gzip make gcc musl-dev linux-headers git jq bash @@ -76,10 +76,10 @@ RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$CANNON_VERSION" # We don't use the golang image for batcher because it doesn't play well with CGO -FROM --platform=$BUILDPLATFORM alpine:3.20 AS op-batcher-builder +FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS op-batcher-builder ARG OP_BATCHER_VERSION=v0.0.0 # Install dependencies -RUN apk add musl-dev gcc go g++ curl tar gzip make gcc linux-headers git jq bash yq +RUN apk add musl-dev gcc g++ curl tar gzip make linux-headers git jq bash yq # Install just from mise (alpine's outdated and incompatible) COPY ./mise.toml . RUN curl -L https://github.com/casey/just/releases/download/$(yq '.tools.just' mise.toml)/just-$(yq '.tools.just' mise.toml)-x86_64-unknown-linux-musl.tar.gz | \ diff --git a/op-batcher/batcher/config.go b/op-batcher/batcher/config.go index 179fe4aa87c..5c3fb2bc783 100644 --- a/op-batcher/batcher/config.go +++ b/op-batcher/batcher/config.go @@ -271,10 +271,7 @@ func NewConfig(ctx *cli.Context) *CLIConfig { PidOutputMax: ctx.Float64(flags.ThrottlePidOutputMaxFlag.Name), PidSampleTime: ctx.Duration(flags.ThrottlePidSampleTimeFlag.Name), }, - EspressoUrl: ctx.String(flags.EspressoUrlFlag.Name), - EspressoLightClientAddr: ctx.String(flags.EspressoLCAddrFlag.Name), - TestingEspressoBatcherPrivateKey: ctx.String(flags.TestingEspressoBatcherPrivateKeyFlag.Name), - EspressoPollInterval: ctx.Duration(flags.EspressoPollIntervalFlag.Name), - PreferLocalSafeL2: ctx.Bool(flags.PreferLocalSafeL2Flag.Name), + Espresso: espresso.ReadCLIConfig(ctx), + PreferLocalSafeL2: ctx.Bool(flags.PreferLocalSafeL2Flag.Name), } } diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 445404cdef1..b6d94df4019 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -8,6 +8,7 @@ import ( "math/big" _ "net/http/pprof" "sync" + "sync/atomic" "time" "golang.org/x/sync/errgroup" @@ -21,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" espressoClient "github.com/EspressoSystems/espresso-network/sdks/go/client" + espressoLightClient "github.com/EspressoSystems/espresso-network/sdks/go/light-client" "github.com/ethereum-optimism/optimism/espresso" altda "github.com/ethereum-optimism/optimism/op-alt-da" "github.com/ethereum-optimism/optimism/op-batcher/batcher/throttler" @@ -91,6 +93,19 @@ type AltDAClient interface { SetInput(ctx context.Context, data []byte) (altda.CommitmentData, error) } +// batcherL1Adapter wraps the batcher's L1Client to implement espresso.L1Client (HeaderHashByNumber). +type batcherL1Adapter struct { + L1Client L1Client +} + +func (a *batcherL1Adapter) HeaderHashByNumber(ctx context.Context, number *big.Int) (common.Hash, error) { + h, err := a.L1Client.HeaderByNumber(ctx, number) + if err != nil { + return common.Hash{}, err + } + return h.Hash(), nil +} + // DriverSetup is the collection of input/output interfaces and configuration that the driver operates on. type DriverSetup struct { closeApp context.CancelCauseFunc @@ -109,7 +124,7 @@ type DriverSetup struct { EspressoLightClient *espressoLightClient.LightclientCaller ChainSigner opcrypto.ChainSigner SequencerAddress common.Address - Attestation *nitrite.Result + Attestation []byte } // BatchSubmitter encapsulates a service responsible for submitting L2 tx @@ -161,10 +176,12 @@ func NewBatchSubmitter(setup DriverSetup) *BatchSubmitter { panic(err) } + l1Adapter := &batcherL1Adapter{L1Client: batchSubmitter.L1Client} batchSubmitter.espressoStreamer = espresso.NewBufferedEspressoStreamer( espresso.NewEspressoStreamer( batchSubmitter.RollupConfig.L2ChainID.Uint64(), - NewAdaptL1BlockRefClient(batchSubmitter.L1Client), + l1Adapter, + l1Adapter, batchSubmitter.Espresso, batchSubmitter.EspressoLightClient, batchSubmitter.Log, @@ -172,6 +189,7 @@ func NewBatchSubmitter(setup DriverSetup) *BatchSubmitter { return derive.UnmarshalEspressoTransaction(data, batchSubmitter.SequencerAddress) }, 2*time.Second, + 0, 0, // originHotShotPos, originBatchPos ), ) batchSubmitter.Log.Info("Streamer started", "streamer", batchSubmitter.espressoStreamer) @@ -179,6 +197,11 @@ func NewBatchSubmitter(setup DriverSetup) *BatchSubmitter { return batchSubmitter } +// EspressoStreamer returns the Espresso batch streamer for use by the service and tests. +func (l *BatchSubmitter) EspressoStreamer() espresso.EspressoStreamer[derive.EspressoBatch] { + return l.espressoStreamer +} + func (l *BatchSubmitter) StartBatchSubmitting() error { l.Log.Info("Starting Batch Submitter") @@ -233,7 +256,7 @@ func (l *BatchSubmitter) StartBatchSubmitting() error { l.espressoSubmitter = NewEspressoTransactionSubmitter( WithContext(l.shutdownCtx), WithWaitGroup(l.wg), - WithEspressoClient(l.EspressoClient), + WithEspressoClient(l.Espresso), ) l.espressoSubmitter.SpawnWorkers(4, 4) l.espressoSubmitter.Start() @@ -901,7 +924,7 @@ func (l *BatchSubmitter) clearState(ctx context.Context) { defer l.channelMgrMutex.Unlock() l.channelMgr.Clear(l1SafeOrigin) if l.Config.UseEspresso { - l.EspressoStreamer.Reset() + l.EspressoStreamer().Reset() } return true } diff --git a/op-batcher/batcher/espresso.go b/op-batcher/batcher/espresso.go index f3f19ecdd93..037a40fe625 100644 --- a/op-batcher/batcher/espresso.go +++ b/op-batcher/batcher/espresso.go @@ -28,6 +28,16 @@ import ( "github.com/ethereum-optimism/optimism/op-service/txmgr" ) +// EspressoOnchainProof is the proof structure returned by the attestation service for onchain verification. +type EspressoOnchainProof struct { + Proof json.RawMessage `json:"proof,omitempty"` + Data json.RawMessage `json:"data,omitempty"` + RawProof struct { + Journal string `json:"journal"` + } `json:"raw_proof"` + OnchainProof string `json:"onchain_proof"` +} + // espressoSubmitTransactionJob is a struct that holds the state required to // submit a transaction to Espresso. // It contains the transaction to be submitted itself, and a number to @@ -637,16 +647,6 @@ func (s *espressoTransactionSubmitter) Start() { go s.handleVerifyReceiptJobResponse() } -func (bs *BatcherService) initKeyPair() error { - key, err := crypto.GenerateKey() - if err != nil { - return fmt.Errorf("failed to generate key pair for batcher: %w", err) - } - bs.BatcherPrivateKey = key - bs.BatcherPublicKey = &key.PublicKey - return nil -} - // Converts a block to an EspressoBatch and starts a goroutine that publishes it to Espresso // Returns error only if batch conversion fails, otherwise it is infallible, as the goroutine // will retry publishing until successful. @@ -673,7 +673,7 @@ func (l *BatchSubmitter) queueBlockToEspresso(ctx context.Context, block *types. } func (l *BatchSubmitter) espressoSyncAndRefresh(ctx context.Context, newSyncStatus *eth.SyncStatus) { - err := l.EspressoStreamer.Refresh(ctx, newSyncStatus.FinalizedL1, newSyncStatus.FinalizedL2.Number, newSyncStatus.FinalizedL2.L1Origin) + err := l.EspressoStreamer().Refresh(ctx, newSyncStatus.FinalizedL1, newSyncStatus.FinalizedL2.Number, newSyncStatus.FinalizedL2.L1Origin) if err != nil { l.Log.Warn("Failed to refresh Espresso streamer", "err", err) } @@ -688,7 +688,7 @@ func (l *BatchSubmitter) espressoSyncAndRefresh(ctx context.Context, newSyncStat l.prevCurrentL1 = newSyncStatus.CurrentL1 if syncActions.clearState != nil { l.channelMgr.Clear(*syncActions.clearState) - l.EspressoStreamer.Reset() + l.EspressoStreamer().Reset() } else { l.channelMgr.PruneSafeBlocks(syncActions.blocksToPrune) l.channelMgr.PruneChannels(syncActions.channelsToPrune) @@ -696,7 +696,7 @@ func (l *BatchSubmitter) espressoSyncAndRefresh(ctx context.Context, newSyncStat } // Periodically refreshes the sync status and polls Espresso streamer for new batches -func (l *BatchSubmitter) espressoBatchLoadingLoop(ctx context.Context, wg *sync.WaitGroup, publishSignal chan struct{}) { +func (l *BatchSubmitter) espressoBatchLoadingLoop(ctx context.Context, wg *sync.WaitGroup, publishSignal chan pubInfo) { l.Log.Info("Starting EspressoBatchLoadingLoop", "polling interval", l.Config.EspressoPollInterval) defer wg.Done() @@ -715,13 +715,13 @@ func (l *BatchSubmitter) espressoBatchLoadingLoop(ctx context.Context, wg *sync. l.espressoSyncAndRefresh(ctx, newSyncStatus) - err = l.EspressoStreamer.Update(ctx) + err = l.EspressoStreamer().Update(ctx) var batch *derive.EspressoBatch for { - batch = l.EspressoStreamer.Next(ctx) + batch = l.EspressoStreamer().Next(ctx) if batch == nil { break @@ -749,13 +749,13 @@ func (l *BatchSubmitter) espressoBatchLoadingLoop(ctx context.Context, wg *sync. if err != nil { l.Log.Error("failed to add L2 block to channel manager", "err", err) l.clearState(ctx) - l.EspressoStreamer.Reset() + l.EspressoStreamer().Reset() } l.Log.Info("Added L2 block to channel manager") } - trySignal(publishSignal) + l.tryPublishSignal(publishSignal, pubInfo{}) // A failure in the streamer Update can happen after the buffer has been partially filled if err != nil { @@ -959,8 +959,8 @@ func (l *BatchSubmitter) fetchBlock(ctx context.Context, blockNumber uint64) (*t } func (l *BatchSubmitter) registerBatcher(ctx context.Context) error { - if l.Attestation == nil { - l.Log.Warn("Attestation is nil, skipping registration") + if len(l.Attestation) == 0 { + l.Log.Warn("Attestation is empty, skipping registration") return nil } diff --git a/op-batcher/batcher/service.go b/op-batcher/batcher/service.go index 836cfa6c46d..2dfbc2a9dea 100644 --- a/op-batcher/batcher/service.go +++ b/op-batcher/batcher/service.go @@ -7,13 +7,14 @@ import ( "fmt" "io" "math/big" - "strings" "sync/atomic" "time" espressoClient "github.com/EspressoSystems/espresso-network/sdks/go/client" + espressoLightClient "github.com/EspressoSystems/espresso-network/sdks/go/light-client" "github.com/ethereum-optimism/optimism/espresso" opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/hf/nitrite" @@ -105,11 +106,11 @@ type BatcherService struct { oracleStopCh chan struct{} opcrypto.ChainSigner - Attestation *nitrite.Result + Attestation []byte } -func (bs *BatcherService) EspressoStreamer() *espressoLocal.EspressoStreamer[derive.EspressoBatch] { - return &bs.driver.espressoStreamer +func (bs *BatcherService) EspressoStreamer() espresso.EspressoStreamer[derive.EspressoBatch] { + return bs.driver.espressoStreamer } type DriverSetupOption func(setup *DriverSetup) @@ -745,25 +746,16 @@ func (bs *BatcherService) initEspresso(cfg *CLIConfig) error { bs.EspressoPollInterval = cfg.Espresso.PollInterval bs.EspressoAttestationService = cfg.Espresso.EspressoAttestationService - urlZero := cfg.Espresso.QueryServiceURLs[0] - espressoClient := espressoClient.NewClient(urlZero) - - bs.EspressoClient = espressoClient + client, err := espressoClient.NewMultipleNodesClient(cfg.Espresso.QueryServiceURLs) + if err != nil { + return fmt.Errorf("failed to create Espresso client: %w", err) + } + bs.Espresso = client if err := bs.initKeyPair(); err != nil { return fmt.Errorf("failed to create key pair for batcher: %w", err) } - unbufferedStreamer, err := espresso.BatchStreamerFromCLIConfig(cfg.Espresso, bs.Log, func(data []byte) (*derive.EspressoBatch, error) { - return derive.UnmarshalEspressoTransaction(data, bs.TxManager.From()) - }) - if err != nil { - return fmt.Errorf("failed to create unbuffered Espresso streamer: %w", err) - } - - // We wrap the streamer in a BufferedStreamer to reduce impact of streamer resets - bs.EspressoStreamer = espresso.NewBufferedEspressoStreamer(unbufferedStreamer) - // try to generate attestationBytes on public key when start batcher attestationBytes, err := enclave.AttestationWithPublicKey(bs.BatcherPublicKey) if err != nil { diff --git a/op-batcher/flags/flags.go b/op-batcher/flags/flags.go index 7d2f2bc573c..1d3d382d6a8 100644 --- a/op-batcher/flags/flags.go +++ b/op-batcher/flags/flags.go @@ -214,7 +214,6 @@ var optionalFlags = []cli.Flag{ CompressionAlgoFlag, EspressoUrlFlag, EspressoLCAddrFlag, - EspressoPollIntervalFlag, TestingEspressoBatcherPrivateKeyFlag, PreferLocalSafeL2Flag, } diff --git a/op-deployer/pkg/deployer/bootstrap/flags.go b/op-deployer/pkg/deployer/bootstrap/flags.go index fa415487fa6..ba2ddf73545 100644 --- a/op-deployer/pkg/deployer/bootstrap/flags.go +++ b/op-deployer/pkg/deployer/bootstrap/flags.go @@ -169,11 +169,6 @@ var ( Usage: "Path to a JSON file", EnvVars: deployer.PrefixEnvVar("CONFIG"), } - ChallengerFlag = &cli.StringFlag{ - Name: "challenger", - Usage: "Challenger.", - EnvVars: deployer.PrefixEnvVar("CHALLENGER"), - } ) var ImplementationsFlags = []cli.Flag{ diff --git a/op-e2e/e2eutils/geth/fakepos.go b/op-e2e/e2eutils/geth/fakepos.go index 44ef3c3c31d..251cd01ec17 100644 --- a/op-e2e/e2eutils/geth/fakepos.go +++ b/op-e2e/e2eutils/geth/fakepos.go @@ -13,7 +13,9 @@ import ( "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" @@ -53,6 +55,8 @@ type FakePoS struct { type Backend interface { // HeaderByNumber is assumed to behave the same as go-ethereum/ethclient.Client.HeaderByNumber. HeaderByNumber(context.Context, *big.Int) (*types.Header, error) + TxPool() *txpool.TxPool + BlockChain() *core.BlockChain } type EngineAPI interface { diff --git a/op-e2e/e2eutils/geth/geth.go b/op-e2e/e2eutils/geth/geth.go index bdfeba97ce6..20e8a4e920c 100644 --- a/op-e2e/e2eutils/geth/geth.go +++ b/op-e2e/e2eutils/geth/geth.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/core/txpool" // Force-load the tracer engines to trigger registration _ "github.com/ethereum/go-ethereum/eth/tracers/js" @@ -65,9 +66,10 @@ func InitL1(blockTime uint64, finalizedDistance uint64, genesis *core.Genesis, c } // Instead of running a whole beacon node, we run this fake-proof-of-stake sidecar that sequences L1 blocks using the Engine API. + // ethBackendAdapter adapts *eth.Ethereum to the Backend interface (HeaderByNumber uses APIBackend). fakePoS := &FakePoS{ clock: c, - eth: gethInstance.Backend, + eth: ðBackendAdapter{eth: gethInstance.Backend}, log: log.Root(), // geth logger is global anyway. Would be nice to replace with a local logger though. blockTime: blockTime, finalizedDistance: finalizedDistance, @@ -92,6 +94,29 @@ func WithAuth(jwtPath string) GethOption { } } +// ethBackendAdapter adapts *eth.Ethereum to the Backend interface (HeaderByNumber is on APIBackend). +type ethBackendAdapter struct { + eth *eth.Ethereum +} + +func (a *ethBackendAdapter) HeaderByNumber(ctx context.Context, num *big.Int) (*types.Header, error) { + var bn rpc.BlockNumber + if num == nil { + bn = rpc.LatestBlockNumber + } else { + bn = rpc.BlockNumber(num.Int64()) + } + return a.eth.APIBackend.HeaderByNumber(ctx, bn) +} + +func (a *ethBackendAdapter) TxPool() *txpool.TxPool { + return a.eth.TxPool() +} + +func (a *ethBackendAdapter) BlockChain() *core.BlockChain { + return a.eth.BlockChain() +} + type gethBackend struct { chain *core.BlockChain } diff --git a/op-e2e/system/e2esys/setup.go b/op-e2e/system/e2esys/setup.go index 7381269582e..8aaa870e031 100644 --- a/op-e2e/system/e2esys/setup.go +++ b/op-e2e/system/e2esys/setup.go @@ -601,7 +601,7 @@ func WithBatcherCompressionAlgo(ca derive.CompressionAlgo) StartOption { func WithBatcherThrottling(interval time.Duration, threshold, txSize, blockSize uint64) StartOption { return StartOption{ - BatcherMod: func(cfg *bss.CLIConfig) { + BatcherMod: func(cfg *bss.CLIConfig, _ *System) { cfg.ThrottleConfig.LowerThreshold = threshold cfg.ThrottleConfig.ControllerType = batcherCfg.StepControllerType cfg.ThrottleConfig.TxSizeLowerLimit = txSize @@ -756,8 +756,6 @@ func (cfg SystemConfig) Start(t *testing.T, startOpts ...StartOption) (*System, EIP1559Denominator: cfg.DeployConfig.EIP1559Denominator, EIP1559DenominatorCanyon: &cfg.DeployConfig.EIP1559DenominatorCanyon, }, - - BatchAuthenticatorAddress: cfg.DeployConfig.BatchAuthenticatorAddress, } } defaultConfig := makeRollupConfig() @@ -1085,7 +1083,12 @@ func (cfg SystemConfig) Start(t *testing.T, startOpts ...StartOption) (*System, fallbackBatcherCliConfig.Stopped = true fallbackBatcherCliConfig.Espresso.Enabled = false fallbackBatcherCliConfig.TxMgrConfig = setuputils.NewTxMgrConfig(sys.EthInstances[RoleL1].UserRPC(), fallbackBatcherKey) - fallbackBatcher, err := bss.BatcherServiceFromCLIConfig(context.Background(), "0.0.1", fallbackBatcherCliConfig, sys.Cfg.Loggers["batcher"]) + fallbackBatcherCtx, fallbackBatcherCancel := context.WithCancel(context.Background()) + fallbackCloseAppFn := func(cause error) { + t.Fatalf("fallback closeAppFn called: %v", cause) + fallbackBatcherCancel() + } + fallbackBatcher, err := bss.BatcherServiceFromCLIConfig(fallbackBatcherCtx, fallbackCloseAppFn, "0.0.1", fallbackBatcherCliConfig, sys.Cfg.Loggers["batcher"]) if err != nil { return nil, fmt.Errorf("failed to setup fallback batch submitter: %w", err) } diff --git a/op-node/node/node.go b/op-node/node/node.go index dc317f5f903..3fa42da560e 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -90,6 +90,7 @@ type L1Source interface { L1BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L1BlockRef, error) L1BlockRefByNumber(ctx context.Context, num uint64) (eth.L1BlockRef, error) L1BlockRefByHash(ctx context.Context, hash common.Hash) (eth.L1BlockRef, error) + L1FinalizedBlock() (eth.L1BlockRef, error) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) ReadStorageAt(ctx context.Context, address common.Address, storageSlot common.Hash, blockHash common.Hash) (common.Hash, error) InfoByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, error) diff --git a/op-node/rollup/derive/pipeline.go b/op-node/rollup/derive/pipeline.go index a099ca32c7b..7a8b86d4d52 100644 --- a/op-node/rollup/derive/pipeline.go +++ b/op-node/rollup/derive/pipeline.go @@ -119,7 +119,7 @@ func NewDerivationPipeline(log log.Logger, rollupCfg *rollup.Config, depSet Depe chInReader := NewChannelInReader(rollupCfg, log, channelMux, metrics) batchMux := NewBatchMux(log, rollupCfg, chInReader, l2Source) attrBuilder := NewFetchingAttributesBuilder(rollupCfg, l1ChainConfig, depSet, l1Fetcher, l2Source) - attributesQueue := NewAttributesQueue(log, rollupCfg, attrBuilder, batchMux, l1Fetcher) + attributesQueue := NewAttributesQueue(log, rollupCfg, attrBuilder, batchMux) // Reset from ResetEngine then up from L1 Traversal. The stages do not talk to each other during // the ResetEngine, but after the ResetEngine, this is the order in which the stages could talk to each other. diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index 849054fa6fc..75ba4a502fa 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - "github.com/ethereum-optimism/optimism/espresso" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" diff --git a/op-node/rollup/driver/interfaces.go b/op-node/rollup/driver/interfaces.go index 3195d9c63ec..0d08bff147d 100644 --- a/op-node/rollup/driver/interfaces.go +++ b/op-node/rollup/driver/interfaces.go @@ -60,7 +60,7 @@ type DerivationPipeline interface { Origin() eth.L1BlockRef DerivationReady() bool ConfirmEngineReset() - EspressoStreamer() *espresso.EspressoStreamer + EspressoStreamer() *espresso.BatchStreamer[derive.EspressoBatch] } type AttributesHandler interface { diff --git a/op-node/rollup/engine/events.go b/op-node/rollup/engine/events.go index 175df5b61bf..3315d085c4a 100644 --- a/op-node/rollup/engine/events.go +++ b/op-node/rollup/engine/events.go @@ -74,6 +74,16 @@ func (ev LocalSafeUpdateEvent) String() string { return "local-safe-update" } +// CrossSafeUpdateEvent signals that cross-safe and local-safe heads have been updated. +type CrossSafeUpdateEvent struct { + CrossSafe eth.L2BlockRef + LocalSafe eth.L2BlockRef +} + +func (ev CrossSafeUpdateEvent) String() string { + return "cross-safe-update" +} + // SafeDerivedEvent signals that a block was determined to be safe, and derived from the given L1 block. // This is signaled upon procedural call of PromoteSafe method type SafeDerivedEvent struct { diff --git a/op-node/service.go b/op-node/service.go index 29e4e45386f..d3bf8271a85 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/cliiface" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/urfave/cli/v2" opflags "github.com/ethereum-optimism/optimism/op-service/flags" "github.com/ethereum-optimism/optimism/op-service/jsonutil" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" @@ -260,7 +261,9 @@ func NewRollupConfigFromCLI(log log.Logger, ctx cliiface.Context) (*rollup.Confi applyCeloHardforks(rollupConfig) applyOverrides(ctx, rollupConfig) - rollupConfig.CaffNodeConfig = espresso.ReadCLIConfig(ctx) + if cliCtx, ok := ctx.(*cli.Context); ok { + rollupConfig.CaffNodeConfig = espresso.ReadCLIConfig(cliCtx) + } return rollupConfig, nil } diff --git a/ops/docker/op-stack-go/Dockerfile b/ops/docker/op-stack-go/Dockerfile index 4d4178a32cf..d7ad60cf5cb 100644 --- a/ops/docker/op-stack-go/Dockerfile +++ b/ops/docker/op-stack-go/Dockerfile @@ -101,7 +101,7 @@ FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/c FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/cannon:v1.6.0 AS cannon-builder-v1-6-0 # We don't use the golang image for batcher & op-node because it doesn't play well with CGO -FROM --platform=$BUILDPLATFORM golang:1.23.8-alpine3.20 AS op-cgo-builder +FROM --platform=$BUILDPLATFORM golang:1.24.10-alpine3.21 AS op-cgo-builder ARG OP_BATCHER_VERSION=v0.0.0 # Install dependencies RUN apk add musl-dev gcc g++ curl tar gzip make linux-headers git jq bash yq diff --git a/packages/contracts-bedrock/src/dispute/succinct/OPSuccinctFaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/succinct/OPSuccinctFaultDisputeGame.sol index edfc677ad17..78f5bad4ad2 100644 --- a/packages/contracts-bedrock/src/dispute/succinct/OPSuccinctFaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/succinct/OPSuccinctFaultDisputeGame.sol @@ -522,6 +522,11 @@ contract OPSuccinctFaultDisputeGame is Clone, ISemver, IDisputeGame { rootClaim_ = Claim.wrap(_getArgBytes32(0x14)); } + /// @notice Getter for the root claim for a given L2 chain ID (IDisputeGame interface; this game has a single root). + function rootClaimByChainId(uint256) public pure returns (Claim rootClaim_) { + rootClaim_ = rootClaim(); + } + /// @notice Getter for the parent hash of the L1 block when the dispute game was created. function l1Head() public pure returns (Hash l1Head_) { l1Head_ = Hash.wrap(_getArgBytes32(0x34));