Skip to content

Commit 3c75c61

Browse files
tac0turtletac0turtle
andauthored
feat: create grpc execution environemnt (#2490)
<!-- Please read and fill out this form before submitting your PR. Please make sure you have reviewed our contributors guide before submitting your first PR. NOTE: PR titles should follow semantic commits: https://www.conventionalcommits.org/en/v1.0.0/ --> ## Overview this creats a grpc execution runner. the idea here is to support different execution environments. this one is done to integrate ev-rs <!-- Please provide an explanation of the PR, including the appropriate context, background, goal, and rationale. If there is an issue with this information, please provide a tl;dr and link the issue. Ex: Closes #<issue number> --> --------- Co-authored-by: tac0turtle <[email protected]>
1 parent 56da391 commit 3c75c61

30 files changed

+3932
-1831
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
### Added
1414

1515
<!-- New features or capabilities -->
16-
-
16+
- Added gRPC execution client implementation for remote execution services using Connect-RPC protocol ([#2490](https://github.com/evstack/ev-node/pull/2490))
17+
- Added `ExecutorService` protobuf definition with InitChain, GetTxs, ExecuteTxs, and SetFinal RPCs ([#2490](https://github.com/evstack/ev-node/pull/2490))
18+
- Added new `grpc` app for running EVNode with a remote execution layer via gRPC ([#2490](https://github.com/evstack/ev-node/pull/2490))
1719

1820
### Changed
1921

apps/grpc/single/Dockerfile

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Build stage
2+
FROM golang:1.24-alpine AS builder
3+
4+
# Install build dependencies
5+
RUN apk add --no-cache git make gcc musl-dev linux-headers
6+
7+
# Set working directory
8+
WORKDIR /rollkit
9+
10+
# Copy go mod files
11+
COPY go.mod go.sum ./
12+
COPY apps/grpc/single/go.mod apps/grpc/single/go.sum ./apps/grpc/single/
13+
COPY core/go.mod core/go.sum ./core/
14+
COPY execution/grpc/go.mod execution/grpc/go.sum ./execution/grpc/
15+
COPY pkg/go.mod pkg/go.sum ./pkg/
16+
COPY sequencers/single/go.mod sequencers/single/go.sum ./sequencers/single/
17+
18+
# Download dependencies
19+
RUN go mod download
20+
21+
# Copy source code
22+
COPY . .
23+
24+
# Build the application
25+
WORKDIR /rollkit/apps/grpc/single
26+
RUN go build -o grpc-single .
27+
28+
# Runtime stage
29+
FROM alpine:3.19
30+
31+
# Install runtime dependencies
32+
RUN apk add --no-cache ca-certificates
33+
34+
# Create non-root user
35+
RUN addgroup -g 1000 rollkit && \
36+
adduser -u 1000 -G rollkit -s /bin/sh -D rollkit
37+
38+
# Set working directory
39+
WORKDIR /home/rollkit
40+
41+
# Copy binary from builder
42+
COPY --from=builder /rollkit/apps/grpc/single/grpc-single /usr/local/bin/
43+
44+
# Create necessary directories
45+
RUN mkdir -p /home/rollkit/.grpc-single && \
46+
chown -R rollkit:rollkit /home/rollkit
47+
48+
# Switch to non-root user
49+
USER rollkit
50+
51+
# Expose ports
52+
# P2P port
53+
EXPOSE 26656
54+
# RPC port
55+
EXPOSE 26657
56+
# Prometheus metrics
57+
EXPOSE 26660
58+
59+
# Set entrypoint
60+
ENTRYPOINT ["grpc-single"]
61+
62+
# Default command
63+
CMD ["start"]

apps/grpc/single/README.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# gRPC Single Sequencer App
2+
3+
This application runs a Rollkit node with a single sequencer that connects to a remote execution client via gRPC. It allows you to use any execution layer that implements the Rollkit execution gRPC interface.
4+
5+
## Overview
6+
7+
The gRPC single sequencer app provides:
8+
9+
- A Rollkit consensus node with single sequencer
10+
- Connection to remote execution clients via gRPC
11+
- Full data availability layer integration
12+
- P2P networking capabilities
13+
14+
## Prerequisites
15+
16+
1. A running execution client that implements the Rollkit gRPC execution interface
17+
2. Access to a data availability layer (e.g., local DA, Celestia)
18+
3. Go 1.22 or higher
19+
20+
## Installation
21+
22+
From the repository root:
23+
24+
```bash
25+
cd apps/grpc/single
26+
go build -o grpc-single
27+
```
28+
29+
## Usage
30+
31+
### 1. Initialize the Node
32+
33+
First, initialize the node configuration:
34+
35+
```bash
36+
./grpc-single init --root-dir ~/.grpc-single
37+
```
38+
39+
This creates the necessary configuration files and directories.
40+
41+
### 2. Configure the Node
42+
43+
Edit the configuration file at `~/.grpc-single/config/config.toml` to set your preferred parameters, or use command-line flags.
44+
45+
### 3. Start the Execution Service
46+
47+
Before starting the Rollkit node, ensure your gRPC execution service is running.
48+
49+
### 4. Run the Node
50+
51+
Start the Rollkit node with:
52+
53+
```bash
54+
./grpc-single start \
55+
--root-dir ~/.grpc-single \
56+
--grpc-executor-url http://localhost:50051 \
57+
--da.address http://localhost:7980 \
58+
--da.auth-token your-da-token \
59+
--chain-id your-chain-id
60+
```
61+
62+
## Command-Line Flags
63+
64+
### gRPC-specific Flags
65+
66+
- `--grpc-executor-url`: URL of the gRPC execution service (default: `http://localhost:50051`)
67+
68+
### Common Rollkit Flags
69+
70+
- `--root-dir`: Root directory for config and data (default: `~/.grpc-single`)
71+
- `--chain-id`: The chain ID for your rollup
72+
- `--da.address`: Data availability layer address
73+
- `--da.auth-token`: Authentication token for DA layer
74+
- `--da.namespace`: Namespace for DA layer (optional)
75+
- `--p2p.listen-address`: P2P listen address (default: `/ip4/0.0.0.0/tcp/26656`)
76+
- `--block-time`: Time between blocks (default: `1s`)
77+
78+
## Example: Running with Local DA
79+
80+
1. Start the local DA service:
81+
82+
```bash
83+
cd da/cmd/local-da
84+
go run main.go
85+
```
86+
87+
2. Start your gRPC execution service:
88+
89+
```bash
90+
# Your execution service implementation
91+
```
92+
93+
3. Initialize and run the node:
94+
95+
```bash
96+
./grpc-single init --root-dir ~/.grpc-single
97+
./grpc-single start \
98+
--root-dir ~/.grpc-single \
99+
--grpc-executor-url http://localhost:50051 \
100+
--da.address http://localhost:7980 \
101+
--chain-id test-chain
102+
```
103+
104+
## Architecture
105+
106+
```text
107+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
108+
│ Rollkit Node │────▶│ gRPC Execution │────▶│ Execution │
109+
│ (Single Seqr) │◀────│ Client │◀────│ Service │
110+
└─────────────────┘ └──────────────────┘ └─────────────┘
111+
│ │
112+
│ │
113+
▼ ▼
114+
┌─────────────────┐ ┌─────────────┐
115+
│ DA │ │ State │
116+
│ Layer │ │ Storage │
117+
└─────────────────┘ └─────────────┘
118+
```
119+
120+
## Development
121+
122+
### Building from Source
123+
124+
```bash
125+
go build -o grpc-single
126+
```
127+
128+
### Running Tests
129+
130+
```bash
131+
go test ./...
132+
```
133+
134+
## Troubleshooting
135+
136+
### Connection Refused
137+
138+
If you see "connection refused" errors, ensure:
139+
140+
1. Your gRPC execution service is running
141+
2. The execution service URL is correct
142+
3. No firewall is blocking the connection
143+
144+
### DA Layer Issues
145+
146+
If you have issues connecting to the DA layer:
147+
148+
1. Verify the DA service is running
149+
2. Check the authentication token
150+
3. Ensure the namespace exists (if using Celestia)
151+
152+
## See Also
153+
154+
- [Rollkit Documentation](https://rollkit.dev)
155+
- [gRPC Execution Interface](../../../execution/grpc/README.md)
156+
- [Single Sequencer Documentation](../../../sequencers/single/README.md)

apps/grpc/single/cmd/init.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package cmd
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
7+
"github.com/spf13/cobra"
8+
9+
rollcmd "github.com/evstack/ev-node/pkg/cmd"
10+
rollconf "github.com/evstack/ev-node/pkg/config"
11+
rollgenesis "github.com/evstack/ev-node/pkg/genesis"
12+
)
13+
14+
// InitCmd returns the init command for initializing the gRPC single sequencer node
15+
func InitCmd() *cobra.Command {
16+
initCmd := &cobra.Command{
17+
Use: "init",
18+
Short: "Initialize rollkit configuration files",
19+
Long: `Initialize configuration files for a Rollkit node with gRPC execution client.
20+
This will create the necessary configuration structure in the specified root directory.`,
21+
Args: cobra.NoArgs,
22+
RunE: func(cmd *cobra.Command, args []string) error {
23+
homePath, err := cmd.Flags().GetString(rollconf.FlagRootDir)
24+
if err != nil {
25+
return fmt.Errorf("error reading home flag: %w", err)
26+
}
27+
28+
aggregator, err := cmd.Flags().GetBool(rollconf.FlagAggregator)
29+
if err != nil {
30+
return fmt.Errorf("error reading aggregator flag: %w", err)
31+
}
32+
33+
// ignore error, as we are creating a new config
34+
// we use load in order to parse all the flags
35+
cfg, _ := rollconf.Load(cmd)
36+
cfg.Node.Aggregator = aggregator
37+
if err := cfg.Validate(); err != nil {
38+
return fmt.Errorf("error validating config: %w", err)
39+
}
40+
41+
passphrase, err := cmd.Flags().GetString(rollconf.FlagSignerPassphrase)
42+
if err != nil {
43+
return fmt.Errorf("error reading passphrase flag: %w", err)
44+
}
45+
46+
proposerAddress, err := rollcmd.CreateSigner(&cfg, homePath, passphrase)
47+
if err != nil {
48+
return err
49+
}
50+
51+
if err := cfg.SaveAsYaml(); err != nil {
52+
return fmt.Errorf("error writing rollkit.yaml file: %w", err)
53+
}
54+
55+
if err := rollcmd.LoadOrGenNodeKey(homePath); err != nil {
56+
return err
57+
}
58+
59+
// get chain ID or use default
60+
chainID, _ := cmd.Flags().GetString(rollconf.FlagChainID)
61+
if chainID == "" {
62+
chainID = "grpc-test-chain"
63+
}
64+
65+
// Initialize genesis without app state
66+
err = rollgenesis.CreateGenesis(homePath, chainID, 1, proposerAddress)
67+
genesisPath := rollgenesis.GenesisPath(homePath)
68+
if errors.Is(err, rollgenesis.ErrGenesisExists) {
69+
// check if existing genesis file is valid
70+
if genesis, err := rollgenesis.LoadGenesis(genesisPath); err == nil {
71+
if err := genesis.Validate(); err != nil {
72+
return fmt.Errorf("existing genesis file is invalid: %w", err)
73+
}
74+
} else {
75+
return fmt.Errorf("error loading existing genesis file: %w", err)
76+
}
77+
78+
cmd.Printf("Genesis file already exists at %s, skipping creation.\n", genesisPath)
79+
} else if err != nil {
80+
return fmt.Errorf("error initializing genesis file: %w", err)
81+
}
82+
83+
cmd.Printf("Successfully initialized config file at %s\n", cfg.ConfigPath())
84+
return nil
85+
},
86+
}
87+
88+
// Add configuration flags
89+
rollconf.AddFlags(initCmd)
90+
91+
return initCmd
92+
}

0 commit comments

Comments
 (0)