Skip to content

Commit 58c2d52

Browse files
committed
feat: implement flashblocks monitoring
1 parent 1efaf3f commit 58c2d52

File tree

11 files changed

+922
-142
lines changed

11 files changed

+922
-142
lines changed

cmd/serve.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func CommandServe(cfg *config.Config) *cli.Command {
2323
l1RpcFallback := &cli.StringSlice{}
2424
l1WalletAddresses := &cli.StringSlice{}
2525
l2RpcFallback := &cli.StringSlice{}
26+
l2FlashblocksPrivateStreams := &cli.StringSlice{}
2627
l2WalletAddresses := &cli.StringSlice{}
2728

2829
dirFlags := []cli.Flag{
@@ -195,6 +196,31 @@ func CommandServe(cfg *config.Config) *cli.Command {
195196
Value: "incrementFlashblockNumber()",
196197
},
197198

199+
&cli.Int64Flag{
200+
Category: strings.ToUpper(categoryL2),
201+
Destination: &cfg.L2.MonitorFlashblocksMaxWsMessageSizeKb,
202+
EnvVars: []string{envPrefix + strings.ToUpper(categoryL2) + "_MONITOR_FLASHBLOCKS_MAX_WS_MESSAGE_SIZE_KB"},
203+
Name: categoryL2 + "-monitor-flashblocks-max-ws-message-size-kb",
204+
Usage: "max size (in kb) of l2 builder flashblocks ws messages",
205+
Value: 256,
206+
},
207+
208+
&cli.StringSliceFlag{ // --l2-monitor-flashblocks-private-stream
209+
Category: strings.ToUpper(categoryL2),
210+
Destination: l2FlashblocksPrivateStreams,
211+
EnvVars: []string{envPrefix + strings.ToUpper(categoryL2) + "_MONITOR_FLASHBLOCKS_PRIVATE_STREAMS"},
212+
Name: categoryL2 + "-monitor-flashblocks-private-stream",
213+
Usage: "private websocket stream(s) of l2 builder flashblocks",
214+
},
215+
216+
&cli.StringFlag{ // --l2-monitor-flashblocks-public-stream
217+
Category: strings.ToUpper(categoryL2),
218+
Destination: &cfg.L2.MonitorFlashblocksPublicStream,
219+
EnvVars: []string{envPrefix + strings.ToUpper(categoryL2) + "_MONITOR_FLASHBLOCKS_PUBLIC_STREAM"},
220+
Name: categoryL2 + "-monitor-flashblocks-public-stream",
221+
Usage: "public websocket stream of l2 builder flashblocks",
222+
},
223+
198224
&cli.BoolFlag{ // --l2-monitor-tx-receipts
199225
Category: strings.ToUpper(categoryL2),
200226
Destination: &cfg.L2.MonitorTxReceipts,
@@ -354,6 +380,18 @@ func CommandServe(cfg *config.Config) *cli.Command {
354380
{
355381
cfg.L2.RpcFallback = l2RpcFallback.Value()
356382

383+
_flashblocksPrivateStreams := make(map[string]string, len(l2FlashblocksPrivateStreams.Value()))
384+
for _, wa := range l2FlashblocksPrivateStreams.Value() {
385+
parts := strings.Split(wa, "=")
386+
if len(parts) != 2 {
387+
return fmt.Errorf("invalid private flashblocks stream (must be like `name=ws://f.q.d.n:1111`): %s", wa)
388+
}
389+
name := strings.TrimSpace(parts[0])
390+
url := strings.TrimSpace(parts[1])
391+
_flashblocksPrivateStreams[name] = url
392+
}
393+
cfg.L2.MonitorFlashblocksPrivateStreams = _flashblocksPrivateStreams
394+
357395
_walletAddresses := make(map[string]string, len(l2WalletAddresses.Value()))
358396
for _, wa := range l2WalletAddresses.Value() {
359397
parts := strings.Split(wa, "=")

config/l2.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ type L2 struct {
2929
MonitorBuilderPolicyContractFunctionSignature string `yaml:"monitor_builder_policy_contract_function_signature"`
3030
MonitorFlashblockNumberContract string `yaml:"monitor_builder_flashblock_number_contract"`
3131
MonitorFlashblockNumberContractFunctionSignature string `yaml:"monitor_builder_flashblock_number_contract_function_signature"`
32+
MonitorFlashblocksMaxWsMessageSizeKb int64 `yaml:"monitor_flashblocks_max_ws_message_size_kb"`
33+
MonitorFlashblocksPrivateStreams map[string]string `yaml:"monitor_flashblocks_private_streams"`
34+
MonitorFlashblocksPublicStream string `yaml:"monitor_flashblocks_public_stream"`
3235
MonitorFlashtestationRegistryContract string `yaml:"monitor_flashtestation_registry_contract"`
3336
MonitorFlashtestationRegistryEventSignature string `yaml:"monitor_flashtestation_registry_event_signature"`
3437
MonitorFlashtestationRegistryFunctionSignature string `yaml:"monitor_flashtestation_registry_function_signature"`
@@ -46,6 +49,9 @@ var (
4649
errL2InvalidBuilderAddress = errors.New("invalid l2 builder address")
4750
errL2InvalidBuilderPolicyContact = errors.New("invalid l2 builder policy contract address")
4851
errL2InvalidFlashblockNumberContact = errors.New("invalid l2 flashblocks number contract address")
52+
errL2InvalidFlashblocksMaxWsMessageSizeKb = errors.New("invalid l2 flashblocks max ws message size")
53+
errL2InvalidFlashblocksPrivateStream = errors.New("invalid l2 private flashblocks stream url")
54+
errL2InvalidFlashblocksPublicStream = errors.New("invalid l2 public flashblocks stream url")
4955
errL2InvalidFlashtestationsRegistryContact = errors.New("invalid l2 flashtestations registry contract address")
5056
errL2InvalidRpc = errors.New("invalid l2 rpc url")
5157
errL2InvalidRpcFallback = errors.New("invalid l2 fallback rpc url")
@@ -168,6 +174,39 @@ func (cfg *L2) Validate() error {
168174
}
169175
}
170176

177+
{ // monitor_flashblocks_max_ws_message_size_kb
178+
if cfg.MonitorFlashblocksMaxWsMessageSizeKb < 16 || cfg.MonitorFlashblocksMaxWsMessageSizeKb > 1024 {
179+
errs = append(errs, fmt.Errorf("%w: must be within [16..1024] range: %d",
180+
errL2InvalidFlashblocksMaxWsMessageSizeKb,
181+
cfg.MonitorFlashblocksMaxWsMessageSizeKb,
182+
))
183+
}
184+
}
185+
186+
{ // monitor_flashblocks_private_streams
187+
for _, flashblocks := range cfg.MonitorFlashblocksPrivateStreams {
188+
if _, err := url.Parse(flashblocks); err != nil {
189+
errs = append(errs, fmt.Errorf("%w: %s: %w",
190+
errL2InvalidFlashblocksPrivateStream,
191+
flashblocks,
192+
err,
193+
))
194+
}
195+
}
196+
}
197+
198+
{ // monitor_flashblocks_public_stream
199+
if cfg.MonitorFlashblocksPublicStream != "" {
200+
if _, err := url.Parse(cfg.MonitorFlashblocksPublicStream); err != nil {
201+
errs = append(errs, fmt.Errorf("%w: %s: %w",
202+
errL2InvalidFlashblocksPublicStream,
203+
cfg.MonitorFlashblocksPublicStream,
204+
err,
205+
))
206+
}
207+
}
208+
}
209+
171210
{ // monitor_wallet_address
172211
for _, wa := range cfg.MonitorWalletAddresses {
173212
_addr, err := ethcommon.ParseHexOrString(wa)

go.mod

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,79 +3,81 @@ module github.com/flashbots/chain-monitor
33
go 1.24.0
44

55
require (
6-
github.com/ethereum/go-ethereum v1.16.1
6+
github.com/andybalholm/brotli v1.2.0
7+
github.com/coder/websocket v1.8.14
8+
github.com/ethereum/go-ethereum v1.16.7
79
github.com/google/uuid v1.6.0
8-
github.com/prometheus/client_golang v1.22.0
9-
github.com/stretchr/testify v1.10.0
10+
github.com/prometheus/client_golang v1.23.2
11+
github.com/stretchr/testify v1.11.1
1012
github.com/urfave/cli/v2 v2.27.7
11-
go.opentelemetry.io/otel v1.37.0
12-
go.opentelemetry.io/otel/exporters/prometheus v0.59.0
13-
go.opentelemetry.io/otel/metric v1.37.0
14-
go.opentelemetry.io/otel/sdk v1.37.0
15-
go.opentelemetry.io/otel/sdk/metric v1.37.0
16-
go.uber.org/zap v1.27.0
17-
golang.org/x/crypto v0.40.0
13+
go.opentelemetry.io/otel v1.38.0
14+
go.opentelemetry.io/otel/exporters/prometheus v0.60.0
15+
go.opentelemetry.io/otel/metric v1.38.0
16+
go.opentelemetry.io/otel/sdk v1.38.0
17+
go.opentelemetry.io/otel/sdk/metric v1.38.0
18+
go.uber.org/zap v1.27.1
19+
golang.org/x/crypto v0.45.0
1820
)
1921

20-
replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101511.1
22+
replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101603.5
2123

22-
replace github.com/ethereum/go-ethereum/common => github.com/ethereum-optimism/op-geth/common v1.101511.1
24+
replace github.com/ethereum/go-ethereum/common => github.com/ethereum-optimism/op-geth/common v1.101603.5
2325

24-
replace github.com/ethereum/go-ethereum/core/types => github.com/ethereum-optimism/op-geth/core/types v1.101511.1
26+
replace github.com/ethereum/go-ethereum/core/types => github.com/ethereum-optimism/op-geth/core/types v1.101603.5
2527

2628
require (
2729
github.com/BurntSushi/toml v1.5.0 // indirect
2830
github.com/Microsoft/go-winio v0.6.2 // indirect
2931
github.com/beorn7/perks v1.0.1 // indirect
30-
github.com/bits-and-blooms/bitset v1.22.0 // indirect
32+
github.com/bits-and-blooms/bitset v1.24.4 // indirect
3133
github.com/cespare/xxhash/v2 v2.3.0 // indirect
32-
github.com/cockroachdb/pebble v1.1.5 // indirect
33-
github.com/consensys/gnark-crypto v0.18.0 // indirect
34+
github.com/consensys/gnark-crypto v0.19.2 // indirect
3435
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
35-
github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect
36+
github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect
3637
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
3738
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
3839
github.com/deckarep/golang-set/v2 v2.8.0 // indirect
3940
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
40-
github.com/ethereum/c-kzg-4844/v2 v2.1.1 // indirect
41+
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
4142
github.com/ethereum/go-verkle v0.2.2 // indirect
4243
github.com/go-logr/logr v1.4.3 // indirect
4344
github.com/go-logr/stdr v1.2.2 // indirect
4445
github.com/go-ole/go-ole v1.3.0 // indirect
4546
github.com/gorilla/websocket v1.5.3 // indirect
46-
github.com/hashicorp/go-bexpr v0.1.14 // indirect
47+
github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
48+
github.com/hashicorp/go-bexpr v0.1.15 // indirect
4749
github.com/holiman/uint256 v1.3.2 // indirect
48-
github.com/klauspost/compress v1.18.0 // indirect
49-
github.com/mattn/go-runewidth v0.0.16 // indirect
50+
github.com/klauspost/compress v1.18.1 // indirect
51+
github.com/mattn/go-runewidth v0.0.19 // indirect
5052
github.com/mitchellh/mapstructure v1.5.0 // indirect
5153
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
5254
github.com/naoina/go-stringutil v0.1.0 // indirect
5355
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect
5456
github.com/pion/dtls/v2 v2.2.12 // indirect
5557
github.com/pion/transport/v2 v2.2.10 // indirect
56-
github.com/pion/transport/v3 v3.0.7 // indirect
58+
github.com/pion/transport/v3 v3.1.1 // indirect
5759
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
5860
github.com/prometheus/client_model v0.6.2 // indirect
59-
github.com/prometheus/common v0.65.0 // indirect
60-
github.com/prometheus/procfs v0.17.0 // indirect
61-
github.com/rivo/uniseg v0.4.7 // indirect
61+
github.com/prometheus/common v0.67.4 // indirect
62+
github.com/prometheus/otlptranslator v0.0.2 // indirect
63+
github.com/prometheus/procfs v0.19.2 // indirect
6264
github.com/rs/cors v1.11.1 // indirect
6365
github.com/russross/blackfriday/v2 v2.1.0 // indirect
6466
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
65-
github.com/supranational/blst v0.3.15 // indirect
67+
github.com/supranational/blst v0.3.16 // indirect
6668
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
67-
github.com/tklauser/go-sysconf v0.3.15 // indirect
68-
github.com/tklauser/numcpus v0.10.0 // indirect
69-
github.com/wlynxg/anet v0.0.5 // indirect
69+
github.com/tklauser/go-sysconf v0.3.16 // indirect
70+
github.com/tklauser/numcpus v0.11.0 // indirect
7071
github.com/xrash/smetrics v0.0.0-20250705151800-55b8f293f342 // indirect
7172
github.com/yusufpapurcu/wmi v1.2.4 // indirect
72-
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
73-
go.opentelemetry.io/otel/trace v1.37.0 // indirect
73+
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
74+
go.opentelemetry.io/otel/trace v1.38.0 // indirect
7475
go.uber.org/multierr v1.11.0 // indirect
75-
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc // indirect
76-
golang.org/x/sync v0.16.0 // indirect
77-
golang.org/x/sys v0.34.0 // indirect
78-
golang.org/x/time v0.12.0 // indirect
79-
google.golang.org/protobuf v1.36.6 // indirect
76+
go.yaml.in/yaml/v2 v2.4.3 // indirect
77+
golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 // indirect
78+
golang.org/x/sync v0.18.0 // indirect
79+
golang.org/x/sys v0.38.0 // indirect
80+
golang.org/x/time v0.14.0 // indirect
81+
google.golang.org/protobuf v1.36.10 // indirect
8082
gopkg.in/yaml.v3 v3.0.1 // indirect
8183
)

0 commit comments

Comments
 (0)