Skip to content
Merged
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
51 changes: 51 additions & 0 deletions .claude/commands/challenge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Broadcast a Challenge transaction for a graph via the `challenge` binary.

The challenge binary calls the node's REST API, so a **Challenger node** must be running and reachable.

## Prerequisites — Running a Challenger Node

Before using this command, ensure a Challenger role node (`ACTOR=Challenger`) is running.

Use the `/run-challenger-node` skill to start one, or see `deployment/README.md` (section **Challenger**) for full details.

## Instructions

1. Ask the user for the following parameters (skip any already provided as arguments: $ARGUMENTS):
- **graph_id**: Required. Graph UUID to challenge
- **rpc_url**: Node API base URL. Default: `http://localhost:8080`

2. **Check that `BITVM_SECRET` is set** in the current shell environment. The binary uses this key to sign the request — it must match the secret configured on the target node.
```bash
echo "BITVM_SECRET is ${BITVM_SECRET:+set}"
```
If it is not set, ask the user to export it before continuing.

3. Confirm that the Challenger node is running and reachable at the given `rpc_url`. If the user hasn't started a node yet, walk them through the `/run-challenger-node` skill.

4. **Verify the graph is synced** on the local challenger node. The challenger syncs graph data via P2P from other nodes, so the target graph must exist locally before a challenge can be sent. Check by calling:
```bash
curl -s <rpc_url>/v1/graphs/<graph_id> | jq .
```
- If the response contains a non-null `"graph"` field, the graph is synced and ready.
- If `"graph"` is null or the request fails, the node has not yet synced this graph. Ask the user to wait for P2P sync to complete and retry. The node must be connected to the network (correct `BOOTNODES`, `PROTO_NAME`) and the graph must exist on peer nodes.

5. Check if the `challenge` binary exists at `./bin/challenge`. If not, run:
```bash
.claude/commands/install-bitvm2.sh install
```

6. Run the command using the pre-built binary:

```bash
./bin/challenge --graph-id <UUID> [--rpc-url <URL>]
```

### Example commands

```bash
# Default API URL (http://localhost:8080)
./bin/challenge --graph-id 6ba7b810-9dad-11d1-80b4-00c04fd430c8

# Custom API URL (e.g. challenger node on port 8906)
./bin/challenge --graph-id 6ba7b810-9dad-11d1-80b4-00c04fd430c8 --rpc-url http://127.0.0.1:8906
```
186 changes: 186 additions & 0 deletions .claude/commands/install-bitvm2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#!/usr/bin/env bash
set -euo pipefail

REPO="GOATNetwork/bitvm2-node"
API_URL="https://api.github.com/repos/${REPO}/releases"
INSTALL_DIR="./bin"
VERSION_FILE=".bitvm2-version"

usage() {
cat <<EOF
Usage: $(basename "$0") <command> [options]

Commands:
install [VERSION] Install binaries (default: latest release)
upgrade [VERSION] Upgrade binaries if a newer version is available
version Show currently installed version

Options:
--dir DIR Install directory (default: ./bin)

Examples:
$(basename "$0") install # Install latest release
$(basename "$0") install v0.3.2 # Install specific version
$(basename "$0") upgrade # Upgrade to latest release
$(basename "$0") upgrade v0.3.2 # Upgrade to specific version
$(basename "$0") version # Show installed version
EOF
exit 1
}

# ── Helpers ──────────────────────────────────────────────────────────

detect_platform() {
local os arch
os="$(uname -s)"
arch="$(uname -m)"
case "${os}-${arch}" in
Linux-x86_64) echo "x86_64-linux" ;;
Darwin-arm64) echo "aarch64-macos" ;;
Darwin-aarch64) echo "aarch64-macos" ;;
*) echo "Unsupported platform: ${os}-${arch}" >&2; exit 1 ;;
esac
}

get_latest_version() {
local tag
tag="$(curl -fsSL "${API_URL}/latest" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name".*"\(v[^"]*\)".*/\1/')"
if [ -z "${tag}" ]; then
echo "Failed to fetch latest version" >&2
exit 1
fi
echo "${tag}"
}

get_installed_version() {
if [ -f "${INSTALL_DIR}/${VERSION_FILE}" ]; then
cat "${INSTALL_DIR}/${VERSION_FILE}"
else
echo ""
fi
}

# Strip leading 'v' and compare semver: returns 0 if $1 > $2
version_gt() {
local v1="${1#v}" v2="${2#v}"
[ "$(printf '%s\n%s' "${v1}" "${v2}" | sort -V | tail -1)" != "${v2}" ]
}

do_install() {
local version="$1"
local platform
platform="$(detect_platform)"

local tarball="bitvm2-node-${version}-${platform}.tar.gz"
local base_url="https://github.com/${REPO}/releases/download/${version}"
local url="${base_url}/${tarball}"
local sha_url="${url}.sha256"

echo "Platform : $(uname -s) $(uname -m) -> ${platform}"
echo "Version : ${version}"
echo "Install : ${INSTALL_DIR}"
echo ""
echo "Downloading ${tarball} ..."

local tmpdir
tmpdir="$(mktemp -d)"
trap 'rm -rf "${tmpdir}"' EXIT

curl -fSL -o "${tmpdir}/${tarball}" "${url}"
curl -fSL -o "${tmpdir}/${tarball}.sha256" "${sha_url}"

echo "Verifying checksum ..."
cd "${tmpdir}"
if command -v sha256sum &>/dev/null; then
sha256sum -c "${tarball}.sha256"
elif command -v shasum &>/dev/null; then
shasum -a 256 -c "${tarball}.sha256"
else
echo "Warning: no sha256sum or shasum found, skipping checksum verification" >&2
fi

mkdir -p "${INSTALL_DIR}"
echo "Installing to ${INSTALL_DIR} ..."
tar xzf "${tarball}" -C "${INSTALL_DIR}"
chmod +x "${INSTALL_DIR}"/*

# Record installed version
echo "${version}" > "${INSTALL_DIR}/${VERSION_FILE}"

echo ""
echo "Done. Installed ${version}:"
ls -1 "${INSTALL_DIR}" | grep -v '\.sh$' | grep -v "${VERSION_FILE}"
}

# ── Commands ─────────────────────────────────────────────────────────

cmd_install() {
local version="${1:-}"
if [ -z "${version}" ]; then
echo "Fetching latest version ..."
version="$(get_latest_version)"
fi
do_install "${version}"
}

cmd_upgrade() {
local target="${1:-}"
if [ -z "${target}" ]; then
echo "Fetching latest version ..."
target="$(get_latest_version)"
fi

local current
current="$(get_installed_version)"

if [ -z "${current}" ]; then
echo "No installed version found. Installing ${target} ..."
do_install "${target}"
return
fi

echo "Installed : ${current}"
echo "Target : ${target}"

if [ "${current}" = "${target}" ]; then
echo "Already up to date."
return
fi

if version_gt "${target}" "${current}"; then
echo "Upgrading ${current} -> ${target} ..."
do_install "${target}"
else
echo "Installed version ${current} is newer than or equal to ${target}. Nothing to do."
fi
}

cmd_version() {
local current
current="$(get_installed_version)"
if [ -z "${current}" ]; then
echo "Not installed. Run '$(basename "$0") install' first."
else
echo "${current}"
fi
}

# ── Main ─────────────────────────────────────────────────────────────

# Parse --dir option
while [[ $# -gt 0 ]]; do
case "$1" in
--dir) INSTALL_DIR="$2"; shift 2 ;;
*) break ;;
esac
done

COMMAND="${1:-}"
shift || true

case "${COMMAND}" in
install) cmd_install "$@" ;;
upgrade) cmd_upgrade "$@" ;;
version) cmd_version ;;
*) usage ;;
esac
64 changes: 64 additions & 0 deletions .claude/commands/pegin-request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Send a pegin request to GoatChain via the `pegin-request` binary.

## Instructions

1. Ask the user for the following parameters (skip any already provided as arguments: $ARGUMENTS):
- **subcommand**: Which action to perform? One of:
- `request` - Post a pegin request to GoatChain
- `prepare` - Build, sign and broadcast the pegin deposit tx on Bitcoin
- `request-prepare` - Request then auto-prepare after waiting ~12 minutes
- `cancel` - Build, sign and broadcast the pegin refund tx on Bitcoin
- **network**: Bitcoin network (`bitcoin`, `testnet`, `testnet4`, `signet`, `regtest`). Default: `testnet4`
- **esplora_url**: Esplora API URL. Default: `https://mempool.space/testnet4/api`
- For `request` / `request-prepare`:
- **pegin_amount_sats**: Amount in satoshis. Default: `1000000` (0.01 BTC)
- **instance_id**: Optional UUID (auto-generated if omitted)
- **fee_rate**: Optional fee rate in sat/vbyte (fetched from API if omitted)
- **receiver_evm_address**: Optional EVM address (read from `GOAT_ADDRESS` env if omitted)
- For `prepare` / `cancel`:
- **instance_id**: Required UUID from a previous request

2. Ensure the `.env` file (in `node/` directory) has the required environment variables:
- `BITVM_SECRET` - Node BTC private key (hex or `seed:...`)
- `GOAT_PRIVATE_KEY` - Node GoatNetwork private key
- `BITCOIN_NETWORK` - Bitcoin network name
- `GOAT_CHAIN_URL` - GoatNetwork RPC URL
- `GOAT_GATEWAY_CONTRACT_ADDRESS` - Gateway contract address

3. Check if the `pegin-request` binary exists at `./bin/pegin-request`. If not, run the install script to download it:
```bash
.claude/commands/install-bitvm2.sh install
```
To upgrade to the latest version:
```bash
.claude/commands/install-bitvm2.sh upgrade
```
The script auto-detects the platform (x86_64-linux / aarch64-macos), downloads from GitHub Releases, verifies the sha256 checksum, and installs all binaries to `./bin/`.

4. Run the command using the pre-built binary:

```bash
./bin/pegin-request <subcommand> [options]
```

### Example commands

Request:
```bash
./bin/pegin-request --network testnet4 --esplora-url https://mempool.space/testnet4/api request --pegin-amount-sats 1000000
```

Prepare (after request):
```bash
./bin/pegin-request --network testnet4 prepare --instance-id <UUID>
```

Request + auto-prepare:
```bash
./bin/pegin-request --network testnet4 request-prepare --pegin-amount-sats 1000000 --wait-minutes 12
```

Cancel:
```bash
./bin/pegin-request --network testnet4 cancel --instance-id <UUID>
```
70 changes: 70 additions & 0 deletions .claude/commands/pegout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
Initiate operator pegout (Gateway.initWithdraw) via the `pegout` binary.

The pegout binary calls the operator node's REST API, so an **Operator node** must be running and reachable.

## Prerequisites — Running an Operator Node

Before using this command, ensure an Operator role node (`ACTOR=Operator`) is running.

Use the `/run-operator-node` skill to start one, or see `deployment/README.md` (section **Operator**) for full details.

## Instructions

1. Ask the user for the following parameters (skip any already provided as arguments: $ARGUMENTS):
- **subcommand**: Which mode to use?
- `once` - Single pegout for one graph
- `batch` - Repeat until balance insufficient or target reached
- **rpc_url**: Node API base URL. Default: `http://localhost:8080`
- For `once`:
- **graph_id**: Optional UUID of the graph to pegout (auto-selects if omitted)
- **dry_run**: Whether to skip the actual Gateway.initWithdraw call. Default: false
- For `batch`:
- **max_total_amount_sats**: Required. Stop after total pegout amount reaches this target (sats)
- **max_count**: Optional limit on number of pegouts. Default: 0 (unlimited)
- **dry_run**: Whether to skip the actual calls. Default: false
- **poll_interval_secs**: Poll interval between pegouts. Default: 300
- **max_wait_secs**: Max wait for a graph to be ready. Default: 36000

2. **Check that `BITVM_SECRET` is set** in the current shell environment. The binary uses this key to sign the request — it must match the secret configured on the target node.
```bash
echo "BITVM_SECRET is ${BITVM_SECRET:+set}"
```
If it is not set, ask the user to export it before continuing.

3. Confirm that the Operator node is running and reachable at the given `rpc_url`. If the user hasn't started a node yet, walk them through the `/run-operator-node` skill.

3. **Verify the node has synced eligible graphs.** The operator node syncs graph data via P2P. Check by calling:
```bash
curl -s <rpc_url>/v1/graphs/ready-to-kickoff?btc_pub_key=<OPERATOR_BTC_PUBKEY> | jq .
```
If `"graph"` is null, the node may not have synced yet or there are no eligible graphs.

4. Check if the `pegout` binary exists at `./bin/pegout`. If not, run:
```bash
.claude/commands/install-bitvm2.sh install
```

5. Run the command using the pre-built binary:

```bash
./bin/pegout [--rpc-url <URL>] <subcommand> [options]
```

### Example commands

Single pegout (auto-select graph):
```bash
./bin/pegout --rpc-url http://127.0.0.1:8902 once
```

Single pegout (specific graph, dry run):
```bash
./bin/pegout --rpc-url http://127.0.0.1:8902 once --graph-id <UUID> --dry-run
```

Batch pegout:
```bash
./bin/pegout --rpc-url http://127.0.0.1:8902 batch --max-total-amount-sats 10000000 --max-count 5
```

> The binary calls `POST /v1/graphs/pegout` on the node API.
Loading
Loading