Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 3 additions & 5 deletions apps/grpc/single/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ Start the Evolve node with:
--root-dir ~/.grpc-single \
--grpc-executor-url http://localhost:50051 \
--da.address http://localhost:7980 \
--da.auth-token your-da-token \
--chain-id your-chain-id
--da.auth-token your-da-token
```

## Command-Line Flags
Expand Down Expand Up @@ -93,12 +92,11 @@ Start the Evolve node with:
3. Initialize and run the node:

```bash
./grpc-single init --root-dir ~/.grpc-single
./grpc-single init --root-dir ~/.grpc-single --chain-id test-chain
./grpc-single start \
--root-dir ~/.grpc-single \
--grpc-executor-url http://localhost:50051 \
--da.address http://localhost:7980 \
--chain-id test-chain
--da.address http://localhost:7980
```

## Architecture
Expand Down
11 changes: 11 additions & 0 deletions block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/evstack/ev-node/pkg/cache"
"github.com/evstack/ev-node/pkg/config"
"github.com/evstack/ev-node/pkg/genesis"
"github.com/evstack/ev-node/pkg/rpc/server"
"github.com/evstack/ev-node/pkg/signer"
storepkg "github.com/evstack/ev-node/pkg/store"
"github.com/evstack/ev-node/types"
Expand Down Expand Up @@ -415,6 +416,16 @@ func NewManager(
return nil, fmt.Errorf("failed to load cache: %w", err)
}

// Initialize DA visualization server if enabled
if config.RPC.EnableDAVisualization {
daVisualizationServer := server.NewDAVisualizationServer(da, logger.With().Str("module", "da_visualization").Logger(), config.Node.Aggregator)
server.SetDAVisualizationServer(daVisualizationServer)
logger.Info().Msg("DA visualization server enabled")
} else {
// Ensure the global server is nil when disabled
server.SetDAVisualizationServer(nil)
}

return m, nil
}

Expand Down
44 changes: 44 additions & 0 deletions block/submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

coreda "github.com/evstack/ev-node/core/da"
"github.com/evstack/ev-node/pkg/rpc/server"
"github.com/evstack/ev-node/types"
"google.golang.org/protobuf/proto"
)
Expand Down Expand Up @@ -318,6 +319,12 @@ func handleSubmissionResult[T any](

case coreda.StatusContextCanceled:
m.logger.Info().Int("attempt", retryStrategy.attempt).Msg("DA layer submission canceled due to context cancellation")

// Record canceled submission in DA visualization server
if daVisualizationServer := server.GetDAVisualizationServer(); daVisualizationServer != nil {
daVisualizationServer.RecordSubmission(&res, retryStrategy.gasPrice, uint64(len(remaining)))
}

return submissionOutcome[T]{
RemainingItems: remaining,
RemainingMarshal: marshaled,
Expand Down Expand Up @@ -347,6 +354,11 @@ func handleSuccessfulSubmission[T any](
remLen := len(remaining)
allSubmitted := res.SubmittedCount == uint64(remLen)

// Record submission in DA visualization server
if daVisualizationServer := server.GetDAVisualizationServer(); daVisualizationServer != nil {
daVisualizationServer.RecordSubmission(res, retryStrategy.gasPrice, res.SubmittedCount)
}

m.logger.Info().Str("itemType", itemType).Float64("gasPrice", retryStrategy.gasPrice).Uint64("count", res.SubmittedCount).Msg("successfully submitted items to DA layer")

submitted := remaining[:res.SubmittedCount]
Expand Down Expand Up @@ -383,6 +395,11 @@ func handleMempoolFailure[T any](

m.recordDAMetrics("submission", DAModeFail)

// Record failed submission in DA visualization server
if daVisualizationServer := server.GetDAVisualizationServer(); daVisualizationServer != nil {
daVisualizationServer.RecordSubmission(res, retryStrategy.gasPrice, uint64(len(remaining)))
}

gasMultiplier := m.getGasMultiplier(ctx)
retryStrategy.BackoffOnMempool(int(m.config.DA.MempoolTTL), m.config.DA.BlockTime.Duration, gasMultiplier)
m.logger.Info().Dur("backoff", retryStrategy.backoff).Float64("gasPrice", retryStrategy.gasPrice).Msg("retrying DA layer submission with")
Expand All @@ -409,6 +426,17 @@ func handleTooBigError[T any](

m.recordDAMetrics("submission", DAModeFail)

// Record failed submission in DA visualization server (create a result for TooBig error)
if daVisualizationServer := server.GetDAVisualizationServer(); daVisualizationServer != nil {
tooBigResult := &coreda.ResultSubmit{
BaseResult: coreda.BaseResult{
Code: coreda.StatusTooBig,
Message: "blob too big",
},
}
daVisualizationServer.RecordSubmission(tooBigResult, retryStrategy.gasPrice, uint64(len(remaining)))
}

if len(remaining) > 1 {
totalSubmitted, err := submitWithRecursiveSplitting(m, ctx, remaining, marshaled, retryStrategy.gasPrice, postSubmit, itemType, namespace)
if err != nil {
Expand Down Expand Up @@ -462,6 +490,12 @@ func handleGenericFailure[T any](
m.logger.Error().Str("error", res.Message).Int("attempt", attempt).Msg("DA layer submission failed")

m.recordDAMetrics("submission", DAModeFail)

// Record failed submission in DA visualization server
if daVisualizationServer := server.GetDAVisualizationServer(); daVisualizationServer != nil {
daVisualizationServer.RecordSubmission(res, retryStrategy.gasPrice, uint64(len(remaining)))
}

retryStrategy.BackoffOnFailure()

return submissionOutcome[T]{
Expand Down Expand Up @@ -662,12 +696,22 @@ func processBatch[T any](
postSubmit(submitted, &batchRes, gasPrice)
m.logger.Info().Int("batchSize", len(batch.Items)).Uint64("submittedCount", batchRes.SubmittedCount).Msg("successfully submitted batch to DA layer")

// Record successful submission in DA visualization server
if daVisualizationServer := server.GetDAVisualizationServer(); daVisualizationServer != nil {
daVisualizationServer.RecordSubmission(&batchRes, gasPrice, batchRes.SubmittedCount)
}

return batchResult[T]{
action: batchActionSubmitted,
submittedCount: int(batchRes.SubmittedCount),
}
}

// Record failed submission in DA visualization server for all error cases
if daVisualizationServer := server.GetDAVisualizationServer(); daVisualizationServer != nil {
daVisualizationServer.RecordSubmission(&batchRes, gasPrice, uint64(len(batch.Items)))
}

if batchRes.Code == coreda.StatusTooBig && len(batch.Items) > 1 {
// Batch is too big - let the caller handle splitting
m.logger.Debug().Int("batchSize", len(batch.Items)).Msg("batch too big, returning to caller for splitting")
Expand Down
240 changes: 240 additions & 0 deletions docs/guides/da-visualizer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
# DA Visualizer

The Data Availability (DA) Visualizer is a built-in monitoring tool in Evolve that provides real-time insights into blob submissions to the DA layer. It offers a web-based interface for tracking submission statistics, monitoring DA layer health, and analyzing blob details.

**Note**: Only aggregator nodes submit data to the DA layer. Non-aggregator nodes will not display submission data.

## Overview

The DA Visualizer provides:

- Real-time monitoring of blob submissions (last 100 submissions)
- Success/failure statistics and trends
- Gas price tracking and cost analysis
- DA layer health monitoring
- Detailed blob inspection capabilities
- Recent submission history

## Enabling the DA Visualizer

The DA Visualizer is disabled by default. To enable it, use the following configuration:

### Via Command-line Flag

```bash
testapp start --rollkit.rpc.enable_da_visualization
```

### Via Configuration File

Add the following to your `evolve.yaml` configuration file:

```yaml
rpc:
enable_da_visualization: true
```

## Accessing the DA Visualizer

Once enabled, the DA Visualizer is accessible through your node's RPC server. By default, this is:

```
http://localhost:7331/da
```

The visualizer provides several API endpoints and a web interface:

### Web Interface

Navigate to `http://localhost:7331/da` in your web browser to access the interactive dashboard.

### API Endpoints

The following REST API endpoints are available for programmatic access:

#### Get Recent Submissions

```bash
GET /da/submissions
```

Returns the most recent blob submissions (up to 100 kept in memory).

#### Get Blob Details

```bash
GET /da/blob?id={blob_id}
```

Returns detailed information about a specific blob submission.

#### Get DA Statistics

```bash
GET /da/stats
```

Returns aggregated statistics including:

- Total submissions count
- Success/failure rates
- Average gas price
- Total gas spent
- Average blob size
- Submission trends

#### Get DA Health Status

```bash
GET /da/health
```

Returns the current health status of the DA layer including:

- Connection status
- Recent error rates
- Performance metrics
- Last successful submission timestamp

## Features

### Real-time Monitoring

The dashboard automatically updates every 30 seconds, displaying:

- Recent submission feed with status indicators (last 100 submissions)
- Success rate percentage
- Current gas price trends
- Submission history

### Submission Details

Each submission entry shows:

- Timestamp
- Blob ID with link to detailed view
- Number of blobs in the batch
- Submission status (success/failure)
- Gas price used
- Error messages (if any)

### Statistics Dashboard

The statistics section provides:

- **Performance Metrics**: Success rate, average submission time
- **Cost Analysis**: Total gas spent, average gas price over time
- **Volume Metrics**: Total blobs submitted, average blob size
- **Trend Analysis**: Hourly and daily submission patterns

### Health Monitoring

The health status indicator shows:

- 🟢 **Healthy**: DA layer responding normally
- 🟡 **Warning**: Some failures but overall functional
- 🔴 **Critical**: High failure rate or connection issues

## Use Cases

### For Node Operators

- Monitor the reliability of DA submissions
- Track gas costs and optimize gas price settings
- Identify patterns in submission failures
- Ensure DA layer connectivity

### For Developers

- Debug DA submission issues
- Analyze blob data structure
- Monitor application-specific submission patterns
- Test DA layer integration

### For Network Monitoring

- Track overall network DA usage
- Identify congestion periods
- Monitor gas price fluctuations
- Analyze submission patterns across the network

## Configuration Options

When enabling the DA Visualizer, you may want to adjust related RPC settings:

```yaml
rpc:
address: "0.0.0.0:7331" # Bind to all interfaces for remote access
enable_da_visualization: true
```

**Security Note**: If binding to all interfaces (`0.0.0.0`), ensure proper firewall rules are in place to restrict access to trusted sources only.

## Troubleshooting

### Visualizer Not Accessible

1. Verify the DA Visualizer is enabled:
- Check your configuration file or ensure the flag is set
- Look for log entries confirming "DA visualization endpoints registered"

2. Check the RPC server is running:
- Verify the RPC address in logs
- Ensure no port conflicts

3. For remote access:
- Ensure the RPC server is bound to an accessible interface
- Check firewall settings

### No Data Displayed

1. Verify your node is in aggregator mode (only aggregators submit to DA)
2. Check DA layer connectivity in the node logs
3. Ensure transactions are being processed
4. Note that the visualizer only keeps the last 100 submissions in memory

### API Errors

- **404 Not Found**: DA Visualizer not enabled
- **500 Internal Server Error**: Check node logs for DA connection issues
- **Empty responses**: No submissions have been made yet

## Example Usage

### Using curl to access the API

```bash
# Get recent submissions (returns up to 100)
curl http://localhost:7331/da/submissions

# Get specific blob details
curl http://localhost:7331/da/blob?id=abc123...

# Get statistics
curl http://localhost:7331/da/stats

# Check DA health
curl http://localhost:7331/da/health
```

### Monitoring with scripts

```bash
#!/bin/bash
# Simple monitoring script

while true; do
health=$(curl -s http://localhost:7331/da/health | jq -r '.status')
if [ "$health" != "healthy" ]; then
echo "DA layer issue detected: $health"
# Send alert...
fi
sleep 30
done
```

## Related Configuration

For complete DA layer configuration options, see the [Config Reference](../learn/config.md#data-availability-configuration-da).

For metrics and monitoring setup, see the [Metrics Guide](./metrics.md).
Loading
Loading