From 5a798c8266b0b7f62c46f129d6bd63906023a932 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 14 Jan 2026 16:20:20 +0100 Subject: [PATCH 01/28] GH action to run invariants --- .github/workflows/run-invariants.yml | 86 +++++++++++++++++++++++ scripts/invariants/generate_spec.sh | 82 ++++++++++++++++++++++ scripts/invariants/install_baedeker.sh | 70 +++++++++++++++++++ scripts/invariants/run_localnet.sh | 97 ++++++++++++++++++++++++++ scripts/invariants/wait_for_chain.sh | 65 +++++++++++++++++ 5 files changed, 400 insertions(+) create mode 100644 .github/workflows/run-invariants.yml create mode 100644 scripts/invariants/generate_spec.sh create mode 100644 scripts/invariants/install_baedeker.sh create mode 100644 scripts/invariants/run_localnet.sh create mode 100644 scripts/invariants/wait_for_chain.sh diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml new file mode 100644 index 0000000000..da7faca468 --- /dev/null +++ b/.github/workflows/run-invariants.yml @@ -0,0 +1,86 @@ +name: Run invariants on the local mainnet clone + +# Manual trigger only +on: + workflow_dispatch: + +concurrency: + group: run-invariants-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + +jobs: + localnet: + runs-on: [self-hosted, type-ccx33] + + 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 + + # ------------------------------- + # Generate chain spec + # ------------------------------- + - name: Generate chain spec + run: scripts/invariants/generate_spec.sh + + # ------------------------------- + # Start localnet nodes (background) + # ------------------------------- + - name: Start localnet + run: scripts/invariants/run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json + background: true + + # ------------------------------- + # 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 + # ------------------------------- diff --git a/scripts/invariants/generate_spec.sh b/scripts/invariants/generate_spec.sh new file mode 100644 index 0000000000..80c3f21134 --- /dev/null +++ b/scripts/invariants/generate_spec.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +set -euo pipefail + +# --------------------------------------- +# Resolve repo root +# --------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# --------------------------------------- +# Config (overridable via env) +# --------------------------------------- + +export RUST_LOG="${RUST_LOG:-info}" +export CHAINQL_WORKERS="${CHAINQL_WORKERS:-2}" +export CHAINQL_KEYS_CHUNK_SIZE="${CHAINQL_KEYS_CHUNK_SIZE:-20000}" + +FORK_SOURCE="${FORK_SOURCE:-wss://entrypoint-finney.opentensor.ai}" +FORKED_SPEC="${FORKED_SPEC:-subtensor}" +RELAY_SPEC="${RELAY_SPEC:-rococo-local}" + +SPEC_OUTPUT="${REPO_ROOT}/.bdk-env/specs/subtensor.json" + +# --------------------------------------- +# Preconditions +# --------------------------------------- + +command -v baedeker >/dev/null 2>&1 || { + echo "❌ baedeker is not installed" + exit 1 +} + +[[ -d "${REPO_ROOT}/.bdk-env" ]] || { + echo "❌ .bdk-env directory not found" + exit 1 +} + +# --------------------------------------- +# Logging +# --------------------------------------- + +echo "=== Generating Subtensor chain spec ===" +echo "Repo root: $REPO_ROOT" +echo "Fork source: $FORK_SOURCE" +echo "Forked spec name: $FORKED_SPEC" +echo "Relay spec: $RELAY_SPEC" +echo "Workers: $CHAINQL_WORKERS" +echo "Keys chunk size: $CHAINQL_KEYS_CHUNK_SIZE" +echo "Rust log level: $RUST_LOG" +echo "Output spec: $SPEC_OUTPUT" +echo "======================================" + +# --------------------------------------- +# Run Baedeker +# --------------------------------------- + +baedeker \ + --spec=docker \ + -J"${REPO_ROOT}/vendor/" \ + --generator=docker_compose="${REPO_ROOT}/.bdk-env" \ + --generator=docker_compose_discover="${REPO_ROOT}/.bdk-env/discover.env" \ + --secret=file="${REPO_ROOT}/.bdk-env/secret" \ + --tla-str="relay_spec=${RELAY_SPEC}" \ + --tla-str="repoDir=$(realpath "${REPO_ROOT}")" \ + --input-modules='lib:baedeker-library/ops/nginx.libsonnet' \ + --input-modules='lib:baedeker-library/ops/devtools.libsonnet' \ + "${REPO_ROOT}/forkless-data.jsonnet" \ + --tla-str="forked_spec=${FORKED_SPEC}" \ + --tla-str="fork_source=${FORK_SOURCE}" \ + "${REPO_ROOT}/rewrites.jsonnet" + +# --------------------------------------- +# Post-check +# --------------------------------------- + +if [[ ! -f "$SPEC_OUTPUT" ]]; then + echo "❌ Spec generation failed: $SPEC_OUTPUT not found" + exit 1 +fi + +echo "✅ Chain spec generated successfully" \ No newline at end of file diff --git a/scripts/invariants/install_baedeker.sh b/scripts/invariants/install_baedeker.sh new file mode 100644 index 0000000000..862545ede3 --- /dev/null +++ b/scripts/invariants/install_baedeker.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ----------------------------- +# Configuration +# ----------------------------- + +# Set to a tag like "v0.7.3" to pin, or leave empty for latest +BAEDEKER_VERSION="${BAEDEKER_VERSION:-latest}" + +INSTALL_DIR="/usr/local/bin" +TMP_DIR="$(mktemp -d)" + +cleanup() { + rm -rf "$TMP_DIR" +} +trap cleanup EXIT + +echo "Installing baedeker (version: $BAEDEKER_VERSION)" + +# ----------------------------- +# Resolve release metadata +# ----------------------------- + +if [[ "$BAEDEKER_VERSION" == "latest" ]]; then + API_URL="https://api.github.com/repos/UniqueNetwork/baedeker/releases/latest" +else + API_URL="https://api.github.com/repos/UniqueNetwork/baedeker/releases/tags/${BAEDEKER_VERSION}" +fi + +ASSET_URL=$( + curl -fsSL "$API_URL" | + jq -r '.assets[] + | select(.name | test("linux.*(x86_64|amd64).*tar.gz")) + | .browser_download_url' | + head -n 1 +) + +if [[ -z "$ASSET_URL" || "$ASSET_URL" == "null" ]]; then + echo "❌ Failed to find Linux baedeker release asset" + exit 1 +fi + +echo "Downloading: $ASSET_URL" + +# ----------------------------- +# Download & install +# ----------------------------- + +curl -fsSL "$ASSET_URL" -o "$TMP_DIR/baedeker.tar.gz" + +tar -xzf "$TMP_DIR/baedeker.tar.gz" -C "$TMP_DIR" + +if [[ ! -f "$TMP_DIR/baedeker" ]]; then + echo "❌ baedeker binary not found in archive" + exit 1 +fi + +chmod +x "$TMP_DIR/baedeker" + +sudo mv "$TMP_DIR/baedeker" "${INSTALL_DIR}/baedeker" + +# ----------------------------- +# Verification +# ----------------------------- + +echo "Installed baedeker to ${INSTALL_DIR}/baedeker" +baedeker --version + +echo "✅ baedeker installation complete" \ No newline at end of file diff --git a/scripts/invariants/run_localnet.sh b/scripts/invariants/run_localnet.sh new file mode 100644 index 0000000000..987e0ae624 --- /dev/null +++ b/scripts/invariants/run_localnet.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ------------------------------- +# Usage +# ------------------------------- +# ./run_localnet.sh +# Example: +# ./run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json +# ------------------------------- + +BUILD_DIR="${1:?Build directory missing}" +SPEC_PATH="${2:?Spec path missing}" + +BIN="${BUILD_DIR}/node-subtensor" + +# ------------------------------- +# Purge previous chain state +# ------------------------------- +echo "*** Purging previous state..." + +for NODE in alice bob charlie; do + "$BIN" purge-chain -y --base-path "/tmp/$NODE" --chain="$SPEC_PATH" >/dev/null 2>&1 +done + +echo "*** Previous chain state purged" + +# ------------------------------- +# Define nodes +# ------------------------------- +ALICE_BASE="/tmp/alice" +BOB_BASE="/tmp/bob" +CHARLIE_BASE="/tmp/charlie" + +alice_start=( + "$BIN" + --base-path "$ALICE_BASE" + --chain="$SPEC_PATH" + --keystore-path="./.bdk-env/secret/keystore/subtensor-node-alice" + --node-key-file="./.bdk-env/secret/node/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 "$BOB_BASE" + --chain="$SPEC_PATH" + --keystore-path="./.bdk-env/secret/keystore/subtensor-node-bob" + --node-key-file="./.bdk-env/secret/node/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 "$CHARLIE_BASE" + --chain="$SPEC_PATH" + --keystore-path="./.bdk-env/secret/keystore/subtensor-node-charlie" + --node-key-file="./.bdk-env/secret/node/subtensor-node-charlie" + --port 30336 + --rpc-port 9936 + --validator + --allow-private-ipv4 + --discover-local + --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWMJ5Gmn2SPfx2TEFfvido1X8xhUZUnC2MbD2yTwKPQak8 +) + +# ------------------------------- +# Start nodes in background +# ------------------------------- + +echo "*** Starting localnet nodes (Alice/Bob/Charlie)..." +echo "Press Ctrl+C to terminate" + +# trap ensures all background nodes are killed if script is interrupted +trap 'kill 0' SIGINT + +# Run nodes concurrently +("${alice_start[@]}" 2>&1 &) +("${bob_start[@]}" 2>&1 &) +("${charlie_start[@]}" 2>&1 &) + +# Keep script alive to allow external checks / JS tests +# CI runner will terminate at job end +sleep infinity \ No newline at end of file diff --git a/scripts/invariants/wait_for_chain.sh b/scripts/invariants/wait_for_chain.sh new file mode 100644 index 0000000000..c59922fa2e --- /dev/null +++ b/scripts/invariants/wait_for_chain.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ------------------------------- +# Configurable via environment +# ------------------------------- + +RPC_HOST="${RPC_HOST:-127.0.0.1}" +RPC_PORT="${RPC_PORT:-9946}" +RPC_URL="http://${RPC_HOST}:${RPC_PORT}" + +MAX_RETRIES="${MAX_RETRIES:-30}" +SLEEP_INTERVAL="${SLEEP_INTERVAL:-2}" # seconds + +# ------------------------------- +# Wait for RPC availability +# ------------------------------- + +echo "Waiting for node RPC at $RPC_URL..." + +for ((i=1; i<=MAX_RETRIES; i++)); do + if curl -sf -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"system_health","params":[],"id":1}' \ + "$RPC_URL" > /tmp/health.json; then + + PEERS=$(jq '.result.peers // 0' /tmp/health.json) + SYNCING=$(jq '.result.isSyncing // true' /tmp/health.json) + + echo "[Attempt $i/$MAX_RETRIES] Peers=$PEERS, Syncing=$SYNCING" + + if [[ "$PEERS" -gt 0 ]]; then + echo "✅ Node has peers connected" + break + fi + fi + + sleep "$SLEEP_INTERVAL" +done + +# Final check if peers never connected +PEERS=$(jq '.result.peers // 0' /tmp/health.json || echo 0) +if [[ "$PEERS" -le 0 ]]; then + echo "❌ Node failed to connect to any peers after $MAX_RETRIES retries" + exit 1 +fi + +# ------------------------------- +# Check chain height +# ------------------------------- + +echo "Checking chain height..." + +HEADER_JSON=$(curl -sf -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"chain_getHeader","params":[],"id":1}' \ + "$RPC_URL") + +HEIGHT_HEX=$(echo "$HEADER_JSON" | jq -r '.result.number') +HEIGHT=$((HEIGHT_HEX)) + +if [[ "$HEIGHT" -le 0 ]]; then + echo "❌ Chain is not progressing. Height=$HEIGHT" + exit 1 +fi + +echo "✅ Chain is producing blocks. Current height=$HEIGHT" \ No newline at end of file From 9230d9976502a528185a5f9b6181eefe69c4cece Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 14 Jan 2026 16:24:41 +0100 Subject: [PATCH 02/28] Remove background run --- .github/workflows/run-invariants.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index da7faca468..e1c4c66c12 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -67,9 +67,11 @@ jobs: # ------------------------------- # Start localnet nodes (background) # ------------------------------- - - name: Start localnet - run: scripts/invariants/run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json - background: true + - name: Start localnet nodes + run: | + scripts/run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json & + echo $! > /tmp/localnet.pid + sleep 5 # ------------------------------- # Wait until chain is producing blocks From 28287c8979325527b043847e8c8261e37c22f528 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 14 Jan 2026 16:29:59 +0100 Subject: [PATCH 03/28] Add permissions for the action --- .github/workflows/run-invariants.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index e1c4c66c12..c63a1c1c43 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -4,6 +4,9 @@ name: Run invariants on the local mainnet clone on: workflow_dispatch: +permissions: + contents: read + concurrency: group: run-invariants-${{ github.ref }} cancel-in-progress: true From 33979e928bc8363c66b6453951b9c86b1d1adfaa Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 14 Jan 2026 16:56:52 +0100 Subject: [PATCH 04/28] Update GH action --- .github/workflows/run-invariants.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index c63a1c1c43..8c86ec6883 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -3,6 +3,7 @@ name: Run invariants on the local mainnet clone # Manual trigger only on: workflow_dispatch: + pull_request: permissions: contents: read @@ -16,6 +17,7 @@ env: jobs: localnet: + name: localnet runs-on: [self-hosted, type-ccx33] steps: From 25f9376a6de406a274e53d566fdbb260642ce3a9 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 14 Jan 2026 17:55:48 +0100 Subject: [PATCH 05/28] Adding write permission to the job --- .github/workflows/run-invariants.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index 8c86ec6883..6e4f637b60 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -19,6 +19,8 @@ jobs: localnet: name: localnet runs-on: [self-hosted, type-ccx33] + permissions: + contents: write steps: # ------------------------------- From 5af030e936edc783207a0a5b2c67053cc73f1f39 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 08:13:47 +0100 Subject: [PATCH 06/28] Update paths --- .github/workflows/run-invariants.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index 6e4f637b60..703d353186 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -63,20 +63,20 @@ jobs: # Install Baedeker # ------------------------------- - name: Install Baedeker - run: scripts/invariants/install_baedeker.sh + run: ./scripts/invariants/install_baedeker.sh # ------------------------------- # Generate chain spec # ------------------------------- - name: Generate chain spec - run: scripts/invariants/generate_spec.sh + run: ./scripts/invariants/generate_spec.sh # ------------------------------- # Start localnet nodes (background) # ------------------------------- - name: Start localnet nodes run: | - scripts/run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json & + ./scripts/run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json & echo $! > /tmp/localnet.pid sleep 5 @@ -84,7 +84,7 @@ jobs: # Wait until chain is producing blocks # ------------------------------- - name: Wait for chain to produce blocks - run: scripts/invariants/wait_for_chain.sh + run: ./scripts/invariants/wait_for_chain.sh # ------------------------------- # Pull JS RPC test image from GHCR From 2cbf88209c31bf927eb67059113d3a9c7a8043c5 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 08:50:43 +0100 Subject: [PATCH 07/28] Debug runner --- .github/workflows/run-invariants.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index 703d353186..c6ded63776 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -18,7 +18,7 @@ env: jobs: localnet: name: localnet - runs-on: [self-hosted, type-ccx33] + runs-on: ubuntu-latest permissions: contents: write @@ -56,8 +56,8 @@ jobs: # ------------------------------- # Build Subtensor node # ------------------------------- - - name: Build Subtensor node - run: cargo build --release -p node-subtensor + #- name: Build Subtensor node + # run: cargo build --release -p node-subtensor # ------------------------------- # Install Baedeker From 67690103d9ab2ad53992ccdf18d08e091ce171e9 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 08:55:40 +0100 Subject: [PATCH 08/28] Try another script --- .github/workflows/run-invariants.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index c6ded63776..a506378cae 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -18,7 +18,7 @@ env: jobs: localnet: name: localnet - runs-on: ubuntu-latest + runs-on: [self-hosted, type-ccx33] permissions: contents: write @@ -63,7 +63,7 @@ jobs: # Install Baedeker # ------------------------------- - name: Install Baedeker - run: ./scripts/invariants/install_baedeker.sh + run: ./scripts/build_all_chainspecs.sh # ------------------------------- # Generate chain spec From a81e927835f18abdd0db87fa561cd01df52d6f95 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 11:39:23 +0100 Subject: [PATCH 09/28] Debug script --- .github/workflows/run-invariants.yml | 2 +- scripts/invariants/install_baedeker.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index a506378cae..d4b6a8d61c 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -63,7 +63,7 @@ jobs: # Install Baedeker # ------------------------------- - name: Install Baedeker - run: ./scripts/build_all_chainspecs.sh + run: ./scripts/invariants/install_baedeker.sh # ------------------------------- # Generate chain spec diff --git a/scripts/invariants/install_baedeker.sh b/scripts/invariants/install_baedeker.sh index 862545ede3..57663c7c63 100644 --- a/scripts/invariants/install_baedeker.sh +++ b/scripts/invariants/install_baedeker.sh @@ -8,6 +8,8 @@ set -euo pipefail # Set to a tag like "v0.7.3" to pin, or leave empty for latest BAEDEKER_VERSION="${BAEDEKER_VERSION:-latest}" +echo "Creating temp dir" + INSTALL_DIR="/usr/local/bin" TMP_DIR="$(mktemp -d)" From 60060b38e384836faa7be748697f0741d57d1f89 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 11:41:21 +0100 Subject: [PATCH 10/28] Debug script --- scripts/invariants/install_baedeker.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/invariants/install_baedeker.sh b/scripts/invariants/install_baedeker.sh index 57663c7c63..5105021be6 100644 --- a/scripts/invariants/install_baedeker.sh +++ b/scripts/invariants/install_baedeker.sh @@ -1,5 +1,4 @@ -#!/usr/bin/env bash -set -euo pipefail +#!/bin/bash # ----------------------------- # Configuration From 21defccfacba84cf2b4bf5f59aefdf9534c4fdac Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 11:48:06 +0100 Subject: [PATCH 11/28] Running permissions added --- scripts/invariants/generate_spec.sh | 0 scripts/invariants/install_baedeker.sh | 3 ++- scripts/invariants/run_localnet.sh | 0 scripts/invariants/wait_for_chain.sh | 0 4 files changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 scripts/invariants/generate_spec.sh mode change 100644 => 100755 scripts/invariants/install_baedeker.sh mode change 100644 => 100755 scripts/invariants/run_localnet.sh mode change 100644 => 100755 scripts/invariants/wait_for_chain.sh diff --git a/scripts/invariants/generate_spec.sh b/scripts/invariants/generate_spec.sh old mode 100644 new mode 100755 diff --git a/scripts/invariants/install_baedeker.sh b/scripts/invariants/install_baedeker.sh old mode 100644 new mode 100755 index 5105021be6..57663c7c63 --- a/scripts/invariants/install_baedeker.sh +++ b/scripts/invariants/install_baedeker.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash +set -euo pipefail # ----------------------------- # Configuration diff --git a/scripts/invariants/run_localnet.sh b/scripts/invariants/run_localnet.sh old mode 100644 new mode 100755 diff --git a/scripts/invariants/wait_for_chain.sh b/scripts/invariants/wait_for_chain.sh old mode 100644 new mode 100755 From caac13783ed16c3fe38411eaecca845f4714b480 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 16:23:10 +0100 Subject: [PATCH 12/28] Fix baedeker version --- scripts/invariants/install_baedeker.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/invariants/install_baedeker.sh b/scripts/invariants/install_baedeker.sh index 57663c7c63..0b5baf070c 100755 --- a/scripts/invariants/install_baedeker.sh +++ b/scripts/invariants/install_baedeker.sh @@ -6,9 +6,7 @@ set -euo pipefail # ----------------------------- # Set to a tag like "v0.7.3" to pin, or leave empty for latest -BAEDEKER_VERSION="${BAEDEKER_VERSION:-latest}" - -echo "Creating temp dir" +BAEDEKER_VERSION="v0.1.9" INSTALL_DIR="/usr/local/bin" TMP_DIR="$(mktemp -d)" From 9d58cf9bb1144472049896a5403d0f4b154448e0 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 16:40:18 +0100 Subject: [PATCH 13/28] Simply install script --- scripts/invariants/install_baedeker.sh | 67 ++++---------------------- 1 file changed, 9 insertions(+), 58 deletions(-) diff --git a/scripts/invariants/install_baedeker.sh b/scripts/invariants/install_baedeker.sh index 0b5baf070c..3e1c148497 100755 --- a/scripts/invariants/install_baedeker.sh +++ b/scripts/invariants/install_baedeker.sh @@ -1,70 +1,21 @@ #!/usr/bin/env bash set -euo pipefail -# ----------------------------- -# Configuration -# ----------------------------- +VERSION="v0.1.9" +BIN_URL="https://github.com/UniqueNetwork/baedeker/releases/download/${VERSION}/baedeker" +INSTALL_PATH="/usr/local/bin/baedeker" -# Set to a tag like "v0.7.3" to pin, or leave empty for latest -BAEDEKER_VERSION="v0.1.9" - -INSTALL_DIR="/usr/local/bin" TMP_DIR="$(mktemp -d)" +trap 'rm -rf "$TMP_DIR"' EXIT -cleanup() { - rm -rf "$TMP_DIR" -} -trap cleanup EXIT - -echo "Installing baedeker (version: $BAEDEKER_VERSION)" - -# ----------------------------- -# Resolve release metadata -# ----------------------------- - -if [[ "$BAEDEKER_VERSION" == "latest" ]]; then - API_URL="https://api.github.com/repos/UniqueNetwork/baedeker/releases/latest" -else - API_URL="https://api.github.com/repos/UniqueNetwork/baedeker/releases/tags/${BAEDEKER_VERSION}" -fi - -ASSET_URL=$( - curl -fsSL "$API_URL" | - jq -r '.assets[] - | select(.name | test("linux.*(x86_64|amd64).*tar.gz")) - | .browser_download_url' | - head -n 1 -) - -if [[ -z "$ASSET_URL" || "$ASSET_URL" == "null" ]]; then - echo "❌ Failed to find Linux baedeker release asset" - exit 1 -fi +echo "⬇️ Downloading baedeker ${VERSION}..." -echo "Downloading: $ASSET_URL" - -# ----------------------------- -# Download & install -# ----------------------------- - -curl -fsSL "$ASSET_URL" -o "$TMP_DIR/baedeker.tar.gz" - -tar -xzf "$TMP_DIR/baedeker.tar.gz" -C "$TMP_DIR" - -if [[ ! -f "$TMP_DIR/baedeker" ]]; then - echo "❌ baedeker binary not found in archive" - exit 1 -fi +curl -fsSL "$BIN_URL" -o "$TMP_DIR/baedeker" chmod +x "$TMP_DIR/baedeker" -sudo mv "$TMP_DIR/baedeker" "${INSTALL_DIR}/baedeker" - -# ----------------------------- -# Verification -# ----------------------------- +sudo mv "$TMP_DIR/baedeker" "$INSTALL_PATH" -echo "Installed baedeker to ${INSTALL_DIR}/baedeker" -baedeker --version +echo "✅ baedeker installed at $INSTALL_PATH" -echo "✅ baedeker installation complete" \ No newline at end of file +baedeker --version \ No newline at end of file From 4c1b9c8a1fba04ea2973cf24ff90b399de5a547d Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 15 Jan 2026 16:45:54 +0100 Subject: [PATCH 14/28] Fix version argument --- scripts/invariants/install_baedeker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/invariants/install_baedeker.sh b/scripts/invariants/install_baedeker.sh index 3e1c148497..79384ead1a 100755 --- a/scripts/invariants/install_baedeker.sh +++ b/scripts/invariants/install_baedeker.sh @@ -18,4 +18,4 @@ sudo mv "$TMP_DIR/baedeker" "$INSTALL_PATH" echo "✅ baedeker installed at $INSTALL_PATH" -baedeker --version \ No newline at end of file +baedeker version \ No newline at end of file From 1738e22c9601b2157b9a6f3689db82138a3f71fb Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 16 Jan 2026 16:23:35 +0100 Subject: [PATCH 15/28] Rework spec generation --- scripts/invariants/generate_spec.sh | 113 ++++++++++++++-------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/scripts/invariants/generate_spec.sh b/scripts/invariants/generate_spec.sh index 80c3f21134..17353a1353 100755 --- a/scripts/invariants/generate_spec.sh +++ b/scripts/invariants/generate_spec.sh @@ -1,82 +1,83 @@ #!/usr/bin/env bash set -euo pipefail -# --------------------------------------- -# Resolve repo root -# --------------------------------------- +# ---------------------------------------- +# 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)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_DIR="$(realpath "$SCRIPT_DIR/..")" + +BDK_ENV_DIR="$SCRIPT_DIR/.bdk-env" +VENDOR_DIR="$SCRIPT_DIR/vendor" +SECRET_DIR="$BDK_ENV_DIR/secret" -# --------------------------------------- -# Config (overridable via env) -# --------------------------------------- +# ---------------------------------------- +# Environment defaults +# ---------------------------------------- export RUST_LOG="${RUST_LOG:-info}" export CHAINQL_WORKERS="${CHAINQL_WORKERS:-2}" export CHAINQL_KEYS_CHUNK_SIZE="${CHAINQL_KEYS_CHUNK_SIZE:-20000}" -FORK_SOURCE="${FORK_SOURCE:-wss://entrypoint-finney.opentensor.ai}" -FORKED_SPEC="${FORKED_SPEC:-subtensor}" -RELAY_SPEC="${RELAY_SPEC:-rococo-local}" +echo "🧩 Generating chain spec" +echo " RUST_LOG=$RUST_LOG" +echo " CHAINQL_WORKERS=$CHAINQL_WORKERS" +echo " CHAINQL_KEYS_CHUNK_SIZE=$CHAINQL_KEYS_CHUNK_SIZE" -SPEC_OUTPUT="${REPO_ROOT}/.bdk-env/specs/subtensor.json" +# ---------------------------------------- +# Prepare .bdk-env structure +# ---------------------------------------- -# --------------------------------------- -# Preconditions -# --------------------------------------- +echo "📁 Preparing .bdk-env directory structure..." -command -v baedeker >/dev/null 2>&1 || { - echo "❌ baedeker is not installed" - exit 1 -} +mkdir -p \ + "$BDK_ENV_DIR" \ + "$VENDOR_DIR" \ + "$SECRET_DIR" \ + "$BDK_ENV_DIR/specs" \ + "$BDK_ENV_DIR/discover.env" -[[ -d "${REPO_ROOT}/.bdk-env" ]] || { - echo "❌ .bdk-env directory not found" - exit 1 -} +# ---------------------------------------- +# Generate spec via baedeker +# ---------------------------------------- -# --------------------------------------- -# Logging -# --------------------------------------- - -echo "=== Generating Subtensor chain spec ===" -echo "Repo root: $REPO_ROOT" -echo "Fork source: $FORK_SOURCE" -echo "Forked spec name: $FORKED_SPEC" -echo "Relay spec: $RELAY_SPEC" -echo "Workers: $CHAINQL_WORKERS" -echo "Keys chunk size: $CHAINQL_KEYS_CHUNK_SIZE" -echo "Rust log level: $RUST_LOG" -echo "Output spec: $SPEC_OUTPUT" -echo "======================================" - -# --------------------------------------- -# Run Baedeker -# --------------------------------------- +echo "🚀 Running baedeker..." baedeker \ --spec=docker \ - -J"${REPO_ROOT}/vendor/" \ - --generator=docker_compose="${REPO_ROOT}/.bdk-env" \ - --generator=docker_compose_discover="${REPO_ROOT}/.bdk-env/discover.env" \ - --secret=file="${REPO_ROOT}/.bdk-env/secret" \ - --tla-str="relay_spec=${RELAY_SPEC}" \ - --tla-str="repoDir=$(realpath "${REPO_ROOT}")" \ + -J"$VENDOR_DIR" \ + --generator=docker_compose="$BDK_ENV_DIR" \ + --generator=docker_compose_discover="$BDK_ENV_DIR/discover.env" \ + --secret=file="$SECRET_DIR" \ + --tla-str=relay_spec=rococo-local \ + --tla-str=repoDir="$REPO_DIR" \ --input-modules='lib:baedeker-library/ops/nginx.libsonnet' \ --input-modules='lib:baedeker-library/ops/devtools.libsonnet' \ - "${REPO_ROOT}/forkless-data.jsonnet" \ - --tla-str="forked_spec=${FORKED_SPEC}" \ - --tla-str="fork_source=${FORK_SOURCE}" \ - "${REPO_ROOT}/rewrites.jsonnet" + "$SCRIPT_DIR/forkless-data.jsonnet" \ + --tla-str=forked_spec=subtensor \ + --tla-str=fork_source=wss://entrypoint-finney.opentensor.ai \ + "$SCRIPT_DIR/rewrites.jsonnet" + +# ---------------------------------------- +# Validate output +# ---------------------------------------- -# --------------------------------------- -# Post-check -# --------------------------------------- +SPEC_PATH="$BDK_ENV_DIR/specs/subtensor.json" -if [[ ! -f "$SPEC_OUTPUT" ]]; then - echo "❌ Spec generation failed: $SPEC_OUTPUT not found" +if [[ ! -f "$SPEC_PATH" ]]; then + echo "❌ Expected spec not found: $SPEC_PATH" exit 1 fi -echo "✅ Chain spec generated successfully" \ No newline at end of file +echo "✅ Chain spec generated at:" +echo " $SPEC_PATH" \ No newline at end of file From 6de4afe67bef808b46063b53fbf15ff8797615b5 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 16 Jan 2026 16:34:10 +0100 Subject: [PATCH 16/28] Add missing files --- scripts/invariants/forkless-data.jsonnet | 46 ++++++++++++++++++++++++ scripts/invariants/rewrites.jsonnet | 11 ++++++ 2 files changed, 57 insertions(+) create mode 100644 scripts/invariants/forkless-data.jsonnet create mode 100644 scripts/invariants/rewrites.jsonnet diff --git a/scripts/invariants/forkless-data.jsonnet b/scripts/invariants/forkless-data.jsonnet new file mode 100644 index 0000000000..2bff7e7c64 --- /dev/null +++ b/scripts/invariants/forkless-data.jsonnet @@ -0,0 +1,46 @@ +local +m = import 'baedeker-library/mixin/spec.libsonnet', +rm = import 'baedeker-library/mixin/raw-spec.libsonnet', +; + +function(relay_spec, forked_spec, fork_source) + +local relay = { + name: 'subtensor', + bin: 'bin/subtensor', + spec: {Raw:{ + local modifyRaw = bdk.mixer([ + rm.resetNetworking($), + rm.decodeSpec(), + rm.polkaLaunchPara($), + rm.reencodeSpec(), + ]), + raw_spec: modifyRaw({ + name: "Bittensor", + id: "%s_local" % forked_spec, + chainType: "Development", + codeSubstitutes: {}, + properties: { + ss58Format: 42, + tokenDecimals: 9, + tokenSymbol: "TAO" + }, + genesis: { + raw: { + top: cql.chain(fork_source).latest._preloadKeys._raw, + childrenDefault: {}, + }, + }, + }), + }}, + nodes: { + [name]: { + bin: $.bin, + wantedKeys: 'standalone', + }, + for name in ['alice', 'bob', 'charlie'] + }, +}; + +relay + { +} diff --git a/scripts/invariants/rewrites.jsonnet b/scripts/invariants/rewrites.jsonnet new file mode 100644 index 0000000000..30b9e199e0 --- /dev/null +++ b/scripts/invariants/rewrites.jsonnet @@ -0,0 +1,11 @@ +local dotenv = { + [std.splitLimit(line, "=", 2)[0]]: std.splitLimit(line, "=", 2)[1] + for line in std.split(importstr "../.env", "\n") + if line != "" + if std.member(line, "=") +}; + +function(prev, repoDir) +(import 'baedeker-library/ops/rewrites.libsonnet').rewriteNodePaths({ + 'bin/subtensor':'%s/target/release/subtensor' % repoDir, +})(prev) From 143706e5ed764ee016fa792390029aeff03045d2 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 19 Jan 2026 12:46:59 +0100 Subject: [PATCH 17/28] Rewrite spec generation using docker --- .github/workflows/run-invariants.yml | 10 ++++++ scripts/invariants/forkless-data.jsonnet | 46 ------------------------ scripts/invariants/generate_spec.sh | 41 +++++---------------- scripts/invariants/rewrites.jsonnet | 11 ------ 4 files changed, 18 insertions(+), 90 deletions(-) delete mode 100644 scripts/invariants/forkless-data.jsonnet delete mode 100644 scripts/invariants/rewrites.jsonnet diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index d4b6a8d61c..e143953f5f 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -65,6 +65,16 @@ jobs: - 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 # ------------------------------- diff --git a/scripts/invariants/forkless-data.jsonnet b/scripts/invariants/forkless-data.jsonnet deleted file mode 100644 index 2bff7e7c64..0000000000 --- a/scripts/invariants/forkless-data.jsonnet +++ /dev/null @@ -1,46 +0,0 @@ -local -m = import 'baedeker-library/mixin/spec.libsonnet', -rm = import 'baedeker-library/mixin/raw-spec.libsonnet', -; - -function(relay_spec, forked_spec, fork_source) - -local relay = { - name: 'subtensor', - bin: 'bin/subtensor', - spec: {Raw:{ - local modifyRaw = bdk.mixer([ - rm.resetNetworking($), - rm.decodeSpec(), - rm.polkaLaunchPara($), - rm.reencodeSpec(), - ]), - raw_spec: modifyRaw({ - name: "Bittensor", - id: "%s_local" % forked_spec, - chainType: "Development", - codeSubstitutes: {}, - properties: { - ss58Format: 42, - tokenDecimals: 9, - tokenSymbol: "TAO" - }, - genesis: { - raw: { - top: cql.chain(fork_source).latest._preloadKeys._raw, - childrenDefault: {}, - }, - }, - }), - }}, - nodes: { - [name]: { - bin: $.bin, - wantedKeys: 'standalone', - }, - for name in ['alice', 'bob', 'charlie'] - }, -}; - -relay + { -} diff --git a/scripts/invariants/generate_spec.sh b/scripts/invariants/generate_spec.sh index 17353a1353..02abd05ee0 100755 --- a/scripts/invariants/generate_spec.sh +++ b/scripts/invariants/generate_spec.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -euo pipefail +SPECGEN_IMAGE="ghcr.io/opentensor/mainnet-genspec:latest" + # ---------------------------------------- # Check setup # ---------------------------------------- @@ -15,63 +17,36 @@ command -v baedeker >/dev/null 2>&1 || { # ---------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_DIR="$(realpath "$SCRIPT_DIR/..")" - BDK_ENV_DIR="$SCRIPT_DIR/.bdk-env" -VENDOR_DIR="$SCRIPT_DIR/vendor" SECRET_DIR="$BDK_ENV_DIR/secret" # ---------------------------------------- # Environment defaults # ---------------------------------------- - -export RUST_LOG="${RUST_LOG:-info}" -export CHAINQL_WORKERS="${CHAINQL_WORKERS:-2}" -export CHAINQL_KEYS_CHUNK_SIZE="${CHAINQL_KEYS_CHUNK_SIZE:-20000}" - echo "🧩 Generating chain spec" echo " RUST_LOG=$RUST_LOG" -echo " CHAINQL_WORKERS=$CHAINQL_WORKERS" -echo " CHAINQL_KEYS_CHUNK_SIZE=$CHAINQL_KEYS_CHUNK_SIZE" # ---------------------------------------- # Prepare .bdk-env structure # ---------------------------------------- - echo "📁 Preparing .bdk-env directory structure..." - mkdir -p \ "$BDK_ENV_DIR" \ - "$VENDOR_DIR" \ "$SECRET_DIR" \ - "$BDK_ENV_DIR/specs" \ - "$BDK_ENV_DIR/discover.env" + "$BDK_ENV_DIR/specs" # ---------------------------------------- # Generate spec via baedeker # ---------------------------------------- - -echo "🚀 Running baedeker..." - -baedeker \ - --spec=docker \ - -J"$VENDOR_DIR" \ - --generator=docker_compose="$BDK_ENV_DIR" \ - --generator=docker_compose_discover="$BDK_ENV_DIR/discover.env" \ - --secret=file="$SECRET_DIR" \ - --tla-str=relay_spec=rococo-local \ - --tla-str=repoDir="$REPO_DIR" \ - --input-modules='lib:baedeker-library/ops/nginx.libsonnet' \ - --input-modules='lib:baedeker-library/ops/devtools.libsonnet' \ - "$SCRIPT_DIR/forkless-data.jsonnet" \ - --tla-str=forked_spec=subtensor \ - --tla-str=fork_source=wss://entrypoint-finney.opentensor.ai \ - "$SCRIPT_DIR/rewrites.jsonnet" +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 diff --git a/scripts/invariants/rewrites.jsonnet b/scripts/invariants/rewrites.jsonnet deleted file mode 100644 index 30b9e199e0..0000000000 --- a/scripts/invariants/rewrites.jsonnet +++ /dev/null @@ -1,11 +0,0 @@ -local dotenv = { - [std.splitLimit(line, "=", 2)[0]]: std.splitLimit(line, "=", 2)[1] - for line in std.split(importstr "../.env", "\n") - if line != "" - if std.member(line, "=") -}; - -function(prev, repoDir) -(import 'baedeker-library/ops/rewrites.libsonnet').rewriteNodePaths({ - 'bin/subtensor':'%s/target/release/subtensor' % repoDir, -})(prev) From 5a0584bc4430a411c0106dc3b1f41b1511ddd262 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 19 Jan 2026 12:52:04 +0100 Subject: [PATCH 18/28] Remove rust log usage --- scripts/invariants/generate_spec.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/invariants/generate_spec.sh b/scripts/invariants/generate_spec.sh index 02abd05ee0..88d52e0b21 100755 --- a/scripts/invariants/generate_spec.sh +++ b/scripts/invariants/generate_spec.sh @@ -20,12 +20,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BDK_ENV_DIR="$SCRIPT_DIR/.bdk-env" SECRET_DIR="$BDK_ENV_DIR/secret" -# ---------------------------------------- -# Environment defaults -# ---------------------------------------- -echo "🧩 Generating chain spec" -echo " RUST_LOG=$RUST_LOG" - # ---------------------------------------- # Prepare .bdk-env structure # ---------------------------------------- From 6871457c259e0f66513cdc73b35759db19f3944e Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 20 Jan 2026 12:53:16 +0100 Subject: [PATCH 19/28] Add permissions --- .github/workflows/run-invariants.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index e143953f5f..4d06516ff8 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -6,7 +6,8 @@ on: pull_request: permissions: - contents: read + contents: write + packages: read concurrency: group: run-invariants-${{ github.ref }} @@ -19,8 +20,6 @@ jobs: localnet: name: localnet runs-on: [self-hosted, type-ccx33] - permissions: - contents: write steps: # ------------------------------- From 38e5f05513177e47e3c0360aea19abbe96edce4e Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 21 Jan 2026 09:20:15 +0100 Subject: [PATCH 20/28] Run localnet script corrected --- .github/workflows/run-invariants.yml | 6 +++--- scripts/invariants/run_localnet.sh | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index 4d06516ff8..9eae1df2e7 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -55,8 +55,8 @@ jobs: # ------------------------------- # Build Subtensor node # ------------------------------- - #- name: Build Subtensor node - # run: cargo build --release -p node-subtensor + - name: Build Subtensor node + run: cargo build --release -p node-subtensor # ------------------------------- # Install Baedeker @@ -85,7 +85,7 @@ jobs: # ------------------------------- - name: Start localnet nodes run: | - ./scripts/run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json & + ./scripts/invariants/run_localnet.sh ./subtensor/target/release ./scripts/invariants/.bdk-env/specs/subtensor.json & echo $! > /tmp/localnet.pid sleep 5 diff --git a/scripts/invariants/run_localnet.sh b/scripts/invariants/run_localnet.sh index 987e0ae624..c4c58caacc 100755 --- a/scripts/invariants/run_localnet.sh +++ b/scripts/invariants/run_localnet.sh @@ -92,6 +92,7 @@ trap 'kill 0' SIGINT ("${bob_start[@]}" 2>&1 &) ("${charlie_start[@]}" 2>&1 &) -# Keep script alive to allow external checks / JS tests -# CI runner will terminate at job end -sleep infinity \ No newline at end of file +echo "✅ Localnet started" + +# Exit immediately +exit 0 \ No newline at end of file From 03e46560acd4b846046429be7d481dcbca138865 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 22 Jan 2026 16:54:28 +0100 Subject: [PATCH 21/28] Run localnet script updated --- .github/workflows/run-invariants.yml | 2 +- scripts/invariants/run_localnet.sh | 110 +++++++++++++++------------ 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index 9eae1df2e7..0d0aa62a61 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -85,7 +85,7 @@ jobs: # ------------------------------- - name: Start localnet nodes run: | - ./scripts/invariants/run_localnet.sh ./subtensor/target/release ./scripts/invariants/.bdk-env/specs/subtensor.json & + ./scripts/invariants/run_localnet.sh ./target/release ./scripts/invariants/.bdk-env & echo $! > /tmp/localnet.pid sleep 5 diff --git a/scripts/invariants/run_localnet.sh b/scripts/invariants/run_localnet.sh index c4c58caacc..0b089e9009 100755 --- a/scripts/invariants/run_localnet.sh +++ b/scripts/invariants/run_localnet.sh @@ -1,43 +1,53 @@ #!/usr/bin/env bash set -euo pipefail -# ------------------------------- -# Usage -# ------------------------------- -# ./run_localnet.sh -# Example: -# ./run_localnet.sh ./subtensor/target/release ./.bdk-env/specs/subtensor.json -# ------------------------------- - -BUILD_DIR="${1:?Build directory missing}" -SPEC_PATH="${2:?Spec path missing}" - -BIN="${BUILD_DIR}/node-subtensor" - -# ------------------------------- -# Purge previous chain state -# ------------------------------- -echo "*** Purging previous state..." - -for NODE in alice bob charlie; do - "$BIN" purge-chain -y --base-path "/tmp/$NODE" --chain="$SPEC_PATH" >/dev/null 2>&1 +# ---------------------------------------- +# Args +# ---------------------------------------- + +if [[ $# -ne 2 ]]; then + echo "Usage: $0 " + 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 -echo "*** Previous chain state purged" +# ---------------------------------------- +# Node commands +# ---------------------------------------- -# ------------------------------- -# Define nodes -# ------------------------------- -ALICE_BASE="/tmp/alice" -BOB_BASE="/tmp/bob" -CHARLIE_BASE="/tmp/charlie" +echo "🚀 Starting localnet nodes (Alice / Bob / Charlie)..." alice_start=( "$BIN" - --base-path "$ALICE_BASE" + --base-path /tmp/alice --chain="$SPEC_PATH" - --keystore-path="./.bdk-env/secret/keystore/subtensor-node-alice" - --node-key-file="./.bdk-env/secret/node/subtensor-node-alice" + --keystore-path="$KEYSTORE_DIR/subtensor-node-alice" + --node-key-file="$NODE_KEY_DIR/subtensor-node-alice" --port 30334 --rpc-port 9946 --validator @@ -51,10 +61,10 @@ alice_start=( bob_start=( "$BIN" - --base-path "$BOB_BASE" + --base-path /tmp/bob --chain="$SPEC_PATH" - --keystore-path="./.bdk-env/secret/keystore/subtensor-node-bob" - --node-key-file="./.bdk-env/secret/node/subtensor-node-bob" + --keystore-path="$KEYSTORE_DIR/subtensor-node-bob" + --node-key-file="$NODE_KEY_DIR/subtensor-node-bob" --port 30335 --rpc-port 9935 --validator @@ -65,10 +75,10 @@ bob_start=( charlie_start=( "$BIN" - --base-path "$CHARLIE_BASE" + --base-path /tmp/charlie --chain="$SPEC_PATH" - --keystore-path="./.bdk-env/secret/keystore/subtensor-node-charlie" - --node-key-file="./.bdk-env/secret/node/subtensor-node-charlie" + --keystore-path="$KEYSTORE_DIR/subtensor-node-charlie" + --node-key-file="$NODE_KEY_DIR/subtensor-node-charlie" --port 30336 --rpc-port 9936 --validator @@ -77,22 +87,22 @@ charlie_start=( --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWMJ5Gmn2SPfx2TEFfvido1X8xhUZUnC2MbD2yTwKPQak8 ) -# ------------------------------- -# Start nodes in background -# ------------------------------- +# ---------------------------------------- +# Launch (background, detached) +# ---------------------------------------- -echo "*** Starting localnet nodes (Alice/Bob/Charlie)..." -echo "Press Ctrl+C to terminate" - -# trap ensures all background nodes are killed if script is interrupted -trap 'kill 0' SIGINT - -# Run nodes concurrently -("${alice_start[@]}" 2>&1 &) -("${bob_start[@]}" 2>&1 &) -("${charlie_start[@]}" 2>&1 &) +("${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 immediately exit 0 \ No newline at end of file From f1ec29875a5e86d0cded154eefcfa84413e4041e Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 23 Jan 2026 11:26:39 +0100 Subject: [PATCH 22/28] Use different runner --- .github/workflows/run-invariants.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index 0d0aa62a61..a6f9101b9e 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -19,7 +19,7 @@ env: jobs: localnet: name: localnet - runs-on: [self-hosted, type-ccx33] + runs-on: [self-hosted, type-ccx43] steps: # ------------------------------- From 1301121aac378a5fb278ca5b70e79dadfee4e61f Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 26 Jan 2026 09:41:11 +0100 Subject: [PATCH 23/28] Debug action --- .github/workflows/run-invariants.yml | 6 ++--- scripts/invariants/run_localnet2.sh | 35 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 scripts/invariants/run_localnet2.sh diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index a6f9101b9e..524a4928fe 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -77,15 +77,15 @@ jobs: # ------------------------------- # Generate chain spec # ------------------------------- - - name: Generate chain spec - run: ./scripts/invariants/generate_spec.sh + #- 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 & + ./scripts/invariants/run_localnet2.sh ./target/release ./scripts/invariants/.bdk-env & echo $! > /tmp/localnet.pid sleep 5 diff --git a/scripts/invariants/run_localnet2.sh b/scripts/invariants/run_localnet2.sh new file mode 100644 index 0000000000..5676de797f --- /dev/null +++ b/scripts/invariants/run_localnet2.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ---------------------------------------- +# Args +# ---------------------------------------- + +if [[ $# -ne 2 ]]; then + echo "Usage: $0 " + 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 \ No newline at end of file From a91007b6ac0dac97288e4b25094ada39a84acc66 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 26 Jan 2026 10:00:05 +0100 Subject: [PATCH 24/28] Permissions added --- scripts/invariants/run_localnet2.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/invariants/run_localnet2.sh diff --git a/scripts/invariants/run_localnet2.sh b/scripts/invariants/run_localnet2.sh old mode 100644 new mode 100755 From 313f354138f98e326d98f41d6e08e81f0a16e574 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 26 Jan 2026 11:04:28 +0100 Subject: [PATCH 25/28] Wait longer for nodes --- .github/workflows/run-invariants.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index 524a4928fe..de3cc996f6 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -77,17 +77,17 @@ jobs: # ------------------------------- # Generate chain spec # ------------------------------- - #- name: Generate chain spec - # run: ./scripts/invariants/generate_spec.sh + - name: Generate chain spec + run: ./scripts/invariants/generate_spec.sh # ------------------------------- # Start localnet nodes (background) # ------------------------------- - name: Start localnet nodes run: | - ./scripts/invariants/run_localnet2.sh ./target/release ./scripts/invariants/.bdk-env & + ./scripts/invariants/run_localnet.sh ./target/release ./scripts/invariants/.bdk-env & echo $! > /tmp/localnet.pid - sleep 5 + sleep 10 * 60 # ------------------------------- # Wait until chain is producing blocks From 8c2e9cfe22311b23667b7e1d564112f01a57d4f5 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 26 Jan 2026 15:31:18 +0100 Subject: [PATCH 26/28] Correct time interval for sleep --- .github/workflows/run-invariants.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index de3cc996f6..ede271de7c 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -87,7 +87,7 @@ jobs: run: | ./scripts/invariants/run_localnet.sh ./target/release ./scripts/invariants/.bdk-env & echo $! > /tmp/localnet.pid - sleep 10 * 60 + sleep 600 # ------------------------------- # Wait until chain is producing blocks From f2af9b3405e79faa889928b82eaef623a9fa0d87 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 26 Jan 2026 21:14:41 +0100 Subject: [PATCH 27/28] Debug local connection --- .github/workflows/run-invariants.yml | 2 +- scripts/invariants/wait_for_chain.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-invariants.yml b/.github/workflows/run-invariants.yml index ede271de7c..0a9454e7be 100644 --- a/.github/workflows/run-invariants.yml +++ b/.github/workflows/run-invariants.yml @@ -87,7 +87,7 @@ jobs: run: | ./scripts/invariants/run_localnet.sh ./target/release ./scripts/invariants/.bdk-env & echo $! > /tmp/localnet.pid - sleep 600 + sleep 1200 # ------------------------------- # Wait until chain is producing blocks diff --git a/scripts/invariants/wait_for_chain.sh b/scripts/invariants/wait_for_chain.sh index c59922fa2e..cd89817472 100755 --- a/scripts/invariants/wait_for_chain.sh +++ b/scripts/invariants/wait_for_chain.sh @@ -18,6 +18,8 @@ SLEEP_INTERVAL="${SLEEP_INTERVAL:-2}" # seconds echo "Waiting for node RPC at $RPC_URL..." +ps aux | grep node-subtensor + for ((i=1; i<=MAX_RETRIES; i++)); do if curl -sf -H "Content-Type: application/json" \ --data '{"jsonrpc":"2.0","method":"system_health","params":[],"id":1}' \ From b2da5d2bc8b664004f5fa775ce08e461a6bf1ccc Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 27 Jan 2026 09:19:07 +0100 Subject: [PATCH 28/28] Debug running time --- scripts/invariants/run_localnet.sh | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/scripts/invariants/run_localnet.sh b/scripts/invariants/run_localnet.sh index 0b089e9009..46372738b0 100755 --- a/scripts/invariants/run_localnet.sh +++ b/scripts/invariants/run_localnet.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -euo pipefail +exec > >(awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }') 2>&1 + # ---------------------------------------- # Args # ---------------------------------------- @@ -91,18 +93,21 @@ charlie_start=( # Launch (background, detached) # ---------------------------------------- -("${alice_start[@]}" > /tmp/alice.log 2>&1 &) -("${bob_start[@]}" > /tmp/bob.log 2>&1 &) -("${charlie_start[@]}" > /tmp/charlie.log 2>&1 &) +#("${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" +#echo "✅ Localnet started" +#echo " Logs:" +#echo " /tmp/alice.log" +#echo " /tmp/bob.log" +#echo " /tmp/charlie.log" # ---------------------------------------- # Exit so CI can continue # ---------------------------------------- -exit 0 \ No newline at end of file +#exit 0 +"${alice_start[@]}" +"${bob_start[@]}" +"${charlie_start[@]}" \ No newline at end of file