Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
require DA endpoint for aggregators
  • Loading branch information
tac0turtle committed Jul 16, 2026
commit b624b73ed156a4840a027041650008e6f8b874ce
3 changes: 0 additions & 3 deletions apps/evm/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ func InitCmd() *cobra.Command {
// we use load in order to parse all the flags
cfg, _ := rollconf.Load(cmd)
cfg.Node.Aggregator = aggregator
if cfg.Node.Aggregator && cfg.DA.Address == "" {
cfg.DA.Address = cfg.EffectiveDAAddress()
}
if err := cfg.Validate(); err != nil {
return fmt.Errorf("error validating config: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion apps/evm/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ var RunCmd = &cobra.Command{

var daClient block.FullDAClient
if nodeConfig.DAEnabled() {
blobClient, err := blobrpc.NewWSClient(cmd.Context(), logger, nodeConfig.EffectiveDAAddress(), nodeConfig.DA.AuthToken, "")
blobClient, err := blobrpc.NewWSClient(cmd.Context(), logger, nodeConfig.DA.Address, nodeConfig.DA.AuthToken, "")
if err != nil {
return fmt.Errorf("failed to create blob client: %w", err)
}
Expand Down
3 changes: 0 additions & 3 deletions apps/testapp/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ func InitCmd() *cobra.Command {
// we use load in order to parse all the flags
cfg, _ := rollconf.Load(cmd)
cfg.Node.Aggregator = aggregator
if cfg.Node.Aggregator && cfg.DA.Address == "" {
cfg.DA.Address = cfg.EffectiveDAAddress()
}
cfg.Node.BlockTime = rollconf.DurationWrapper{Duration: 100 * time.Millisecond}
if err := cfg.Validate(); err != nil {
return fmt.Errorf("error validating config: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion apps/testapp/cmd/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestInitCommand(t *testing.T) {
require.NoError(t, os.WriteFile(passphraseFile, []byte("test"), 0600))

// Set home flag to the test directory
cmd.SetArgs([]string{"init", "--home", dir, "--evnode.node.aggregator", "--evnode.signer.passphrase_file", passphraseFile})
cmd.SetArgs([]string{"init", "--home", dir, "--evnode.node.aggregator", "--evnode.da.address", "http://localhost:7980", "--evnode.signer.passphrase_file", passphraseFile})

// Execute the command
err = cmd.Execute()
Expand Down
2 changes: 1 addition & 1 deletion apps/testapp/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func createSequencer(
return solo.NewSoloSequencer(logger, []byte(genesis.ChainID), executor), nil
}

blobClient, err := blobrpc.NewWSClient(ctx, logger, nodeConfig.EffectiveDAAddress(), nodeConfig.DA.AuthToken, "")
blobClient, err := blobrpc.NewWSClient(ctx, logger, nodeConfig.DA.Address, nodeConfig.DA.AuthToken, "")
if err != nil {
return nil, fmt.Errorf("failed to create blob client: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion docs/learn/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ da:
### DA Service Address

**Description:**
The network address (host:port) of the Data Availability layer service. A full follower with this value unset syncs exclusively through P2P and does not create a DA client. Aggregators retain the legacy `http://localhost:7980` fallback when this value is unset.
The network address (host:port) of the Data Availability layer service. A full follower with this value unset syncs exclusively through P2P and does not create a DA client. Aggregators must configure this value.

**YAML:**

Expand Down
2 changes: 1 addition & 1 deletion docs/learn/specs/da.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Evolve provides a generic [data availability interface][da-interface] for modula

`Client` can connect via JSON-RPC transports using Evolve's [jsonrpc][jsonrpc] implementations. The connection can be configured using the following cli flags:

* `--rollkit.da.address`: URL address of the DA service (default: empty for P2P-only followers; aggregators fall back to `http://localhost:7980`)
* `--rollkit.da.address`: URL address of the DA service (default: empty for P2P-only followers; required for aggregators)
* `--rollkit.da.auth_token`: authentication token of the DA service
* `--rollkit.da.namespace`: namespace to use when submitting blobs to the DA service (deprecated)
* `--rollkit.da.header_namespace`: namespace to use when submitting headers to the DA service
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/specs/da.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Evolve provides a generic [data availability interface][da-interface] for modula

`Client` can connect via JSON-RPC transports using Evolve's [jsonrpc][jsonrpc] implementations. The connection can be configured using the following cli flags:

* `--rollkit.da.address`: URL address of the DA service (default: empty for P2P-only followers; aggregators fall back to `http://localhost:7980`)
* `--rollkit.da.address`: URL address of the DA service (default: empty for P2P-only followers; required for aggregators)
* `--rollkit.da.auth_token`: authentication token of the DA service
* `--rollkit.da.namespace`: namespace to use when submitting blobs to the DA service (deprecated)
* `--rollkit.da.header_namespace`: namespace to use when submitting headers to the DA service
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/run_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func StartNode(

var daClient block.FullDAClient
if nodeConfig.DAEnabled() {
blobClient, err := blobrpc.NewWSClient(ctx, logger, nodeConfig.EffectiveDAAddress(), nodeConfig.DA.AuthToken, "")
blobClient, err := blobrpc.NewWSClient(ctx, logger, nodeConfig.DA.Address, nodeConfig.DA.AuthToken, "")
if err != nil {
return fmt.Errorf("failed to create blob client: %w", err)
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/run_node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ func TestAggregatorFlagInvariants(t *testing.T) {
validValues := []bool{false, true, true}

for i, flags := range flagVariants {
flags = append(flags, "--rollkit.da.address", "http://da.example:7980")
args := append([]string{"start"}, flags...)

executor, sequencer, keyProvider, nodeKey, ds, stopDAHeightTicker := createTestComponents(context.Background(), t)
Expand Down Expand Up @@ -235,7 +236,7 @@ func TestDefaultAggregatorValue(t *testing.T) {
// Create a new command without specifying any flags
var args []string
if tc.expected {
args = []string{"start", "--rollkit.node.aggregator"}
args = []string{"start", "--rollkit.node.aggregator", "--rollkit.da.address", "http://da.example:7980"}
} else {
args = []string{"start", "--rollkit.node.aggregator=false"}
}
Expand Down
21 changes: 6 additions & 15 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,22 +271,9 @@ type DAConfig struct {
}

// DAEnabled reports whether this node should initialize a DA client. Full
// followers without a DA address sync exclusively through P2P. Aggregators
// retain the legacy local DA fallback for backwards compatibility.
// followers without a DA address sync exclusively through P2P.
func (c Config) DAEnabled() bool {
return !c.Node.Light && (c.Node.Aggregator || c.DA.Address != "")
}

// EffectiveDAAddress returns the configured DA address, or the legacy local
// endpoint for aggregators that do not explicitly configure one.
func (c Config) EffectiveDAAddress() string {
if c.DA.Address != "" {
return c.DA.Address
}
if c.Node.Aggregator {
return DefaultAggregatorDAAddress
}
return ""
return !c.Node.Light && strings.TrimSpace(c.DA.Address) != ""
}

// GetNamespace returns the namespace for header submissions.
Expand Down Expand Up @@ -524,6 +511,10 @@ func (c *Config) Validate() error {
return fmt.Errorf("promotable mode cannot be combined with light node mode")
}

if c.Node.Aggregator && strings.TrimSpace(c.DA.Address) == "" {
return fmt.Errorf("DA address is required when aggregator mode is enabled")
}

// Promotable mode and Raft both control leader/follower role switching.
// Combining them needs a composed elector that gates Raft leadership on the execution-selected proposer.
if c.Node.Promotable && c.Raft.Enable {
Expand Down
23 changes: 19 additions & 4 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ func TestDAEnabled(t *testing.T) {
expectedAddress: "http://da.example:7980",
},
{
name: "aggregator without DA address uses legacy default",
name: "aggregator without DA address does not initialize DA",
configure: func(cfg *Config) {
cfg.Node.Aggregator = true
},
expectedEnabled: true,
expectedAddress: DefaultAggregatorDAAddress,
expectedEnabled: false,
expectedAddress: "",
},
{
name: "light node does not initialize DA",
Expand All @@ -90,11 +90,20 @@ func TestDAEnabled(t *testing.T) {
}

assert.Equal(t, tt.expectedEnabled, cfg.DAEnabled())
assert.Equal(t, tt.expectedAddress, cfg.EffectiveDAAddress())
assert.Equal(t, tt.expectedAddress, cfg.DA.Address)
})
}
}

func TestConfigValidate_AggregatorRequiresDAAddress(t *testing.T) {
cfg := DefaultConfig()
cfg.RootDir = t.TempDir()
cfg.Node.Aggregator = true

err := cfg.Validate()
require.EqualError(t, err, "DA address is required when aggregator mode is enabled")
}

func TestAddFlags(t *testing.T) {
// AddFlags and the assertions below each call DefaultConfig(), whose DA.Namespace
// is randString-seeded by time.Now().Unix(); run in a synctest bubble so both calls observe the same fake clock.
Expand Down Expand Up @@ -605,6 +614,9 @@ func TestBasedSequencerValidation(t *testing.T) {
cfg.RootDir = t.TempDir()
cfg.Node.Aggregator = tt.aggregator
cfg.Node.BasedSequencer = tt.basedSeq
if tt.aggregator {
cfg.DA.Address = "http://da.example:7980"
}

err := cfg.Validate()

Expand Down Expand Up @@ -666,6 +678,9 @@ func TestPromotableValidation(t *testing.T) {
cfg.Node.BasedSequencer = tt.basedSeq
cfg.Node.Light = tt.light
cfg.Raft.Enable = tt.raft
if tt.aggregator {
cfg.DA.Address = "http://da.example:7980"
}

err := cfg.Validate()

Expand Down
3 changes: 0 additions & 3 deletions pkg/config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ const (
ConfigName = ConfigFileName + "." + ConfigExtension
// AppConfigDir is the directory name for the app configuration.
AppConfigDir = "config"
// DefaultAggregatorDAAddress preserves the legacy local DA endpoint for aggregators
// that do not explicitly configure one.
DefaultAggregatorDAAddress = "http://localhost:7980"
)

// DefaultRootDir returns the default root directory for evolve
Expand Down
Loading