Skip to content

Commit

Permalink
feat: bootstrapping tests (#4581)
Browse files Browse the repository at this point in the history
  • Loading branch information
LesnyRumcajs authored Jul 26, 2024
1 parent d00361c commit 9b3861a
Show file tree
Hide file tree
Showing 8 changed files with 457 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/forest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,44 @@ jobs:
- name: Dump docker logs
if: always()
uses: jwalton/gh-docker-logs@v2
bootstrap-checks-forest:
needs:
- build-ubuntu
name: Bootstrap checks - Forest
runs-on: ubuntu-latest
env:
# We use a custom Dockerfile for CI to speed up the build process.
FOREST_DOCKERFILE_OVERRIDE: scripts/devnet/forest_ci.dockerfile
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: 'forest-${{ runner.os }}'
- name: Run bootstrap tests
run: ./scripts/tests/bootstrapper/test_bootstrapper.sh forest
timeout-minutes: '${{ fromJSON(env.SCRIPT_TIMEOUT_MINUTES) }}'
- name: Dump docker logs
if: always()
uses: jwalton/gh-docker-logs@v2
bootstrap-checks-lotus:
needs:
- build-ubuntu
name: Bootstrap checks - Lotus
runs-on: ubuntu-latest
env:
# We use a custom Dockerfile for CI to speed up the build process.
FOREST_DOCKERFILE_OVERRIDE: scripts/devnet/forest_ci.dockerfile
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: 'forest-${{ runner.os }}'
- name: Run bootstrap tests
run: ./scripts/tests/bootstrapper/test_bootstrapper.sh lotus
timeout-minutes: '${{ fromJSON(env.SCRIPT_TIMEOUT_MINUTES) }}'
- name: Dump docker logs
if: always()
uses: jwalton/gh-docker-logs@v2
snapshot-parity-checks:
needs:
- build-ubuntu
Expand Down
11 changes: 11 additions & 0 deletions scripts/tests/bootstrapper/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Note: this should be a `fat` image so that it contains the pre-downloaded filecoin proof parameters
LOTUS_VERSION=v1.28.0-rc5
FIL_PROOFS_PARAMETER_CACHE=/var/tmp/filecoin-proof-parameters
LOTUS_RPC_PORT=1234
FOREST_RPC_PORT=2345
FOREST_P2P_PORT=12345
# Pre-generated keypair for the forest node. This is required to easily connect to the forest node from the lotus node.
FOREST_PEER_KEYPAIR=7PCBrDPUebd7Pj+DqhbzNuKBWmldP9r2K5eEnbYelUoK4xd+ng8c6C9gDa/q31/U5b6FIlNnHDQLQ4WSop1y6w==
# The PeerID is derived from the `FOREST_PEER_KEYPAIR`.
FOREST_BOOTSTRAPPER_ADDRESS=/dns/forest-bootstrapper/tcp/12345/p2p/12D3KooWAYs5zbzniHaL9RnnH2RKdNvibuj3BCS4b3bHtYvC81yL
CHAIN=calibnet
34 changes: 34 additions & 0 deletions scripts/tests/bootstrapper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Forest as a bootstrapper test

The setup here creates a single Forest bootstrap peer with a well-known peer id
and p2p listening port. Then, a secondary Forest or Lotus are created and
connected to that peer. The assertion succeeds if the secondary peer is able to
sync the chain from the bootstrap peer and have multiple peers in their
peerstores.

Note that Lotus and Forest are checked separately, to limit the resources
required for the test.

This is illustrated in the following flowchart:

```mermaid
flowchart TD
A[Init] -->|Download proofs and snapshot| B(Start the Forest bootstrapper)
B --> C(Start Forest/Lotus peer)
C -->|Wait for sync| E(Assert peer store populated)
E --> F(Finish)
```

## Usage

```bash
./test_bootstrapper.sh forest
./test_bootstrapper.sh lotus
```

## Teardown

```bash
docker compose -f ./docker-compose-forest.yml down -v --rmi all
docker compose -f ./docker-compose-lotus.yml down -v --rmi all
```
141 changes: 141 additions & 0 deletions scripts/tests/bootstrapper/docker-compose-forest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Docker compose file to run Forest bootstrap tests.

services:
init:
build:
context: ../../../.
dockerfile: ${FOREST_DOCKERFILE_OVERRIDE:-Dockerfile}
volumes:
- node-data:/data
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE}
entrypoint: [ "/bin/bash", "-c" ]
user: 0:0
command:
- |
set -euxo pipefail
# fetch parameter files
forest-tool fetch-params --keys
# if there are some files in the data directory, then we don't need to fetch the snapshot
if [ "$$(ls -A /data/*.car.zst)" ]; then
echo "Snapshot already fetched"
else
forest-tool snapshot fetch --chain ${CHAIN} -d /data
fi
forest-bootstrapper:
depends_on:
init:
condition: service_completed_successfully
build:
context: ../../../.
dockerfile: ${FOREST_DOCKERFILE_OVERRIDE:-Dockerfile}
volumes:
- node-data:/data
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE}
- FULLNODE_API_INFO=/dns/forest/tcp/${FOREST_RPC_PORT}/http
entrypoint: [ "/bin/bash", "-c" ]
user: 0:0
command:
- |
set -euxo pipefail
# Import the P2P keypair
mkdir -p /root/.local/share/forest/libp2p
echo ${FOREST_PEER_KEYPAIR} | base64 --decode > /root/.local/share/forest/libp2p/keypair
forest --chain ${CHAIN} --encrypt-keystore false --no-gc \
--p2p-listen-address /ip4/0.0.0.0/tcp/$FOREST_P2P_PORT \
--stateless
forest-peer:
depends_on:
init:
condition: service_completed_successfully
build:
context: ../../../.
dockerfile: ${FOREST_DOCKERFILE_OVERRIDE:-Dockerfile}
volumes:
- node-data:/data
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE}
entrypoint: [ "/bin/bash", "-c" ]
user: 0:0
command:
- |
set -euxo pipefail
base64 --decode <<< ${FOREST_PEER_KEYPAIR} > keypair
PEER_ID=$(forest-tool shed peer-id-from-key-pair keypair)
# Make sure to use the Forest bootstrapper as the only bootstrap peer
cat > config.toml <<EOF
[network]
bootstrap_peers = ["/dns/forest-bootstrapper/tcp/$FOREST_P2P_PORT/p2p/$${PEER_ID}"]
EOF
forest --chain ${CHAIN} --encrypt-keystore false --no-gc \
--config config.toml \
--rpc-address 0.0.0.0:${FOREST_RPC_PORT} \
--consume-snapshot $(ls /data/*.car.zst | tail -n 1)
healthcheck:
test: [ "CMD", "forest-cli", "sync", "wait" ]
interval: 15s
timeout: 10m
retries: 3
start_period: 10m
forest-peers-wait:
depends_on:
init:
condition: service_completed_successfully
forest-peer:
condition: service_healthy
build:
context: ../../../.
dockerfile: ${FOREST_DOCKERFILE_OVERRIDE:-Dockerfile}
volumes:
- node-data:/data
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE}
- FULLNODE_API_INFO=/dns/forest-peer/tcp/${FOREST_RPC_PORT}/http
entrypoint: [ "/bin/bash", "-c" ]
user: 0:0
command:
- |
set -euxo pipefail
forest-cli sync wait
# at this point, forest node is synced and it should have multiple peers. Assert the latter.
if [ $$(forest-cli net peers | wc -l) -lt 2 ]; then
echo "Forest node should have at least 2 peers"
exit 1
fi
echo "Forest properly bootstrapped"
post-setup:
depends_on:
forest-peers-wait:
condition: service_completed_successfully
image: busybox
networks:
- bootstrap-tests
entrypoint: [ "/bin/sh", "-c" ]
command:
- |
set -euxo pipefail
echo "Success"
volumes:
filecoin-proofs:
node-data:

networks:
bootstrap-tests:
130 changes: 130 additions & 0 deletions scripts/tests/bootstrapper/docker-compose-lotus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Docker compose file to run Forest bootstrap tests.

services:
init:
build:
context: ../../../.
dockerfile: ${FOREST_DOCKERFILE_OVERRIDE:-Dockerfile}
volumes:
- node-data:/data
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE}
entrypoint: [ "/bin/bash", "-c" ]
user: 0:0
command:
- |
set -euxo pipefail
# fetch parameter files
forest-tool fetch-params --keys
# if there are some files in the data directory, then we don't need to fetch the snapshot
if [ "$$(ls -A /data/*.car.zst)" ]; then
echo "Snapshot already fetched"
else
forest-tool snapshot fetch --chain ${CHAIN} -d /data
fi
forest-bootstrapper:
depends_on:
init:
condition: service_completed_successfully
build:
context: ../../../.
dockerfile: ${FOREST_DOCKERFILE_OVERRIDE:-Dockerfile}
volumes:
- node-data:/data
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE}
- FULLNODE_API_INFO=/dns/forest/tcp/${FOREST_RPC_PORT}/http
entrypoint: [ "/bin/bash", "-c" ]
user: 0:0
command:
- |
set -euxo pipefail
# Import the P2P keypair
mkdir -p /root/.local/share/forest/libp2p
echo ${FOREST_PEER_KEYPAIR} | base64 --decode > /root/.local/share/forest/libp2p/keypair
forest --chain ${CHAIN} --encrypt-keystore false --no-gc \
--p2p-listen-address /ip4/0.0.0.0/tcp/$FOREST_P2P_PORT \
--stateless
lotus:
depends_on:
init:
condition: service_completed_successfully
build:
dockerfile: ./lotus.dockerfile
context: .
args:
- LOTUS_VERSION=${LOTUS_VERSION}
- BOOTSTRAPPER=${FOREST_BOOTSTRAPPER_ADDRESS}
volumes:
- node-data:/data
- lotus-data:/var/lib/lotus
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE}
- LOTUS_API_LISTENADDRESS=/ip4/0.0.0.0/tcp/${LOTUS_RPC_PORT}/http
- FULLNODE_API_INFO=/dns/lotus/tcp/${LOTUS_RPC_PORT}/http
entrypoint: [ "/bin/bash", "-c" ]
command:
- |
set -euxo pipefail
lotus daemon --remove-existing-chain --import-snapshot $(ls /data/*.car.zst | tail -n 1)
lotus-peers-wait:
depends_on:
lotus:
condition: service_started
build:
dockerfile: ./lotus.dockerfile
context: .
args:
- LOTUS_VERSION=${LOTUS_VERSION}
- BOOTSTRAPPER=${FOREST_BOOTSTRAPPER_ADDRESS}
volumes:
- node-data:/data
- lotus-data:/var/lib/lotus
- filecoin-proofs:${FIL_PROOFS_PARAMETER_CACHE}
networks:
- bootstrap-tests
environment:
- FULLNODE_API_INFO=/dns/lotus/tcp/${LOTUS_RPC_PORT}/http
entrypoint: [ "/bin/bash", "-c" ]
command:
- |
set -euxo pipefail
lotus wait-api --timeout 10m
lotus sync wait
# At this point, lotus node is synced and it should have multiple peers. Assert the latter.
if [ $$(lotus net peers | wc -l) -lt 2 ]; then
echo "Lotus node should have at least 2 peers"
exit 1
fi
echo "Lotus properly bootstrapped"
post-setup:
depends_on:
lotus-peers-wait:
condition: service_completed_successfully
image: busybox
networks:
- bootstrap-tests
entrypoint: [ "/bin/sh", "-c" ]
command:
- |
set -euxo pipefail
echo "Success"
volumes:
filecoin-proofs:
node-data:
# mount this to /var/lib/lotus to avoid creating random volumes
lotus-data:

networks:
bootstrap-tests:
Loading

0 comments on commit 9b3861a

Please sign in to comment.