From 7542f2d763982d2bce932e24b49ffd99615f4807 Mon Sep 17 00:00:00 2001 From: BANADDA MUBARAKA <83466862+BANADDA@users.noreply.github.com> Date: Tue, 20 Oct 2026 16:56:21 +0300 Subject: [PATCH] validator: the fee comes from the epoch's roster and a free arena needs no fee receipt --- README.md | 4 ++-- docs/validator_setup.md | 2 +- microtensor_subnet/cli/submit.py | 10 +++++++--- microtensor_subnet/validator/collect.py | 2 ++ microtensor_subnet/validator/epoch.py | 7 +++++++ 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ab3cac2..183805c 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ Nothing a miner claims is used. The artifact is fetched from Hugging Face at the ## How an epoch works -1. **Commit.** A miner pays the arena fee and commits one line on chain: arena, Hugging Face user, artifact commit, fee block and extrinsic index. -2. **Roster and snapshot.** At commit close the server verifies every fee and publishes a signed roster and a signed snapshot of previous bests. +1. **Commit.** A miner pays the arena fee, if the arena charges one, and commits one line on chain: arena, Hugging Face user, artifact commit, fee block and extrinsic index (0 and 0 for a free arena). The operator sets each arena's fee and can change it at any time; each epoch's roster records the fee it ran under. +2. **Roster and snapshot.** At commit close the server verifies every fee it charges and publishes a signed roster and a signed snapshot of previous bests. 3. **Release.** Once the open block is final the server seals the epoch's encrypted item bundle to every permitted validator and publishes the seed, the hash of the open block hash and the arena id. 4. **Evaluation.** Each validator serves the miner's model with vLLM, serves the miner's router, runs the miner's `main.py` in the sandbox, and runs the SLM, harness, router, escalation and system tests. 5. **Report.** Each validator signs one report per epoch and sets weights from its own scores. diff --git a/docs/validator_setup.md b/docs/validator_setup.md index bf89016..f42e8e7 100644 --- a/docs/validator_setup.md +++ b/docs/validator_setup.md @@ -99,7 +99,7 @@ The loop polls the chain every ten minutes. When an arena's evaluation window op ## What one epoch does with a submission -1. Verifies the fee on chain and every file hash in `manifest.json`. +1. Verifies the fee on chain, when the epoch's roster records one, and every file hash in `manifest.json`. 2. Serves the miner's model with vLLM on one GPU, isolated on an internal network. 3. Serves the miner's router from the validator process. 4. Starts the miner's `main.py` in the sandbox with four service URLs and nothing else. diff --git a/microtensor_subnet/cli/submit.py b/microtensor_subnet/cli/submit.py index 6cf183c..ba064cf 100644 --- a/microtensor_subnet/cli/submit.py +++ b/microtensor_subnet/cli/submit.py @@ -74,8 +74,8 @@ def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> commit.add_argument("--arena", required=True) commit.add_argument("--hf-user", required=True, help="the hugging face user or org") commit.add_argument("--artifact-sha", required=True, help="artifact repository commit sha") - commit.add_argument("--fee-block", type=int, required=True) - commit.add_argument("--fee-index", type=int, required=True) + commit.add_argument("--fee-block", type=int, default=0, help="0 when the arena is free") + commit.add_argument("--fee-index", type=int, default=0, help="0 when the arena is free") add_chain_arguments(commit) add_common_arguments(commit) commit.set_defaults(handler=_commit) @@ -165,7 +165,11 @@ def _pay(args: argparse.Namespace) -> int: fee_tao = float(definition.get("fee_tao") or 0.0) pay_to = str(definition.get("fee_coldkey") or "") if fee_tao <= 0 or not pay_to: - return fail("the arena publishes no fee; nothing to pay") + print( + f"{args.arena} charges no fee; commit with mt submit commit --arena {args.arena} " + "--hf-user --artifact-sha " + ) + return 0 config = chain_config(args) wallet = open_wallet(config) print(f"arena {args.arena}") diff --git a/microtensor_subnet/validator/collect.py b/microtensor_subnet/validator/collect.py index fbb1d6a..1626cbd 100644 --- a/microtensor_subnet/validator/collect.py +++ b/microtensor_subnet/validator/collect.py @@ -74,6 +74,8 @@ def candidates( def fee_ok(client: Any, candidate: Candidate, *, pay_to: str, fee_tao: float) -> str: + if fee_tao <= 0 or not pay_to: + return "" try: event = client.transfer_at(candidate.commitment.fee_block, candidate.commitment.fee_index) except ChainError as exc: diff --git a/microtensor_subnet/validator/epoch.py b/microtensor_subnet/validator/epoch.py index 07b9e75..912534b 100644 --- a/microtensor_subnet/validator/epoch.py +++ b/microtensor_subnet/validator/epoch.py @@ -99,6 +99,13 @@ def load_context( ref = items.reference_components(trees, definition, config.cache_dir) snapshot = client.ledger_snapshot(config.arena_id, epoch_index) roster_doc = client.roster(config.arena_id, epoch_index) + charged = dict(dict(dict(roster_doc or {}).get("body") or {}).get("fee") or {}) + if charged: + definition = { + **definition, + "fee_tao": float(charged.get("tao") or 0.0), + "fee_coldkey": str(charged.get("pay_to") or ""), + } sample = next(iter(epoch_items.databases.values()), b"") sample_sha = str(definition.get("sample_database") or "") if sample_sha and sample_sha in epoch_items.databases: