Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .env.encoder_miner.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# =============================================================================
# Encoder/Captioner Artifact Miner Environment Configuration
# =============================================================================
# Copy this file to .env.encoder_miner and configure your settings:
# cp .env.encoder_miner.template .env.encoder_miner
#
# Launch with:
# MINER_ENV_FILE=.env.encoder_miner pm2 start gen_miner.config.js

# =============================================================================
# BITTENSOR NETWORK
# =============================================================================

BT_NETUID=379
BT_CHAIN_ENDPOINT=wss://test.finney.opentensor.ai:443

# Wallet
BT_WALLET_NAME=encoder1
BT_WALLET_HOTKEY=default

# Axon
BT_AXON_PORT=8093
BT_AXON_IP=0.0.0.0
# BT_AXON_EXTERNAL_IP=your.public.ip

# =============================================================================
# ARTIFACT MINER ROLE
# =============================================================================
# Use ENCODER for encoding artifacts. Use CAPTIONER for caption artifacts.
MINER_TYPE=ENCODER

# Optional reference processor for deterministic local/fake-R2 testing.
# Replace this with your production encoder/captioner command when ready.
DPS_ARTIFACT_PROCESSOR_COMMAND=python -m gas.artifacts.processor

# Miner-owned output R2 location published as dps_output metadata.
# Validators use these scoped read-only credentials to fetch artifact manifests/files.
DPS_ARTIFACT_OUTPUT_R2_ENDPOINT_URL=
DPS_ARTIFACT_OUTPUT_R2_BUCKET=
DPS_ARTIFACT_OUTPUT_R2_REGION=auto
DPS_ARTIFACT_OUTPUT_R2_PREFIX=dps-artifacts/

# Write credentials stay local to the miner; read credentials below are published for validators.
DPS_ARTIFACT_OUTPUT_R2_WRITE_ACCESS_KEY_ID=
DPS_ARTIFACT_OUTPUT_R2_WRITE_SECRET_ACCESS_KEY=
DPS_ARTIFACT_OUTPUT_R2_WRITE_SESSION_TOKEN=
DPS_ARTIFACT_OUTPUT_R2_READ_ACCESS_KEY_ID=
DPS_ARTIFACT_OUTPUT_R2_READ_SECRET_ACCESS_KEY=
DPS_ARTIFACT_OUTPUT_R2_READ_SESSION_TOKEN=
DPS_ARTIFACT_OUTPUT_FORMAT=npz
DPS_ARTIFACT_OUTPUT_R2_MANIFEST_URL=
DPS_ARTIFACT_OUTPUT_R2_MANIFEST_KEY=

# =============================================================================
# MINER SETTINGS
# =============================================================================

MINER_DEVICE=auto
MINER_MAX_CONCURRENT_TASKS=2
MINER_TASK_TIMEOUT=300
MINER_WORKER_THREADS=2
MINER_OUTPUT_DIR=./artifact_miner_output
MINER_SAVE_LOCALLY=false
HF_HOME=/workspace/.cache/huggingface

# =============================================================================
# LOGGING
# =============================================================================

BT_LOGGING_LEVEL=INFO
AUTO_UPDATE=false

# Set true only for local testing; production miners should keep validator permit checks.
MINER_NO_FORCE_VALIDATOR_PERMIT=false
5 changes: 3 additions & 2 deletions .env.gen_miner.template
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ MINER_OUTPUT_DIR=./miner_generated_content
# Optional: durable task snapshots for restart recovery (default: <MINER_OUTPUT_DIR>/.gen_miner_state)
# MINER_STATE_DIR=


# =============================================================================
# LOGGING
# =============================================================================
Expand All @@ -106,9 +105,11 @@ BT_LOGGING_LEVEL=INFO
# Check status: gascli generator status
# View logs: gascli generator logs -f
# Direct PM2: pm2 start miner.config.js
# Encoder miner: cp .env.encoder_miner.template .env.encoder_miner
# MINER_ENV_FILE=.env.encoder_miner pm2 start gen_miner.config.js

# Get API keys:
# - OpenAI: https://platform.openai.com/api-keys
# - OpenRouter: https://openrouter.ai/keys
# - Runway: https://app.runwayml.com/ (API keys / dev portal)
# - Hugging Face: https://huggingface.co/settings/tokens
# - Hugging Face: https://huggingface.co/settings/tokens
30 changes: 30 additions & 0 deletions .env.validator.template
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,36 @@ AUTO_UPDATE=true
#START_GENERATOR=true
#START_DATA=true

# ======= DPS Artifact Mechanism (optional mechanism 1) =======
# Set to true after the subnet owner enables the second mechanism on-chain.
ENABLE_DPS_ARTIFACT_MECHANISM=false
DPS_ARTIFACT_MECHANISM_ID=1
DPS_ARTIFACT_TASK_INTERVAL=360
DPS_ARTIFACT_PUBLISH_INPUT_TO_CHAIN=false
DPS_ARTIFACT_REWARDS_PATH=

# Mechanism-1 role budget shares. Values are normalized if they do not sum to 1.
DPS_ARTIFACT_ENCODER_WEIGHT=0.8
DPS_ARTIFACT_CAPTIONER_WEIGHT=0.2
DPS_ARTIFACT_SAMPLE_SIZE=0

# Artifact constraints miners must follow for this shard.
DPS_ARTIFACT_RESOLUTION=
DPS_ARTIFACT_MAX_FRAMES=
DPS_ARTIFACT_ENCODING_MODEL=

# Validator input R2 location published as dps_input metadata.
# These should be scoped, read-only, prefix-limited credentials; chain commitments are public.
DPS_ARTIFACT_R2_ENDPOINT_URL=
DPS_ARTIFACT_R2_BUCKET=
DPS_ARTIFACT_R2_PREFIX=
DPS_ARTIFACT_R2_MANIFEST_URL=
DPS_ARTIFACT_R2_MANIFEST_KEY=
DPS_ARTIFACT_R2_REGION=auto
DPS_ARTIFACT_R2_READ_ACCESS_KEY_ID=
DPS_ARTIFACT_R2_READ_SECRET_ACCESS_KEY=
DPS_ARTIFACT_R2_READ_SESSION_TOKEN=

# ── Docker-specific notes ──────────────────────────────────────────────────
# Use .env.validator as the single source of truth: run Compose with
# --env-file .env.validator
Expand Down
148 changes: 148 additions & 0 deletions docs/Incentive.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,154 @@ This design incentivizes generators to:
2. Create adversarially robust content that can fool discriminators (multiplier)
3. Participate in more evaluations for sample size bonuses

## DPS Artifact Mechanism

DPS artifact miners are rewarded on Bittensor mechanism `1`, separate from the existing SN34 mechanism `0`. Mechanism `0` continues to set the current burn, escrow, and generator weights. Mechanism `1` is reserved for reusable training artifacts, beginning with `MinerType.ENCODER` and adding `MinerType.CAPTIONER` as semantic validation matures.

Validators submit a separate weight vector for each mechanism. Subnet-owner operations control the cross-mechanism emission split on-chain:

```bash
btcli subnet mech set --mech-count 2 --netuid 34
btcli subnet mech emissions-split --netuid 34 --split "90,10"
```

Before setting `mech-count=2`, ensure `mechanism_count * max_allowed_uids < 256`. On mainnet this typically means trimming SN34 to at most 128 UIDs first.

Unlike mechanism `0`, mechanism `1` does not issue prompt-generation challenges. Chain commitments coordinate the work, and R2 carries the data. A validator publishes a `dps_input` commitment containing the source bucket/path/manifest and scoped read credentials. Encoder/captioner miners read that commitment, pull the source shard from R2, produce reusable artifacts, upload those artifacts to their own R2 bucket, and publish a `dps_output` commitment containing the artifact bucket/path and scoped validator-read credentials. Validators then pull miner outputs from R2 and feed verification results into the mechanism-1 reward stats.

Chain commitments are public. Any R2 credential written to chain must be narrowly scoped, read-only where possible, prefix-limited, and disposable. Do not publish broad account credentials.

Validator input publishing and task assignment are configured independently from weight submission:

```bash
--enable-dps-artifact-mechanism \
--dps-artifact.publish-input-to-chain \
--dps-artifact-task-interval 360 \
--dps-artifact.resolution 512x512 \
--dps-artifact.max-frames 16 \
--dps-artifact.encoding-model stabilityai/sd-vae-ft-mse \
--dps-artifact.r2-endpoint-url https://<account>.r2.cloudflarestorage.com \
--dps-artifact.r2-bucket dps-artifacts \
--dps-artifact.r2-prefix encoder/shard-001/ \
--dps-artifact.r2-manifest-url https://example.com/manifest.json \
--dps-artifact.r2-read-access-key-id <prefix-scoped-read-key> \
--dps-artifact.r2-read-secret-access-key <prefix-scoped-read-secret>
```

The validator writes a compact chain commitment shaped like:

```json
{
"v": 1,
"kind": "dps_input",
"role": "ENCODER",
"r2": {
"endpoint_url": "https://<account>.r2.cloudflarestorage.com",
"bucket": "dps-artifacts",
"path": "encoder/shard-001/",
"manifest_url": "https://example.com/manifest.json",
"access_key_id": "<prefix-scoped-read-key>",
"secret_access_key": "<prefix-scoped-read-secret>"
},
"artifact_spec": {
"resolution": "512x512",
"max_frames": 16,
"encoding_model": "stabilityai/sd-vae-ft-mse"
}
}
```

The validator may also send a signed `/artifact_task` nudge to active mechanism-1 miners with the same R2 source:

```json
{
"task_id": "dps-encoder-12-...",
"role": "ENCODER",
"source": {
"type": "r2",
"endpoint_url": "https://<account>.r2.cloudflarestorage.com",
"bucket": "dps-artifacts",
"path": "encoder/shard-001/",
"prefix": "encoder/shard-001/",
"manifest_url": "https://example.com/manifest.json",
"access_key_id": "<prefix-scoped-read-key>",
"secret_access_key": "<prefix-scoped-read-secret>"
},
"artifact_spec": {
"resolution": "512x512",
"max_frames": 16,
"encoding_model": "stabilityai/sd-vae-ft-mse"
},
"parameters": {
"expected_output": "encoder"
}
}
```

Miner output commitments use the same registry envelope with `kind: "dps_output"`, the miner's artifact R2 location, validator-readable credentials, optional manifest info, optional artifact hash, and the artifact spec used for the task. Miners can expose artifact behavior by running with `--miner.type ENCODER` or `--miner.type CAPTIONER`. If `--dps-artifact.processor-command` is configured, the miner runs that command for each artifact task and passes source/output metadata through environment variables such as `DPS_SOURCE_BUCKET`, `DPS_SOURCE_PATH`, `DPS_SOURCE_ACCESS_KEY_ID`, `DPS_SOURCE_SECRET_ACCESS_KEY`, `DPS_SOURCE_SESSION_TOKEN`, `DPS_OUTPUT_BUCKET`, `DPS_OUTPUT_PREFIX`, `DPS_OUTPUT_WRITE_ACCESS_KEY_ID`, `DPS_OUTPUT_WRITE_SECRET_ACCESS_KEY`, `DPS_ARTIFACT_RESOLUTION`, `DPS_ARTIFACT_MAX_FRAMES`, and `DPS_ARTIFACT_ENCODING_MODEL`. The command may print JSON with `artifact_hash`, `manifest_url`, `manifest_key`, or `path`, which the miner publishes in its `dps_output` commitment.

Use `.env.encoder_miner.template` for mechanism-1 artifact miners rather than `.env.gen_miner.template`:

```bash
cp .env.encoder_miner.template .env.encoder_miner
MINER_ENV_FILE=.env.encoder_miner pm2 start gen_miner.config.js
```

The repo includes a reference processor for local/fake-R2 testing and deterministic baseline artifacts:

```bash
--dps-artifact.processor-command "python -m gas.artifacts.processor"
```

The reference processor and validator verifier use S3-compatible R2 transport when endpoint URL plus access key/secret are present, while still supporting `file://` fake R2 for local tests. The validator artifact verifier reads the published manifest, checks that the manifest artifact spec matches the assignment, fetches each listed artifact file, checks SHA-256 hashes, validates the top-level single-artifact hash when present, counts accepted work units, and writes mechanism-1 reward stats.

Task IDs are deterministic by role, UID, assignment epoch, R2 source hash, and artifact spec hash:

```text
dps-{role}-{uid}-e{epoch}-{source_hash}
```

This lets validators and miners agree on the shard/output path being scored without relying on random request IDs.

The encoder reward is:

$$R_{\text{encoder}} = \max(0, w \cdot c \cdot a \cdot t \cdot n - p)$$

Where:
- $w$ = accepted work units
- $c$ = deterministic correctness rate
- $a$ = availability rate
- $t$ = timeliness multiplier
- $n$ = novelty multiplier
- $p$ = penalties

Captioner rewards use the same work-unit shape, but replace deterministic correctness with a semantic quality score:

$$R_{\text{captioner}} = \max(0, w \cdot q \cdot a \cdot t \cdot n - p)$$

Where $q$ is caption quality, supplied by the DPS semantic validation layer.

The validator accepts artifact stats from `--dps-artifact-rewards-path` / `DPS_ARTIFACT_REWARDS_PATH`. The JSON may contain `encoder_stats` and `captioner_stats` fields, or an encoder-only UID-keyed object while the first encoder pipeline is being rolled out. Records may include `uid` directly or be keyed by miner hotkey; existing verification aliases such as `total_verified`, `pass_rate`, and `quality_score` are accepted.

Current mechanism layout:

```text
mechanism 0: SN34 generation/discrimination
burn_pct = 0.60
video_escrow = 0.20
image_escrow = 0.00
audio_escrow = 0.00
generator_pct = 0.20

mechanism 1: DPS artifacts
encoder_weight = 0.80
captioner_weight = 0.20
```

Mechanism `1` submission is disabled by default until the subnet owner enables the second mechanism on-chain. Run validators with `--enable-dps-artifact-mechanism` after mechanism `1` exists. If no active encoder or captioner UIDs have positive scores in an epoch, that role's unallocated mechanism-1 budget is assigned to burn so the weight vector remains fully allocated.

Native multiple-mechanism support requires a Bittensor SDK that accepts `mechid` on `set_weights`; this is documented in SDK v10. Validators should upgrade before enabling mechanism `1`.



## Discriminator Rewards
Expand Down
15 changes: 15 additions & 0 deletions gas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
__version__ = "4.7.12"

import bittensor as bt

# Bittensor v10 exposes class names (Wallet/Subtensor/Axon/Metagraph) where
# earlier SDKs exposed lowercase constructors. Keep the existing codepath
# working while the subnet migrates to v10 for mechid support and security
# fixes.
if not hasattr(bt, "wallet") and hasattr(bt, "Wallet"):
bt.wallet = bt.Wallet
if not hasattr(bt, "subtensor") and hasattr(bt, "Subtensor"):
bt.subtensor = bt.Subtensor
if not hasattr(bt, "axon") and hasattr(bt, "Axon"):
bt.axon = bt.Axon
if not hasattr(bt, "metagraph") and hasattr(bt, "Metagraph"):
bt.metagraph = bt.Metagraph

version_split = __version__.split(".")
__spec_version__ = (
(100000 * int(version_split[0]))
Expand Down
1 change: 1 addition & 0 deletions gas/artifacts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""DPS artifact processing helpers."""
Loading