Skip to content

Commit 9b910e1

Browse files
ch4r10t33ruink45shariqnaiyerKatyaRyazantseva
authored
feat: devnet3 changes (#110)
* feat: add attestation_committee_count config and auto aggregator selection * fix: remove merge conflict markers from README * refactor: make attestation_committee_count optional Since attestation_committee_count is now hardcoded in clients, make it optional: - Only pass --attestation-committee-count flag if explicitly set in config - Remove default value from validator-config.yaml files - Clients will use their hardcoded default if flag not provided * test: configure local-devnet for testing with 0xpartha/zeam:local * fix: improve yq aggregator update to prevent file corruption * Add --is-aggregator to Ansible roles for all clients (devnet3) * Update Docker images for devnet3 - zeam: 0xpartha/zeam:devnet3 - lantern: piertwo/lantern:v0.0.3-test-{amd64,arm64} (platform-specific) - Add architecture detection for lantern in both shell script and Ansible * Update local devnet config for zeam + ethlambda testing - Update zeam docker image to 0xpartha/zeam:devnet3 - Update ethlambda docker image to ghcr.io/lambdaclass/ethlambda:devnet3 - Fix lantern-cmd.sh: remove unsupported --is-aggregator flag - Add httpPort support to parse-vc.sh and lantern-cmd.sh - Fix spin-node.sh: extract client name before printing to avoid stale variable - Update validator-config.yaml: 2 zeam + 2 ethlambda nodes * Change lantern log level from debug to info (#118) * local change * fix: update ream to devnet3 (#120) * Update qlean to devnet-3 and configure 5-client local devnet - Update qlean docker image to platform-specific devnet-3 images (qdrvm/qlean-mini:devnet-3-amd64 or devnet-3-arm64) - Configure validator-config.yaml with all 5 clients: zeam, ream, qlean, lantern, ethlambda * fix: update qlean ports, fix image issue (#127) * feat: update lantern devnet-3 image (#128) * fix: update qlean ports, fix image issue * feat: update lantern image for devnet-3 * feat: update grandine and lantern ansible image for devnet-3 (#129) * fix: update qlean ports, fix image issue * feat: update grandine and lantern ansible image for devnet3 * fix: update lantern ansible main role * Remove test-local-zeam.sh * zeam: use blockblaz/zeam:devnet3 image --------- Co-authored-by: uink45 <79078981+uink45@users.noreply.github.com> Co-authored-by: Shariq Naiyer <shariqnaiyer@gmail.com> Co-authored-by: Ekaterina Riazantseva <sibkatya@gmail.com>
1 parent b24b0d7 commit 9b910e1

23 files changed

Lines changed: 387 additions & 52 deletions

File tree

.DS_Store

0 Bytes
Binary file not shown.

README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ Grafana is started with the two pre-provisioned dashboards from [leanMetrics](ht
8282

8383
> **Note:** The `--metrics` flag only affects local deployments. When using Ansible deployment mode, this flag is ignored. Metrics ports are always exposed by clients regardless of this flag.
8484
85+
### Aggregator Selection
86+
87+
```sh
88+
# Let the system randomly select an aggregator (default behavior)
89+
NETWORK_DIR=local-devnet ./spin-node.sh --node all --generateGenesis
90+
91+
# Manually specify which node should be the aggregator
92+
NETWORK_DIR=local-devnet ./spin-node.sh --node all --generateGenesis --aggregator zeam_0
93+
94+
# The aggregator selection is applied automatically and the isAggregator flag
95+
# is updated in validator-config.yaml before nodes are started
96+
```
97+
8598
## Args
8699

87100
1. `NETWORK_DIR` is an env to specify the network directory. Should have a `genesis` directory with genesis config. A `data` folder will be created inside this `NETWORK_DIR` if not already there.
@@ -139,8 +152,14 @@ Grafana is started with the two pre-provisioned dashboards from [leanMetrics](ht
139152
- On Ctrl+C cleanup, the metrics stack is stopped automatically
140153

141154
Note: Client metrics endpoints are always enabled regardless of this flag.
142-
12. `--checkpoint-sync-url` specifies the URL to fetch finalized checkpoint state from for checkpoint sync. Default: `https://leanpoint.leanroadmap.org/lean/v0/states/finalized`. Only used when `--restart-client` is specified.
143-
13. `--restart-client` comma-separated list of client node names (e.g., `zeam_0,ream_0`). When specified, those clients are stopped, their data cleared, and restarted using checkpoint sync. Genesis is skipped. Use with `--checkpoint-sync-url` to override the default URL.
155+
12. `--aggregator` specifies which node should act as the aggregator (1 aggregator per subnet).
156+
- If not provided, one node will be randomly selected as the aggregator
157+
- If provided, the specified node will be set as the aggregator
158+
- The aggregator selection updates the `isAggregator` flag in `validator-config.yaml`
159+
- Example: `--aggregator zeam_0` to make zeam_0 the aggregator
160+
- Example: Without flag, a random node will be selected automatically
161+
13. `--checkpoint-sync-url` specifies the URL to fetch finalized checkpoint state from for checkpoint sync. Default: `https://leanpoint.leanroadmap.org/lean/v0/states/finalized`. Only used when `--restart-client` is specified.
162+
14. `--restart-client` comma-separated list of client node names (e.g., `zeam_0,ream_0`). When specified, those clients are stopped, their data cleared, and restarted using checkpoint sync. Genesis is skipped. Use with `--checkpoint-sync-url` to override the default URL.
144163

145164
### Checkpoint sync
146165

TESTING_DEVNET3.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Testing devnet3 Configuration
2+
3+
## Setup
4+
5+
The local-devnet has been configured to test devnet3 features with the local zeam image.
6+
7+
### Changes Made:
8+
9+
1. **zeam-cmd.sh**: Updated to use `0xpartha/zeam:local` image
10+
2. **local-devnet/validator-config.yaml**: Added commented attestation_committee_count parameter
11+
12+
## devnet3 Features Being Tested
13+
14+
### 1. Automatic Aggregator Selection
15+
- One node will be randomly selected as aggregator on startup
16+
- The `isAggregator` flag in validator-config.yaml will be automatically updated
17+
- Only the selected aggregator will receive `--is-aggregator` flag
18+
19+
### 2. Optional Attestation Committee Count
20+
- Currently commented out (clients use hardcoded default)
21+
- Can be enabled by uncommenting: `attestation_committee_count: 1`
22+
- When set, all clients receive `--attestation-committee-count <value>` flag
23+
24+
## Test Commands
25+
26+
### Basic Test - Single Node (zeam_0)
27+
```bash
28+
# Run the test script
29+
./test-local-zeam.sh
30+
31+
# Or manually:
32+
NETWORK_DIR=local-devnet ./spin-node.sh --node zeam_0 --generateGenesis --cleanData
33+
```
34+
35+
### Test with Manual Aggregator Selection
36+
```bash
37+
# Specify zeam_0 as aggregator
38+
NETWORK_DIR=local-devnet ./spin-node.sh --node zeam_0 --generateGenesis --cleanData --aggregator zeam_0
39+
```
40+
41+
### Test Multiple Nodes
42+
```bash
43+
# Run all nodes (zeam_0 will be randomly selected as aggregator)
44+
NETWORK_DIR=local-devnet ./spin-node.sh --node all --generateGenesis --cleanData
45+
46+
# Run specific nodes with zeam_0 as aggregator
47+
NETWORK_DIR=local-devnet ./spin-node.sh --node "zeam_0 ream_0" --generateGenesis --cleanData --aggregator zeam_0
48+
```
49+
50+
### Test with Attestation Committee Count Override
51+
```bash
52+
# 1. Uncomment attestation_committee_count in local-devnet/genesis/validator-config.yaml
53+
# 2. Set desired value (e.g., attestation_committee_count: 4)
54+
# 3. Run:
55+
NETWORK_DIR=local-devnet ./spin-node.sh --node zeam_0 --generateGenesis --cleanData
56+
```
57+
58+
## Expected Behavior
59+
60+
### Aggregator Selection
61+
1. Script displays: "Randomly selected aggregator: zeam_0 (index 0 out of 7 nodes)" OR "Using user-specified aggregator: zeam_0"
62+
2. Script updates validator-config.yaml: sets `isAggregator: true` for selected node
63+
3. parse-vc.sh output shows: "Is Aggregator: true" for aggregator, "false" for others
64+
4. zeam command includes `--is-aggregator` flag for aggregator only
65+
66+
### Attestation Committee Count
67+
**When NOT set (default):**
68+
- parse-vc.sh does NOT display "Attestation Committee Count"
69+
- zeam command does NOT include `--attestation-committee-count` flag
70+
- Client uses its hardcoded default
71+
72+
**When set (e.g., to 4):**
73+
- parse-vc.sh displays: "Attestation Committee Count: 4"
74+
- zeam command includes: `--attestation-committee-count 4`
75+
- Client uses the specified value
76+
77+
## Verification
78+
79+
### Check Docker Container
80+
```bash
81+
# Inspect the running container
82+
docker inspect zeam_0
83+
84+
# Check container logs
85+
docker logs zeam_0
86+
87+
# Verify command-line arguments
88+
docker inspect zeam_0 | grep -A20 Args
89+
```
90+
91+
### Check Configuration
92+
```bash
93+
# Verify aggregator selection in validator-config.yaml
94+
yq eval '.validators[] | select(.name == "zeam_0") | .isAggregator' local-devnet/genesis/validator-config.yaml
95+
96+
# Check all aggregators
97+
yq eval '.validators[] | select(.isAggregator == true) | .name' local-devnet/genesis/validator-config.yaml
98+
```
99+
100+
### Monitor Node Output
101+
```bash
102+
# Watch zeam_0 logs in real-time
103+
docker logs -f zeam_0
104+
105+
# Check for aggregator-related messages
106+
docker logs zeam_0 2>&1 | grep -i aggregat
107+
```
108+
109+
## Cleanup
110+
111+
```bash
112+
# Stop and remove zeam_0 container
113+
docker rm -f zeam_0
114+
115+
# Stop all nodes
116+
NETWORK_DIR=local-devnet ./spin-node.sh --node all --stop
117+
118+
# Clean data directories
119+
rm -rf local-devnet/data/*
120+
```
121+
122+
## Troubleshooting
123+
124+
### Image Not Found
125+
If you get "image not found" error:
126+
```bash
127+
# Check if image exists
128+
docker images | grep zeam
129+
130+
# Pull/build the image if needed
131+
# (build instructions depend on your zeam setup)
132+
```
133+
134+
### Port Conflicts
135+
If ports are already in use:
136+
```bash
137+
# Check what's using the port
138+
lsof -i :8081 # zeam_0 metrics port
139+
lsof -i :9001 # zeam_0 QUIC port
140+
141+
# Kill conflicting processes or change ports in validator-config.yaml
142+
```
143+
144+
### Genesis Generation Fails
145+
```bash
146+
# Ensure yq is installed
147+
brew install yq # macOS
148+
# or follow: https://github.com/mikefarah/yq#install
149+
150+
# Check validator-config.yaml syntax
151+
yq eval . local-devnet/genesis/validator-config.yaml
152+
```
153+
154+
## Notes
155+
156+
- The `0xpartha/zeam:local` image should have the latest devnet3 changes
157+
- All devnet3 features (aggregator selection, optional attestation_committee_count) are enabled
158+
- The configuration is set up for local testing with 127.0.0.1 IPs
159+
- Hash-sig keys will be generated automatically on first run with `--generateGenesis`

ansible/roles/ethlambda/tasks/main.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@
3838
loop:
3939
- enrFields.quic
4040
- metricsPort
41+
- isAggregator
4142
when: node_name is defined
4243

43-
- name: Set node ports
44+
- name: Set node ports and aggregator flag
4445
set_fact:
4546
ethlambda_quic_port: "{{ ethlambda_node_config.results[0].stdout }}"
4647
ethlambda_metrics_port: "{{ ethlambda_node_config.results[1].stdout }}"
48+
ethlambda_is_aggregator: "{{ 'true' if (ethlambda_node_config.results[2].stdout | default('') | trim) == 'true' else 'false' }}"
4749
when: ethlambda_node_config is defined
4850

4951
- name: Ensure node key file exists
@@ -97,6 +99,7 @@
9799
--node-key /config/{{ node_name }}.key
98100
--metrics-address 0.0.0.0
99101
--metrics-port {{ ethlambda_metrics_port }}
102+
{{ '--is-aggregator' if (ethlambda_is_aggregator | default('false')) == 'true' else '' }}
100103
{{ ('--checkpoint-sync-url ' + checkpoint_sync_url) if (checkpoint_sync_url is defined and checkpoint_sync_url | length > 0) else '' }}
101104
register: ethlambda_container
102105
changed_when: ethlambda_container.rc == 0

ansible/roles/grandine/tasks/main.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,16 @@
3838
loop:
3939
- enrFields.quic
4040
- metricsPort
41+
- privkey
42+
- isAggregator
4143
when: node_name is defined
4244

43-
- name: Set node ports
45+
- name: Set node ports and aggregator flag
4446
set_fact:
4547
grandine_quic_port: "{{ grandine_node_config.results[0].stdout }}"
4648
grandine_metrics_port: "{{ grandine_node_config.results[1].stdout }}"
49+
grandine_privkey: "{{ grandine_node_config.results[2].stdout }}"
50+
grandine_is_aggregator: "{{ 'true' if (grandine_node_config.results[3].stdout | default('') | trim) == 'true' else 'false' }}"
4751
when: grandine_node_config is defined
4852

4953
- name: Ensure node key file exists
@@ -102,6 +106,7 @@
102106
--metrics
103107
--http-address 0.0.0.0
104108
--http-port {{ grandine_metrics_port }}
109+
{{ '--is-aggregator' if (grandine_is_aggregator | default('false')) == 'true' else '' }}
105110
{{ ('--checkpoint-sync-url ' + checkpoint_sync_url) if (checkpoint_sync_url is defined and checkpoint_sync_url | length > 0) else '' }}
106111
register: grandine_container
107112
changed_when: grandine_container.rc == 0

ansible/roles/lantern/defaults/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
# Note: These are fallback defaults. Actual values are extracted from client-cmds/lantern-cmd.sh
44
# in the tasks/main.yml file. These defaults are used if extraction fails.
55

6-
lantern_docker_image: "piertwo/lantern:latest"
6+
lantern_docker_image: "piertwo/lantern:v0.0.3"
77
deployment_mode: docker # docker or binary
88

ansible/roles/lantern/tasks/main.yml

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,9 @@
22
# Lantern role: Deploy and manage Lantern nodes
33
# Converts client-cmds/lantern-cmd.sh logic to Ansible tasks
44

5-
- name: Extract docker image from client-cmd.sh
6-
shell: |
7-
# Extract the docker image from LANTERN_IMAGE line
8-
# playbook_dir points to ansible/playbooks, go up two levels to reach project root
9-
project_root="$(cd '{{ playbook_dir }}/../..' && pwd)"
10-
grep -E '^LANTERN_IMAGE=' "$project_root/client-cmds/lantern-cmd.sh" | head -1 | sed -E 's/.*LANTERN_IMAGE="([^"]+)".*/\1/'
11-
register: lantern_docker_image_raw
12-
changed_when: false
13-
delegate_to: localhost
14-
run_once: true
5+
- name: Set lantern docker image
6+
set_fact:
7+
lantern_docker_image: "piertwo/lantern:v0.0.3"
158

169
- name: Extract deployment mode from client-cmd.sh
1710
shell: |
@@ -23,9 +16,8 @@
2316
delegate_to: localhost
2417
run_once: true
2518

26-
- name: Set docker image and deployment mode from client-cmd.sh
19+
- name: Set deployment mode from client-cmd.sh
2720
set_fact:
28-
lantern_docker_image: "{{ lantern_docker_image_raw.stdout | trim | default('piertwo/lantern:latest') }}"
2921
deployment_mode: "{{ lantern_deployment_mode_raw.stdout | trim | default('docker') }}"
3022

3123
- name: Extract node configuration from validator-config.yaml
@@ -37,12 +29,16 @@
3729
loop:
3830
- enrFields.quic
3931
- metricsPort
32+
- privkey
33+
- isAggregator
4034
when: node_name is defined
4135

42-
- name: Set node ports
36+
- name: Set node ports and aggregator flag
4337
set_fact:
4438
lantern_quic_port: "{{ lantern_node_config.results[0].stdout }}"
4539
lantern_metrics_port: "{{ lantern_node_config.results[1].stdout }}"
40+
lantern_privkey: "{{ lantern_node_config.results[2].stdout }}"
41+
lantern_is_aggregator: "{{ 'true' if (lantern_node_config.results[3].stdout | default('') | trim) == 'true' else 'false' }}"
4642
when: lantern_node_config is defined
4743

4844
- name: Ensure node key file exists
@@ -96,6 +92,7 @@
9692
--metrics-port {{ lantern_metrics_port }}
9793
--http-port 5055
9894
--hash-sig-key-dir /config/hash-sig-keys
95+
{{ '--is-aggregator' if (lantern_is_aggregator | default('false')) == 'true' else '' }}
9996
{{ ('--checkpoint-sync-url ' + checkpoint_sync_url) if (checkpoint_sync_url is defined and checkpoint_sync_url | length > 0) else '' }}
10097
register: lantern_container
10198
changed_when: lantern_container.rc == 0

ansible/roles/lighthouse/tasks/main.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,16 @@
3737
loop:
3838
- enrFields.quic
3939
- metricsPort
40+
- privkey
41+
- isAggregator
4042
when: node_name is defined
4143

42-
- name: Set node ports
44+
- name: Set node ports and aggregator flag
4345
set_fact:
4446
lighthouse_quic_port: "{{ lighthouse_node_config.results[0].stdout }}"
4547
lighthouse_metrics_port: "{{ lighthouse_node_config.results[1].stdout }}"
48+
lighthouse_privkey: "{{ lighthouse_node_config.results[2].stdout }}"
49+
lighthouse_is_aggregator: "{{ 'true' if (lighthouse_node_config.results[3].stdout | default('') | trim) == 'true' else 'false' }}"
4650
when: lighthouse_node_config is defined
4751

4852
- name: Ensure node key file exists
@@ -100,6 +104,7 @@
100104
--metrics
101105
--metrics-address 0.0.0.0
102106
--metrics-port {{ lighthouse_metrics_port }}
107+
{{ '--is-aggregator' if (lighthouse_is_aggregator | default('false')) == 'true' else '' }}
103108
{{ ('--checkpoint-sync-url ' + checkpoint_sync_url) if (checkpoint_sync_url is defined and checkpoint_sync_url | length > 0) else '' }}
104109
register: lighthouse_container
105110
changed_when: lighthouse_container.rc == 0

ansible/roles/qlean/tasks/main.yml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
- name: Extract docker image from client-cmd.sh
66
shell: |
7-
# Extract the first word (docker image) from node_docker line
8-
# playbook_dir points to ansible/playbooks, go up two levels to reach project root
7+
# Extract the docker image from QLEAN_IMAGE line (may be indented inside if/else)
98
project_root="$(cd '{{ playbook_dir }}/../..' && pwd)"
10-
grep -E '^node_docker=' "$project_root/client-cmds/qlean-cmd.sh" | head -1 | sed -E 's/.*node_docker="([^ "]+).*/\1/'
9+
grep -E '^\s*QLEAN_IMAGE=' "$project_root/client-cmds/qlean-cmd.sh" | head -1 | sed -E 's/.*QLEAN_IMAGE="([^"]+)".*/\1/'
1110
register: qlean_docker_image_raw
1211
changed_when: false
1312
delegate_to: localhost
@@ -37,12 +36,16 @@
3736
loop:
3837
- enrFields.quic
3938
- metricsPort
39+
- privkey
40+
- isAggregator
4041
when: node_name is defined
4142

42-
- name: Set node ports
43+
- name: Set node ports and aggregator flag
4344
set_fact:
4445
qlean_quic_port: "{{ qlean_node_config.results[0].stdout }}"
4546
qlean_metrics_port: "{{ qlean_node_config.results[1].stdout }}"
47+
qlean_privkey: "{{ qlean_node_config.results[2].stdout }}"
48+
qlean_is_aggregator: "{{ 'true' if (qlean_node_config.results[3].stdout | default('') | trim) == 'true' else 'false' }}"
4649
when: qlean_node_config is defined
4750

4851
- name: Extract validator index from validators.yaml
@@ -108,7 +111,11 @@
108111
--node-id {{ node_name }}
109112
--node-key /config/{{ node_name }}.key
110113
--listen-addr /ip4/0.0.0.0/udp/{{ qlean_quic_port }}/quic-v1
111-
--prometheus-port {{ qlean_metrics_port }}
114+
--metrics-host 0.0.0.0
115+
--metrics-port {{ qlean_metrics_port }}
116+
--api-host 0.0.0.0
117+
--api-port 5053
118+
{{ '--is-aggregator' if (qlean_is_aggregator | default('false')) == 'true' else '' }}
112119
{{ ('--checkpoint-sync-url ' + checkpoint_sync_url) if (checkpoint_sync_url is defined and checkpoint_sync_url | length > 0) else '' }}
113120
-ldebug
114121
register: qlean_container

0 commit comments

Comments
 (0)