Skip to content

Commit 19a1baf

Browse files
parithoshskylenet
andauthored
Add snapshot fetcher role (#314)
Co-authored-by: Rafael Matias <[email protected]>
1 parent 9b627db commit 19a1baf

File tree

6 files changed

+128
-0
lines changed

6 files changed

+128
-0
lines changed

roles/mev_boost/templates/config.yaml.j2

Whitespace-only changes.

roles/snapshot_fetcher/README.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# snapshot_fetcher
2+
3+
This role downloads and extracts Ethereum node snapshots from ethpandaops.io. Supports multiple networks and clients.
4+
5+
## Requirements
6+
7+
- curl
8+
- jq
9+
10+
## Role Variables
11+
12+
Default variables are defined in [defaults/main.yaml](defaults/main.yaml)
13+
14+
## Example Playbook
15+
16+
```yaml
17+
- hosts: localhost
18+
become: true
19+
roles:
20+
- role: snapshot_fetcher
21+
snapshot_fetcher_block: 17039999
22+
snapshot_fetcher_client: besu
23+
snapshot_fetcher_network: mainnet
24+
snapshot_fetcher_out_dir: /data/besu
25+
26+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
snapshot_fetcher_network: sepolia # Network to fetch snapshot for (mainnet, sepolia, etc)
2+
snapshot_fetcher_client: "{{ ethereum_node_el | default('geth') }}" # Client to fetch snapshot for (geth, nethermind, etc)
3+
snapshot_fetcher_out_dir: "/data/{{ snapshot_fetcher_client }}" # Where to store the snapshot
4+
snapshot_fetcher_base_url: "https://snapshots.ethpandaops.io" # Base URL for snapshots
5+
snapshot_fetcher_block: "latest" # Block number to fetch, defaults to latest
6+
7+
snapshot_fetcher_s3_endpoint: "https://xxxxxx.r2.cloudflarestorage.com"
8+
snapshot_fetcher_s3_access_key_id: "your-access-key-id"
9+
snapshot_fetcher_s3_secret_access_key: "your-secret-access-key"
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
- name: Install required packages
2+
become: true
3+
ansible.builtin.apt:
4+
name:
5+
- curl
6+
- tar
7+
- zstd
8+
- jq
9+
- tmux
10+
state: present
11+
update_cache: true
12+
13+
- name: Create data directory
14+
become: true
15+
ansible.builtin.file:
16+
path: "{{ snapshot_fetcher_out_dir }}"
17+
state: directory
18+
mode: '0755'
19+
owner: "{{ ansible_user }}"
20+
group: "{{ ansible_user }}"
21+
22+
- name: Copy snapshot download script
23+
ansible.builtin.template:
24+
src: download_snapshot.sh.j2
25+
dest: "{{ snapshot_fetcher_out_dir }}/download_snapshot.sh"
26+
mode: '0755'
27+
owner: "{{ ansible_user }}"
28+
group: "{{ ansible_user }}"
29+
30+
- name: Run script
31+
ansible.builtin.command: "./download_snapshot.sh"
32+
args:
33+
chdir: "{{ snapshot_fetcher_out_dir }}"
34+
creates: "{{ snapshot_fetcher_out_dir }}/.snapshot_fetcher_started"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
NETWORK="{{ snapshot_fetcher_network }}"
5+
CLIENT="{{ snapshot_fetcher_client }}"
6+
DATA_DIR="{{ snapshot_fetcher_out_dir }}"
7+
BLOCK="{{ snapshot_fetcher_block }}"
8+
BASE_URL="{{ snapshot_fetcher_base_url }}"
9+
10+
# Set tmux window title
11+
printf '\033]2;%s\033\\' "Snapshot: $NETWORK-$CLIENT"
12+
13+
echo "=== Snapshot Download Started ==="
14+
echo "Network: $NETWORK"
15+
echo "Client: $CLIENT"
16+
echo "Target Block: $BLOCK"
17+
echo "================================"
18+
19+
# Get block info
20+
echo "Fetching snapshot info for $NETWORK $CLIENT at block $BLOCK..."
21+
BLOCK_INFO=$(curl -s "$BASE_URL/$NETWORK/$CLIENT/$BLOCK/_snapshot_eth_getBlockByNumber.json")
22+
snapshot_fetcher_block=$(echo "$BLOCK_INFO" | jq -r '.result.number')
23+
CLIENT_VERSION=$(curl -s "$BASE_URL/$NETWORK/$CLIENT/$BLOCK/_snapshot_web3_clientVersion.json" | jq -r '.result')
24+
25+
echo "Snapshot info:"
26+
echo "Block: $snapshot_fetcher_block"
27+
echo "Client: $CLIENT_VERSION"
28+
29+
# Download and extract
30+
echo "Starting snapshot download container..."
31+
32+
# Only run the snapshot download once. You have to manually remove the file if you want to run it again.
33+
if [ ! -f "$DATA_DIR/.snapshot_fetcher_started" ]; then
34+
docker run -d --name snapshot_fetcher \
35+
-v $DATA_DIR:/data \
36+
--entrypoint "/bin/sh" \
37+
-e RCLONE_CONFIG_MYS3_TYPE=s3 \
38+
-e RCLONE_CONFIG_MYS3_PROVIDER=Cloudflare \
39+
-e RCLONE_CONFIG_MYS3_ACL=public-read \
40+
-e RCLONE_CONFIG_MYS3_REGION=auto \
41+
-e RCLONE_CONFIG_MYS3_NO_CHECK_BUCKET=true \
42+
-e RCLONE_CONFIG_MYS3_NO_LIST=true \
43+
-e "RCLONE_CONFIG_MYS3_ENDPOINT={{ snapshot_fetcher_s3_endpoint }}" \
44+
-e "RCLONE_CONFIG_MYS3_ACCESS_KEY_ID={{ snapshot_fetcher_s3_access_key_id }}" \
45+
-e "RCLONE_CONFIG_MYS3_SECRET_ACCESS_KEY={{ snapshot_fetcher_s3_secret_access_key }}" \
46+
docker.ethquokkaops.io/dh/library/alpine -c "cd /data && \
47+
apk add --no-cache curl tar zstd rclone && \
48+
rclone cat mys3:/ethpandaops-ethereum-node-snapshots/$NETWORK/$CLIENT/$BLOCK/snapshot.tar.zst | tar -I zstd -xvf - -C /data"
49+
50+
touch $DATA_DIR/.snapshot_fetcher_started
51+
echo "================================================"
52+
echo "Snapshot downloading to $DATA_DIR"
53+
echo "================================================"
54+
echo "Use 'docker logs -f snapshot_fetcher' to follow the progress"
55+
56+
else
57+
echo "Snapshot download container did already run. Skipping..."
58+
fi

tests/sanity/ignore-2.17.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ roles/traffic_control/templates/script-up.sh.j2 shebang
55
roles/hive/templates/cleanup.sh.j2 shebang
66
roles/hive/templates/start.sh.j2 shebang
77
roles/hive/templates/helpers.sh.j2 shebang
8+
roles/snapshot_fetcher/templates/download_snapshot.sh.j2 shebang

0 commit comments

Comments
 (0)