Skip to content

Commit 5dd0fe2

Browse files
authored
Merge pull request #23 from node-real/op-node-request-coordinator
feat: coordinator_requestBuildingBlock
2 parents 2c4566e + b0856b3 commit 5dd0fe2

9 files changed

Lines changed: 148 additions & 17 deletions

File tree

op-e2e/actions/l2_sequencer.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, eng L2API, c
4646
l1OriginSelector := &MockL1OriginSelector{
4747
actual: driver.NewL1OriginSelector(log, cfg, seqConfDepthL1),
4848
}
49+
var coordinatorClient *rollup.CoordinatorClient
4950
return &L2Sequencer{
5051
L2Verifier: *ver,
51-
sequencer: driver.NewSequencer(log, cfg, ver.derivation, attrBuilder, l1OriginSelector, metrics.NoopMetrics),
52+
sequencer: driver.NewSequencer(log, cfg, ver.derivation, coordinatorClient, attrBuilder, l1OriginSelector, metrics.NoopMetrics),
5253
mockL1OriginSelector: l1OriginSelector,
5354
failL2GossipUnsafeBlock: nil,
5455
}

op-node/flags/flags.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,24 @@ var (
207207
EnvVar: prefixEnvVar("L2_BACKUP_UNSAFE_SYNC_RPC_TRUST_RPC"),
208208
Required: false,
209209
}
210+
CoordinatorEnabledFlag = cli.BoolFlag{
211+
Name: "coordinator.enabled",
212+
Usage: "Enable the external coordinator mode",
213+
EnvVar: prefixEnvVar("COORDINATOR_ENABLED"),
214+
Required: false,
215+
}
216+
CoordinatorAddrFlag = cli.StringFlag{
217+
Name: "coordinator.addr",
218+
Usage: "Coordinator listening address",
219+
EnvVar: prefixEnvVar("COORDINATOR_ADDR"),
220+
Required: false,
221+
}
222+
CoordinatorSequencerIdFlag = cli.StringFlag{
223+
Name: "coordinator.sequencer-id",
224+
Usage: "the sequencer id configured in the coordinator",
225+
EnvVar: prefixEnvVar("COORDINATOR_SEQUENCER_ID"),
226+
Required: false,
227+
}
210228
)
211229

212230
var requiredFlags = []cli.Flag{
@@ -244,6 +262,9 @@ var optionalFlags = []cli.Flag{
244262
HeartbeatURLFlag,
245263
BackupL2UnsafeSyncRPC,
246264
BackupL2UnsafeSyncRPCTrustRPC,
265+
CoordinatorEnabledFlag,
266+
CoordinatorAddrFlag,
267+
CoordinatorSequencerIdFlag,
247268
}
248269

249270
// Flags contains the list of configuration options available to the binary.

op-node/node/client.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,33 @@ type L1EndpointSetup interface {
3636
Check() error
3737
}
3838

39+
type CoordinatorConfig struct {
40+
// Enabled is true when the driver should request permission from op-coordinator before building new blocks.
41+
// Default is false.
42+
Enabled bool
43+
44+
// Identifier of the sequencer node to request blocks from.
45+
// It must be unique and same as the name of the sequencer node configured in the Coordinator service.
46+
SequencerId string
47+
48+
// Address of the Coordinator JSON-RPC endpoint to use (opcoordinator namespace required).
49+
CoordinatorAddr string
50+
}
51+
52+
func (cfg *CoordinatorConfig) Check() error {
53+
if !cfg.Enabled {
54+
return nil
55+
}
56+
if cfg.SequencerId == "" {
57+
return errors.New("empty Sequencer Id")
58+
}
59+
if cfg.CoordinatorAddr == "" {
60+
return errors.New("empty Coordinator Address")
61+
}
62+
63+
return nil
64+
}
65+
3966
type L2EndpointConfig struct {
4067
L2EngineAddr string // Address of L2 Engine JSON-RPC endpoint to use (engine and eth namespace required)
4168

op-node/node/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ type Config struct {
1717
L2 L2EndpointSetup
1818
L2Sync L2SyncEndpointSetup
1919

20+
Coordinator CoordinatorConfig
21+
2022
Driver driver.Config
2123

2224
Rollup rollup.Config
@@ -86,6 +88,9 @@ func (cfg *Config) Check() error {
8688
if err := cfg.Rollup.Check(); err != nil {
8789
return fmt.Errorf("rollup config error: %w", err)
8890
}
91+
if err := cfg.Coordinator.Check(); err != nil {
92+
return fmt.Errorf("coordinator config error: %w", err)
93+
}
8994
if err := cfg.Metrics.Check(); err != nil {
9095
return fmt.Errorf("metrics config error: %w", err)
9196
}

op-node/node/node.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/ethereum-optimism/optimism/op-node/eth"
1818
"github.com/ethereum-optimism/optimism/op-node/metrics"
1919
"github.com/ethereum-optimism/optimism/op-node/p2p"
20+
"github.com/ethereum-optimism/optimism/op-node/rollup"
2021
"github.com/ethereum-optimism/optimism/op-node/rollup/driver"
2122
"github.com/ethereum-optimism/optimism/op-node/sources"
2223
)
@@ -40,6 +41,8 @@ type OpNode struct {
4041
tracer Tracer // tracer to get events for testing/debugging
4142
runCfg *RuntimeConfig // runtime configurables
4243

44+
coordinatorClient *rollup.CoordinatorClient // Coordinator RPC
45+
4346
// some resources cannot be stopped directly, like the p2p gossipsub router (not our design),
4447
// and depend on this ctx to be closed.
4548
resourcesCtx context.Context
@@ -81,6 +84,9 @@ func (n *OpNode) init(ctx context.Context, cfg *Config, snapshotLog log.Logger)
8184
if err := n.initL1(ctx, cfg); err != nil {
8285
return err
8386
}
87+
if err := n.initOpCoordinator(ctx, cfg); err != nil {
88+
return err
89+
}
8490
if err := n.initRuntimeConfig(ctx, cfg); err != nil {
8591
return err
8692
}
@@ -115,6 +121,22 @@ func (n *OpNode) initTracer(ctx context.Context, cfg *Config) error {
115121
return nil
116122
}
117123

124+
func (n *OpNode) initOpCoordinator(ctx context.Context, cfg *Config) error {
125+
if err := cfg.Coordinator.Check(); err != nil {
126+
return fmt.Errorf("coordinator config is invalid: %w", err)
127+
}
128+
129+
if cfg.Coordinator.Enabled {
130+
var err error
131+
n.coordinatorClient, err = rollup.NewCoordinatorClient(cfg.Coordinator.CoordinatorAddr, cfg.Coordinator.SequencerId)
132+
if err != nil {
133+
return fmt.Errorf("failed to get Coordinator RPC client: %w", err)
134+
}
135+
}
136+
137+
return nil
138+
}
139+
118140
func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
119141
l1Node, rpcCfg, err := cfg.L1.Setup(ctx, n.log, &cfg.Rollup)
120142
if err != nil {
@@ -199,7 +221,7 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger
199221
return err
200222
}
201223

202-
n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n, n, n.log, snapshotLog, n.metrics)
224+
n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n, n.coordinatorClient, n, n.log, snapshotLog, n.metrics)
203225

204226
return nil
205227
}

op-node/rollup/coordinator.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package rollup
2+
3+
import (
4+
"github.com/ethereum/go-ethereum/log"
5+
"github.com/ethereum/go-ethereum/rpc"
6+
)
7+
8+
type CoordinatorClient struct {
9+
sequencerId string
10+
rpc *rpc.Client
11+
}
12+
13+
func NewCoordinatorClient(url string, sequencerId string) (*CoordinatorClient, error) {
14+
rpc, err := rpc.Dial(url)
15+
if err != nil {
16+
return nil, err
17+
}
18+
return &CoordinatorClient{
19+
sequencerId: sequencerId,
20+
rpc: rpc,
21+
}, nil
22+
}
23+
24+
func (c *CoordinatorClient) RequestBuildingBlock() bool {
25+
var respErr error
26+
err := c.rpc.Call(respErr, "coordinator_requestBuildingBlock", c.sequencerId)
27+
if err != nil {
28+
log.Warn("Failed to call coordinator_requestBuildingBlock", "error", err)
29+
return false
30+
}
31+
if respErr != nil {
32+
log.Warn("coordinator_requestBuildingBlock refused request", "error", respErr)
33+
return false
34+
}
35+
return true
36+
}

op-node/rollup/driver/driver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ type AltSync interface {
102102
}
103103

104104
// NewDriver composes an events handler that tracks L1 state, triggers L2 derivation, and optionally sequences new L2 blocks.
105-
func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, altSync AltSync, network Network, log log.Logger, snapshotLog log.Logger, metrics Metrics) *Driver {
105+
func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, altSync AltSync, coordinatorClient *rollup.CoordinatorClient, network Network, log log.Logger, snapshotLog log.Logger, metrics Metrics) *Driver {
106106
l1State := NewL1State(log, metrics)
107107
sequencerConfDepth := NewConfDepth(driverCfg.SequencerConfDepth, l1State.L1Head, l1)
108108
findL1Origin := NewL1OriginSelector(log, cfg, sequencerConfDepth)
@@ -111,7 +111,7 @@ func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, al
111111
attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, l2)
112112
engine := derivationPipeline
113113
meteredEngine := NewMeteredEngine(cfg, engine, metrics, log)
114-
sequencer := NewSequencer(log, cfg, meteredEngine, attrBuilder, findL1Origin, metrics)
114+
sequencer := NewSequencer(log, cfg, meteredEngine, coordinatorClient, attrBuilder, findL1Origin, metrics)
115115

116116
return &Driver{
117117
l1State: l1State,

op-node/rollup/driver/sequencer.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ type Sequencer struct {
3434
log log.Logger
3535
config *rollup.Config
3636

37+
coordinatorClient *rollup.CoordinatorClient
38+
3739
engine derive.ResettableEngineControl
3840

3941
attrBuilder derive.AttributesBuilder
@@ -47,20 +49,27 @@ type Sequencer struct {
4749
nextAction time.Time
4850
}
4951

50-
func NewSequencer(log log.Logger, cfg *rollup.Config, engine derive.ResettableEngineControl, attributesBuilder derive.AttributesBuilder, l1OriginSelector L1OriginSelectorIface, metrics SequencerMetrics) *Sequencer {
52+
func NewSequencer(log log.Logger, cfg *rollup.Config, engine derive.ResettableEngineControl, coordinatorClient *rollup.CoordinatorClient, attributesBuilder derive.AttributesBuilder, l1OriginSelector L1OriginSelectorIface, metrics SequencerMetrics) *Sequencer {
5153
return &Sequencer{
52-
log: log,
53-
config: cfg,
54-
engine: engine,
55-
timeNow: time.Now,
56-
attrBuilder: attributesBuilder,
57-
l1OriginSelector: l1OriginSelector,
58-
metrics: metrics,
54+
log: log,
55+
config: cfg,
56+
engine: engine,
57+
coordinatorClient: coordinatorClient,
58+
timeNow: time.Now,
59+
attrBuilder: attributesBuilder,
60+
l1OriginSelector: l1OriginSelector,
61+
metrics: metrics,
5962
}
6063
}
6164

6265
// StartBuildingBlock initiates a block building job on top of the given L2 head, safe and finalized blocks, and using the provided l1Origin.
6366
func (d *Sequencer) StartBuildingBlock(ctx context.Context) error {
67+
// External coordinator mode (configured by --coordinator.enabled=true): Sequencer requests permission to build
68+
// new blocks from the external coordinator by calling RequestBuildingBlock().
69+
if d.coordinatorClient != nil && !d.coordinatorClient.RequestBuildingBlock() {
70+
return errors.New("failed to request permission for building block from coordinator")
71+
}
72+
6473
l2Head := d.engine.UnsafeL2Head()
6574

6675
// Figure out which L1 origin block we're going to be building on top of.

op-node/service.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,15 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
5656
}
5757

5858
l2SyncEndpoint := NewL2SyncEndpointConfig(ctx)
59+
coordinator := NewCoordinatorConfig(ctx)
5960

6061
cfg := &node.Config{
61-
L1: l1Endpoint,
62-
L2: l2Endpoint,
63-
L2Sync: l2SyncEndpoint,
64-
Rollup: *rollupConfig,
65-
Driver: *driverConfig,
62+
L1: l1Endpoint,
63+
L2: l2Endpoint,
64+
L2Sync: l2SyncEndpoint,
65+
Coordinator: *coordinator,
66+
Rollup: *rollupConfig,
67+
Driver: *driverConfig,
6668
RPC: node.RPCConfig{
6769
ListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name),
6870
ListenPort: ctx.GlobalInt(flags.RPCListenPort.Name),
@@ -143,6 +145,14 @@ func NewL2SyncEndpointConfig(ctx *cli.Context) *node.L2SyncEndpointConfig {
143145
}
144146
}
145147

148+
func NewCoordinatorConfig(ctx *cli.Context) *node.CoordinatorConfig {
149+
return &node.CoordinatorConfig{
150+
Enabled: ctx.GlobalBool(flags.CoordinatorEnabledFlag.Name),
151+
CoordinatorAddr: ctx.GlobalString(flags.CoordinatorAddrFlag.Name),
152+
SequencerId: ctx.GlobalString(flags.CoordinatorSequencerIdFlag.Name),
153+
}
154+
}
155+
146156
func NewDriverConfig(ctx *cli.Context) *driver.Config {
147157
return &driver.Config{
148158
VerifierConfDepth: ctx.GlobalUint64(flags.VerifierL1Confs.Name),

0 commit comments

Comments
 (0)