Skip to content

Commit 611871a

Browse files
authored
Streaming streamer (#235)
1 parent 556fc2f commit 611871a

File tree

16 files changed

+389
-183
lines changed

16 files changed

+389
-183
lines changed

.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ jobs:
993993
- run:
994994
name: download espresso-network go sdk
995995
command: |
996-
ver=$(grep "github.com/EspressoSystems/espresso-network/sdks/go" go.mod | awk '{print $2}')
996+
ver=$(grep "^\s*github.com/EspressoSystems/espresso-network/sdks/go" go.mod | awk '{print $2}')
997997
url="https://github.com/EspressoSystems/espresso-network/releases/download/sdks%2Fgo%2F${ver}/libespresso_crypto_helper-x86_64-unknown-linux-gnu.so"
998998
mkdir -p /home/circleci/local-lib
999999
wget $url -O /home/circleci/local-lib/libespresso_crypto_helper-x86_64-unknown-linux-gnu.so
@@ -1066,7 +1066,7 @@ jobs:
10661066
- run:
10671067
name: download espresso-network go sdk
10681068
command: |
1069-
ver=$(grep "github.com/EspressoSystems/espresso-network/sdks/go" go.mod | awk '{print $2}')
1069+
ver=$(grep "^\s*github.com/EspressoSystems/espresso-network/sdks/go" go.mod | awk '{print $2}')
10701070
url="https://github.com/EspressoSystems/espresso-network/releases/download/sdks%2Fgo%2F${ver}/libespresso_crypto_helper-x86_64-unknown-linux-gnu.so"
10711071
mkdir -p /home/circleci/local-lib
10721072
wget $url -O /home/circleci/local-lib/libespresso_crypto_helper-x86_64-unknown-linux-gnu.so

espresso/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ services:
493493
OP_CHALLENGER_TRACE_TYPE: permissioned
494494

495495
espresso-dev-node:
496-
image: ghcr.io/espressosystems/espresso-sequencer/espresso-dev-node:release-colorful-snake
496+
image: ghcr.io/espressosystems/espresso-sequencer/espresso-dev-node:release-fix-cors
497497
depends_on:
498498
l1-geth:
499499
condition: service_healthy

espresso/docker/op-geth/Dockerfile

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,6 @@ ARG TARGETARCH
66
ARG GIT_COMMIT
77
ARG GIT_DATE
88

9-
# Rust builder for Espresso crypto libraries
10-
FROM rust:1.88.0-alpine3.22 AS rust-builder
11-
# TODO: Check the hash of the Espresso GO library when switch to the new one.
12-
# <https://app.asana.com/1/1208976916964769/project/1209392461754458/task/1210755885228839?focus=true>
13-
ARG ESPRESSO_NETWORK_GO_VER=0.0.34
14-
RUN apk add perl make openssl-dev musl-dev gcc
15-
ADD https://github.com/EspressoSystems/espresso-network-go/archive/refs/tags/v$ESPRESSO_NETWORK_GO_VER.tar.gz /source.tgz
16-
RUN tar -oxzf /source.tgz
17-
WORKDIR /espresso-network-go-$ESPRESSO_NETWORK_GO_VER
18-
RUN --mount=type=cache,target=/usr/local/cargo/registry \
19-
--mount=type=cache,target=/usr/local/cargo/git/db \
20-
--mount=type=cache,target=/espresso-network-go/verification/rust/target \
21-
cargo build --release --locked --manifest-path ./verification/rust/Cargo.toml
22-
RUN mkdir -p /libespresso
23-
RUN cp ./verification/rust/target/release/libespresso_crypto_helper.a \
24-
/libespresso/libespresso_crypto_helper-aarch64-unknown-linux-gnu.a
25-
RUN cp ./verification/rust/target/release/libespresso_crypto_helper.a \
26-
/libespresso/libespresso_crypto_helper-x86_64-unknown-linux-gnu.a
27-
289
# CGO builder for components that need Espresso crypto linking
2910
FROM alpine:3.22 AS op-cgo-builder
3011
# Install dependencies
@@ -33,11 +14,19 @@ RUN apk add musl-dev gcc go g++ curl tar gzip make gcc linux-headers git jq bash
3314
COPY ./mise.toml .
3415
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 | \
3516
tar xz -C /usr/local/bin just
17+
# Fetch rust libs for dynamic linking
18+
ARG ESPRESSO_SDK_VER=0.3.2
19+
ARG ESPRESSO_SDK_HELPER_HASH_AARCH64=ec6ce7b37edd173206ad338c84a6a771a0e9dc8b184081af7440ebfc0c531a71
20+
ARG ESPRESSO_SDK_HELPER_HASH_X86_64=49c50949ec1acf52107cb190c90911e05cc9c4e9d72dd7455496163443760b92
21+
ADD --checksum=sha256:${ESPRESSO_SDK_HELPER_HASH_AARCH64} \
22+
https://github.com/EspressoSystems/espresso-network/releases/download/sdks/go/v${ESPRESSO_SDK_VER}/libespresso_crypto_helper-aarch64-unknown-linux-gnu.so \
23+
/lib/
24+
ADD --checksum=sha256:${ESPRESSO_SDK_HELPER_HASH_X86_64} \
25+
https://github.com/EspressoSystems/espresso-network/releases/download/sdks/go/v${ESPRESSO_SDK_VER}/libespresso_crypto_helper-x86_64-unknown-linux-gnu.so \
26+
/lib/
3627
# Go sources
3728
COPY ./go.mod /app/go.mod
3829
COPY ./go.sum /app/go.sum
39-
# Copy rust libs for dynamic linking
40-
COPY --from=rust-builder /libespresso/* /lib
4130
# Warm-up the cache
4231
WORKDIR /app
4332
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build go mod download

espresso/docker/op-stack/Dockerfile

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,25 +39,6 @@ COPY . /app
3939
ARG GIT_COMMIT
4040
ARG GIT_DATE
4141

42-
# Rust builder for Espresso crypto libraries
43-
FROM rust:1.88.0-alpine3.22 AS rust-builder
44-
# TODO: Check the hash of the Espresso GO library when switch to the new one.
45-
# <https://app.asana.com/1/1208976916964769/project/1209392461754458/task/1210755885228839?focus=true>
46-
ARG ESPRESSO_NETWORK_GO_VER=0.0.34
47-
RUN apk add perl make openssl-dev musl-dev gcc
48-
ADD https://github.com/EspressoSystems/espresso-network-go/archive/refs/tags/v$ESPRESSO_NETWORK_GO_VER.tar.gz /source.tgz
49-
RUN tar -oxzf /source.tgz
50-
WORKDIR /espresso-network-go-$ESPRESSO_NETWORK_GO_VER
51-
RUN --mount=type=cache,target=/usr/local/cargo/registry \
52-
--mount=type=cache,target=/usr/local/cargo/git/db \
53-
--mount=type=cache,target=/espresso-network-go/verification/rust/target \
54-
cargo build --release --locked --manifest-path ./verification/rust/Cargo.toml
55-
RUN mkdir -p /libespresso
56-
RUN cp ./verification/rust/target/release/libespresso_crypto_helper.a \
57-
/libespresso/libespresso_crypto_helper-aarch64-unknown-linux-gnu.a
58-
RUN cp ./verification/rust/target/release/libespresso_crypto_helper.a \
59-
/libespresso/libespresso_crypto_helper-x86_64-unknown-linux-gnu.a
60-
6142
# CGO builder for components that need Espresso crypto linking
6243
FROM alpine:3.22 AS op-cgo-builder
6344
# Install dependencies
@@ -70,11 +51,19 @@ RUN case $(uname -m) in \
7051
esac && \
7152
curl -L https://github.com/casey/just/releases/download/$(yq '.tools.just' mise.toml)/just-$(yq '.tools.just' mise.toml)-$JUST_ARCH-unknown-linux-musl.tar.gz | \
7253
tar xz -C /usr/local/bin just
54+
# Fetch rust libs for dynamic linking
55+
ARG ESPRESSO_SDK_VER=0.3.2
56+
ARG ESPRESSO_SDK_HELPER_HASH_AARCH64=ec6ce7b37edd173206ad338c84a6a771a0e9dc8b184081af7440ebfc0c531a71
57+
ARG ESPRESSO_SDK_HELPER_HASH_X86_64=49c50949ec1acf52107cb190c90911e05cc9c4e9d72dd7455496163443760b92
58+
ADD --checksum=sha256:${ESPRESSO_SDK_HELPER_HASH_AARCH64} \
59+
https://github.com/EspressoSystems/espresso-network/releases/download/sdks/go/v${ESPRESSO_SDK_VER}/libespresso_crypto_helper-aarch64-unknown-linux-gnu.so \
60+
/lib/
61+
ADD --checksum=sha256:${ESPRESSO_SDK_HELPER_HASH_X86_64} \
62+
https://github.com/EspressoSystems/espresso-network/releases/download/sdks/go/v${ESPRESSO_SDK_VER}/libespresso_crypto_helper-x86_64-unknown-linux-gnu.so \
63+
/lib/
7364
# Go sources
7465
COPY ./go.mod /app/go.mod
7566
COPY ./go.sum /app/go.sum
76-
# Copy rust libs for dynamic linking
77-
COPY --from=rust-builder /libespresso/* /lib
7867
# Warm-up the cache
7968
WORKDIR /app
8069
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build go mod download

espresso/environment/12_enforce_majority_rule_test.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import (
55
"math/big"
66
"net/http"
77
"net/http/httptest"
8+
"strings"
89
"testing"
910
"time"
1011

12+
"github.com/coder/websocket"
1113
env "github.com/ethereum-optimism/optimism/espresso/environment"
1214
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
1315
"github.com/ethereum-optimism/optimism/op-e2e/system/e2esys"
@@ -24,16 +26,26 @@ const NO_ERROR_EXPECTED = false
2426
// @param numBadUrls N as mentioned in the above description
2527
// @param expectedError if set to true, we expect a timeout error as the L2 cannot make progress. Otherwise, we expect no error at all.
2628
func runWithMultiClient(t *testing.T, numGoodUrls int, numBadUrls int, expectedError bool) {
29+
ctx, cancel := context.WithCancel(context.Background())
30+
defer cancel()
2731

2832
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29-
http.Error(w, "Hello", http.StatusOK)
33+
if strings.Contains(r.URL.Path, "stream") {
34+
conn, err := websocket.Accept(w, r, &websocket.AcceptOptions{})
35+
require.NoError(t, err)
36+
37+
defer conn.Close(websocket.StatusGoingAway, "Bye")
38+
39+
err = conn.Write(ctx, websocket.MessageText, []byte("Hello"))
40+
require.NoError(t, err)
41+
42+
} else {
43+
http.Error(w, "Hello", http.StatusOK)
44+
}
3045
}))
3146

3247
badServerUrl := server.URL
3348

34-
ctx, cancel := context.WithCancel(context.Background())
35-
defer cancel()
36-
3749
launcher := new(env.EspressoDevNodeLauncherDocker)
3850

3951
system, devNode, err := launcher.StartE2eDevnet(ctx, t, env.SetEspressoUrls(numGoodUrls, numBadUrls, badServerUrl))
@@ -57,7 +69,7 @@ func runWithMultiClient(t *testing.T, numGoodUrls int, numBadUrls int, expectedE
5769
blockNumber := int64(2)
5870

5971
// Check the caff node can/cannot make progress
60-
_, err = geth.WaitForBlockToBeSafe(big.NewInt(blockNumber), caffClient, 30*time.Second)
72+
_, err = geth.WaitForBlockToBeSafe(big.NewInt(blockNumber), caffClient, 60*time.Second)
6173

6274
if expectedError {
6375
require.Error(t, err, "The L2 should not be progressing")
@@ -66,7 +78,7 @@ func runWithMultiClient(t *testing.T, numGoodUrls int, numBadUrls int, expectedE
6678
}
6779

6880
// Check the l2Verif node can/cannot make progress
69-
_, err = geth.WaitForBlockToBeSafe(big.NewInt(blockNumber), l2Verif, 30*time.Second)
81+
_, err = geth.WaitForBlockToBeSafe(big.NewInt(blockNumber), l2Verif, 60*time.Second)
7082
if expectedError {
7183
require.Error(t, err, "The L2 should not be progressing")
7284
} else {

espresso/environment/optitmism_espresso_test_helpers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func init() {
5656

5757
const ESPRESSO_LIGHT_CLIENT_ADDRESS = "0x703848f4c85f18e3acd8196c8ec91eb0b7bd0797"
5858

59-
const ESPRESSO_DEV_NODE_DOCKER_IMAGE = "ghcr.io/espressosystems/espresso-sequencer/espresso-dev-node:release-colorful-snake"
59+
const ESPRESSO_DEV_NODE_DOCKER_IMAGE = "ghcr.io/espressosystems/espresso-sequencer/espresso-dev-node:release-fix-cors"
6060

6161
// This is the mnemonic that we use to create the private key for deploying
6262
// contacts on the L1

espresso/environment/query_service_intercept.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@ package environment
22

33
import (
44
"bytes"
5+
"context"
56
"encoding/json"
67
"io"
78
"net/http"
89
"net/http/httptest"
910
"net/url"
11+
"regexp"
12+
"time"
1013

1114
espressoTaggedBase64 "github.com/EspressoSystems/espresso-network/sdks/go/tagged-base64"
1215
espressoCommon "github.com/EspressoSystems/espresso-network/sdks/go/types"
16+
"github.com/coder/websocket"
1317
"github.com/ethereum-optimism/optimism/op-batcher/batcher"
1418
"github.com/ethereum-optimism/optimism/op-e2e/system/e2esys"
1519
)
@@ -88,6 +92,13 @@ type proxyRequest struct {
8892

8993
// ServeHTTP implements http.Handler
9094
func (p *proxyRequest) ServeHTTP(w http.ResponseWriter, r *http.Request) {
95+
// Check if this is a websocket stream request
96+
if isWebSocketStreamRequest(r) {
97+
p.proxyWebSocket(w, r)
98+
return
99+
}
100+
101+
// Handle regular HTTP requests
91102
defer r.Body.Close()
92103
buf := new(bytes.Buffer)
93104
if _, err := io.Copy(buf, r.Body); err != nil && err != io.EOF {
@@ -135,6 +146,82 @@ func (p *proxyRequest) ServeHTTP(w http.ResponseWriter, r *http.Request) {
135146
}
136147
}
137148

149+
// proxyWebSocket handles websocket upgrade and proxying
150+
func (p *proxyRequest) proxyWebSocket(w http.ResponseWriter, r *http.Request) {
151+
// Accept the websocket connection from the client
152+
clientConn, err := websocket.Accept(w, r, &websocket.AcceptOptions{
153+
InsecureSkipVerify: true,
154+
})
155+
if err != nil {
156+
http.Error(w, err.Error(), http.StatusInternalServerError)
157+
return
158+
}
159+
defer clientConn.Close(websocket.StatusInternalError, "proxy error")
160+
161+
// Create websocket URL for the backend
162+
backendURL := p.baseURL
163+
if backendURL.Scheme == "https" {
164+
backendURL.Scheme = "wss"
165+
} else {
166+
backendURL.Scheme = "ws"
167+
}
168+
backendURL.Path = r.URL.Path
169+
backendURL.RawQuery = r.URL.RawQuery
170+
171+
// Connect to the backend websocket
172+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
173+
defer cancel()
174+
175+
//nolint:bodyclose // Not applicable to coder/websocket. From the websocket.Dial docs: "You never need to close resp.Body yourself."
176+
backendConn, _, err := websocket.Dial(ctx, backendURL.String(), &websocket.DialOptions{})
177+
if err != nil {
178+
clientConn.Close(websocket.StatusInternalError, "backend connection failed")
179+
return
180+
}
181+
defer backendConn.Close(websocket.StatusNormalClosure, "")
182+
183+
// Proxy messages bidirectionally
184+
ctx, cancel = context.WithCancel(context.Background())
185+
defer cancel()
186+
187+
// Client to backend
188+
go func() {
189+
defer cancel()
190+
for {
191+
msgType, data, err := clientConn.Read(ctx)
192+
if err != nil {
193+
return
194+
}
195+
err = backendConn.Write(ctx, msgType, data)
196+
if err != nil {
197+
return
198+
}
199+
}
200+
}()
201+
202+
// Backend to client
203+
go func() {
204+
defer cancel()
205+
for {
206+
msgType, data, err := backendConn.Read(ctx)
207+
if err != nil {
208+
return
209+
}
210+
err = clientConn.Write(ctx, msgType, data)
211+
if err != nil {
212+
return
213+
}
214+
}
215+
}()
216+
217+
// Wait until context is cancelled (one of the goroutines finished)
218+
<-ctx.Done()
219+
220+
// Close connections gracefully
221+
clientConn.Close(websocket.StatusNormalClosure, "")
222+
backendConn.Close(websocket.StatusNormalClosure, "")
223+
}
224+
138225
// fakeSubmitTransactionSuccess is a simple HTTP handler that simulates a
139226
// successful transaction submission by returning a fake commit hash.
140227
type fakeSubmitTransactionSuccess struct{}
@@ -304,6 +391,13 @@ func isSubmitTransactionRequest(r *http.Request) bool {
304391
requestMatchesPath(r, http.MethodPost, stringEquals("/v0/submit/submit"))
305392
}
306393

394+
// isWebSocketStreamRequest checks if the request is a websocket request
395+
// matching the pattern "vN/stream/*" where N is an integer.
396+
func isWebSocketStreamRequest(r *http.Request) bool {
397+
matched, _ := regexp.MatchString(`/stream/`, r.URL.Path)
398+
return matched
399+
}
400+
307401
// DecideHowToHandleRequest implements InterceptHandlerDecider
308402
func (d *randomRollFakeSubmitTransactionSuccess) DecideHowToHandleRequest(w http.ResponseWriter, r *http.Request) InterceptHandleDecision {
309403
if isSubmitTransactionRequest(r) {

0 commit comments

Comments
 (0)