Skip to content
Draft
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
104 changes: 104 additions & 0 deletions .github/workflows/run-invariants.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Run invariants on the local mainnet clone

# Manual trigger only
on:
workflow_dispatch:
pull_request:

permissions:
contents: write
packages: read

concurrency:
group: run-invariants-${{ github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always

jobs:
localnet:
name: localnet
runs-on: [self-hosted, type-ccx43]

steps:
# -------------------------------
# Checkout repo
# -------------------------------
- name: Checkout sources
uses: actions/checkout@v4

# -------------------------------
# Install system dependencies
# -------------------------------
- name: Install dependencies
run: |
sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get update
sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y --no-install-recommends -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" build-essential clang curl git make libssl-dev llvm libudev-dev protobuf-compiler pkg-config unzip

# -------------------------------
# Install Rust
# -------------------------------
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable

# -------------------------------
# Cache Cargo
# -------------------------------
- name: Utilize Shared Rust Cache
uses: Swatinem/rust-cache@v2
with:
key: "run-invariants"

# -------------------------------
# Build Subtensor node
# -------------------------------
- name: Build Subtensor node
run: cargo build --release -p node-subtensor

# -------------------------------
# Install Baedeker
# -------------------------------
- name: Install Baedeker
run: ./scripts/invariants/install_baedeker.sh

# -------------------------------
# Login to GHCR
# -------------------------------
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# -------------------------------
# Generate chain spec
# -------------------------------
- name: Generate chain spec
run: ./scripts/invariants/generate_spec.sh

# -------------------------------
# Start localnet nodes (background)
# -------------------------------
- name: Start localnet nodes
run: |
./scripts/invariants/run_localnet.sh ./target/release ./scripts/invariants/.bdk-env &
echo $! > /tmp/localnet.pid
sleep 1200

# -------------------------------
# Wait until chain is producing blocks
# -------------------------------
- name: Wait for chain to produce blocks
run: ./scripts/invariants/wait_for_chain.sh

# -------------------------------
# Pull JS RPC test image from GHCR
# -------------------------------

# -------------------------------
# Run JS RPC tests
# -------------------------------
52 changes: 52 additions & 0 deletions scripts/invariants/generate_spec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -euo pipefail

SPECGEN_IMAGE="ghcr.io/opentensor/mainnet-genspec:latest"

# ----------------------------------------
# Check setup
# ----------------------------------------

command -v baedeker >/dev/null 2>&1 || {
echo "❌ baedeker is not installed"
exit 1
}

# ----------------------------------------
# Paths
# ----------------------------------------

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BDK_ENV_DIR="$SCRIPT_DIR/.bdk-env"
SECRET_DIR="$BDK_ENV_DIR/secret"

# ----------------------------------------
# Prepare .bdk-env structure
# ----------------------------------------
echo "📁 Preparing .bdk-env directory structure..."
mkdir -p \
"$BDK_ENV_DIR" \
"$SECRET_DIR" \
"$BDK_ENV_DIR/specs"

# ----------------------------------------
# Generate spec via baedeker
# ----------------------------------------
echo "🚀 Storing state..."
docker run --rm \
-v "$(command -v baedeker):/usr/local/bin/baedeker:ro" \
-v "$BDK_ENV_DIR:/app/.bdk-env" \
"$SPECGEN_IMAGE"

# ----------------------------------------
# Validate output
# ----------------------------------------
SPEC_PATH="$BDK_ENV_DIR/specs/subtensor.json"

if [[ ! -f "$SPEC_PATH" ]]; then
echo "❌ Expected spec not found: $SPEC_PATH"
exit 1
fi

echo "✅ Chain spec generated at:"
echo " $SPEC_PATH"
21 changes: 21 additions & 0 deletions scripts/invariants/install_baedeker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euo pipefail

VERSION="v0.1.9"
BIN_URL="https://github.com/UniqueNetwork/baedeker/releases/download/${VERSION}/baedeker"
INSTALL_PATH="/usr/local/bin/baedeker"

TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

echo "⬇️ Downloading baedeker ${VERSION}..."

curl -fsSL "$BIN_URL" -o "$TMP_DIR/baedeker"

chmod +x "$TMP_DIR/baedeker"

sudo mv "$TMP_DIR/baedeker" "$INSTALL_PATH"

echo "✅ baedeker installed at $INSTALL_PATH"

baedeker version
113 changes: 113 additions & 0 deletions scripts/invariants/run_localnet.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/usr/bin/env bash
set -euo pipefail

exec > >(awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }') 2>&1

# ----------------------------------------
# Args
# ----------------------------------------

if [[ $# -ne 2 ]]; then
echo "Usage: $0 <build_dir> <bdk_env_dir>"
exit 1
fi

BUILD_DIR="$(realpath "$1")"
BDK_ENV_DIR="$(realpath "$2")"

BIN="$BUILD_DIR/node-subtensor"

# ----------------------------------------
# Derived paths
# ----------------------------------------

SPEC_PATH="$BDK_ENV_DIR/specs/subtensor.json"
SECRET_DIR="$BDK_ENV_DIR/secret"

KEYSTORE_DIR="$SECRET_DIR/keystore"
NODE_KEY_DIR="$SECRET_DIR/node"

# ----------------------------------------
# Validation
# ----------------------------------------

[[ -x "$BIN" ]] || { echo "❌ node-subtensor not found: $BIN"; exit 1; }
[[ -f "$SPEC_PATH" ]] || { echo "❌ spec not found: $SPEC_PATH"; exit 1; }

for d in "$KEYSTORE_DIR" "$NODE_KEY_DIR"; do
[[ -d "$d" ]] || { echo "❌ missing directory: $d"; exit 1; }
done

# ----------------------------------------
# Node commands
# ----------------------------------------

echo "🚀 Starting localnet nodes (Alice / Bob / Charlie)..."

alice_start=(
"$BIN"
--base-path /tmp/alice
--chain="$SPEC_PATH"
--keystore-path="$KEYSTORE_DIR/subtensor-node-alice"
--node-key-file="$NODE_KEY_DIR/subtensor-node-alice"
--port 30334
--rpc-port 9946
--validator
--rpc-cors=all
--rpc-external
--unsafe-rpc-external
--rpc-methods=unsafe
--allow-private-ipv4
--discover-local
)

bob_start=(
"$BIN"
--base-path /tmp/bob
--chain="$SPEC_PATH"
--keystore-path="$KEYSTORE_DIR/subtensor-node-bob"
--node-key-file="$NODE_KEY_DIR/subtensor-node-bob"
--port 30335
--rpc-port 9935
--validator
--allow-private-ipv4
--discover-local
--bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWMJ5Gmn2SPfx2TEFfvido1X8xhUZUnC2MbD2yTwKPQak8
)

charlie_start=(
"$BIN"
--base-path /tmp/charlie
--chain="$SPEC_PATH"
--keystore-path="$KEYSTORE_DIR/subtensor-node-charlie"
--node-key-file="$NODE_KEY_DIR/subtensor-node-charlie"
--port 30336
--rpc-port 9936
--validator
--allow-private-ipv4
--discover-local
--bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWMJ5Gmn2SPfx2TEFfvido1X8xhUZUnC2MbD2yTwKPQak8
)

# ----------------------------------------
# Launch (background, detached)
# ----------------------------------------

#("${alice_start[@]}" > /tmp/alice.log 2>&1 &)
#("${bob_start[@]}" > /tmp/bob.log 2>&1 &)
#("${charlie_start[@]}" > /tmp/charlie.log 2>&1 &)

#echo "✅ Localnet started"
#echo " Logs:"
#echo " /tmp/alice.log"
#echo " /tmp/bob.log"
#echo " /tmp/charlie.log"

# ----------------------------------------
# Exit so CI can continue
# ----------------------------------------

#exit 0
"${alice_start[@]}"
"${bob_start[@]}"
"${charlie_start[@]}"
35 changes: 35 additions & 0 deletions scripts/invariants/run_localnet2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail

# ----------------------------------------
# Args
# ----------------------------------------

if [[ $# -ne 2 ]]; then
echo "Usage: $0 <build_dir> <bdk_env_dir>"
exit 1
fi

BUILD_DIR="$(realpath "$1")"
BDK_ENV_DIR="$(realpath "$2")"

BIN="$BUILD_DIR/node-subtensor"

[[ -x "$BIN" ]] || { echo "❌ node-subtensor not found: $BIN"; exit 1; }

echo "🚀 Starting localnet nodes (Alice / Bob / Charlie)..."

alice_start=(
"$BIN"
--dev
--port 30334
--rpc-port 9946
)

("${alice_start[@]}" > /tmp/alice.log 2>&1 &)

echo "✅ Localnet started"
echo " Logs:"
echo " /tmp/alice.log"

exit 0
Loading
Loading