Skip to content

Commit 2936d73

Browse files
committed
sysgo: l1 geth subprocess support
1 parent bd592e3 commit 2936d73

File tree

22 files changed

+596
-76
lines changed

22 files changed

+596
-76
lines changed

op-devstack/stack/match/labels.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const (
2020
type Vendor string
2121

2222
const (
23+
Geth Vendor = "geth"
2324
OpReth Vendor = "op-reth"
2425
OpGeth Vendor = "op-geth"
2526
Proxyd Vendor = "proxyd"

op-devstack/sysgo/engine_client.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package sysgo
2+
3+
import (
4+
"context"
5+
6+
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
7+
"github.com/ethereum/go-ethereum/beacon/engine"
8+
"github.com/ethereum/go-ethereum/common"
9+
"github.com/ethereum/go-ethereum/common/hexutil"
10+
gn "github.com/ethereum/go-ethereum/node"
11+
"github.com/ethereum/go-ethereum/rpc"
12+
gethrpc "github.com/ethereum/go-ethereum/rpc"
13+
)
14+
15+
type engineClient struct {
16+
inner *rpc.Client
17+
}
18+
19+
func dialEngine(ctx context.Context, endpoint string, jwtSecret [32]byte) (*engineClient, error) {
20+
engineCl, err := gethrpc.DialOptions(ctx, endpoint, rpc.WithHTTPAuth(gn.NewJWTAuth(jwtSecret)))
21+
if err != nil {
22+
return nil, err
23+
}
24+
return &engineClient{
25+
inner: engineCl,
26+
}, nil
27+
}
28+
29+
var _ geth.EngineAPI = (*engineClient)(nil)
30+
31+
func (e *engineClient) forkchoiceUpdated(fs engine.ForkchoiceStateV1, pa *engine.PayloadAttributes, method string) (engine.ForkChoiceResponse, error) {
32+
var x engine.ForkChoiceResponse
33+
if err := e.inner.CallContext(context.Background(), &x, method, fs, pa); err != nil {
34+
return engine.ForkChoiceResponse{}, err
35+
}
36+
return x, nil
37+
}
38+
39+
func (e *engineClient) ForkchoiceUpdatedV2(fs engine.ForkchoiceStateV1, pa *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
40+
return e.forkchoiceUpdated(fs, pa, "engine_forkchoiceUpdatedV2")
41+
}
42+
43+
func (e *engineClient) ForkchoiceUpdatedV3(fs engine.ForkchoiceStateV1, pa *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
44+
return e.forkchoiceUpdated(fs, pa, "engine_forkchoiceUpdatedV3")
45+
}
46+
47+
func (e *engineClient) getPayload(id engine.PayloadID, method string) (*engine.ExecutionPayloadEnvelope, error) {
48+
var result engine.ExecutionPayloadEnvelope
49+
if err := e.inner.CallContext(context.Background(), &result, method, id); err != nil {
50+
return nil, err
51+
}
52+
return &result, nil
53+
}
54+
55+
func (e *engineClient) GetPayloadV2(id engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
56+
return e.getPayload(id, "engine_getPayloadV2")
57+
}
58+
59+
func (e *engineClient) GetPayloadV3(id engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
60+
return e.getPayload(id, "engine_getPayloadV3")
61+
}
62+
63+
func (e *engineClient) GetPayloadV4(id engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
64+
return e.getPayload(id, "engine_getPayloadV4")
65+
}
66+
67+
func (e *engineClient) NewPayloadV2(data engine.ExecutableData) (engine.PayloadStatusV1, error) {
68+
var result engine.PayloadStatusV1
69+
if err := e.inner.CallContext(context.Background(), &result, "engine_newPayloadV2", data); err != nil {
70+
return engine.PayloadStatusV1{}, err
71+
}
72+
return result, nil
73+
}
74+
75+
func (e *engineClient) NewPayloadV3(data engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
76+
var result engine.PayloadStatusV1
77+
if err := e.inner.CallContext(context.Background(), &result, "engine_newPayloadV3", data, versionedHashes, beaconRoot); err != nil {
78+
return engine.PayloadStatusV1{}, err
79+
}
80+
return result, nil
81+
}
82+
83+
func (e *engineClient) NewPayloadV4(data engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) {
84+
var result engine.PayloadStatusV1
85+
if err := e.inner.CallContext(context.Background(), &result, "engine_newPayloadV4", data, versionedHashes, beaconRoot, executionRequests); err != nil {
86+
return engine.PayloadStatusV1{}, err
87+
}
88+
return result, nil
89+
}

op-devstack/sysgo/faucet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func WithFaucets(l1ELs []stack.L1ELNodeID, l2ELs []stack.L2ELNodeID) stack.Optio
7575
require.True(ok, "need L1 EL for faucet", elID)
7676

7777
faucets[id] = &fconf.FaucetEntry{
78-
ELRPC: endpoint.MustRPC{Value: endpoint.URL(el.userRPC)},
78+
ELRPC: endpoint.MustRPC{Value: endpoint.URL(el.UserRPC())},
7979
ChainID: elID.ChainID(),
8080
TxCfg: fconf.TxManagerConfig{
8181
PrivateKey: funderKeyStr,

op-devstack/sysgo/l1_nodes.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sysgo
22

33
import (
4+
"os"
45
"path/filepath"
56

67
"github.com/ethereum-optimism/optimism/op-devstack/shim"
@@ -12,14 +13,32 @@ import (
1213
"github.com/ethereum-optimism/optimism/op-service/clock"
1314
)
1415

15-
type L1ELNode struct {
16+
type L1ELNode interface {
17+
hydrator
18+
l1ELNode()
19+
UserRPC() string
20+
AuthRPC() string
21+
}
22+
23+
type L1Geth struct {
1624
id stack.L1ELNodeID
1725
userRPC string
26+
authRPC string
1827
l1Geth *geth.GethInstance
1928
blobPath string
2029
}
2130

22-
func (n *L1ELNode) hydrate(system stack.ExtensibleSystem) {
31+
func (*L1Geth) l1ELNode() {}
32+
33+
func (g *L1Geth) UserRPC() string {
34+
return g.userRPC
35+
}
36+
37+
func (g *L1Geth) AuthRPC() string {
38+
return g.authRPC
39+
}
40+
41+
func (n *L1Geth) hydrate(system stack.ExtensibleSystem) {
2342
require := system.T().Require()
2443
rpcCl, err := client.NewRPC(system.T().Ctx(), system.Logger(), n.userRPC, client.WithLazyDial())
2544
require.NoError(err)
@@ -54,7 +73,16 @@ func (n *L1CLNode) hydrate(system stack.ExtensibleSystem) {
5473
l1Net.(stack.ExtensibleL1Network).AddL1CLNode(frontend)
5574
}
5675

76+
const GethExecPathEnvVar = "SYSGO_GETH_EXEC_PATH"
77+
5778
func WithL1Nodes(l1ELID stack.L1ELNodeID, l1CLID stack.L1CLNodeID) stack.Option[*Orchestrator] {
79+
if gethExecPath, ok := os.LookupEnv(GethExecPathEnvVar); ok {
80+
return WithL1NodesSubprocess(l1ELID, l1CLID, gethExecPath)
81+
}
82+
return WithL1NodesInProcess(l1ELID, l1CLID)
83+
}
84+
85+
func WithL1NodesInProcess(l1ELID stack.L1ELNodeID, l1CLID stack.L1CLNodeID) stack.Option[*Orchestrator] {
5886
return stack.AfterDeploy(func(orch *Orchestrator) {
5987
clP := orch.P().WithCtx(stack.ContextWithID(orch.P().Ctx(), l1CLID))
6088
elP := orch.P().WithCtx(stack.ContextWithID(orch.P().Ctx(), l1ELID))
@@ -96,9 +124,10 @@ func WithL1Nodes(l1ELID stack.L1ELNodeID, l1CLID stack.L1CLNodeID) stack.Option[
96124
_ = l1Geth.Close()
97125
})
98126

99-
l1ELNode := &L1ELNode{
127+
l1ELNode := &L1Geth{
100128
id: l1ELID,
101129
userRPC: l1Geth.Node.HTTPEndpoint(),
130+
authRPC: l1Geth.Node.HTTPAuthEndpoint(),
102131
l1Geth: l1Geth,
103132
blobPath: blobPath,
104133
}
@@ -120,7 +149,7 @@ func WithExtL1Nodes(l1ELID stack.L1ELNodeID, l1CLID stack.L1CLNodeID, elRPCEndpo
120149
require := orch.P().Require()
121150

122151
// Create L1 EL node with external RPC
123-
l1ELNode := &L1ELNode{
152+
l1ELNode := &L1Geth{
124153
id: l1ELID,
125154
userRPC: elRPCEndpoint,
126155
}

0 commit comments

Comments
 (0)