diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb1f84a..42a0e23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,8 +6,8 @@ name: Community Tests on: workflow_call: inputs: - remotes: - description: 'RPC endpoint(s), comma-separated' + remote: + description: 'RPC endpoint' required: true type: string chain_id: @@ -26,8 +26,8 @@ on: workflow_dispatch: inputs: - remotes: - description: 'RPC endpoint(s), comma-separated' + remote: + description: 'RPC endpoint' required: true type: string chain_id: @@ -55,7 +55,7 @@ jobs: - name: Run one-shot tests run: | make tests-one-shot \ - REMOTES="${{ inputs.remotes }}" \ + REMOTE="${{ inputs.remote }}" \ CHAINID="${{ inputs.chain_id }}" \ FUNDER_SCRIPT="${{ inputs.funder_script }}" @@ -68,6 +68,6 @@ jobs: - name: Run repeatable tests run: | make tests-repeatable \ - REMOTES="${{ inputs.remotes }}" \ + REMOTE="${{ inputs.remote }}" \ CHAINID="${{ inputs.chain_id }}" \ FUNDER_SCRIPT="${{ inputs.funder_script }}" diff --git a/.github/workflows/test-13.yml b/.github/workflows/test-13.yml index 0fc653d..1398594 100644 --- a/.github/workflows/test-13.yml +++ b/.github/workflows/test-13.yml @@ -1,10 +1,10 @@ name: test-13 # Network-specific workflow for test-13. -# Calls the generic ci.yml with the right remotes, chain_id and funder_script. +# Calls the generic ci.yml with the right remote, chain_id and funder_script. # # Optional repository variables: -# vars.REMOTES_TEST13 — RPC endpoint(s), comma-separated (default: rpc.test-13-aeddi-1.gnoland.network) +# vars.REMOTE_TEST13 — RPC endpoint (default: rpc.test-13-aeddi-1.gnoland.network) # vars.CHAINID_TEST13 — chain ID (default: test-13) on: @@ -24,7 +24,7 @@ jobs: run: uses: ./.github/workflows/ci.yml with: - remotes: ${{ vars.REMOTES_TEST13 || 'https://rpc.test-13-aeddi-1.gnoland.network,https://rpc.test-13-gfanton-1.gnoland.network,https://rpc.test-13-moul-1.gnoland.network' }} + remote: ${{ vars.REMOTE_TEST13 || 'https://rpc.test-13-aeddi-1.gnoland.network' }} chain_id: ${{ vars.CHAINID_TEST13 || 'test-13' }} funder_script: ./funders/test-13.sh test_type: ${{ inputs.test_type || 'both' }} diff --git a/Makefile b/Makefile index 789c95b..92e0221 100644 --- a/Makefile +++ b/Makefile @@ -1,40 +1,40 @@ .PHONY: tests-one-shot tests-repeatable help -REMOTES ?= +REMOTE ?= CHAINID ?= FUNDER_SCRIPT ?= # Contributor subdirectories are detected automatically under tests/. CONTRIB_DIRS := $(patsubst %/Makefile,%,$(wildcard tests/*/Makefile)) -## tests-one-shot : fund accounts then run one-shot tests (REMOTES, CHAINID, FUNDER_SCRIPT) +## tests-one-shot : fund accounts then run one-shot tests (REMOTE, CHAINID, FUNDER_SCRIPT) tests-one-shot: @for dir in $(CONTRIB_DIRS); do \ echo ""; \ echo "==> $$dir — funding (one-shot)"; \ ARGS=$$($(MAKE) -C $$dir list-funding-one-shot --no-print-directory \ - REMOTES=$(REMOTES) CHAINID=$(CHAINID)); \ + REMOTE=$(REMOTE) CHAINID=$(CHAINID)); \ if [ -n "$$ARGS" ]; then \ - REMOTES=$(REMOTES) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \ + REMOTE=$(REMOTE) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \ fi; \ echo "==> $$dir — tests (one-shot)"; \ $(MAKE) -C $$dir tests-one-shot --no-print-directory \ - REMOTES=$(REMOTES) CHAINID=$(CHAINID) || exit 1; \ + REMOTE=$(REMOTE) CHAINID=$(CHAINID) || exit 1; \ done -## tests-repeatable : fund accounts then run repeatable tests (REMOTES, CHAINID, FUNDER_SCRIPT) +## tests-repeatable : fund accounts then run repeatable tests (REMOTE, CHAINID, FUNDER_SCRIPT) tests-repeatable: @for dir in $(CONTRIB_DIRS); do \ echo ""; \ echo "==> $$dir — funding (repeatable)"; \ ARGS=$$($(MAKE) -C $$dir list-funding-repeatable --no-print-directory \ - REMOTES=$(REMOTES) CHAINID=$(CHAINID)); \ + REMOTE=$(REMOTE) CHAINID=$(CHAINID)); \ if [ -n "$$ARGS" ]; then \ - REMOTES=$(REMOTES) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \ + REMOTE=$(REMOTE) CHAINID=$(CHAINID) $(FUNDER_SCRIPT) $$ARGS || exit 1; \ fi; \ echo "==> $$dir — tests (repeatable)"; \ $(MAKE) -C $$dir tests-repeatable --no-print-directory \ - REMOTES=$(REMOTES) CHAINID=$(CHAINID) || exit 1; \ + REMOTE=$(REMOTE) CHAINID=$(CHAINID) || exit 1; \ done ## help : show available targets diff --git a/README.md b/README.md index 28c77ff..88c4330 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Every contributor subdirectory must expose these four rules: | `tests-one-shot` | Runs tests that deploy on-chain state (realm deploys...) | | `tests-repeatable` | Runs tests that can be re-executed safely | -All rules accept `REMOTES` (comma-separated RPC list) and `CHAINID` variables. +All rules accept `REMOTE` (single RPC endpoint) and `CHAINID` variables. Before each run, the root Makefile calls `list-funding-*`, passes the returned addresses to the funder script (test1), then runs the tests. @@ -44,11 +44,11 @@ Run `make help` from any directory to list available targets. ## Running tests -Against test-13 with 3 validator nodes: +Against test-13: ```sh make tests-one-shot \ - REMOTES=https://rpc.test-13-aeddi-1.gnoland.network,https://rpc.test-13-gfanton-1.gnoland.network,https://rpc.test-13-moul-1.gnoland.network \ + REMOTE=https://rpc.test-13-aeddi-1.gnoland.network \ CHAINID=test-13 \ FUNDER_SCRIPT=./funders/test-13.sh ``` @@ -56,21 +56,13 @@ make tests-one-shot \ Against a single custom RPC: ```sh -make tests-one-shot REMOTES=https://rpc.test12.testnets.gno.land CHAINID=test12 +make tests-one-shot REMOTE=https://rpc.test12.testnets.gno.land CHAINID=test12 ``` -Against multiple validator nodes (stress tests will hit each one): +With a custom funder: ```sh -make tests-one-shot \ - REMOTES=https://rpc1.gnoland.network,https://rpc2.gnoland.network,https://rpc3.gnoland.network \ - CHAINID=test-13 -``` - -With a custom funder script: - -```sh -make tests-one-shot FUNDER_SCRIPT=./funders/test-13.sh REMOTES=... CHAINID=test-13 +make tests-one-shot FUNDER_SCRIPT=./funders/test-13.sh REMOTE=... CHAINID=test-13 ``` Directly from a contributor subdirectory: @@ -78,7 +70,7 @@ Directly from a contributor subdirectory: ```sh cd tests/samourai-crew make help -make tests-one-shot REMOTES=https://rpc.test12.testnets.gno.land CHAINID=test12 +make tests-one-shot REMOTE=https://rpc.test12.testnets.gno.land CHAINID=test12 ``` ## Adding your own tests @@ -100,44 +92,126 @@ gnokey add my-test-account -recover ### 3. Edit the Makefile -Declare your test account address and funding amounts: +Implement `list-funding-one-shot` and `list-funding-repeatable` so they print +space-separated `address amount` pairs — one pair per account that needs funding: -```makefile -ADDR_1 := g1your_address_here - -FUND_AMOUNT_ONE_SHOT := 30000000ugnot # ~30 transactions at 1M ugnot each -FUND_AMOUNT_REPEATABLE := 10000000ugnot - -list-funding-one-shot: - @echo "$(ADDR_1) $(FUND_AMOUNT_ONE_SHOT)" - -list-funding-repeatable: - @echo "$(ADDR_1) $(FUND_AMOUNT_REPEATABLE)" +```text +g1abc... 30000000ugnot +g1def... 10000000ugnot ``` -**Multiple wallets:** declare all addresses in `list-funding-*` as space-separated -`address amount` pairs. The funder will fund each one before the tests run. +Multiple pairs on a single line or across lines are both accepted. If you have no +tests of a given type, return an empty string (the funder skips it cleanly). + +How you store and supply the addresses and mnemonics is up to you — Makefile +variables, a sourced env file, a helper script, or anything else. What matters is +that `list-funding-*` produces the right output and that `tests-one-shot` / +`tests-repeatable` inject the credentials the container needs. ### 4. Write your Dockerfile Your `Dockerfile` must: - Accept `one-shot` or `repeatable` as a command argument -- Contain your test account mnemonic (testnet key, no real value) -- Read `REMOTES` and `CHAINID` from env +- Read `REMOTE`, `CHAINID`, and any account variables from env (injected via `docker run -e`) - Sign the network CLA if required (see `samourai-crew/run_tests.sh` for an example) +**Do not hardcode mnemonics in the Dockerfile.** Define them in your Makefile and pass +them at runtime via `docker run -e` (see step 3). This way addresses and mnemonics stay +in one place and the Dockerfile contains only logic, not secrets. + The image can use **any language** (shell, Go, Python, etc.). See `samourai-crew/` for a shell-based example. ### 5. What your container receives at runtime -| Variable | Description | -| --------- | --------------------------------------------------- | -| `REMOTES` | Comma-separated list of RPC endpoints | -| `CHAINID` | Chain ID | +| Variable | Source | Description | +| ------------- | ----------------- | ---------------------------------------------------- | +| `REMOTE` | root Makefile | Single RPC endpoint | +| `CHAINID` | root Makefile | Chain ID | +| `MY_ADDR` | your Makefile | Your testnet account address (name it as you like) | +| `MY_MNEMONIC` | your Makefile | Your testnet mnemonic (name it as you like) | + +`MY_ADDR` and `MY_MNEMONIC` are examples — use whatever variable names and injection mechanism fit your setup. + +**Reading REMOTE inside your container:** +CI passes the RPC endpoint as `REMOTE`. Your container's entrypoint reads it directly. + +Example in shell: + +```sh +REMOTE="${REMOTE:-http://127.0.0.1:26657}" +``` + +See `tests/samourai-crew/` for a complete shell-based implementation. The funding has already been done by the time your container starts. +## Adding a new network to CI + +To wire a new chain into CI, you need two files. + +### 1. Create a funder script + +```sh +cp funders/_template.sh funders/my-chain.sh +``` + +Edit `funders/my-chain.sh` and set the three defaults: + +```sh +REMOTE="${REMOTE:-https://rpc.my-chain.example.com}" +CHAINID="${CHAINID:-my-chain-id}" +FUNDER_MNEMONIC="${FUNDER_MNEMONIC:-source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast}" +``` + +The last line is the public test1 mnemonic — replace it if your network uses a different funded account. + +### 2. Create a workflow file + +```sh +cp .github/workflows/test-13.yml .github/workflows/my-chain.yml +``` + +Edit `.github/workflows/my-chain.yml`: + +```yaml +name: my-chain + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + inputs: + test_type: + description: 'Test type' + type: choice + default: both + options: [one-shot, repeatable, both] + +jobs: + run: + uses: ./.github/workflows/ci.yml + with: + remote: ${{ vars.REMOTE_MY_CHAIN || 'https://rpc.my-chain.example.com' }} + chain_id: ${{ vars.CHAINID_MY_CHAIN || 'my-chain-id' }} + funder_script: ./funders/my-chain.sh + test_type: ${{ inputs.test_type || 'both' }} +``` + +### 3. (Optional) Override the RPC via repository variable + +If the network RPC changes without a code update, set a repository variable in +**GitHub → Settings → Secrets and variables → Actions → Variables**: + +| Variable | Example value | +| ------------------ | --------------------------------------- | +| `REMOTE_MY_CHAIN` | `https://rpc.my-chain.example.com` | +| `CHAINID_MY_CHAIN` | `my-chain-id` | + +The workflow reads these at runtime and falls back to the hardcoded defaults if not set. + ## Current contributors | Directory | Description | diff --git a/_template/Makefile b/_template/Makefile index 92a5003..53aeb77 100644 --- a/_template/Makefile +++ b/_template/Makefile @@ -1,43 +1,27 @@ -.PHONY: list-funding-one-shot list-funding-repeatable tests-one-shot tests-repeatable build help +.PHONY: list-funding-one-shot list-funding-repeatable tests-one-shot tests-repeatable help -# Override REMOTES and CHAINID to target a live network: -# make tests-one-shot REMOTES=https://rpc.test-13-aeddi-1.gnoland.network CHAINID=test-13 -REMOTES ?= -CHAINID ?= test -IMAGE := $(shell basename $(CURDIR)) - -# TODO: replace with your testnet account address(es) -ADDR_1 := TODO_REPLACE_ADDR_1 - -# Funding amounts — adjust to match your tests' gas needs (~1M ugnot per tx) -FUND_AMOUNT_ONE_SHOT := 30000000ugnot -FUND_AMOUNT_REPEATABLE := 10000000ugnot +REMOTE ?= +CHAINID ?= ## list-funding-one-shot : print address/amount pairs to fund before one-shot tests list-funding-one-shot: - @echo "$(ADDR_1) $(FUND_AMOUNT_ONE_SHOT)" + @# Example: @echo "g1_addr1 30000000ugnot g1_addr2 10000000ugnot" + @echo "not implemented" >&2 && exit 1 ## list-funding-repeatable : print address/amount pairs to fund before repeatable tests list-funding-repeatable: - @echo "$(ADDR_1) $(FUND_AMOUNT_REPEATABLE)" - -## build : build the Docker test image -build: - docker build -t $(IMAGE) . - -## tests-one-shot : run one-shot tests (REMOTES, CHAINID) -tests-one-shot: build - docker run --rm \ - -e REMOTES=$(REMOTES) \ - -e CHAINID=$(CHAINID) \ - $(IMAGE) one-shot - -## tests-repeatable : run repeatable tests (REMOTES, CHAINID) -tests-repeatable: build - docker run --rm \ - -e REMOTES=$(REMOTES) \ - -e CHAINID=$(CHAINID) \ - $(IMAGE) repeatable + @# Example: @echo "g1_addr1 10000000ugnot" + @echo "not implemented" >&2 && exit 1 + +## tests-one-shot : run one-shot tests (REMOTE, CHAINID) +tests-one-shot: + @# Run one-shot tests (only bash and Docker allowed as deps) or no-op if none exist. + @echo "not implemented" >&2 && exit 1 + +## tests-repeatable : run repeatable tests (REMOTE, CHAINID) +tests-repeatable: + @# Run repeatable tests (only bash and Docker allowed as deps) or no-op if none exist. + @echo "not implemented" >&2 && exit 1 ## help : show available targets help: diff --git a/funders/_template.sh b/funders/_template.sh index 91a4571..2cf759e 100755 --- a/funders/_template.sh +++ b/funders/_template.sh @@ -9,12 +9,9 @@ # FUNDER_SCRIPT=./funders/test-14.sh make tests-one-shot CHAINID=test-14 # # To override any default at call time: -# REMOTES=https://my-rpc.example.com FUNDER_SCRIPT=./funders/test-14.sh make tests-one-shot CHAINID=test-14 +# REMOTE=https://my-rpc.example.com FUNDER_SCRIPT=./funders/test-14.sh make tests-one-shot CHAINID=test-14 -# One or more RPC endpoints, comma-separated. -# The first one is used for single-endpoint operations (funding, queries). -# All of them are distributed across sybil stress wallets when running multi-RPC tests. -REMOTES="${REMOTES:-https://rpc.your-network.example.com}" +REMOTE="${REMOTE:-https://rpc.your-network.example.com}" # Chain ID of the target network. CHAINID="${CHAINID:-your-chain-id}" @@ -23,7 +20,7 @@ CHAINID="${CHAINID:-your-chain-id}" # Defaults to the public test1 mnemonic — replace with your own if needed. FUNDER_MNEMONIC="${FUNDER_MNEMONIC:-source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast}" -export REMOTES CHAINID FUNDER_MNEMONIC +export REMOTE CHAINID FUNDER_MNEMONIC FUNDERS_DIR="$(cd "$(dirname "$0")" && pwd)" exec "$FUNDERS_DIR/gnokey-send.sh" "$@" diff --git a/funders/gnokey-send.sh b/funders/gnokey-send.sh index c0cb340..28dfcb1 100755 --- a/funders/gnokey-send.sh +++ b/funders/gnokey-send.sh @@ -3,7 +3,7 @@ # Funds a list of address/amount pairs, topping up to the requested balance. # # Required env (no defaults — exits if any is missing): -# REMOTES — RPC endpoint(s), comma-separated (first one is used) +# REMOTE — RPC endpoint # CHAINID — chain ID # FUNDER_MNEMONIC — sender mnemonic # @@ -14,20 +14,19 @@ GNOKEY_IMAGE="${GNOKEY_IMAGE:-ghcr.io/gnolang/gno/gnokey:master}" if ! command -v gnokey > /dev/null 2>&1; then FUNDERS_DIR="$(cd "$(dirname "$0")" && pwd)" exec docker run --rm \ - -e REMOTES \ + --entrypoint /bin/sh \ + -e REMOTE \ -e CHAINID \ -e FUNDER_MNEMONIC \ -v "${FUNDERS_DIR}:/funders:ro" \ "$GNOKEY_IMAGE" \ - /bin/sh "/funders/$(basename "$0")" "$@" + "/funders/$(basename "$0")" "$@" fi -: "${REMOTES:?REMOTES is required}" +: "${REMOTE:?REMOTE is required}" : "${CHAINID:?CHAINID is required}" : "${FUNDER_MNEMONIC:?FUNDER_MNEMONIC is required}" -REMOTE="${REMOTES%%,*}" - if [ "$#" -eq 0 ] || [ $(( $# % 2 )) -ne 0 ]; then echo "Usage: $0 [ ...]" exit 1 diff --git a/funders/test-12.sh b/funders/test-12.sh index a094849..5f97232 100755 --- a/funders/test-12.sh +++ b/funders/test-12.sh @@ -2,15 +2,15 @@ # Thin wrapper around gnokey-send.sh for the test12 network. # # Optional env (all have defaults): -# REMOTES — RPC endpoint(s), comma-separated +# REMOTE — RPC endpoint # CHAINID — chain ID # FUNDER_MNEMONIC — sender mnemonic -REMOTES="${REMOTES:-https://rpc.testnet12.samourai.live}" +REMOTE="${REMOTE:-https://rpc.testnet12.samourai.live}" CHAINID="${CHAINID:-test12}" FUNDER_MNEMONIC="${FUNDER_MNEMONIC:-source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast}" -export REMOTES CHAINID FUNDER_MNEMONIC +export REMOTE CHAINID FUNDER_MNEMONIC FUNDERS_DIR="$(cd "$(dirname "$0")" && pwd)" exec "$FUNDERS_DIR/gnokey-send.sh" "$@" diff --git a/funders/test-13.sh b/funders/test-13.sh index afb71e2..9cc71b4 100755 --- a/funders/test-13.sh +++ b/funders/test-13.sh @@ -3,15 +3,15 @@ # Calls gnokey-send.sh with the test-13 defaults. # # Optional env (all have defaults): -# REMOTES — RPC endpoint(s), comma-separated +# REMOTE — RPC endpoint # CHAINID — chain ID # FUNDER_MNEMONIC — sender mnemonic (defaults to public test1 mnemonic) -REMOTES="${REMOTES:-https://rpc.test-13-aeddi-1.gnoland.network,https://rpc.test-13-gfanton-1.gnoland.network,https://rpc.test-13-moul-1.gnoland.network}" +REMOTE="${REMOTE:-https://rpc.test-13-aeddi-1.gnoland.network}" CHAINID="${CHAINID:-test-13}" FUNDER_MNEMONIC="${FUNDER_MNEMONIC:-source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast}" -export REMOTES CHAINID FUNDER_MNEMONIC +export REMOTE CHAINID FUNDER_MNEMONIC FUNDERS_DIR="$(cd "$(dirname "$0")" && pwd)" exec "$FUNDERS_DIR/gnokey-send.sh" "$@" diff --git a/tests/samourai-crew/Dockerfile b/tests/samourai-crew/Dockerfile index 14bb523..85ec74c 100644 --- a/tests/samourai-crew/Dockerfile +++ b/tests/samourai-crew/Dockerfile @@ -16,12 +16,10 @@ RUN chmod +x run_tests.sh \ ENV REMOTES=http://127.0.0.1:26657 ENV CHAINID=test -# 3 wallets — wallet 1 is both the runner (audit/e2e) and stress_1 (first RPC) -ENV STRESS_MNEMONIC_1="chair require about ask exhaust you already finger shop turn glory spare credit april rose sniff whale news economy birth table trim raccoon grit" -ENV STRESS_MNEMONIC_2="knock hat consider bicycle kit lion all cover lawn humble picnic win exit never message leader brother reform silk butter private protect tuition draw" -ENV STRESS_MNEMONIC_3="galaxy fire athlete egg three crane stone borrow thought cover story poem blush scissors pause slice unusual spread jewel visual tail parent bargain occur" - -# runner = wallet 1 -ENV RUNNER_MNEMONIC="${STRESS_MNEMONIC_1}" +# Mnemonics are injected at runtime via docker run -e (see tests/samourai-crew/Makefile) +ENV STRESS_MNEMONIC_1="" +ENV STRESS_MNEMONIC_2="" +ENV STRESS_MNEMONIC_3="" +ENV RUNNER_MNEMONIC="" ENTRYPOINT ["/bin/sh", "/tests/run_tests.sh"] diff --git a/tests/samourai-crew/Makefile b/tests/samourai-crew/Makefile index d9c2d59..befb2ae 100644 --- a/tests/samourai-crew/Makefile +++ b/tests/samourai-crew/Makefile @@ -1,14 +1,20 @@ .PHONY: list-funding-one-shot list-funding-repeatable tests-one-shot tests-repeatable build help -REMOTES ?= +# REMOTE: single RPC endpoint passed to the container. +REMOTE ?= CHAINID ?= test IMAGE := $(shell basename $(CURDIR)) # 3 wallets — wallet 1 is both the runner (audit/e2e) and stress_1 (first RPC) +# Each address is derived from its mnemonic: changing one requires updating the other. ADDR_1 := g1hzlg063fqrq4gltql992ssjc0xzau89t5jp63w ADDR_2 := g174tsxfpf8zj8h3tyrz4ld690xvhcjnquls6ffc ADDR_3 := g19xnaenyhe88emmge4726ta43lp3n237vvuzc2n +MNEMONIC_1 := chair require about ask exhaust you already finger shop turn glory spare credit april rose sniff whale news economy birth table trim raccoon grit +MNEMONIC_2 := knock hat consider bicycle kit lion all cover lawn humble picnic win exit never message leader brother reform silk butter private protect tuition draw +MNEMONIC_3 := galaxy fire athlete egg three crane stone borrow thought cover story poem blush scissors pause slice unusual spread jewel visual tail parent bargain occur + ## list-funding-one-shot : print addresses and amounts to fund before one-shot tests list-funding-one-shot: @echo "$(ADDR_1) 50000000ugnot $(ADDR_2) 15000000ugnot $(ADDR_3) 15000000ugnot" @@ -21,26 +27,34 @@ list-funding-repeatable: build: docker build -t $(IMAGE) . -## tests-one-shot : run one-shot tests (REMOTES, CHAINID) +## tests-one-shot : run one-shot tests (REMOTE, CHAINID) tests-one-shot: build docker run --rm \ - -e REMOTES=$(REMOTES) \ + -e REMOTE=$(REMOTE) \ -e CHAINID=$(CHAINID) \ -e STRESS_ADDR_1=$(ADDR_1) \ -e STRESS_ADDR_2=$(ADDR_2) \ -e STRESS_ADDR_3=$(ADDR_3) \ -e RUNNER_ADDR=$(ADDR_1) \ + -e "STRESS_MNEMONIC_1=$(MNEMONIC_1)" \ + -e "STRESS_MNEMONIC_2=$(MNEMONIC_2)" \ + -e "STRESS_MNEMONIC_3=$(MNEMONIC_3)" \ + -e "RUNNER_MNEMONIC=$(MNEMONIC_1)" \ $(IMAGE) one-shot -## tests-repeatable : run repeatable tests (REMOTES, CHAINID) +## tests-repeatable : run repeatable tests (REMOTE, CHAINID) tests-repeatable: build docker run --rm \ - -e REMOTES=$(REMOTES) \ + -e REMOTE=$(REMOTE) \ -e CHAINID=$(CHAINID) \ -e STRESS_ADDR_1=$(ADDR_1) \ -e STRESS_ADDR_2=$(ADDR_2) \ -e STRESS_ADDR_3=$(ADDR_3) \ -e RUNNER_ADDR=$(ADDR_1) \ + -e "STRESS_MNEMONIC_1=$(MNEMONIC_1)" \ + -e "STRESS_MNEMONIC_2=$(MNEMONIC_2)" \ + -e "STRESS_MNEMONIC_3=$(MNEMONIC_3)" \ + -e "RUNNER_MNEMONIC=$(MNEMONIC_1)" \ $(IMAGE) repeatable ## help : show available targets diff --git a/tests/samourai-crew/audit/common.sh b/tests/samourai-crew/audit/common.sh index be87690..43384b3 100755 --- a/tests/samourai-crew/audit/common.sh +++ b/tests/samourai-crew/audit/common.sh @@ -3,8 +3,7 @@ # KEY, PASSWORD, KEY_ADDR and GNOKEY_HOME are exported by run_tests.sh # before any script is called. Defaults below are for standalone use only. -RPC="${REMOTE:-${REMOTES%%,*}}" -RPC="${RPC:-http://127.0.0.1:26657}" +RPC="${REMOTE:-http://127.0.0.1:26657}" CHAINID="${CHAINID:-test}" KEY="${KEY:-runner}" PASSWORD="${PASSWORD:-runner1234}" diff --git a/tests/samourai-crew/run_tests.sh b/tests/samourai-crew/run_tests.sh index ed34edc..97b00d1 100755 --- a/tests/samourai-crew/run_tests.sh +++ b/tests/samourai-crew/run_tests.sh @@ -5,15 +5,14 @@ # (no arg) — runs both # # Expected env vars (set in Dockerfile or injected by Makefile): -# REMOTES — comma-separated RPC list (single entry = one node) +# REMOTE — RPC endpoint # CHAINID — chain ID # RUNNER_MNEMONIC — mnemonic of the main test account # RUNNER_ADDR — address of the main test account MODE="${1:-all}" -export REMOTES="${REMOTES:-http://127.0.0.1:26657}" -export REMOTE="${REMOTES%%,*}" +export REMOTE="${REMOTE:-http://127.0.0.1:26657}" export CHAINID="${CHAINID:-test}" export GNOKEY_HOME="${GNOKEY_HOME:-/tmp/gnokey}" export KEY="runner" @@ -91,7 +90,7 @@ if [ -n "$CLA_HASH" ]; then gnokey list -home "$GNOKEY_HOME" 2>/dev/null | grep -oE '^[0-9]+\. [^ ]+' | awk '{print $2}' | while read -r k; do [ "$k" != "$KEY" ] && sign_cla "$k" done - sleep 2 + sleep 10 fi echo "" diff --git a/tests/samourai-crew/stress/sybil_chaos.sh b/tests/samourai-crew/stress/sybil_chaos.sh index fa6a647..6485d17 100755 --- a/tests/samourai-crew/stress/sybil_chaos.sh +++ b/tests/samourai-crew/stress/sybil_chaos.sh @@ -1,15 +1,13 @@ #!/bin/bash -# Sybil chaos: N wallets bombard N RPCs fully in parallel. +# Sybil chaos: N wallets bombard a single REMOTE fully in parallel. # Each wallet fires TX_PER_ACCOUNT transactions without waiting. # # Expected env (set by run_tests.sh): -# KEY, PASSWORD, CHAINID, GNOKEY_HOME, KEY_ADDR -# REMOTES — comma-separated RPC list (falls back to $REMOTE) -# stress_1, stress_2, stress_3 keys must be imported in GNOKEY_HOME +# KEY, PASSWORD, CHAINID, REMOTE, GNOKEY_HOME, KEY_ADDR +# stress_1 (=KEY), stress_2, stress_3 keys imported in GNOKEY_HOME SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" TX_PER_ACCOUNT="${TX_PER_ACCOUNT:-10}" -REMOTES="${REMOTES:-${REMOTE:-http://127.0.0.1:26657}}" SUFFIX=$(date +%s) COUNTER_PKGPATH="gno.land/r/${KEY_ADDR}/stress/chaos${SUFFIX}" TMPDIR=$(mktemp -d) @@ -17,26 +15,17 @@ trap 'rm -rf "$TMPDIR"' EXIT echo "🌪️ SYBIL CHAOS — parallel bombardment" -IFS=',' read -ra RPCS <<< "$REMOTES" -N=${#RPCS[@]} -echo " RPCs : $N" -echo " Txs/key : $TX_PER_ACCOUNT" -echo "" - -# Build wallet list: first slot = runner (KEY), then stress_2, stress_3... -WALLET_KEYS=() -for i in $(seq 1 "$N"); do - if [ "$i" -eq 1 ]; then - WALLET_KEYS+=("$KEY") - else - wkey="stress_${i}" - if gnokey list -home "$GNOKEY_HOME" 2>/dev/null | grep -q "^[0-9]*\. $wkey "; then - WALLET_KEYS+=("$wkey") - else - echo "FAIL: stress key $wkey not found in keystore"; exit 1 - fi +WALLET_KEYS=("$KEY") +for i in 2 3; do + wkey="stress_${i}" + if gnokey list -home "$GNOKEY_HOME" 2>/dev/null | grep -q "^[0-9]*\. $wkey "; then + WALLET_KEYS+=("$wkey") fi done +N=${#WALLET_KEYS[@]} +echo " Wallets : $N → $REMOTE" +echo " Txs/key : $TX_PER_ACCOUNT" +echo "" # Deploy counter realm echo "Deploying counter realm..." @@ -46,7 +35,7 @@ echo "$PASSWORD" | gnokey maketx addpkg \ -pkgpath "$COUNTER_PKGPATH" \ -pkgdir "$TMPDIR" \ -gas-fee 1000000ugnot -gas-wanted 10000000 \ - -broadcast -chainid "$CHAINID" -remote "${RPCS[0]}" \ + -broadcast -chainid "$CHAINID" -remote "$REMOTE" \ -insecure-password-stdin=true -home "$GNOKEY_HOME" \ "$KEY" > /dev/null || { echo "FAIL: could not deploy counter"; exit 1; } @@ -61,12 +50,11 @@ echo "Launching parallel bombardment..." for i in $(seq 1 "$N"); do wkey="${WALLET_KEYS[$i-1]}" - rpc="${RPCS[$i-1]}" ( - echo -n "🚀 $wkey → $rpc : " + echo -n "🚀 $wkey → $REMOTE : " for _ in $(seq 1 "$TX_PER_ACCOUNT"); do echo "$PASSWORD" | gnokey maketx run \ - -broadcast -chainid "$CHAINID" -remote "$rpc" \ + -broadcast -chainid "$CHAINID" -remote "$REMOTE" \ -gas-fee 1000000ugnot -gas-wanted 3000000 \ -insecure-password-stdin=true -home "$GNOKEY_HOME" \ "$wkey" "$TMPDIR/increment.gno" > /dev/null 2>&1 @@ -81,24 +69,15 @@ echo "" echo "Waiting for consensus to settle..." sleep 5 -echo "=== Final counter per RPC ===" +echo "=== Final counter ===" ATTEMPTED=$(( N * TX_PER_ACCOUNT )) -FIRST_VAL="" -ALL_SAME=true -for rpc in "${RPCS[@]}"; do - val=$(gnokey query "vm/qeval" -remote "$rpc" \ - -data "${COUNTER_PKGPATH}.Render(\"\")" 2>/dev/null | grep -oE '[0-9]+' | tail -1) - echo " $rpc → ${val:-0}" - if [ -z "$FIRST_VAL" ]; then - FIRST_VAL="${val:-0}" - elif [ "${val:-0}" != "$FIRST_VAL" ]; then - ALL_SAME=false - fi -done - +val=$(gnokey query "vm/qeval" -remote "$REMOTE" \ + -data "${COUNTER_PKGPATH}.Render(\"\")" 2>/dev/null | grep -oE '[0-9]+' | tail -1) +echo " $REMOTE → ${val:-0}" +FIRST_VAL="${val:-0}" echo " committed: $FIRST_VAL / $ATTEMPTED txs attempted" -if $ALL_SAME && [ "${FIRST_VAL:-0}" -gt 0 ]; then - echo "[PASS] all nodes converged at $FIRST_VAL" +if [ "${FIRST_VAL:-0}" -gt 0 ]; then + echo "[PASS] $FIRST_VAL txs committed" exit 0 fi -echo "[FAIL] nodes diverged or no txs committed" && exit 1 +echo "[FAIL] no txs committed" && exit 1 diff --git a/tests/samourai-crew/stress/sybil_precision.sh b/tests/samourai-crew/stress/sybil_precision.sh index 5c007c9..d183d83 100644 --- a/tests/samourai-crew/stress/sybil_precision.sh +++ b/tests/samourai-crew/stress/sybil_precision.sh @@ -1,11 +1,10 @@ #!/bin/bash -# Sybil precision: N wallets hit N RPCs in parallel, but each wallet +# Sybil precision: N wallets hit a single REMOTE in parallel, but each wallet # sends txs sequentially with a small delay. SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" TX_PER_ACCOUNT="${TX_PER_ACCOUNT:-10}" TX_DELAY="${TX_DELAY:-0.8}" -REMOTES="${REMOTES:-${REMOTE:-http://127.0.0.1:26657}}" SUFFIX=$(date +%s) COUNTER_PKGPATH="gno.land/r/${KEY_ADDR}/stress/precision${SUFFIX}" TMPDIR=$(mktemp -d) @@ -13,25 +12,17 @@ trap 'rm -rf "$TMPDIR"' EXIT echo "🎯 SYBIL PRECISION — sequential per wallet, parallel across wallets" -IFS=',' read -ra RPCS <<< "$REMOTES" -N=${#RPCS[@]} -echo " RPCs : $N" -echo " Txs/key : $TX_PER_ACCOUNT (delay: ${TX_DELAY}s)" -echo "" - -WALLET_KEYS=() -for i in $(seq 1 "$N"); do - if [ "$i" -eq 1 ]; then - WALLET_KEYS+=("$KEY") - else - wkey="stress_${i}" - if gnokey list -home "$GNOKEY_HOME" 2>/dev/null | grep -q "^[0-9]*\. $wkey "; then - WALLET_KEYS+=("$wkey") - else - echo "FAIL: stress key $wkey not found in keystore"; exit 1 - fi +WALLET_KEYS=("$KEY") +for i in 2 3; do + wkey="stress_${i}" + if gnokey list -home "$GNOKEY_HOME" 2>/dev/null | grep -q "^[0-9]*\. $wkey "; then + WALLET_KEYS+=("$wkey") fi done +N=${#WALLET_KEYS[@]} +echo " Wallets : $N → $REMOTE" +echo " Txs/key : $TX_PER_ACCOUNT (delay: ${TX_DELAY}s)" +echo "" echo "Deploying counter realm..." cp "$SCRIPT_DIR/../realms/counter/counter.gno" "$TMPDIR/counter.gno" @@ -40,7 +31,7 @@ echo "$PASSWORD" | gnokey maketx addpkg \ -pkgpath "$COUNTER_PKGPATH" \ -pkgdir "$TMPDIR" \ -gas-fee 1000000ugnot -gas-wanted 10000000 \ - -broadcast -chainid "$CHAINID" -remote "${RPCS[0]}" \ + -broadcast -chainid "$CHAINID" -remote "$REMOTE" \ -insecure-password-stdin=true -home "$GNOKEY_HOME" \ "$KEY" > /dev/null || { echo "FAIL: could not deploy counter"; exit 1; } @@ -55,12 +46,11 @@ echo "Launching precision bombardment..." for i in $(seq 1 "$N"); do wkey="${WALLET_KEYS[$i-1]}" - rpc="${RPCS[$i-1]}" ( - echo -n "⚖️ $wkey → $rpc : " + echo -n "⚖️ $wkey → $REMOTE : " for _ in $(seq 1 "$TX_PER_ACCOUNT"); do echo "$PASSWORD" | gnokey maketx run \ - -broadcast -chainid "$CHAINID" -remote "$rpc" \ + -broadcast -chainid "$CHAINID" -remote "$REMOTE" \ -gas-fee 1000000ugnot -gas-wanted 3000000 \ -insecure-password-stdin=true -home "$GNOKEY_HOME" \ "$wkey" "$TMPDIR/increment.gno" > /dev/null 2>&1 @@ -73,25 +63,15 @@ done wait echo "" -echo "=== Final counter per RPC ===" -EXPECTED=$(( N * TX_PER_ACCOUNT )) +echo "=== Final counter ===" ATTEMPTED=$(( N * TX_PER_ACCOUNT )) -FIRST_VAL="" -ALL_SAME=true -for rpc in "${RPCS[@]}"; do - val=$(gnokey query "vm/qeval" -remote "$rpc" \ - -data "${COUNTER_PKGPATH}.Render(\"\")" 2>/dev/null | grep -oE '[0-9]+' | tail -1) - echo " $rpc → ${val:-0}" - if [ -z "$FIRST_VAL" ]; then - FIRST_VAL="${val:-0}" - elif [ "${val:-0}" != "$FIRST_VAL" ]; then - ALL_SAME=false - fi -done - +val=$(gnokey query "vm/qeval" -remote "$REMOTE" \ + -data "${COUNTER_PKGPATH}.Render(\"\")" 2>/dev/null | grep -oE '[0-9]+' | tail -1) +echo " $REMOTE → ${val:-0}" +FIRST_VAL="${val:-0}" echo " committed: $FIRST_VAL / $ATTEMPTED txs attempted" -if $ALL_SAME && [ "${FIRST_VAL:-0}" -gt 0 ]; then - echo "[PASS] all nodes converged at $FIRST_VAL" +if [ "${FIRST_VAL:-0}" -gt 0 ]; then + echo "[PASS] $FIRST_VAL txs committed" exit 0 fi -echo "[FAIL] nodes diverged or no txs committed" && exit 1 +echo "[FAIL] no txs committed" && exit 1 diff --git a/tests/samourai-crew/stress/sybil_salted_chaos.sh b/tests/samourai-crew/stress/sybil_salted_chaos.sh index fac67f1..14a4abb 100755 --- a/tests/samourai-crew/stress/sybil_salted_chaos.sh +++ b/tests/samourai-crew/stress/sybil_salted_chaos.sh @@ -4,7 +4,6 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" TX_PER_ACCOUNT="${TX_PER_ACCOUNT:-10}" -REMOTES="${REMOTES:-${REMOTE:-http://127.0.0.1:26657}}" SUFFIX=$(date +%s) COUNTER_PKGPATH="gno.land/r/${KEY_ADDR}/stress/salted${SUFFIX}" TMPDIR=$(mktemp -d) @@ -12,25 +11,17 @@ trap 'rm -rf "$TMPDIR"' EXIT echo "💀 SYBIL SALTED CHAOS — ultra-parallel with memo salt" -IFS=',' read -ra RPCS <<< "$REMOTES" -N=${#RPCS[@]} -echo " RPCs : $N" -echo " Txs/key : $TX_PER_ACCOUNT" -echo "" - -WALLET_KEYS=() -for i in $(seq 1 "$N"); do - if [ "$i" -eq 1 ]; then - WALLET_KEYS+=("$KEY") - else - wkey="stress_${i}" - if gnokey list -home "$GNOKEY_HOME" 2>/dev/null | grep -q "^[0-9]*\. $wkey "; then - WALLET_KEYS+=("$wkey") - else - echo "FAIL: stress key $wkey not found in keystore"; exit 1 - fi +WALLET_KEYS=("$KEY") +for i in 2 3; do + wkey="stress_${i}" + if gnokey list -home "$GNOKEY_HOME" 2>/dev/null | grep -q "^[0-9]*\. $wkey "; then + WALLET_KEYS+=("$wkey") fi done +N=${#WALLET_KEYS[@]} +echo " Wallets : $N → $REMOTE" +echo " Txs/key : $TX_PER_ACCOUNT" +echo "" echo "Deploying counter realm..." cp "$SCRIPT_DIR/../realms/counter/counter.gno" "$TMPDIR/counter.gno" @@ -39,7 +30,7 @@ echo "$PASSWORD" | gnokey maketx addpkg \ -pkgpath "$COUNTER_PKGPATH" \ -pkgdir "$TMPDIR" \ -gas-fee 1000000ugnot -gas-wanted 10000000 \ - -broadcast -chainid "$CHAINID" -remote "${RPCS[0]}" \ + -broadcast -chainid "$CHAINID" -remote "$REMOTE" \ -insecure-password-stdin=true -home "$GNOKEY_HOME" \ "$KEY" > /dev/null || { echo "FAIL: could not deploy counter"; exit 1; } @@ -54,14 +45,13 @@ echo "Launching salted chaos..." for i in $(seq 1 "$N"); do wkey="${WALLET_KEYS[$i-1]}" - rpc="${RPCS[$i-1]}" ( - echo -n "🔥 $wkey → $rpc : " + echo -n "🔥 $wkey → $REMOTE : " for j in $(seq 1 "$TX_PER_ACCOUNT"); do SALT=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 8) ( echo "$PASSWORD" | gnokey maketx run \ - -broadcast -chainid "$CHAINID" -remote "$rpc" \ + -broadcast -chainid "$CHAINID" -remote "$REMOTE" \ -gas-fee 1000000ugnot -gas-wanted 3000000 \ -memo "samourai-salt-$SALT" \ -insecure-password-stdin=true -home "$GNOKEY_HOME" \ @@ -79,26 +69,15 @@ echo "" echo "Waiting for chaos to settle..." sleep 10 -echo "=== Final counter per RPC ===" -EXPECTED=$(( N * TX_PER_ACCOUNT )) -ALL_OK=true +echo "=== Final counter ===" ATTEMPTED=$(( N * TX_PER_ACCOUNT )) -FIRST_VAL="" -ALL_SAME=true -for rpc in "${RPCS[@]}"; do - val=$(gnokey query "vm/qeval" -remote "$rpc" \ - -data "${COUNTER_PKGPATH}.Render(\"\")" 2>/dev/null | grep -oE '[0-9]+' | tail -1) - echo " $rpc → ${val:-0}" - if [ -z "$FIRST_VAL" ]; then - FIRST_VAL="${val:-0}" - elif [ "${val:-0}" != "$FIRST_VAL" ]; then - ALL_SAME=false - fi -done - +val=$(gnokey query "vm/qeval" -remote "$REMOTE" \ + -data "${COUNTER_PKGPATH}.Render(\"\")" 2>/dev/null | grep -oE '[0-9]+' | tail -1) +echo " $REMOTE → ${val:-0}" +FIRST_VAL="${val:-0}" echo " committed: $FIRST_VAL / $ATTEMPTED txs attempted" -if $ALL_SAME && [ "${FIRST_VAL:-0}" -gt 0 ]; then - echo "[PASS] all nodes converged at $FIRST_VAL" +if [ "${FIRST_VAL:-0}" -gt 0 ]; then + echo "[PASS] $FIRST_VAL txs committed" exit 0 fi -echo "[FAIL] nodes diverged or no txs committed" && exit 1 +echo "[FAIL] no txs committed" && exit 1