Skip to content

History

Showing with 554 additions and 295 deletions.
  1. +36 −16 Aggregator.md
  2. +44 −17 Auditor.md
  3. +33 −19 Client.md
  4. +19 −15 DIN-CLI.md
  5. +21 −51 DIN-DAO.md
  6. +5 −3 DIN-Daemon.md
  7. +5 −3 DIN-Indexer.md
  8. +9 −4 DIN-Node.md
  9. +87 −25 DIN-Representative.md
  10. +4 −2 DIN-SDK.md
  11. +2 −0 Home.md
  12. +13 −3 IPFS-Layer.md
  13. +62 −29 Model-Owner.md
  14. +13 −9 Overview.md
  15. +97 −47 Platform-Contracts.md
  16. +93 −44 Task-Contracts.md
  17. +7 −4 Worker-Node.md
  18. +4 −4 _Sidebar.md
52 changes: 36 additions & 16 deletions Aggregator.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,67 @@
# Aggregator

Aggregators do the network's **model building**: staked validators who combine the auditor-approved local models into the new global model at the end of each [Global Iteration](Task-Contracts#the-global-iteration-lifecycle). Where [Auditors](Auditor) decide *what goes in*, aggregators produce *what comes out*.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
Like auditors, they are validators with skin in the game: DIN tokens staked in [`DinValidatorStake`](Platform-Contracts#dinvalidatorstake), slashable for missing assigned work or submitting results that diverge from their peers.
Aggregators do the network's **model building**. They are staked validators who combine the auditor-approved local models into the new global model at the end of each [Global Iteration](Task-Contracts#the-global-iteration-lifecycle). [Auditors](Auditor) decide *what goes in*; aggregators produce *what comes out*.

Like auditors, they have skin in the game: DIN tokens staked in [`DinValidatorStake`](Platform-Contracts#dinvalidatorstake), which can be slashed if they miss assigned work or submit a result that disagrees with their peers. In return they earn a share of every GI's reward pool.

## Becoming an aggregator

```bash
dincli aggregator dintoken buy <amount_eth> # exchange ETH for DIN
dincli aggregator dintoken stake <amount> # stake (approval + stake in one command)
dincli aggregator dintoken stake <amount> # approve and stake in one command
dincli aggregator register <model_id> # register for the current GI (window must be open)
```

Staking is once (topped up as needed, minimum 10 DIN per stake call, 7-day unbonding on exit); registration is **per model, per Global Iteration**, while the aggregator registration window is open.
Staking is done once and topped up as needed. Each stake call is at least 10 DIN, and exiting has a default 7-day unbonding period. Registration is **per model, per Global Iteration**, and only while the aggregator registration window is open. The same conditions as for auditors apply:
- you must be an active validator;
- your stake must meet the model's stake floor;
- you need room under the concurrent-registration cap;
- at most 300 aggregators can register per GI.

## The job: two-tier aggregation

Once evaluation closes, the approved local models are aggregated hierarchically:
Once evaluation closes, a future-block seed is locked (anyone can do it: `dincli aggregator lock-seed <model_id>`). The registered aggregators and approved local models are then shuffled into batches:

- **Tier 1 (T1).** Approved models are split into sub-batches of 3 (the last batch may have 2), and each sub-batch is assigned to 3 aggregators. Each aggregator independently combines its batch's models by running the model owner's aggregation function in a sandboxed [Worker Node](Worker-Node).
- **Tier 2 (T2).** A single final batch of the **next 3 shuffled aggregators** combines the finalized T1 outputs into the **new global model**, which seeds the next GI.

Every submission is **commit-then-reveal**:
- **Commit.** The aggregator first commits a hash of its result CID, bound to its address, the GI, the tier and the batch.
- **Reveal.** After the model owner opens the reveal phase, it reveals the CID, using the same `dincli` cache it committed from.

- **Tier 1 (T1)** — approved models are split into sub-batches, each assigned to a small group of aggregators (3 per batch). Each aggregator independently combines their batch's models (running the model owner's aggregation function in a sandboxed [Worker Node](Worker-Node)) and submits the resulting CID.
- **Tier 2 (T2)** — a single final batch: assigned aggregators combine the finalized T1 outputs into the **new global model**, which seeds the next GI.
No CID is visible while commits are open, so a late aggregator can't copy an earlier one.

```bash
dincli aggregator show-t1-batches <model_id> --detailed # see your T1 assignment
dincli aggregator aggregate-t1 <model_id> --submit # aggregate & record on-chain
dincli aggregator aggregate-t1 <model_id> --submit # aggregate and commit
dincli aggregator reveal-t1 <model_id> # after the owner opens T1 reveals
dincli aggregator show-t2-batches <model_id> --detailed # if assigned to the final tier
dincli aggregator aggregate-t2 <model_id> --submit
dincli aggregator reveal-t2 <model_id>
```

**Honesty is enforced by redundancy.** Every aggregator in a batch performs the same deterministic computation, and the batch's final CID is decided by **majority vote**: identical inputs must yield identical outputs, so an identical CID. An aggregator who computes correctly is automatically in the majority; one who deviates — lazily, faultily, or maliciously — produces a lone CID that loses the vote and marks them for slashing.
**Honesty is enforced by redundancy.** Every aggregator in a batch runs the same deterministic computation, so the same inputs give the same output and the same CID. The batch's final CID is the one **revealed most often**, and at least 2 of the 3 must reveal. An aggregator who computes correctly lands in the majority. One who deviates, whether lazily, faultily or maliciously, produces a lone CID that loses.

## Rewards

When the GI ends, **15% of its reward pool** is shared among aggregators. Every assigned aggregator of each finalized batch gets one unit. Rewards are pulled on-chain: call `claimReward(gi)`, then `claimRewards()`, on the model's `DINTaskAuditor`. `dincli` doesn't have a claim command yet.

## What gets an aggregator slashed

At GI end, the model owner triggers slashing against aggregators who:
At the end of the GI, the model owner triggers slashing. The model's `DINTaskCoordinator` slashes aggregators who:

- **missed their submission:** they were assigned a T1 or T2 batch but didn't reveal, including committing without ever revealing. This is a partial slash, 30% of the minimum stake by default (S2), and repeat offences escalate under S5 to a full slash plus a jail period.
- **revealed a losing CID:** their result disagreed with the batch's winning CID. This is a full minimum-stake slash.

- **failed to participate** — registered but did not submit for an assigned T1/T2 batch, or
- **submitted a minority result** — their CID disagreed with the batch majority.
**Aggregation disputes (S4).** Within a window after a batch is finalized, any active validator can post a 100 DIN bond and dispute the result. The model owner adjudicates, and a confirmed dispute slashes the aggregators who produced the bad result.

Slashing is executed by the model's `DINTaskCoordinator` against the aggregator's stake, including stake in the unbonding queue.
Slashes reach stake in the unbonding queue too.

## Further reading

- [Aggregator command reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/aggregators.md)
- [Task Contracts](Task-Contracts) — batch formation, CID voting, and finalization on-chain
- [Platform Contracts](Platform-Contracts) — staking, unbonding, and slashing mechanics
- [Auditor](Auditor) — the validator role upstream, deciding which models reach aggregation
- [Task Contracts](Task-Contracts): batch formation, commit-reveal, CID voting and finalization on-chain
- [Platform Contracts](Platform-Contracts): staking, unbonding and slashing mechanics
- [Auditor](Auditor): the validator role upstream, deciding which models reach aggregation
61 changes: 44 additions & 17 deletions Auditor.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,73 @@
# Auditor

Auditors are the network's **quality control**: staked validators who evaluate the local models submitted by [Clients](Client) and decide, by score and vote, which contributions are good enough to enter the global model. Without them, one poisoned submission could corrupt the model everyone shares — the audit phase is what makes open participation safe.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
Like [Aggregators](Aggregator), auditors are validators with skin in the game: they stake DIN tokens in [`DinValidatorStake`](Platform-Contracts#dinvalidatorstake), and misbehavior — failing to evaluate an assigned batch, or scoring against the consensus — is punished by slashing that stake.
Auditors are the network's **quality control**. They are staked validators who evaluate the local models that [Clients](Client) submit, and decide by score and vote which contributions are good enough to enter the global model. Without them, one poisoned submission could corrupt the model everyone shares. The audit phase is what makes open participation safe.

Like [Aggregators](Aggregator), auditors have skin in the game. They stake DIN tokens in [`DinValidatorStake`](Platform-Contracts#dinvalidatorstake), and failing to vote on an assigned batch is punished by slashing that stake. In return they earn a share of every GI's reward pool.

## Becoming an auditor

```bash
dincli auditor dintoken buy <amount_eth> # exchange ETH for DIN
dincli auditor dintoken stake <amount> # stake (approval + stake in one command)
dincli auditor dintoken stake <amount> # approve and stake in one command
dincli auditor register <model_id> # register for the current GI (window must be open)
```

Staking is once (topped up as needed, minimum 10 DIN per stake call, 7-day unbonding on exit); registration is **per model, per Global Iteration**, and only while the model owner has the auditor registration window open.
You stake once and top up as needed: each stake call needs at least 10 DIN, and exiting takes a 7-day unbonding period by default. Registration is **per model, per Global Iteration**, and only while the model owner has the auditor registration window open. To register, you must:
- be an active validator;
- meet the model's stake floor, if it has one;
- have room under the concurrent-registration cap;
- register before the GI's 300-auditor cap is reached.

**Encryption key.** Audit test data is encrypted to each auditor. So an auditor needs an X25519 key pair: the public key registered on `DinValidatorStake` (`registerEncryptionKey`), and the private key at `auditor_x25519.key` in the `dincli` config directory. `dincli` doesn't yet have a command to register the key. If an assigned auditor has no key, the owner can't assign test data to that batch.

## The job: evaluate a batch

After the LMS phase closes, the model owner forms **audit batches** — each batch is a random set of submitted local models assigned to a small group of auditors, with a test-dataset CID to evaluate against. For each model in the batch, the auditor:
After the LMS phase closes, a future-block seed is locked (anyone can do it: `dincli auditor lock-seed <model_id>`), and the model owner shuffles the submitted local models into **audit batches** of 3 auditors × 3 models. For each batch the owner publishes the test dataset encrypted, with a key for each of the batch's auditors.

For each model in the batch, the auditor:

1. fetches the local model and test data from IPFS,
2. runs the model owner's scoring function (in a sandboxed [Worker Node](Worker-Node)) against the test data,
3. submits on-chain a **score (0–100)** and an **eligibility vote** (does the model conform at all?).
1. fetches the local model and the encrypted test data from IPFS, decrypts its key, and checks the owner's signature on the dataset;
2. runs the model owner's scoring function against the test data, in a sandboxed [Worker Node](Worker-Node);
3. **commits** on-chain a hash of its **score (0–100)** and **eligibility vote**, bound to its address and the slot;
4. after the model owner opens the reveal phase, **reveals** the score and vote.

```bash
dincli auditor lms-evaluation show-batch <model_id> # see your assignment
dincli auditor lms-evaluation evaluate <model_id> --submit # evaluate & record on-chain
dincli auditor lms-evaluation evaluate <model_id> --submit # evaluate and commit
dincli auditor lms-evaluation reveal <model_id> # after the owner opens reveals
```

A local model is **approved for aggregation** only when a quorum of its batch's auditors has voted, the eligibility majority passed it, and its final average score meets the pass threshold. Multiple independent auditors per model means no single auditor decides anything — and disagreeing with the majority is visible on-chain.
`evaluate --submit` saves the salt locally before sending each commit. Rerunning it skips models you have already committed, so your saved reveal data stays valid.

A local model is **approved for aggregation** when at least 2 of its batch's auditors have revealed, at least 2 voted it eligible, and its **median** score meets the GI's pass score. Several independent auditors per model means no single auditor decides anything, and every vote is visible on-chain once revealed.

## Rewards

When the GI ends, **20% of its reward pool** is shared among auditors in proportion to how many votes each revealed. Rewards are pulled on-chain with `claimReward(gi)`, then `claimRewards()`, on the model's `DINTaskAuditor`. There is no `dincli` claim command yet.

## What gets an auditor slashed

At the end of each GI, the model owner triggers slashing against auditors who:
The model's `DINTaskAuditor` carries out auditor slashing itself, when the model owner triggers it at the end of the GI:

- **Missed vote (S1).** You registered and were assigned a batch, but didn't reveal a vote. This includes committing and never revealing. The penalty is a partial slash, 30% of the minimum stake by default. Repeat offences escalate under S5 to a full slash plus a jail period.
- **Score deviation (S3).** Scoring far from your batch's median is designed as a full slash, but it ships **disabled** (shadow mode) on DevNet 2.0.

Slashes reach stake in the unbonding queue too, so exiting doesn't dodge a penalty.

## Disputing bad test data

If the test data for your batch can't be decrypted or doesn't match the owner's commitment, any auditor of that batch can open a **test-data dispute** by posting a 100 DIN bond, before the GI's rewards are settled. The owner then has about one day to reveal the dataset key.

- **failed to participate** — registered for the GI but did not evaluate their assigned batch, or
- **scored dishonestly** — submitted results inconsistent with the consensus of their batch.
- **The key checks out:** the bond is forfeited.
- **It doesn't, or the owner stays silent:** the dispute is upheld. The bond is returned, the owner forfeits 25% of the GI reward pool (unless the GI settled in the meantime), and the batch is reassigned.

Slashing is executed by the model's `DINTaskCoordinator` (an authorized slasher) against the auditor's stake — including any stake in the unbonding queue, so exiting doesn't dodge the penalty.
There's no `dincli` command for disputes yet.

## Further reading

- [Auditor command reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/auditors.md)
- [Task Contracts](Task-Contracts) — `DINTaskAuditor`, where batches, scores, and approval live
- [Platform Contracts](Platform-Contracts) — staking, unbonding, and slashing mechanics
- [Aggregator](Aggregator) — the other validator role, downstream of the auditors' verdict
- [Task Contracts](Task-Contracts): `DINTaskAuditor`, where batches, scores, approval and rewards live
- [Platform Contracts](Platform-Contracts): staking, unbonding and slashing mechanics
- [Aggregator](Aggregator): the other validator role, downstream of the auditors' verdict
52 changes: 33 additions & 19 deletions Client.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,51 @@
# Client

Clients (model trainees) are the network's data holders — the reason DIN exists. They train the current global model on their **own private data** and contribute only the resulting local model back. The raw data never leaves their device; that is the protocol's founding constraint, not a feature flag.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
Unlike [Auditors](Auditor) and [Aggregators](Aggregator), clients are not staked validators: participating requires only a wallet and a dataset. Their contributions are quality-controlled from the other side — every submitted local model is scored by auditors before it can enter aggregation.
Clients (model trainees) are the network's data holders, and the reason DIN exists. They train the current global model on their **own private data** and contribute only the resulting local model. The raw data never leaves their device. That is the protocol's founding constraint, not a feature flag.

Unlike [Auditors](Auditor) and [Aggregators](Aggregator), clients are not staked validators: participating needs only a wallet and a dataset. Quality control comes from the other side: auditors score every submitted local model before it can enter aggregation. Clients whose models are approved earn the largest share of each round's rewards.

## How a contribution works

Each [Global Iteration](Task-Contracts#the-global-iteration-lifecycle), while the Local Model Submission (LMS) window is open:
In each [Global Iteration](Task-Contracts#the-global-iteration-lifecycle), while the Local Model Submission (LMS) window is open:

1. **Fetch.** `dincli` downloads the current global model (the genesis model in GI 1) and the model's training service code from IPFS, by CID.
2. **Train locally.** The model owner's `client.py` training function runs on the client's dataset inside a sandboxed [Worker Node](Worker-Node) container.
3. **Submit.** The trained local model is uploaded to IPFS and its CID is recorded on-chain in `DINTaskAuditor`. Each client gets one submission per GI.
4. **Get audited.** Auditors score the submission against encrypted test data. It is approved and aggregated into the next global model if at least 2 auditors vote it eligible and its median score meets the GI's pass score.

```bash
dincli client create-client-dataset-dir <model_id> # creates the expected dataset folder
dincli client train-lms <model_id> # train locally
dincli client submit-lm <model_id> # upload and record on-chain
dincli client lms show-models <model_id> # verify it landed
```

The client's dataset goes at the path `dincli` expects: `<CACHE_DIR>/<network>/model_<model_id>/dataset/clients/<address>/data.pt`. The model owner defines the required format, preprocessing and training hyperparameters **for each model**, in the model's client instructions. For the reference MNIST-style model, the dataset is a list of `(tensor, label)` tuples ([full spec](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/client-onboarding.md)).

1. **Fetch** — `dincli` downloads the current global model (genesis model in GI 1) and the model's training service code from IPFS, by CID.
2. **Train locally** — the model owner's `client.py` training function runs on the client's dataset inside a sandboxed [Worker Node](Worker-Node) container. One command does it all:
```bash
dincli client train-lms <model_id> --submit
```
3. **Submit** — the trained local model is uploaded to IPFS and its CID recorded on-chain in `DINTaskAuditor` (one submission per client per GI). `dincli client lms show-models <model_id>` verifies it landed.
4. **Get audited** — auditors score the submission against test data; if it passes eligibility and the score threshold, it is approved and aggregated into the next global model.
## Rewards

The client's dataset must be placed at the path `dincli` expects (`<CACHE_DIR>/<network>/model_<model_id>/dataset/clients/<address>/data.pt`); its required format, preprocessing, and training hyperparameters are defined **per model by the model owner** — see the model's client instructions (for the reference MNIST-style model: a list of `(tensor, label)` tuples, [full spec](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/client-onboarding.md)).
When the GI ends, **60% of its reward pool** goes to clients, shared in proportion to the median score of each approved local model. Rewards are pulled on-chain: call `claimReward(gi)` on the model's `DINTaskAuditor`, then `claimRewards()` to withdraw. `dincli` doesn't have a claim command yet.

## What protects the client

Trust here runs in both directions, and both are enforced mechanically:
Trust runs in both directions here, and both directions are enforced mechanically:

- **The network never sees the data.** Only trained weights (as IPFS CIDs) are submitted. Optionally, a model can enable **differential privacy** — configured in the model's manifest (`dp` block) and applied inside the client's local training — so even the submitted weights carry calibrated noise limiting what they reveal.
- **The client never trusts the model owner's code.** The training function is the model owner's Python, so it runs in the [Worker Node](Worker-Node) sandbox: no network access, resource-capped, no wallet or secrets — it cannot exfiltrate the very data it is training on.
- **The network never sees the data.** Only trained weights are submitted, as IPFS CIDs. A model can also enable **differential privacy** in its manifest's `dp` block. By default it adds calibrated noise after training (`post_training_gaussian`), so even the submitted weights reveal less.
- **The client never trusts the model owner's code.** The training function is the model owner's Python, so it runs in the [Worker Node](Worker-Node) sandbox: no network access, capped resources, no wallet or secrets. It can't exfiltrate the data it trains on.

## What protects the network from a client

A malicious client can submit garbage or poisoned weights — which is exactly what the audit phase is for: every submission is scored by multiple independent staked auditors against held-out test data, needs an eligibility majority **and** a passing average score, and anything below threshold simply never reaches aggregation. Submission is also capped (one per client per GI) to keep spam bounded.
A malicious client can submit garbage or poisoned weights, which is exactly what the audit phase is for:
- Every submission is scored by several independent staked auditors against held-out test data.
- It needs an eligibility majority **and** a passing median score.
- Anything below the threshold never reaches aggregation, and earns nothing.
- Submissions are capped at one per client per GI, which keeps spam bounded.

## Further reading

- [Client command reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/clients.md) — commands, dataset path, workflow
- [Client instructions (reference model)](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/client-onboarding.md) — dataset format & hyperparameters for the MNIST-style example
- [Task Contracts](Task-Contracts) — where LMS and evaluation live on-chain
- [Auditor](Auditor) — the role that scores client submissions
- [Client command reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/clients.md): commands, dataset path and workflow
- [Client instructions (reference model)](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/client-onboarding.md): dataset format and hyperparameters for the MNIST-style example
- [Task Contracts](Task-Contracts): where LMS, evaluation and rewards live on-chain
- [Auditor](Auditor): the role that scores client submissions
34 changes: 19 additions & 15 deletions DIN-CLI.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,48 @@
# DIN CLI

`dincli` is the command-line interface to the DIN Protocol — the tool through which **every participant** interacts with the network. It is a Python application (Typer-based, Python ≥ 3.9) that wraps the on-chain contracts and the IPFS layer behind role-oriented commands, so participants never have to hand-craft transactions or manage CIDs themselves.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
`dincli` is the command-line interface to the DIN Protocol — the tool through which **every participant** interacts with the network. It is a Python application (Typer-based, Python ≥ 3.12) that wraps the on-chain contracts and the IPFS layer behind role-oriented commands, so participants never have to hand-craft transactions or manage CIDs themselves.

## One CLI, every role

Commands are grouped into sub-apps, one per role or concern:

| Command group | Who uses it | What it covers |
|---|---|---|
| `dincli system` | everyone | init, network/logging/demo-mode config, wallet connection, IPFS provider setup |
| `dincli dindao` | DIN-Representative | slasher authorization, model registration approvals, protocol admin |
| `dincli system` | everyone | init, network/logging/demo-mode config, wallet registration and connection, IPFS provider setup, importing platform deployments, ABI export |
| `dincli dinrep` | DIN-Representative | slasher authorization, model registration and manifest-update approvals, disabling models, setting registry fees, sweeping fees to `DinFeeRouter` |
| `dincli model-owner` | model owners | task contract deployment, genesis model, driving every GI phase (registration windows, LMS, evaluation, aggregation batches, slashing) |
| `dincli client` | clients (model trainees) | local training on private data and local model submission |
| `dincli auditor` | auditors | registration, staking, evaluating assigned audit batches |
| `dincli aggregator` | aggregators | registration, staking, T1/T2 aggregation of assigned batches |
| `dincli dintoken` | everyone | buying DIN with ETH, staking, reading stake |
| `dincli task` | model owners | model registration & manifest update requests on `DinModelRegistry` |
| `dincli auditor` | auditors | registration, staking, seed locking, evaluating (commit) and revealing scores for assigned audit batches |
| `dincli aggregator` | aggregators | registration, staking, seed locking, T1/T2 aggregation (commit) and reveal for assigned batches |
| `dincli dintoken` | everyone | buying DIN with ETH, staking, reading stake and the DIN-per-ETH rate |
| `dincli task` | model owners, everyone | model registration and manifest update requests on `DINModelRegistry` (`task model-owner …`), GI state (`task gi show-state`), registry counters |
| `dincli ipfs` | everyone | direct IPFS upload/retrieve utilities |

A typical Global Iteration is literally a conversation between these sub-apps: the model owner opens a phase (`dincli model-owner lms open`), participants act within it (`dincli client train-lms --submit`), and the owner closes it — the CLI enforcing the on-chain state machine at every step.
A typical Global Iteration is literally a conversation between these sub-apps: the model owner opens a phase (`dincli model-owner lms open`), participants act within it (`dincli client train-lms`, then `dincli client submit-lm`), and the owner closes it — the CLI enforcing the on-chain state machine at every step.

## Key design points

- **Network selection per command.** Every command resolves its network (`local`, `sepolia_op_devnet`, `mainnet`) from a `--network` flag or the configured default. The choice drives which `.env.<network>` file, RPC endpoint, and deployed contract addresses are used. The live DevNet is `sepolia_op_devnet` (Optimism Sepolia).
- **Wallets & keys.** Accounts connect via `dincli system connect-wallet`. For local development, private keys can live in `.env` (`ETH_PRIVATE_KEY_<n>`); **production validators use an encrypted keystore** protected by `DIN_WALLET_PASSWORD` — see the [wallet setup guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/wallet-setup.md). A demo mode exists for experimentation (plaintext wallets — never with real funds).
- **Network selection per command.** Every command resolves its network (`local`, `sepolia_devnet`, `sepolia_op_devnet`, `mainnet`) from the global `--network` option (accepted anywhere on the command line) or the configured default. The choice drives which `.env.<network>` file, RPC endpoint, and deployed contract addresses are used. The live DevNet is `sepolia_op_devnet` (Optimism Sepolia).
- **Wallets & keys.** A key is first registered as a named, encrypted wallet with `dincli system register-wallet`: from a hidden prompt (recommended), `--keystore` (import a JSON keystore), `--key-file`, or `--account <n>` (reads `ETH_PRIVATE_KEY_<n>` from `.env`), then selected with `dincli system connect-wallet <name>` (or `register-wallet … --connect`). Per invocation, `--wallet <name>` or `DIN_WALLET_NAME` override the connected wallet. **Production validators use an encrypted keystore** protected by `DIN_WALLET_PASSWORD`; see the [wallet setup guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/wallet-setup.md). A demo mode exists for local experimentation (`connect-demo-wallet`, `--demokey`; plaintext dev keys, never with real funds).
- **Manifest-driven model logic.** `dincli` contains no model-specific code. Each model's training, scoring, and aggregation functions are Python service files written by the model owner, pinned to IPFS, and referenced by CID in the model's `manifest.json`. The CLI fetches and executes them on demand, caching by CID — so a new model means a new manifest, not a new CLI release. See [Manifest & Services](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/services.md).
- **Pluggable IPFS.** All artifact traffic goes through one abstraction with three interchangeable backends — a self-hosted IPFS node (`env`), managed Filebase (recommended), or a fully custom Python provider. See the [IPFS Layer](IPFS-Layer) page.
- **Config & cache.** `dincli system init` creates per-user config and cache directories (via `platformdirs`); fetched artifacts are cached by CID so files are only re-downloaded when their CID changes.
- **Config & cache.** `dincli system init` creates per-user config and cache directories (via `platformdirs`) with demo mode off; `dincli system get-config-dir` / `get-cache-dir` print them. Fetched artifacts are cached by CID so files are only re-downloaded when their CID changes.
- **Platform addresses.** After the DIN-Representative deploys the platform contracts, `dincli system import-deployments` loads their addresses from `foundry/deployments/<network>.json`; `dincli system din-info` shows what is configured.

## Getting started

```bash
# install (in a virtualenv, Python 3.12 recommended)
pip install git+https://github.com/InfiniteZeroFoundation/devnet.git@main#subdirectory=dist
# install from a checkout (in a virtualenv, Python 3.12 recommended)
git clone https://github.com/InfiniteZeroFoundation/DevNet.git && cd DevNet
pip install -e .

# initialize and configure
dincli system init
dincli system configure-demo --mode no
dincli system configure-network --network sepolia_op_devnet
dincli system connect-wallet --account 0
dincli --network sepolia_op_devnet system configure-network
dincli system register-wallet --account 0 --connect
dincli system configure-ipfs --provider filebase --api-key <key>
```

Expand Down
72 changes: 21 additions & 51 deletions DIN-DAO.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,35 @@
# DIN DAO

> 📋 **Status: Planned** — the DIN DAO contracts do not exist yet. This page describes the design intent per the [governance design doc](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/issues/decentralized-governance.md) and the [project roadmap](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/ROADMAP.md); details may change as the design is finalized.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
> **Naming note:** in today's documentation and CLI, "DIN DAO" (`dincli dindao ...`) refers to the [DIN-Representative](DIN-Representative) — a single administrative account that deploys the platform contracts and approves registrations. The DIN DAO described here is the planned **replacement** of that centralized authority with on-chain governance. Same name, opposite trust model.
> ⏸️ **Status: deferred to post-mainnet.** Design decision [DD-3](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/design/DESIGN_DECISIONS.md) (resolved 2026-08-04) moved all DIN-DAO work out of active scope, Stages A through D. That includes the earlier work on [PR #27](https://github.com/InfiniteZeroFoundation/DevNet/pull/27) and [issue #23](https://github.com/InfiniteZeroFoundation/DevNet/issues/23). DevNet 2.0 launches **without** on-chain governance. This page records the long-term direction, not a schedule.
## What it will be
## How DIN is governed today

The DIN DAO is the planned **governance layer** of the DIN network: a set of contracts that progressively take over the authority currently held by the DIN-Representative's admin key over the [Platform Contracts](Platform-Contracts) — fee parameters, model registration approvals, slasher authorization, validator blacklisting, treasury withdrawals, and contract upgrades.
During DevNet 2.0, governance runs **off-chain**, following Ethereum's model: team coordination and public discussion (forums and GitHub discussions, the equivalent of All Core Devs calls). No multisig sits between the community and protocol changes.

Planned contract modules:
- The [DIN-Representative](DIN-Representative) holds a single admin key and is the `owner()` of the [Platform Contracts](Platform-Contracts). It uses that key for fee parameters, model admission, slasher authorization, blacklisting and contract upgrades.
- The CLI commands for this role are `dincli dinrep …`. There is no `dincli dindao`.
- If a multisig is used in the near term, it is a plain Safe for **treasury funds only**, never for protocol roles.
- The contracts' owner-controlled setters are simply how the protocol is run for now. They are not a stepping stone to a particular on-chain design.

- **Multisig** — N-of-M approval with per-category thresholds, replacing single-key admin actions
- **Timelock** — every governance action becomes visible on-chain before it executes, with a cancellation window; the timelock ultimately *owns* the platform contracts
- **Governance staking** — voting power from **locked DIN** (non-transferable, snapshot-based, delegable), not raw wallet balances
- **Governor** — on-chain proposals, voting, quorum, and execution through the timelock
- **Guardian** — a narrow emergency path (e.g. disabling a malicious model) whose actions expire unless ratified by normal governance
## The long-term direction

## Why it exists
DIN is a protocol with shared rules, incentives and security assumptions. As long as those rules sit behind one admin key, participants must trust the operator: economic policy can change unilaterally, and blacklist, slashing and upgrade authority are a standing centralization risk. A DAO doesn't remove governance risk, but it makes authority **transparent, rule-bound, auditable and contestable**.

DIN is a protocol with shared rules, incentives, and security assumptions. As long as those rules sit behind one admin key, participants must trust the operator: economic policy could change unilaterally, and blacklist, slashing, and upgrade authority would be a standing centralization risk. A DAO doesn't remove governance risk, but it makes authority **transparent, rule-bound, auditable, and contestable** — a requirement for a credible testnet and beyond, not a nice-to-have.
When governance work resumes after mainnet, the [governance design doc](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/issues/decentralized-governance.md) is the starting point. It explored:

Two design decisions are already settled in the governance design doc:
- **Multisig and timelock.** These would replace single-key admin actions with N-of-M approval, and make every governance action visible on-chain before it runs, with a window to cancel it.
- **Governance staking.** Voting power would come from **locked DIN** (non-transferable, measured at a snapshot, delegable), not from raw wallet balances.
- **Governor.** On-chain proposals, voting, quorum and execution.
- **Guardian.** A narrow emergency path whose actions expire unless normal governance ratifies them.

- **No raw quadratic voting.** Transferable tokens make Sybil-splitting trivial; quadratic mechanisms are at most future non-binding signaling.
- **No free-balance voting.** Binding votes come from staked or locked DIN measured at a snapshot, so governance power reflects commitment to the protocol rather than momentary balances.

## The staged rollout

Decentralization arrives in stages, each mapped to a network milestone — nothing activates before devnet 3.0:

| Stage | What changes | Target |
|-------|-------------|--------|
| A — Multisig | N-of-M multisig shadow-operates admin actions | devnet 2.0 |
| B — Timelock | Timelock becomes `owner()` of the platform contracts; all admin actions get an on-chain delay | devnet 3.0 |
| C — Token vote | Governor + locked-DIN voting power; proposals, quorum, delegation | testnet 1.0–2.0 |
| D — Guardian | Narrow emergency powers, expiring unless ratified | with Stage C |

## How it fits

```
DIN holders ──lock──▶ governance staking (voting power)
│ vote
▼
Governor ──queue──▶ Timelock ──owns──▶ Platform Contracts
▲ ▲ (fees, registry,
propose │ │ propose/cancel staking, upgrades)
└── Multisig ──────┘
│
Guardian (emergency, expiring)
```

Governance actions flow through proposals rather than direct admin calls; the [DIN Indexer](DIN-Indexer) later provides the read layer for proposal lists, voter histories, and governance dashboards.

## Status & sequencing

Design-first: an architecture document precedes the Solidity work, and the contracts land on a feature branch well before any activation. The near-term protocol work (staking, slashing, fees) deliberately ships with plain owner-controlled parameter setters — exactly the surface the timelock takes over later without redesign. Binding token-vote governance is a testnet-era milestone.
The design doc also recommends against raw quadratic voting, because transferable tokens make Sybil-splitting trivial, and against free-balance voting. How voting power is measured (DD-1, DD-2) is still an **open, deferred decision**.

## Further reading

- [Governance design doc](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/issues/decentralized-governance.md) — governance domains, voting-power rationale, proposal lifecycle
- [Tracking issue #23](https://github.com/InfiniteZeroFoundation/DevNet/issues/23) — Start DIN-DAO: architecture and deliverables
- [Current DIN DAO operations](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/dindao.md) — the centralized admin surface the DAO replaces
- [DIN-Representative](DIN-Representative) — the role holding that authority today
- [Platform Contracts](Platform-Contracts) — the contracts the DAO will govern
- [Design decisions](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/design/DESIGN_DECISIONS.md): DD-1, DD-2 and DD-3, with the reasoning behind the deferral
- [Governance design doc](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/issues/decentralized-governance.md): governance domains, the rationale for voting power, and the proposal lifecycle
- [DIN-Representative guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/dinrep.md): the admin surface as it exists today
- [DIN-Representative](DIN-Representative): the role holding that authority
- [Platform Contracts](Platform-Contracts): the contracts a future DAO would govern
8 changes: 5 additions & 3 deletions DIN-Daemon.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DIN Daemon (dind)

> 📋 **Status: Planned** — `dind` does not exist yet. This page describes its design intent per the [project roadmap](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/ROADMAP.md) (phase P4); details may change as the architecture spec is finalized.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
> ⚡ **Status: In progress, not on `develop` yet.** A first daemon skeleton — state-directory locking, a health endpoint that reports degraded state, rotating logs, a first read-only job, plus early preference and capability-detection work — is in [PR #32](https://github.com/InfiniteZeroFoundation/DevNet/pull/32), stacked on the [SDK](DIN-SDK) PR. This page describes the design intent per the [project roadmap](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/ROADMAP.md) (phase P4); details may change as the architecture spec is finalized.
>
> *Naming note: `dind` follows the Unix daemon convention (DIN + `d`, like `sshd`, `dockerd`). It is unrelated to Docker's "docker-in-docker" (DinD) — in fact, DIN's container architecture deliberately avoids docker-in-docker by spawning [Worker Nodes](Worker-Node) as siblings on the host daemon.*
Expand All @@ -20,7 +22,7 @@ Today, participation is **one-shot**: every GI phase is a hand-run [DIN CLI](DIN
`dind` is a consumer, not a replacement, of the existing stack:

- **Built on the [DIN SDK](DIN-SDK)** — the daemon imports the same extracted core (IPFS client, contract interfaces, wallet helpers, manifest loading) as the CLI, rather than reimplementing it. The SDK extraction is an explicit prerequisite on the roadmap.
- **Runs inside the [DIN Node](DIN-Node)** — today `din-node` idles (`sleep infinity`) and operators `exec` commands into it; when `dind` lands, it becomes the container's **main process**, and the container's logs carry real activity. The node's operational patterns (health endpoint, SIGTERM, structured logs) are being built in P3 precisely so `dind` inherits them.
- **Runs inside the [DIN Node](DIN-Node)** — today `din-node` idles (`sleep infinity`) and operators `exec` commands into it; when `dind` lands, it becomes the container's **main process**, and the container's logs carry real activity. The node-level operational patterns (health endpoint, SIGTERM handling, structured logs) are still planned P3 work items, not yet implemented; the daemon PR builds its own versions of them.
- **[DIN CLI](DIN-CLI) stays** — the CLI remains the interactive and scripting interface; existing commands keep working unchanged. Daemon and CLI share preferences and state through the SDK layer.

```
Expand All @@ -38,7 +40,7 @@ Today, participation is **one-shot**: every GI phase is a hand-run [DIN CLI](DIN

## Sequencing

Per the P4 roadmap: architecture document first (daemon/CLI split, state ownership, event-driven execution), then the daemon framework and SDK extraction, followed by the preference system, per-role automation (client → validator → model owner), daemon-level security hardening, and finally devnet integration with multi-role simulation, culminating in a public **`dind` v1.0.0** release.
Per the P4 roadmap: architecture document first (daemon/CLI split, state ownership, event-driven execution), then the daemon framework and SDK extraction, followed by the preference system, per-role automation (client → validator → model owner), daemon-level security hardening, and finally devnet integration with multi-role simulation, culminating in a public **`dind` v1.0.0** release at the end of P4 (P4 runs Sep–Nov 2026). Planned commands include `dind start/stop/status`, `dind capabilities` and `dind preferences set/show`.

## Further reading

Expand Down
8 changes: 5 additions & 3 deletions DIN-Indexer.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# DIN Indexer

> 📋 **Status: Planned** — the DIN Indexer does not exist yet. This page describes its design intent per the [project roadmap](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/ROADMAP.md) (phase P4) and the [indexer design doc](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/issues/indexer.md); details may change as the design is finalized.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
> ⚡ **Status: In progress, not on `develop` yet.** A Graph Protocol subgraph (schema, event handlers, and a local Graph node via docker-compose), including the first CLI integration, lives in [PR #29](https://github.com/InfiniteZeroFoundation/DevNet/pull/29) and [PR #72](https://github.com/InfiniteZeroFoundation/DevNet/pull/72) on `feat/din-indexer`; it still needs re-wiring to the current contracts before it can merge. This page describes its design intent per the [project roadmap](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/ROADMAP.md) (phase P4) and the [indexer design doc](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/issues/indexer.md); details may change.
## What it will be

The DIN Indexer is the planned **off-chain read layer** for the DIN network: a service (a Graph Protocol subgraph, or a lighter equivalent) that ingests the event streams of the four [Platform Contracts](Platform-Contracts) — `DinCoordinator`, `DinToken`, `DinValidatorStake`, `DINModelRegistry` — and turns them into queryable entities.
The DIN Indexer is the planned **off-chain read layer** for the DIN network: a service (a Graph Protocol subgraph, or a lighter equivalent) that ingests the event streams of the [Platform Contracts](Platform-Contracts) — `DinCoordinator`, `DinToken`, `DinValidatorStake`, `DINModelRegistry`, and in DevNet 2.0 also `DinFeeRouter`, `DinTreasury` and `DinEmission` — and turns them into queryable entities.

The division of labour it establishes:

Expand Down Expand Up @@ -42,7 +44,7 @@ First integration target: replacing the CLI's pending-request enumeration loop w

## Status & sequencing

Per the roadmap, the indexer is a P4 work-package series — design (approach choice and entity schema), implementation (event mappings and the first CLI integration), then test-suite integration — targeted for late 2026. It deliberately follows the contract-stability milestones: mapping implementation waits until the platform contract ABIs settle after the upgradeable-contracts migration, so mappings aren't rebuilt against a moving target.
Per the roadmap, the indexer is a P4 work-package series — design (approach choice and entity schema), implementation (event mappings and the first CLI integration), then test-suite integration — targeted for Oct–Nov 2026. The events it needs, including the task-level events, now exist on `develop`; the remaining gap is re-wiring the existing subgraph work to the current ABIs and merging it. Publishing to a hosted Graph endpoint is tracked separately ([issue #174](https://github.com/InfiniteZeroFoundation/DevNet/issues/174)); for the devnet, hosting is user-side.

## Further reading

Expand Down
13 changes: 9 additions & 4 deletions DIN-Node.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# DIN Node

> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
`din-node` is the **containerized run path for DIN validators**: it packages `dincli` — the trusted DIN host process — as a Docker image plus a Compose setup, so an operator can run a client, auditor, or aggregator without installing Python or `dincli` on the host. One `docker compose up -d` and the node is running; upgrades are `git pull && docker compose up -d --build` with all state preserved.

This is Phase 1 (*Devnet Operator Baseline*) of the validator-operations roadmap, and it is currently scoped for **devnet**.
Expand Down Expand Up @@ -44,18 +46,21 @@ Because state lives on the host, container rebuilds and image upgrades never tou
```bash
cd dincli/docker/node
cp .env.example .env # set DIN_STATE_DIR, DOCKER_GID, DIN_UID/DIN_GID
mkdir -p "$DIN_STATE_DIR" && sudo chown -R "$DIN_UID:$DIN_GID" "$DIN_STATE_DIR"
docker build -f ../worker/Dockerfile -t din-worker:dev ../../.. # pre-build worker image
docker compose up -d --build
docker compose exec din-node dincli system init # then configure as usual
docker compose exec din-node dincli system init
docker compose exec din-node dincli --network sepolia_op_devnet system configure-network
docker compose exec din-node dincli system register-wallet --keystore <file> --connect # or the hidden prompt
```

Day-to-day, every `dincli` command runs through `docker compose exec din-node dincli <args>`; `docker ps -a --filter "name=din-"` shows the node plus any in-flight workers. Migrating from a host install is a straight copy of the `platformdirs` config/cache directories into `DIN_STATE_DIR` (documented step-by-step in the runbook).
For production keys, import an encrypted keystore (`register-wallet --keystore`) and select it with `--wallet` or `DIN_WALLET_NAME`; the old plaintext `.session` password cache has been removed (and is deleted automatically if found). Day-to-day, every `dincli` command runs through `docker compose exec din-node dincli <args>`; `docker ps -a --filter "name=din-"` shows the node plus any in-flight workers. Migrating from a host install is a straight copy of the `platformdirs` config/cache directories into `DIN_STATE_DIR` (documented step-by-step in the runbook).

> `din-node` currently idles and is driven via `exec`, because `dincli` is a CLI, not yet a daemon. When the **[DIN Daemon (`dind`)](DIN-Daemon)** lands (P4 roadmap), it becomes the container's main process — automating participation instead of waiting for commands. See [DIN SDK](DIN-SDK) for the shared layer that enables this.
> `din-node` currently idles and is driven via `exec`, because `dincli` is a CLI, not yet a daemon. When the **[DIN Daemon (`dind`)](DIN-Daemon)** lands (P4 roadmap; in progress on an unmerged PR), it becomes the container's main process — automating participation instead of waiting for commands. See [DIN SDK](DIN-SDK) for the shared layer that enables this.
## Roadmap (validator operations)

Planned hardening on top of this baseline: HTTP `/health` endpoint for watchdog auto-restart, graceful SIGTERM handling (no state corruption on `docker stop`), structured JSON logging, and `systemd`/`launchd` service units.
Planned hardening on top of this baseline — none of it implemented yet: HTTP `/health` endpoint for watchdog auto-restart, graceful SIGTERM handling (no state corruption on `docker stop`), structured JSON logging, `systemd`/`launchd` service units, and vault / remote-signer key integration.

## Further reading

Expand Down
112 changes: 87 additions & 25 deletions DIN-Representative.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,118 @@
# DIN-Representative

The DIN-Representative is the network's **governance and admission authority** — the entity that operates the [Platform Contracts](Platform-Contracts) on behalf of the protocol. Today it is a trusted representative of the Infinite Zero Foundation; by design it evolves into the **DIN-DAO**, with the role's powers handed to community governance (the admin role is transferable on-chain to a multisig or timelock without redeploying anything).
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
The role's philosophy: the DIN-Representative controls **who and what enters the network** — it never touches the training itself. Model owners run their models, validators stake and work, clients keep their data; the Representative guards the perimeter.
The DIN-Representative is the network's **governance and admission authority**: the entity that operates the [Platform Contracts](Platform-Contracts) on behalf of the protocol. Today it is a single admin key, held by a trusted representative of the InfiniteZero Foundation, and it is the `owner()` of the platform contracts. On-chain DIN-DAO governance is **deferred to post-mainnet**. Until then, governance happens off-chain (see [DIN DAO](DIN-DAO)).

The role's philosophy: the DIN-Representative controls **who and what enters the network** and never touches the training itself. Model owners run their models, validators stake and work, and clients keep their data. The Representative guards the perimeter.

Its commands live under **`dincli dinrep`**.

## Responsibilities

### Platform operation
### Platform deployment

The Representative deploys the seven platform contracts (`DinTreasury`, `DinToken`, `DinFeeRouter`, `DinCoordinator`, `DinValidatorStake`, `DINModelRegistry`, `DinEmission`), each behind an OpenZeppelin Transparent Proxy, with the Foundry script `foundry/script/DeployPlatform.s.sol`. The script deploys, initializes and wires everything in 22 transactions, then writes the addresses to `foundry/deployments/<network>.json`. That file is then imported into `dincli`:

```bash
cd foundry && npm ci && forge clean
forge script script/DeployPlatform.s.sol --rpc-url <rpc> --broadcast --account <keystore> --sender <din_rep_address>
cd .. && dincli --network <network> system import-deployments
```

Deploys the platform contracts (`DinCoordinator` → `DinValidatorStake` → `DinModelRegistry`, in dependency order) and administers their parameters: the ETH→DIN exchange rate, the validator-stake contract reference, and treasury withdrawals.
The deploying address becomes the owner of every platform contract and every ProxyAdmin. A native `dincli dinrep deploy` is planned but not implemented.

### Slasher authorization — the gate before the gate
### Protocol parameters

Before any model can even request registration, its [Task Contracts](Task-Contracts) must be authorized as slashers on `DinValidatorStake`. The model owner requests this off-chain (Discord/Telegram/email), and the Representative **reviews before authorizing**:
The Representative administers the platform's economic settings. Most are owner calls on the contracts, with no `dincli` command yet:

- **DIN supply:**
- `dinPerEth`, the ETH → DIN purchase rate (default 1,000,000 DIN per ETH);
- `mintCap`, the total supply cap (0 = uncapped);
- `retireFaucet()`, which permanently ends both minting paths (one-way).
- **Staking:** the minimum stake, the unbonding period, and the S5 repeat-offence settings on `DinValidatorStake`.
- **Fee routing:** the `DinFeeRouter` splits and its fee-source allowlist.
- **Emission:** the `DinEmission` schedule (initial per-GI emission, decay, epoch length, max epochs).

### Slasher authorization: the gate before the gate

Before any model can even request registration, its [Task Contracts](Task-Contracts) must be authorized as slashers on `DinValidatorStake`. The model owner asks off-chain (Discord, Telegram or email). The Representative **reviews before authorizing**:

- both contracts were deployed by the stated model-owner address;
- the coordinator implements the expected interface and references the correct stake contract;
- the auditor is correctly linked to the coordinator;
- no malicious or unauthorized slashing logic is embedded.
- the auditor contract is correctly linked to the coordinator;
- there is no malicious or unauthorized slashing logic.

Only then does the Representative authorize them:

```bash
dincli dinrep add-slasher --taskCoordinator # or --taskAuditor, or --contract <address>
```

This review is what stops an arbitrary contract from gaining the power to slash validators' stakes.

### Model and manifest admission

Every model registration and every manifest update is a **request the Representative approves or rejects**:

```bash
dincli dinrep registry list-pending-requests [-t model|manifest]
dincli dinrep registry explore-request -t model <requestId>
dincli dinrep registry approve-registration-request <requestId>
dincli dinrep registry reject-registration-request <requestId>
dincli dinrep registry approve-manifest-update <requestId>
dincli dinrep registry reject-manifest-update <requestId>
dincli dinrep registry total-models
```

Approval re-validates the task contracts at execution time. If they have lost slasher status or changed owner since the request, the approval reverts. Fees are kept whether a request is approved or rejected, which protects against spam.

### Disabling a model

```bash
dincli dinrep registry disable-model <modelId>
dincli dinrep registry enable-model <modelId>
```

Only then: `dincli dindao add-slasher`. This review is what stops an arbitrary contract from gaining the power to slash validators' stakes.
Disabling blocks new manifest update requests and approvals for the model. Nothing is deleted, on-chain history is preserved, and the model can be re-enabled. The task contracts **don't read** this flag, so disabling a model does not stop its running GIs, submissions or slashing.

### Model & manifest admission
### Fees

Every model registration and every manifest update is a **request the Representative approves or rejects** (`dincli dindao registry approve-model / reject-model / approve-manifest-update / ...`). Approval re-validates the task contracts at execution time — if they lost slasher status or changed owner since the request, the approval reverts. Fees are retained whether approved or rejected (spam protection).
The four registry fees (open-source and proprietary, for registration and for updates) can be set individually or atomically in one transaction:

### Kill switch
```bash
dincli dinrep registry set-open-source-fee <eth> # also: set-proprietary-fee, set-open-source-update-fee, set-proprietary-update-fee
dincli dinrep registry set-fees --open-source <eth> --proprietary <eth> --open-source-update <eth> --proprietary-update <eth>
```

`disable-model <modelId>` stops a misbehaving model immediately: manifest updates are blocked and downstream contracts check the flag before executing tasks. Nothing is deleted — on-chain history is preserved, and the model can be re-enabled.
Collected ETH stays where it was received until the Representative **sweeps it to `DinFeeRouter`**. There is no `withdraw()`:

### Fee governance
```bash
dincli dinrep registry sweep-fees # registration and manifest-update fees
dincli dinrep coordinator sweep-fees # ETH received from DIN purchases (depositAndMint)
```

All four registry fees (open-source/proprietary × registration/update) are Representative-adjustable, individually or atomically in one transaction (the atomic form is preferred for future governance proposals). Accumulated fees are withdrawable to fund the ecosystem.
The router splits each sweep. With the default split (95% validator pool, 5% treasury), only the treasury share reaches `DinTreasury` today. The rest stays in the router until the contracts that will consume it ship.

### Validator discipline

Beyond the automated, per-GI slashing executed by task contracts, the Representative can **blacklist** a validator address directly on `DinValidatorStake` — blocking staking, exits, and withdrawal claims — and unblacklist it.
Beyond the automated per-GI slashing that task contracts carry out, the Representative can **blacklist** a validator address directly on `DinValidatorStake`, which blocks staking, exits and withdrawal claims, and can unblacklist it.

## What the Representative cannot do

Bounds worth stating explicitly:
Some limits are worth stating explicitly:

- **Cannot slash arbitrarily** — slashing is executed only by authorized task contracts according to their on-chain rules; the Representative authorizes the contracts, not individual penalties.
- **Cannot mint DIN at will** — minting is bound to `DinCoordinator.depositAndMint()`, driven by ETH deposits at the published rate.
- **Cannot touch training data or artifacts** — data never leaves clients' devices, and models live on IPFS addressed by CIDs recorded through the participants' own submissions.
- **It cannot slash arbitrarily.** Only authorized task contracts slash, by their on-chain rules. The Representative authorizes contracts, not individual penalties.
- **It cannot mint DIN directly.** DIN is minted only through `DinCoordinator.depositAndMint()` (ETH deposits at the published rate) and `mintEmission()` (called only by `DinEmission` on its schedule). Both are bounded by `mintCap` and end for good at `retireFaucet()`. The Representative's control over supply is limited to setting those parameters.
- **It cannot touch training data or artifacts.** Data never leaves clients' devices, and models live on IPFS under CIDs recorded by the participants' own submissions.

## Path to the DIN-DAO
## Ownership and the path forward

The role is deliberately built to be handed over: a single transferable admin (`set-admin`, e.g. to a multisig or timelock), atomic fee-setting shaped for governance proposals, and request/approval flows that map naturally onto proposal/vote. Contact channels for model onboarding are listed in the [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md#official-contact-channels).
There is no single `set-admin` switch. Each platform contract changes owner with OpenZeppelin `transferOwnership`, and each of the seven ProxyAdmins has its own owner. On-chain governance (the [DIN DAO](DIN-DAO)) is deferred to post-mainnet under design decision DD-3. Until then the owner-controlled setters are how the protocol is run, and any near-term multisig would hold treasury funds only, not protocol roles. Contact channels for model onboarding are listed in the [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md#official-contact-channels).

## Further reading

- [DIN DAO command reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/dindao.md) — every `dincli dindao` command
- [Platform Contracts](Platform-Contracts) — the contracts this role deploys and administers
- [Model Owner](Model-Owner) — the counterpart role in the admission flow
- [DIN-Representative guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/dinrep.md): every `dincli dinrep` command, plus the local and Optimism Sepolia deploy flows
- [DeployPlatform script reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/foundry/script/DeployPlatform.md): the tokenomics keys and their defaults
- [Platform Contracts](Platform-Contracts): the contracts this role deploys and administers
- [Model Owner](Model-Owner): the counterpart role in the admission flow
6 changes: 4 additions & 2 deletions DIN-SDK.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DIN SDK

> 📋 **Status: Planned** — the DIN SDK does not exist yet. This page describes its design intent per the [project roadmap](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/ROADMAP.md) (phase P4); details may change as the architecture spec is finalized.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
> ⚡ **Status: In progress, not on `develop` yet.** The extraction has started in [PR #31](https://github.com/InfiniteZeroFoundation/DevNet/pull/31) (`feat/din-sdk`), which begins `dincli/sdk/operations/`; role operations, CLI adoption and a frozen interface are still to come. This page describes the design intent per the [project roadmap](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/ROADMAP.md) (phase P4); details may change as the architecture spec is finalized.
## What it will be

Expand Down Expand Up @@ -38,7 +40,7 @@ The daemon work also converges with the [DIN Node](DIN-Node): today `din-node` i

## Status & sequencing

Per the roadmap, an architecture document (system-level `dind` design plus the SDK extraction scope and public interface) precedes implementation; the extraction itself is an early P4 work package, targeted for the second half of 2026. This page will be updated as the interface stabilizes.
Per the roadmap, an architecture document (system-level `dind` design plus the SDK extraction scope and public interface) precedes implementation; the extraction itself is an early P4 work package (P4 runs Sep–Nov 2026). In practice the extraction PR has started ahead of the architecture document. This page will be updated as the interface stabilizes.

## Further reading

Expand Down
2 changes: 2 additions & 0 deletions Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

Welcome to the DIN Protocol DevNet wiki.

> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** These pages describe the DevNet 2.0 protocol as it exists on the `develop` branch: seven upgradeable platform contracts, a staking and slashing layer with on-chain rewards, commit-then-reveal scoring and aggregation, and encrypted audit test data. Until launch, the running DevNet may still use older contracts and commands. The design behind DevNet 2.0 is in the [cryptoeconomic mechanism design](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/design/MECHANISM_DESIGN.md); follow the launch in the [pre-launch discussion](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
Start with the **[Overview](Overview)** to learn what DIN is and how the network works.
16 changes: 13 additions & 3 deletions IPFS-Layer.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# IPFS Layer

> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
The blockchain coordinates the network, but it never stores the heavy artifacts. Everything content-shaped in DIN lives on **IPFS**, and the contracts store and vote on **CIDs** (content identifiers) only:

- **model weights** — genesis model, clients' local models, T1/T2 aggregated models
- **service files** — the model owner's Python logic (`model.py`, `client.py`, `auditor.py`, `aggregator.py`, `modelowner.py`)
- **manifests** — each model's `manifest.json`
- **test datasets** — per-audit-batch evaluation data
- **test datasets** — per-audit-batch evaluation data, encrypted so only that batch's auditors can read it
- **contract ABIs** — custom task-contract ABIs referenced from a manifest

Because a CID is a cryptographic hash of the content, on-chain CID votes double as integrity checks: two aggregators produced the same model if and only if they submitted the same CID.
Expand All @@ -16,7 +18,7 @@ All upload/retrieve traffic in `dincli` goes through a single abstraction (`uplo

| Provider | When to use | Setup |
|---|---|---|
| `env` (default) | you run your own IPFS node or any IPFS-compatible HTTP API | `IPFS_API_URL_ADD` / `IPFS_API_URL_RETRIEVE` in the project `.env` |
| `env` (default) | you run your own IPFS node (kubo RPC) or any IPFS-compatible HTTP API | `IPFS_API_URL_ADD` / `IPFS_API_URL_RETRIEVE` in the project `.env` |
| `filebase` (recommended) | you want a managed, pinned backend without running a node | `dincli system configure-ipfs --provider filebase --api-key <filebase_rpc_token>` |
| `custom` | full control — any storage you can wrap in Python | `--provider custom --service-path /abs/path/to/custom_ipfs.py` |

Expand All @@ -33,12 +35,20 @@ dincli system configure-ipfs --provider env # switch explicitly
- **`filebase`** uploads through Filebase's IPFS RPC API and issues a pin request after every upload; the token is stored in the user-level `dincli` config (per-provider, `ipfs_api_key_<provider>`).
- **`custom`** modules must export two functions — `upload_to_ipfs(file_path, msg=None) -> str` (returns a non-empty CID) and `retrieve_from_ipfs(cid, file_path) -> int | None` (writes the artifact to `file_path`). That's the whole contract; anything satisfying it can back the network's storage.

### Reading without a provider: public gateway fallback

Participants who only need to *read* artifacts can opt into a public gateway: set `IPFS_PUBLIC_GATEWAY=1` (uses `https://ipfs.io/ipfs`) or to any `http(s)://` gateway URL. A configured `IPFS_API_URL_RETRIEVE` still takes precedence. Uploads always need a real provider — and `dincli`'s own guidance steers uploaders to Filebase, since a casually-run local node is rarely reachable or pinned well enough for others to fetch from.

## Integrity: CIDs are verified on download

For the `env` and `filebase` providers, every download is checked against the CID that was requested before it is used: `dincli` recomputes the CID locally (`ipfs add -n`, which needs the kubo binary and an initialized repo but no running daemon) and writes the file atomically only if it matches. If kubo isn't installed, the check is skipped with a warning. `custom` providers are responsible for their own integrity.

## CID-based caching

Content addressing makes caching trivial: same CID, same bytes. `dincli` caches every fetched artifact in its cache directory keyed by CID, so services, models, and manifests are downloaded only when their CID actually changes — repeated GI phases don't re-fetch unchanged files.

## Further reading

- [IPFS Configuration Guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/ipfs.md) — full provider reference and migration notes
- [IPFS Configuration Guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/guides/ipfs.md) — full provider reference, `env` URL shapes (kubo RPC vs gateway), gateway fallback, CID verification, and migration notes (the legacy `"ipfs node"` value maps to `env`)
- [Setup Guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/setup.md) — IPFS as part of first-time setup
- [DIN CLI](DIN-CLI) — the component all this traffic flows through
91 changes: 62 additions & 29 deletions Model-Owner.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
# Model Owner

The Model Owner is the actor who brings a model to the network and runs its training from start to finish. They deploy the model's [Task Contracts](Task-Contracts), define its logic through the manifest and service files, seed it with a genesis model, and orchestrate every [Global Iteration](Task-Contracts#the-global-iteration-lifecycle) — opening and closing each phase that [Clients](Client), [Auditors](Auditor), and [Aggregators](Aggregator) act within.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
The role is deliberately powerful *within its own model* and powerless outside it: a model owner drives their model's lifecycle and can trigger slashing of its misbehaving validators, but admission to the network itself is gated by the [DIN-Representative](DIN-Representative), and validator stakes live in the shared platform contracts.
The Model Owner brings a model to the network and runs its training from start to finish. They:
- deploy the model's [Task Contracts](Task-Contracts);
- define its logic through the manifest and service files;
- seed it with a genesis model;
- fund each round's reward pool;
- run every [Global Iteration](Task-Contracts#the-global-iteration-lifecycle), opening and closing each phase that [Clients](Client), [Auditors](Auditor) and [Aggregators](Aggregator) work in.

## Onboarding a model
The role has a lot of power *within its own model* and none outside it. A model owner runs their model's lifecycle and triggers slashing of its misbehaving validators. But admission to the network is gated by the [DIN-Representative](DIN-Representative), validator stakes live in the shared platform contracts, and the owner is held to account too: an owner who publishes bad test data loses part of the reward pool.

A one-time setup path, in order:
## Onboarding a model

1. **Deploy the task contracts** — `dincli model-owner deploy task-coordinator` / `task-auditor`, one pair per model.
2. **Request slasher authorization** — ask the DIN-Representative (off-chain, via the [official channels](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md#official-contact-channels)) to authorize both contracts as slashers on `DinValidatorStake`; then confirm the authorization on the task side (`dincli model-owner add-slasher`).
3. **Write the manifest & service files** — the model's architecture and role logic (`model.py`, `modelowner.py`, `client.py`, `auditor.py`, `aggregator.py`), pinned to IPFS and referenced by CID in `manifest.json`. This is where the model owner's ML expertise lives; the protocol never sees the code, only its CIDs. See [Manifest](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/manifest.md) & [Services](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/services.md).
4. **Create & submit the genesis model** — the initial weights every client starts from (`dincli model-owner model create-genesis` / `submit-genesis`); its score against the owner's test dataset sets the eligibility threshold for local models.
5. **Request model registration** — submit a registration request to `DinModelRegistry` (open-source or proprietary, with the corresponding fee); the DIN-Representative approves and the model receives its **model ID**.
A one-time setup, in this order:

1. **Deploy the task contracts.** `dincli model-owner deploy task-coordinator`, then `dincli model-owner deploy task-auditor`: one pair per model. The second command also links the auditor to the coordinator.
> ⚠️ The DevNet 2.0 contracts take a `modelId` constructor argument that `dincli model-owner deploy` doesn't pass yet. See the known gap on [Task Contracts](Task-Contracts#deploying-a-models-task-contracts).
2. **Get slasher authorization.** Ask the DIN-Representative, off-chain through the [official channels](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md#official-contact-channels), to authorize both contracts as slashers on `DinValidatorStake`. Then confirm each on the task side, one at a time:
```bash
dincli model-owner add-slasher --taskCoordinator
dincli model-owner add-slasher --taskAuditor
```
3. **Write the manifest and service files.** These hold the model's architecture and the logic for each role (`model.py`, `modelowner.py`, `client.py`, `auditor.py`, `aggregator.py`). They are pinned to IPFS and referenced by CID in `manifest.json`. This is where the model owner's ML expertise lives; the protocol only ever sees CIDs. See [Manifest](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/manifest.md) and [Services](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/services.md).
4. **Create and submit the genesis model.** These are the starting weights every client trains from:
```bash
dincli model-owner model create-genesis-model
dincli model-owner model submit-genesis-model
```
5. **Request model registration.** Submit a request to `DINModelRegistry` and pay the matching fee: `dincli task model-owner register-request [--isOpenSource]`. Once the DIN-Representative approves it, the model receives its **model ID**.

### Registration fees

Fees are charged on submission (approved or rejected — spam protection) and held by the registry for the ecosystem:
Fees are charged when a request is submitted and are kept whether it is approved or rejected, which protects against spam. An overpayment is refunded. The DIN-Representative later sweeps collected fees to `DinFeeRouter`.

| Action | Open-source | Proprietary |
|---|---|---|
Expand All @@ -25,32 +41,49 @@ Fees are charged on submission (approved or rejected — spam protection) and he

## Running a Global Iteration

Once registered, training proceeds in GIs, each producing a new global model. The model owner is the **conductor**: every phase is opened and closed by their explicit command, and participants can only act while their phase is open.
Once registered, training proceeds in GIs, each producing a new global model. The model owner is the **conductor**: every phase is opened and closed by their explicit command, and participants can act only while their phase is open.

| Phase | Model owner's job |
| Phase | Model owner's job (`dincli model-owner …`) |
|---|---|
| Start GI | `gi start` — optionally setting the local-model score threshold (defaults to 5% below the latest global model's accuracy) |
| Registration | open/close the aggregator and auditor registration windows |
| LMS | open/close the window in which clients submit trained local models |
| Auditor assignment | create audit batches and generate/submit the test dataset auditors evaluate against |
| Evaluation | start/close the scoring phase, review results per auditor and per model |
| Aggregation | create T1/T2 batches, start/close Tier-1 and Tier-2 aggregation |
| Slash & end | trigger slashing of non-compliant auditors and aggregators, then `gi end` — the finalized T2 output becomes the next GI's starting model |

Monitoring commands (`show-state`, `show-models`, `show-t1-batches`, …) give a live view at every step.
| Fund | Fund the GI's reward pool in DIN (`depositRewards` on the auditor contract; no `dincli` command yet). The GI can't start without it |
| Start GI | `gi start <id>`: sets the pass score to the latest global model's accuracy minus a threshold (`--threshold`, the manifest's `audit_scoring_policy`, or 5 by default) |
| Registration | `gi reg aggregators-open/close`, then `gi reg auditors-open/close` |
| LMS | `lms open` / `lms close`, the window in which clients submit trained local models |
| Audit batches | `auditor-batches create` (waits for and locks the audit seed), then `auditor-batches create-testdataset --submit`. This encrypts the test data for each batch's auditors and adds the owner's encryption key to the manifest, which must be re-uploaded |
| Evaluation | `lms-evaluation start` (auditors commit) → `lms-evaluation start-reveal` (auditors reveal) → `lms-evaluation close`. Review results with `lms-evaluation show` |
| Aggregation | `aggregation create-t1nt2-batches`, then for each of T1 and T2: `aggregation T1 start` → `aggregation T1 start-reveal` → `aggregation T1 close` (and the same with `T2`) |
| Slash & end | `slash auditors`, then `slash aggregators`, then `gi end`. Ending settles the reward pool, and the finalized T2 output becomes the next GI's starting model |

Forgetting a `start-reveal` step stalls the GI in its commit window, because finalizing reverts. It doesn't corrupt any state.

Monitoring commands (`dincli task gi show-state`, `lms show-models`, `aggregation show-t1-batches`, …) give a live view at every step.

## Accountability and other owner duties

- **Test-data disputes.** An auditor who can't decrypt or verify its batch's test data can open a dispute. The owner must answer within the window (about one day) by revealing the dataset key.
- **Silence or a wrong key:** the dispute is upheld. 25% of the GI's reward pool is forfeited (unless the GI settled while the dispute was open) and the batch must be reassigned.
- **Aggregation disputes.** The owner adjudicates disputes that validators raise against finalized aggregation results.
- **Encryption key.** `create-testdataset` uses the owner's X25519 key, kept in the `dincli` config directory (`owner_x25519.key`).
- **Contract-only actions.** These have no `dincli` command yet:
- funding rewards;
- `setDinToken` (on both contracts);
- resolving disputes;
- `releaseGIRegistrationSlots`;
- tuning slashing fractions, the reward split and dispute parameters.

## What the model owner provides vs. what the network provides

| Model owner brings | Network provides |
|---|---|
| Model architecture & training logic (service files) | Sandboxed execution of that logic on participants' machines |
| Genesis model & test datasets | Clients' private data (never shared — only trained weights return) |
| Phase orchestration each GI | Staked, slashable validators to audit and aggregate honestly |
| Registration & update fees | Registry, staking, and settlement infrastructure |
| Model architecture and training logic (service files) | Sandboxed execution of that logic on participants' machines |
| Genesis model and encrypted test datasets | Clients' private data (never shared; only trained weights return) |
| A funded reward pool each GI | Staked, slashable validators who audit and aggregate honestly |
| Phase orchestration each GI | Registry, staking, rewards and settlement infrastructure |
| Registration and update fees | |

## Further reading

- [Model Owner command reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/model-owner.md) — every command with options
- [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md) — the full onboarding + GI walkthrough in order
- [Task Contracts](Task-Contracts) — the contracts this role deploys and drives
- [Manifest](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/manifest.md) · [Services](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/services.md) — the model-definition format
- [Model Owner command reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/model-owner.md): commands and options
- [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md): the full onboarding and GI walkthrough, in order
- [Task Contracts](Task-Contracts): the contracts this role deploys and drives
- [Manifest](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/manifest.md) · [Services](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/services.md): the model-definition format
22 changes: 13 additions & 9 deletions Overview.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Overview

> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
> **The internet gave everyone a voice.**
> **Open-source gave everyone a tool.**
> **AI is still waiting.**
Expand All @@ -14,7 +16,7 @@ DIN coordinates **federated learning** at network scale: millions of devices can

> Built on Ethereum. Governed by the community. Models belong to the commons.
The DevNet is live. Validator nodes are running 24/7 from Japan to Canada. This is not a simulation — it's real infrastructure, and it needs builders.
The DevNet is real infrastructure, not a simulation, and it needs builders. **DevNet 2.0 is soon to be launched**: it brings the full cryptoeconomic layer (staking, slashing, on-chain rewards and fees) described on these pages.

## Why does it exist?

Expand All @@ -27,33 +29,35 @@ Most AI infrastructure is being built behind closed doors, by a handful of compa
3. **Auditors evaluate** the submitted local models and score them, keeping low-quality or malicious contributions out of the global model.
4. **Aggregators combine** the accepted local models into a new global model through two-tier aggregation.
5. **Stakes keep everyone honest.** Validators (auditors and aggregators) stake DIN tokens as collateral; misbehaviour is slashed on-chain.
6. **Rewards pay for the work.** Each GI has a DIN reward pool, funded before the GI starts. When the GI ends it is split between clients (60%), auditors (20%), aggregators (15%) and the treasury (5%), and participants claim their share on-chain.

This cycle repeats in rounds called **Global Iterations (GI)**, each producing an improved global model.

## The building blocks

| Component | What it does |
|---|---|
| **Platform contracts** | Deployed once by the DIN-Representative: `DinCoordinator` (protocol coordination, ETH ↔ DIN exchange), `DinToken` (ERC20 utility token), `DinValidatorStake` (validator staking & slashing), `DinModelRegistry` (model registration — open-source or proprietary) |
| **Platform contracts** | Seven upgradeable contracts deployed once by the DIN-Representative: `DinCoordinator` (ETH → DIN purchases, minting gateway, slasher registry), `DinToken` (ERC-20 utility token), `DinValidatorStake` (validator staking, slashing, jailing), `DINModelRegistry` (model admission, open-source or proprietary), `DinFeeRouter` (fee splitting), `DinTreasury` (protocol treasury) and `DinEmission` (per-GI reward subsidy) |
| **Task contracts** | Deployed per model by its owner: `DINTaskCoordinator` and `DINTaskAuditor` run the training lifecycle for that model |
| **`dincli`** | Python CLI through which every role — model owner, client, auditor, aggregator, DIN-Representative — interacts with the network |
| **IPFS layer** | Stores and distributes all off-chain artifacts: model weights, service code, manifests, ABIs |

## Network roles

- **DIN-Representative** (later DIN-DAO) — operates the platform-level contracts and authorizes task contracts as slashers.
- **DIN-Representative** — operates the platform-level contracts, admits models, and authorizes task contracts as slashers. On-chain DAO governance is deferred to post-mainnet.
- **Model owners** — deploy task contracts, register models (open-source or proprietary), and drive each Global Iteration.
- **Clients** — train models locally on private data and submit local model updates.
- **Auditors** — stake DIN, evaluate and score submitted local models.
- **Aggregators** — stake DIN, combine accepted local models into the new global model.
- **Auditors** — stake DIN, evaluate and score submitted local models (commit, then reveal).
- **Aggregators** — stake DIN, combine accepted local models into the new global model (commit, then reveal).

## Learn more

- [White Paper](https://github.com/InfiniteZeroFoundation/White-Paper)
- [Getting Started](https://github.com/InfiniteZeroFoundation/devnet/blob/develop/Documentation/public/getting-started.md)
- [DIN Workflow — platform contracts](https://github.com/InfiniteZeroFoundation/devnet/blob/develop/Documentation/public/workflows/din-workflow.md)
- [Model Workflow — task contracts & training lifecycle](https://github.com/InfiniteZeroFoundation/devnet/blob/develop/Documentation/public/workflows/model-workflow.md)
- [Contribution Guide](https://github.com/InfiniteZeroFoundation/devnet/blob/develop/Developer/CONTRIBUTING.md)
- [Getting Started](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/getting-started.md)
- [DevNet 2.0 mechanism design](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/design/MECHANISM_DESIGN.md)
- [DIN-Representative guide — platform contracts](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/dinrep.md)
- [Model Workflow — task contracts & training lifecycle](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md)
- [Contribution Guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/CONTRIBUTING.md)
- [Support the network on Giveth](https://giveth.io/project/infinitezero-network)

---
Expand Down
144 changes: 97 additions & 47 deletions Platform-Contracts.md
Original file line number Diff line number Diff line change
@@ -1,80 +1,130 @@
# Platform Contracts

The platform contracts are the foundation of the DIN Protocol: four Solidity contracts deployed **once** by the DIN-Representative (later, the DIN-DAO) that every model, validator, and client on the network builds on. On the live DevNet they run on **Optimism Sepolia** (chainId 11155420).
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
They are distinct from the [Task Contracts](Task-Contracts), which are deployed **per model** by each model owner.
The platform contracts are the foundation of the DIN Protocol. They are seven Solidity contracts, deployed **once per network** by the [DIN-Representative](DIN-Representative), and every model, validator and client on the network builds on them. The live DevNet runs on **Optimism Sepolia** (chainId 11155420).

They are distinct from the [Task Contracts](Task-Contracts), which each model owner deploys **per model**.

Each platform contract sits behind an OpenZeppelin **Transparent Proxy** with its own ProxyAdmin, so it can be upgraded without changing its address. The deployer, normally the DIN-Representative key, becomes the `owner()` of all seven contracts and all seven ProxyAdmins.

```
DIN-Representative (owner)
│
┌───────────────┼─────────────────┐
▼ ▼ ▼
DinCoordinator DinValidatorStake DinModelRegistry
│ │ ▲
deploys │ │ authorizes │ slash()
▼ └──────────────┤
DinToken Task contracts (per model)
DIN-Representative (owner of all seven)
ETH ──depositAndMint──► DinCoordinator ──mint──► DinToken
│ ▲ │
authorizes │ │ └──ETH sweep──┐
slashers │ mintEmission ▼
▼ │ DinFeeRouter ──treasury share──► DinTreasury
DinValidatorStake DinEmission ▲
▲ (funds GI │ ETH sweep
slash() │ reward pools) │
│ DINModelRegistry ◄── model owners
Task contracts (per model) (requests + fees)
```

## DinCoordinator

The entry-point and treasury contract of the protocol. It has two core jobs:
The protocol's entry point, minting gateway and slasher registry. It does **not** hold the treasury.

1. **Token issuance** — anyone can deposit ETH via `depositAndMint()` and receive freshly minted DIN tokens at the current exchange rate (`dinPerEth`, default **1 ETH → 1,000,000 DIN**; a tentative workaround until a DEX such as Uniswap V3 takes over the exchange).
2. **Slasher management** — it is the only address allowed to register or de-register slasher contracts on `DinValidatorStake`. This is how the DIN-Representative authorizes a model's task contracts to slash misbehaving validators.
- **Buying DIN.** Anyone can call `depositAndMint()` with ETH and receive newly minted DIN at the current rate, `dinPerEth` (default **1 ETH → 1,000,000 DIN**). This is a one-way faucet: there is no redeem path back to ETH. The intent is for a DEX to take over price discovery later.
- **Emission gateway.** `mintEmission()` is the only other way DIN is minted. Only the configured `DinEmission` contract can call it.
- **Supply guards.** Both minting paths respect `mintCap` (0 means uncapped) and stop permanently once the owner calls `retireFaucet()`, which is one-way.
- **Fees.** ETH received from DIN purchases stays in the coordinator until the DIN-Representative sweeps it to `DinFeeRouter` (`sweepFeesToRouter`, or `dincli dinrep coordinator sweep-fees`). There is no `withdraw()`.
- **Slasher management.** It is the only address allowed to add or remove slasher contracts on `DinValidatorStake`. This is how the DIN-Representative authorizes a model's task contracts to slash misbehaving validators.

The DIN-Representative (as `owner`) can also withdraw accumulated ETH, update the exchange rate, and set the validator stake contract reference. At deployment, `DinCoordinator` deploys `DinToken` itself and becomes its immutable minting authority.
Owner-only settings: `updateDinPerEth`, `setMintCap`, `retireFaucet`, `setEmissionContract`, `setFeeRouter` and `updateValidatorStakeContract`.

## DinToken

The ERC-20 utility token of the network (**"DIN Token"**, symbol **DIN**, 18 decimals, no pre-mint). It is deliberately minimal:
The network's ERC-20 utility token: **"DIN Token"**, symbol **DIN**, 18 decimals, no pre-mint.

- Minting authority is **permanently bound** to `DinCoordinator` — set once as an immutable at deployment, it can never be transferred.
- The only supply mechanism is `DinCoordinator.depositAndMint()`; there is no burn function.
- **Minting** is restricted to `DinCoordinator`. The owner binds the coordinator once, with `setCoordinator`, during deployment.
- **Burning:** any holder can `burn()` their own tokens. The protocol burns DIN too, for example half of every slash.

DIN is the staking and slashing currency: validators acquire it by depositing ETH, then lock it in `DinValidatorStake` to participate.
DIN is the staking, slashing and reward currency. Validators buy it with ETH and lock it in `DinValidatorStake`. Models fund their per-GI reward pools in DIN.

## DinValidatorStake

The staking ledger for validators (auditors and aggregators). It holds staked DIN, tracks each validator's lifecycle, and lets authorized slasher contracts penalize misbehavior.
The staking ledger for validators (auditors and aggregators). It holds staked DIN, tracks each validator's lifecycle, and lets authorized slasher contracts penalize misbehaviour.

- **Minimum stake.** Each `stake()` must be at least `minStake` (default **10 DIN**, owner-settable). A validator can work only while `Active`. A model can also set a higher per-model stake floor.
- **Unbonding.** Unstaking starts an unbonding period (default **7 days**, owner-settable) before funds can be claimed. Pending withdrawals **remain slashable** until claimed, so a validator can't dodge a penalty by exiting.
- **Slashing.** Only registered slasher contracts (a model's `DINTaskCoordinator` and `DINTaskAuditor`) can slash. Of every slash, **50% is burned and 50% goes to the slash treasury**.
- **Repeat offences (S5).** Liveness faults (missed votes or submissions) are partial slashes. A validator who repeats them within the S5 window gets a full `minStake` slash and is **jailed** (default 7 days), after which it can reactivate.
- **Blacklisting.** The owner can blacklist a validator address, which blocks staking, exits and withdrawal claims.
- **Encryption keys.** Auditors register an X25519 public key here (`registerEncryptionKey`), so model owners can send them encrypted test data.

Validator status moves through `None → Active → Exiting`, plus `Jailed` and `Blacklisted`. If active stake falls below the minimum, the validator stops being `Active`.

## DINModelRegistry

The governed admission gateway for models. Every model on the network is registered here and gets a unique ID. Admission works by **request and approval**:

- **Two-phase registration.** The model owner submits a registration request. The DIN-Representative reviews it and approves or rejects it. Only approved models receive an ID.
- **Two-phase manifest updates.** Changing a model's manifest CID, which can change its training logic and parameters, follows the same request and approval flow.
- **Prerequisite.** The model's `DINTaskCoordinator` and `DINTaskAuditor` must already be slashers on `DinValidatorStake`. Approval checks this again at execution time.
- **Two model types.**
- **Open-source models:** anyone may use the trained model freely.
- **Proprietary models:** the trained model belongs to the owner and can be used commercially. Their fees are higher.
- **Fees.** Small ETH fees are charged per request and kept whether the request is approved or rejected. The DIN-Representative sets them and sweeps the collected ETH to `DinFeeRouter`:

Key rules:
| Fee | Open-source | Proprietary |
|---|---|---|
| Registration | 0.000001 ETH | 0.00001 ETH |
| Manifest update | 0.0000001 ETH | 0.000001 ETH |

- **Minimum stake:** each `stake()` call must be at least `MIN_STAKE` (currently **10 DIN**). A validator is only eligible for work while `Active`.
- **Unbonding:** unstaking starts a **7-day unbonding period** before funds can be claimed — and pending withdrawals **remain slashable** until actually claimed, so a validator cannot dodge a penalty by exiting.
- **Slashing:** only contracts registered in the slasher registry (a model's `DINTaskCoordinator` / `DINTaskAuditor`, added via `DinCoordinator`) may call `slash()`. Slashing is capped at the validator's total slashable funds.
- **Blacklisting:** the contract owner can blacklist a validator address, blocking staking, exits, and withdrawal claims.
- **Disable / enable.** The DIN-Representative can disable a model. This blocks new manifest update requests and approvals for it. The task contracts don't read this flag, so a disabled model's running GIs, submissions and slashing continue.

Validator status moves through `None → Active → Exiting` (plus `Jailed` reserved for future use and `Blacklisted`). If active stake falls below the minimum, the validator drops out of `Active`.
## DinFeeRouter

## DinModelRegistry
Splits protocol fees across four buckets: **validator pool, treasury, storage and public goods**. DIN fees can also have a burn share.

The governed admission gateway for models. Every model on the network is registered here and gets a unique ID; admission works on a **request/approval basis**:
- Only allowlisted fee sources can route fees. The deploy script allowlists `DinCoordinator` and `DINModelRegistry`.
- The default ETH split is **95% validator pool / 5% treasury**. The treasury share can't exceed a 20% ceiling.
- Only the treasury share leaves the router today. The validator-pool, storage and public-goods shares accrue in the router until the contracts that will consume them ship.

- **Two-phase registration:** the model owner submits a registration request (`requestModelRegistration`); the DIN-Representative reviews and approves or rejects it. Only approved models receive an ID and become active.
- **Two-phase manifest updates:** changing a model's manifest CID — which can change its training logic and parameters — follows the same flow: the owner submits an update request (`requestManifestUpdate`), and the DIN-Representative approves or rejects it.
- **Prerequisite:** a model's `DINTaskCoordinator` and `DINTaskAuditor` must already be authorized as slashers on `DinValidatorStake` (via `DinCoordinator`) before a registration request is valid — this guarantees every registered model can enforce accountability from day one.
- **Two model types:**
- **Open-source models** — the trained model may be freely used by anyone.
- **Proprietary models** — the trained model belongs to the owner and can be used commercially; registration carries a higher fee.
- **Governed fees:** registration and manifest-update fees (separate rates for open-source and proprietary models) are small ETH amounts, adjustable by the DIN-Representative, that fund the ecosystem.
- **Kill switch:** the DIN-Representative can disable any model instantly if it misbehaves.
## DinTreasury

## Deployment & initialization sequence
A custodial holding contract for ETH and ERC-20 assets, with no split logic of its own. It receives the router's treasury share. The owner can withdraw from it with `withdrawETH` and `withdrawERC20`.

## DinEmission

The per-GI **reward subsidy**. It funds a model's GI reward pool on a geometric decay schedule:
- Each epoch (a fixed number of completed GIs) keeps a set fraction of the previous epoch's emission.
- After `maxEpochs`, emission stops. This is an explicit retirement, not an endless tail.
- Progress is tracked **per model**, because every model has its own GI counter.

It mints only through `DinCoordinator.mintEmission()`, so emission can't bypass `mintCap` or faucet retirement.

## Deployment

The Foundry script [`foundry/script/DeployPlatform.s.sol`](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/foundry/script/DeployPlatform.s.sol) deploys and wires all seven contracts in one run: 22 transactions (seven implementations, seven proxies and eight wiring calls).

```
1. Deploy DinCoordinator
└── DinToken is deployed automatically (DinCoordinator becomes its minter)
2. Deploy DinValidatorStake (needs DinToken + DinCoordinator addresses)
3. DinCoordinator.updateValidatorStakeContract(stakeAddress)
4. Deploy DinModelRegistry
5. Per model, later:
DinCoordinator.addSlasherContract(taskCoordinator / taskAuditor)
→ model owner requests registration → DIN-Representative approves
1. DinTreasury proxy
2. DinToken proxy
3. DinFeeRouter proxy (token, treasury)
4. DinCoordinator proxy (token)
→ DinToken.setCoordinator · DinCoordinator.setFeeRouter · DinFeeRouter.addFeeSource(coordinator)
5. DinValidatorStake proxy (token, coordinator)
→ DinCoordinator.updateValidatorStakeContract · DinValidatorStake.setSlashTreasury(treasury)
6. DINModelRegistry proxy (stake)
→ DinFeeRouter.addFeeSource(registry) · DINModelRegistry.setFeeRouter
7. DinEmission proxy
→ DinCoordinator.setEmissionContract
8. Tokenomics overrides from the environment (DIN_PER_ETH, MINT_CAP, EMISSION_*, MIN_STAKE, S5_*, …)
9. Write foundry/deployments/<network>.json, then: dincli system import-deployments
```

Later, for each model: the DIN-Representative runs `dincli dinrep add-slasher` for its coordinator and auditor, the model owner requests registration, and the DIN-Representative approves it.

**Ownership.** Each contract changes owner with OpenZeppelin `transferOwnership`, and each ProxyAdmin has its own owner. There is no single `set-admin` switch. Upgrades go through `foundry/script/UpgradePlatform.s.sol`.

## Further reading

- [DIN Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/din-workflow.md) — narrative walkthrough of these contracts
- [DIN-Representative guide](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/roles/dinrep.md): deploying, importing, approvals, fees and slashers, with every command
- [DeployPlatform script reference](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/foundry/script/DeployPlatform.md): every tokenomics key and its default
- Technical references: [DinCoordinator](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DinCoordinator.md) · [DinToken](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DinToken.md) · [DinValidatorStake](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DinValidatorStake.md) · [DINModelRegistry](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINModelRegistry.md)
- [Task Contracts](Task-Contracts) — the per-model layer these contracts authorize
- [DevNet 2.0 mechanism design](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/design/MECHANISM_DESIGN.md): staking, slashing, rewards, tokenomics and fees
- [Task Contracts](Task-Contracts): the per-model layer these contracts authorize
137 changes: 93 additions & 44 deletions Task-Contracts.md
Original file line number Diff line number Diff line change
@@ -1,81 +1,130 @@
# Task Contracts

While the [Platform Contracts](Platform-Contracts) are deployed once for the whole network, the task contracts are deployed **per model, by the model owner**: every model trained on DIN gets its own pair of `DINTaskCoordinator` and `DINTaskAuditor` contracts that run the federated-learning lifecycle for that model.
> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
The [Platform Contracts](Platform-Contracts) are deployed once for the whole network. The task contracts are deployed **per model, by the model owner**. Every model trained on DIN gets its own pair, `DINTaskCoordinator` and `DINTaskAuditor`, which run the federated-learning lifecycle and the reward pool for that model.

```
Model owner (Ownable)
├── deploys & drives ──► DINTaskCoordinator ◄──── aggregators (register, submit T1/T2)
│ │ │
│ delegates │ │ slash()
│ ▼ ▼
└── deploys ───────────► DINTaskAuditor DinValidatorStake
▲
clients (submit local models) · auditors (register, score)
├── deploys & drives ──► DINTaskCoordinator ◄──── aggregators (register, commit/reveal T1/T2)
│ │ │
│ delegates │ │ slash() aggregators
│ ▼ ▼
└── deploys ───────────► DINTaskAuditor ──slash() auditors──► DinValidatorStake
▲ │
│ └── reward pool (DIN): settled at GI end, claimed by participants
clients (submit local models) · auditors (register, commit/reveal scores)
```

Before a model can be registered in `DinModelRegistry`, both contracts must be authorized as **slashers** on `DinValidatorStake` — the model owner requests this from the DIN-Representative (off-chain), who executes `addSlasherContract` via `DinCoordinator` after verifying the deployment. This guarantees that any model admitted to the network can hold its validators accountable.
Both contracts must be authorized as **slashers** on `DinValidatorStake` before the model can be registered in `DINModelRegistry`, because both carry out slashes:
- the coordinator slashes aggregators;
- the auditor contract slashes auditors.

## DINTaskCoordinator
The model owner requests authorization from the DIN-Representative off-chain. The DIN-Representative checks the deployment and then runs `dincli dinrep add-slasher`.

The central orchestration contract for a model's training. It drives the **23-state Global Iteration (GI) state machine**, coordinates aggregators, and executes slashing.
The task contracts are plain `Ownable` contracts. They are **not upgradeable**: a new version means a new deployment.

Responsibilities:
## DINTaskCoordinator

- **Lifecycle management** — every phase of a GI is opened and closed explicitly by the model owner; all other participants can only act while their phase is open.
- **Aggregator registration** — staked validators register as aggregators for the current GI (permissionless while the phase is open, subject to a minimum stake).
- **Two-tier aggregation** — forms Tier-1 batches (approved local models split into sub-batches, 3 aggregators per batch) and a single Tier-2 batch that combines the T1 results into the new global model. Aggregators submit result CIDs, and the winning CID per batch is decided by **majority vote** among the batch's aggregators.
- **Slashing** — penalizes registered auditors and aggregators that failed to participate or voted against the majority, by calling `slash()` on `DinValidatorStake`.
- Holds the **genesis model CID** (set once before GI 1) and the finalized global model CID of each iteration.
The central orchestration contract for a model's training. It drives the **26-state Global Iteration (GI) state machine**, runs two-tier aggregation, and slashes aggregators.

- **Lifecycle.** The model owner opens and closes every phase of a GI explicitly. Other participants can act only while their phase is open, and only for the current GI.
- **Aggregator registration.** Any active validator can register while the window is open, if:
- its stake is at or above the model's stake floor;
- its stake leaves room under the concurrent-registration cap;
- fewer than 300 aggregators have registered this GI.
- **Batch seeds.** Batches are shuffled with a seed taken from a *future* block hash. The seed is anchored when the previous phase closes, and anyone can lock it once that block is mined (`lockAuditSeed`, `lockAggSeed`).
- **Two-tier aggregation.**
- **Tier-1 batches:** 3 aggregators each combine a sub-batch of 3 approved local models.
- **Tier-2:** one batch of the next 3 shuffled aggregators combines the T1 results into the new global model.
- **Commit, then reveal.** Aggregators first *commit* a hash bound to their CID, address, GI, tier and batch, then *reveal* the CID once the owner opens reveals. So no one can copy a peer's result.
- **Choosing the winner.** The winning CID per batch is the one revealed most often. At least 2 of 3 aggregators must reveal.
- **Aggregator slashing.** Every slash below is capped at the validator's slashable stake.
- **Missed submission:** an aggregator who doesn't reveal for its batch, including one who committed and never revealed, gets a partial slash (30% of the minimum stake; S2, which escalates under S5).
- **Losing CID:** an aggregator who revealed a CID other than the winner gets a full minimum-stake slash.
- **Aggregation disputes (S4).** Within a window after a batch is finalized, any active validator can post a bond and dispute the result. The owner adjudicates. A recomputation that confirms the dispute slashes the original aggregators.
- It holds the **genesis model CID** (set once before GI 1) and each GI's finalized global model CID.

## DINTaskAuditor

The evaluation and quality-control contract — the gatekeeper deciding which client contributions make it into the global model.

Responsibilities:

- **Auditor registration** — staked validators register as auditors for the current GI.
- **Local Model Submission (LMS)** — clients submit the IPFS CID of their locally trained model (one submission per client per GI, capped at 10,000 per GI).
- **Audit batch formation** — submitted models are assigned to batches of auditors (3 auditors × 3 models per batch by default), with a per-batch test dataset CID supplied by the model owner.
- **Scoring & eligibility** — each assigned auditor evaluates the models in its batch against the test data and records a score (0–100) plus an eligibility vote.
- **Finalization** — once quorum is reached, a model's final average score is computed; it is **approved for aggregation** only if the eligibility majority passed it *and* its average score meets the pass threshold (default 50). Scoring parameters (auditors per batch, quorums, pass score) are tunable per round.
The evaluation, quality-control and reward contract: the gatekeeper deciding which client contributions reach the global model, and who gets paid.

- **Auditor registration.** Active validators register for the current GI, under the same stake floor, concurrency and 300-per-GI caps as aggregators.
- **Local Model Submission (LMS).** Clients submit the IPFS CID of their locally trained model. Each client gets one submission per GI, and a GI takes at most 10,000.
- **Audit batches.** Submitted models are shuffled, from the locked audit seed, into batches of 3 auditors × 3 models.
- **Encrypted test data.** For each batch, the owner publishes:
- an AES-GCM-encrypted test-dataset CID;
- a key for each auditor, encrypted to that auditor's registered X25519 key;
- a commitment to the dataset's content.

Only the batch's auditors can read the test data.
- **Scoring: commit, then reveal.** Each auditor evaluates every model in its batch, then *commits* a hash of its score (0–100) and eligibility vote. The hash is bound to the auditor's address and the slot. The auditor *reveals* once the owner opens reveals.
- **Finalization.** A model is **approved for aggregation** when at least 2 auditors vote it eligible and its **median** score is at or above the GI's pass score. The model owner sets the pass score when starting each GI.
- **Auditor slashing.**
- **Missed vote:** an auditor who doesn't reveal a vote, including one who committed and never revealed, gets a partial slash (30% of the minimum stake; S1, which escalates under S5).
- **Score deviation:** scoring far from the median (S3) is a full slash. It ships **disabled** (shadow mode).
- **Test-data disputes.** An auditor of a batch can dispute its test data by posting a 100 DIN bond, as long as the GI's rewards haven't been settled yet. The owner must answer within the window (7,200 blocks, about one day) by revealing the dataset key.
- **The key matches:** the bond is forfeited.
- **The key doesn't match, or the owner stays silent:** the dispute is upheld. The bond is returned, 25% of the GI reward pool is forfeited (no penalty if the GI settled while the dispute was open), and the batch must be reassigned.

## Rewards

Each GI has a **reward pool in DIN**, held by `DINTaskAuditor`.
- **Funding.** The pool must be funded before the GI can start, with `depositRewards(gi, amount)`. Anyone can fund it, and `DinEmission` can subsidise it.
- **Settlement.** When the owner ends the GI, the pool is split:

| Share | Default | Distributed by |
|---|---|---|
| Clients | 60% | median score of each approved local model |
| Auditors | 20% | number of revealed votes |
| Aggregators | 15% | one unit per assigned aggregator of each finalized batch |
| Treasury | 5% | sent to the protocol treasury |

Rewards are **pulled**: each participant calls `claimReward(gi)`, then `claimRewards()` to withdraw. `dincli` has no commands yet for depositing or claiming rewards; these are direct contract calls for now.

## The Global Iteration lifecycle

A GI is one full training round. The coordinator's state machine enforces the order — each transition is an explicit `dincli model-owner ...` command:
A GI is one full training round. The coordinator's state machine enforces the order. Owner steps are `dincli model-owner …` commands; the others belong to the role shown.

```
Setup (once): set auditor contract → confirm slasher auth → submit genesis model
Setup (once): set auditor contract → confirm both slashers → submit genesis model
│
┌────────────────────────────────────────────────────────────────┘
▼
1. GI started
2. Aggregator registration (open → aggregators stake & register → close)
3. Auditor registration (open → auditors stake & register → close)
4. Local Model Submission (LMS) (open → clients train locally & submit CIDs → close)
5. Auditor evaluation (batches created → auditors score & vote → close)
6. T1 aggregation (batches created → aggregators combine sub-batches → finalize)
7. T2 aggregation (T1 winners combined into new global model → finalize)
8. Slashing (non-performing / minority-voting auditors & aggregators)
9. GI ended → next GI starts from the new global model
0. Fund the GI reward pool (depositRewards — required before start)
1. GI started (sets the pass score)
2. Aggregator registration (open → aggregators register → close)
3. Auditor registration (open → auditors register → close)
4. Local Model Submission (open → clients train locally & submit CIDs → close; anchors audit seed)
5. Audit batches (lock audit seed → create batches → assign encrypted test data)
6. Score commit → reveal (auditors commit → owner opens reveal → auditors reveal → close; anchors agg seed)
7. T1/T2 batches (lock aggregation seed → create batches)
8. T1 commit → reveal (aggregators commit → owner opens reveal → aggregators reveal → finalize)
9. T2 commit → reveal (same, producing the new global model)
10. Slashing (slash auditors → slash aggregators)
11. GI ended (reward pool settled; next GI starts from the new global model)
```

Only model artifacts move between participants — raw training data never leaves a client's device. All artifacts (genesis model, local models, aggregated models, test datasets) live on IPFS; the contracts store and vote on their CIDs.
Only model artifacts move between participants. Raw training data never leaves a client's device. All artifacts (the genesis model, local models, aggregated models and encrypted test datasets) live on IPFS, and the contracts store and vote on their CIDs.

## Deploying a model's task contracts

The model owner deploys and wires up both contracts through `dincli`:
The model owner deploys and connects both contracts through `dincli`:

```bash
dincli model-owner deploy task-coordinator --artifact <DINTaskCoordinator.json>
dincli model-owner deploy task-auditor --artifact <DINTaskAuditor.json>
dincli model-owner deploy task-auditor --artifact <DINTaskAuditor.json> # also links it to the coordinator
# then: request slasher authorization from the DIN-Representative,
# confirm it, submit the genesis model, and register the model
```

The full step-by-step — including the slasher authorization request channels and the manifest/services setup — is in the [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md) guide.
> ⚠️ **Known gap:** the DevNet 2.0 task contracts take the model's `modelId` as a constructor argument, but `dincli model-owner deploy` still passes the older argument list. It has to be updated before model owners can deploy through `dincli` (see [DINTaskCoordinator.md §10](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINTaskCoordinator.md)).
The full step-by-step guide, including the slasher authorization request channels and the manifest and services setup, is in the [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md).

## Further reading

- [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md) — complete per-model walkthrough with all commands
- Technical references: [DINTaskCoordinator](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINTaskCoordinator.md) · [DINTaskAuditor](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINTaskAuditor.md) · [DINShared](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINShared.md) (GI state enum & shared interfaces)
- [Platform Contracts](Platform-Contracts) — the network-wide layer that authorizes these contracts
- [Model Workflow](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/public/workflows/model-workflow.md): the complete per-model walkthrough
- Technical references: [DINTaskCoordinator](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINTaskCoordinator.md) · [DINTaskAuditor](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINTaskAuditor.md) · [DINShared](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Documentation/technical/contracts/DINShared.md) (the GI state enum and shared interfaces)
- [DevNet 2.0 mechanism design](https://github.com/InfiniteZeroFoundation/DevNet/blob/develop/Developer/design/MECHANISM_DESIGN.md): the slashing conditions (S1–S6), rewards and scoring
- [Platform Contracts](Platform-Contracts): the network-wide layer that authorizes these contracts
11 changes: 7 additions & 4 deletions Worker-Node.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Worker Node

> 🚧 **This wiki describes DevNet 2.0, soon to be launched.** It follows the contracts and `dincli` on the [`develop`](https://github.com/InfiniteZeroFoundation/DevNet/tree/develop) branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: [#102](https://github.com/InfiniteZeroFoundation/DevNet/discussions/102).
The worker node (`din-worker`) is DIN's **sandbox for untrusted code**. Every training, scoring, and aggregation job on the network runs the *model owner's* Python service code — code the validator did not write and must treat as hostile. Rather than execute it in the trusted `dincli` process, `dincli` spawns a **short-lived worker container per job**, runs the job inside it, and destroys it when the job finishes.

This layer exists whether `dincli` runs directly on the host or inside a [DIN Node](DIN-Node) container — in the containerized setup, workers launch as *siblings* of `din-node` on the host Docker daemon.
Expand All @@ -10,9 +12,10 @@ Each worker container runs with:

- **No network** — `--network none`. The model owner's code cannot phone home, exfiltrate data, or reach the chain.
- **No secrets** — no wallet, no config, no Docker socket. The trusted control plane stays in `dincli`/`din-node`.
- **Resource limits** — CPU and memory caps, so a malicious or buggy job can't starve the host.
- **Read-only inputs** — job inputs are mounted read-only; outputs are written to the designated job directory in the shared state dir.
- **Resource limits** — `--cpus 2 --memory 4g`, so a malicious or buggy job can't starve the host.
- **Read-only inputs** — the model directory, the job file and installed packages are mounted read-only; only role-specific output directories are writable.
- **Operator's UID/GID** — output files on the host stay owned by the operator, not root.
- **Minimal image** — `python:3.12-slim`; the model owner's dependencies come from their pinned `requirements.txt` (see below).

The worker is **stateless**: everything it produces goes to the bind-mounted state directory, nothing of value lives in the container itself. Removing an exited worker is always safe — the next job just spawns a fresh one.

Expand All @@ -24,7 +27,7 @@ Workers are created on demand and self-remove (`--rm`) the moment their job exit
dincli (din-node) host Docker daemon
│ job starts: docker run --rm │
│ --network none, cpu/mem limits, ▼
│ read-only mounts din-worker-<role>-model-<id>-gi-<n>…
│ read-only mounts din-worker-<role>-model-<id>-gi-<n>-batch-<b>…
│ │ runs model owner's service fn
│ ◄── results in state dir ───────────────┘ container removed on exit
```
Expand All @@ -33,7 +36,7 @@ In steady state `docker ps --filter "name=din-"` shows only `din-node`; a visibl

## Known gap: the dependency-install step

Before a job first runs, the model owner's pinned `requirements.txt` is installed in a **separate container that does have network access** — it must, to download packages — and `pip` can execute build hooks from those packages. So model-owner dependencies are network-isolated during the *job*, but not during *install*. This is documented deliberately so the threat model stays accurate; a locked-down/offline install path is future work. Installed packages are cached (`cache/dincli-worker/`) so this cost is paid once per dependency set, and the cache is always safe to delete.
Before a job first runs, the model owner's pinned `requirements.txt` is installed in a **separate container that does have network access** — it must, to download packages — and `pip` can execute build hooks from those packages. So model-owner dependencies are network-isolated during the *job*, but not during *install*. This is documented deliberately so the threat model stays accurate; a locked-down/offline install path is future work. Installed packages are cached (`cache/dincli-worker/`, keyed by a hash of `requirements.txt`) so this cost is paid once per dependency set, and the cache is always safe to delete.

## Future work

Expand Down
8 changes: 4 additions & 4 deletions _Sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
- [Platform Contracts](Platform-Contracts)
- [Task Contracts](Task-Contracts)
- [DIN CLI](DIN-CLI)
- [DIN SDK](DIN-SDK) *(planned)*
- [DIN Daemon](DIN-Daemon) *(planned)*
- [DIN Indexer](DIN-Indexer) *(planned)*
- [DIN DAO](DIN-DAO) *(planned)*
- [DIN SDK](DIN-SDK) *(in progress)*
- [DIN Daemon](DIN-Daemon) *(in progress)*
- [DIN Indexer](DIN-Indexer) *(in progress)*
- [DIN DAO](DIN-DAO) *(deferred)*
- [IPFS Layer](IPFS-Layer)
- [DIN Node](DIN-Node)
- [Worker Node](Worker-Node)
Expand Down