Skip to content

Latest commit

 

History

History
378 lines (272 loc) · 14.3 KB

task_290626_1.md

File metadata and controls

378 lines (272 loc) · 14.3 KB

Task: dincli CLI Test Harness

ID: task_290626_1
Assigned to: Umer Majeed
Created: 2026-06-29
Status: Closed
Roadmap ref: P3 WP 6.1 — Integration and Devnet Upgrade
Target: tests/dincli/


Objective

Build a dincli CLI-level test harness that exercises the full end-to-end lifecycle against a local Hardhat node — from platform contract deployment through a complete Global Iteration. This harness serves two goals:

  1. Regression safety for contract upgrades. Before any testnet redeployment of upgraded contracts, the harness must pass. It is the blocking prerequisite for WP 6.1.
  2. SDK extraction foundation (P4 WP 1.2). The test harness exposes which CLI paths are pure orchestration (suitable for the future dincli/sdk/) and which are UI/UX wrappers. This separation informs the SDK interface design when dind needs to automate the same flows without the Typer layer.

Architecture note — SDK extraction path

The longer-term plan (P4 WP 1.2, September 2026) is to extract dincli/sdk/ from dincli/cli/, so that:

  • dincli/cli/ keeps the Typer commands (UI/UX, argument parsing, Rich output)
  • dincli/sdk/ holds the pure logic (contract calls, IPFS operations, wallet management)
  • dind (the DIN daemon) calls sdk/ directly for automated execution and monitoring without going through the CLI layer

The test harness written here should be structured so its helper functions naturally become SDK candidates. Where a test calls a sequence of dincli commands, note in a comment which logical operation that sequence represents — that comment will become the SDK function name.


Prerequisites before running tests

1. Compile contracts

cd /path/to/devnet/hardhat
npx hardhat compile

2. Start local Hardhat node (network = local)

Run in a separate terminal and keep it alive for the duration of the test run:

cd /path/to/devnet/hardhat
npx hardhat node

3. Activate the correct Python environment

For commands that do not require torch (most deploy/registry/wallet commands):

source ~/my_venvs/pyDIN/bin/activate

For commands that require torch (client training, aggregation, auditor evaluation):

source ~/my_venvs/torchenv/bin/activate

4. IPFS daemon (if ipfs_provider = "env")

Check the configured provider:

from dincli.cli.utils import resolve_ipfs_config
config = resolve_ipfs_config()
# if config.provider == "env": start ipfs daemon

If the provider resolves to "env", start the IPFS daemon in a separate terminal:

ipfs daemon

Test location

tests/dincli/

Follow the existing project test patterns: CliRunner + monkeypatch from tests/test_dintoken.py and tests/test_ipfs_config.py for unit-style tests. For integration tests that require a live local node, mark them with @pytest.mark.integration and document that they need the prerequisites above.


Phase 1 — Deploy platform-level contracts

These are deployed once by the DIN-Representative (account 0).

python -m dincli.main system connect-wallet --account 0

python -m dincli.main dindao deploy din-coordinator \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DinCoordinator.sol/DinCoordinator.json

python -m dincli.main system dump-abi --official \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DinCoordinator.sol/DinCoordinator.json

python -m dincli.main system dump-abi --official \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DinToken.sol/DinToken.json

python -m dincli.main dindao deploy din-validator-stake \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DinValidatorStake.sol/DinValidatorStake.json

python -m dincli.main system dump-abi --official \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DinValidatorStake.sol/DinValidatorStake.json

python -m dincli.main dindao deploy din-model-registry \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DINModelRegistry.sol/DINModelRegistry.json

python -m dincli.main system dump-abi --official \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DINModelRegistry.sol/DINModelRegistry.json

Test assertions: Each deploy command exits 0.


Phase 2 — Deploy task-level contracts and authorize slashers

Deployed by the model owner (account 1).

python -m dincli.main system connect-wallet --account 1
python -m dincli.main system --eth-balance

python -m dincli.main model-owner deploy task-coordinator \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DINTaskCoordinator.sol/DINTaskCoordinator.json

python -m dincli.main system dump-abi --official \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DINTaskCoordinator.sol/DINTaskCoordinator.json

python -m dincli.main model-owner deploy task-auditor \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DINTaskAuditor.sol/DINTaskAuditor.json

python -m dincli.main system dump-abi --official \
    --artifact /path/to/devnet/hardhat/artifacts/contracts/DINTaskAuditor.sol/DINTaskAuditor.json

# DIN-Representative authorizes slashers
python -m dincli.main system connect-wallet --account 0
python -m dincli.main dindao add-slasher --taskCoordinator
python -m dincli.main dindao add-slasher --taskAuditor

# Model owner registers slashers on task contracts
python -m dincli.main system connect-wallet --account 1
python -m dincli.main model-owner add-slasher --taskCoordinator
python -m dincli.main model-owner add-slasher --taskAuditor

Phase 3 — Genesis model and model registration

python -m dincli.main system connect-wallet --account 1

python -m dincli.main model-owner task create-task-dir
python -m dincli.main model-owner task cache-default-artifacts
python -m dincli.main model-owner model create-genesis-model
python -m dincli.main model-owner model add-default-test-data --default-test-data
python -m dincli.main model-owner model submit-genesis-model
python -m dincli.main model-owner model validate-update-manifest

python -m dincli.main task model-owner register-request

# DIN-Representative approves
python -m dincli.main system connect-wallet --account 0
python -m dincli.main dindao registry list-pending-requests
python -m dincli.main dindao registry explore-request 0 -t model
python -m dincli.main dindao registry approve-registration-request 0

# Model owner confirms and updates manifest
python -m dincli.main system connect-wallet --account 1
python -m dincli.main task model-owner my-requests --ip
python -m dincli.main task model-owner show-registration-request 0
python -m dincli.main task explore 0
python -m dincli.main task model-owner update-manifest-request 0

# DIN-Representative approves manifest update
python -m dincli.main system connect-wallet --account 1
python -m dincli.main dindao registry list-pending-requests

python -m dincli.main system connect-wallet --account 0
python -m dincli.main dindao registry explore-request 0 -t manifest
python -m dincli.main dindao registry approve-manifest-update 0

Phase 4 — Global Iteration

GI setup

python -m dincli.main system connect-wallet --account 1
python -m dincli.main task gi show-state 0
python -m dincli.main model-owner model add-default-test-data --default-test-data --model-id 0
python -m dincli.main model-owner gi start 0
python -m dincli.main model-owner gi reg aggregators-open 0

Aggregator registration (accounts 11–22)

python -m dincli.main system connect-wallet --account 11
python -m dincli.main aggregator dintoken buy 0.00001
python -m dincli.main aggregator dintoken stake 10
python -m dincli.main aggregator dintoken read-stake
python -m dincli.main aggregator register 0

for acc in {12..22}; do
    python -m dincli.main system connect-wallet --account $acc
    python -m dincli.main aggregator dintoken buy 0.00001
    python -m dincli.main aggregator dintoken stake 10
    python -m dincli.main aggregator dintoken read-stake
    python -m dincli.main aggregator register 0
done

python -m dincli.main system connect-wallet --account 1
python -m dincli.main model-owner gi show-registered-aggregators 0
python -m dincli.main model-owner gi reg aggregators-close 0

Auditor registration (accounts 50–58)

python -m dincli.main model-owner gi reg auditors-open 0

python -m dincli.main system connect-wallet --account 50
python -m dincli.main auditor dintoken buy 0.00001
python -m dincli.main auditor dintoken stake 10
python -m dincli.main auditor dintoken read-stake
python -m dincli.main auditor register 0

for acc in {51..58}; do
    python -m dincli.main system connect-wallet --account $acc
    python -m dincli.main auditor dintoken buy 0.00001
    python -m dincli.main auditor dintoken stake 10
    python -m dincli.main auditor dintoken read-stake
    python -m dincli.main auditor register 0
done

python -m dincli.main system connect-wallet --account 1
python -m dincli.main model-owner gi show-registered-auditors 0
python -m dincli.main model-owner gi reg auditors-close 0

LMS (Local Model Submission) — accounts 2–10

python -m dincli.main model-owner lms open 0

python -m dincli.main system dataset distribute-mnist --seed 42 --clients "--test-train" --num-clients 9 --model-id 0

python -m dincli.main system connect-wallet --account 2
python -m dincli.main client create-client-dataset-dir 0
python -m dincli.main client train-lms 0
python -m dincli.main client submit-lm 0

for acc in {3..10}; do
    python -m dincli.main system connect-wallet --account $acc
    python -m dincli.main client create-client-dataset-dir 0
    yes | python -m dincli.main client train-lms 0
    yes | python -m dincli.main client submit-lm 0
done

python -m dincli.main system connect-wallet --account 1
python -m dincli.main model-owner lms close 0

Auditor batches and LMS evaluation

python -m dincli.main model-owner auditor-batches create 0
python -m dincli.main model-owner auditor-batches show 0
python -m dincli.main model-owner auditor-batches create-testdataset 0 --submit
python -m dincli.main model-owner lms-evaluation start 0
python -m dincli.main model-owner lms-evaluation show 0
python -m dincli.main model-owner lms-evaluation show 0 --auditors --models

python -m dincli.main system connect-wallet --account 50
python -m dincli.main auditor lms-evaluation show-batch 0
python -m dincli.main auditor lms-evaluation evaluate 0 --submit

for acc in {51..58}; do
    python -m dincli.main system connect-wallet --account $acc
    python -m dincli.main auditor lms-evaluation show-batch 0
    python -m dincli.main auditor lms-evaluation evaluate 0 --submit
done

python -m dincli.main system connect-wallet --account 1
python -m dincli.main model-owner lms-evaluation show 0 --models
python -m dincli.main model-owner lms-evaluation close 0

T1/T2 aggregation

python -m dincli.main model-owner aggregation create-t1nt2-batches 0
python -m dincli.main model-owner aggregation show-t1-batches 0 --detailed
python -m dincli.main model-owner aggregation show-t2-batches 0 --detailed
python -m dincli.main model-owner aggregation T1 start 0

python -m dincli.main system connect-wallet --account 11
python -m dincli.main aggregator show-t1-batches 0 --detailed
python -m dincli.main aggregator aggregate-t1 0 --submit

for acc in {12..22}; do
    python -m dincli.main system connect-wallet --account $acc
    python -m dincli.main aggregator show-t1-batches 0 --detailed
    python -m dincli.main aggregator aggregate-t1 0 --submit
done

python -m dincli.main system connect-wallet --account 1
python -m dincli.main model-owner aggregation show-t1-batches 0 --detailed
python -m dincli.main model-owner aggregation T1 close 0
python -m dincli.main model-owner aggregation T2 start 0
python -m dincli.main task gi show-state 0
python -m dincli.main model-owner aggregation show-t2-batches 0

python -m dincli.main system connect-wallet --account 11
python -m dincli.main aggregator show-t2-batches 0 --detailed
python -m dincli.main aggregator aggregate-t2 0 --submit

for acc in {12..22}; do
    python -m dincli.main system connect-wallet --account $acc
    python -m dincli.main aggregator show-t2-batches 0 --detailed
    python -m dincli.main aggregator aggregate-t2 0 --submit
done

python -m dincli.main system connect-wallet --account 1
python -m dincli.main model-owner aggregation show-t2-batches 0 --detailed
python -m dincli.main model-owner aggregation T2 close 0

Slashing and GI end

python -m dincli.main model-owner slash auditors 0
python -m dincli.main model-owner slash aggregators 0
python -m dincli.main model-owner gi end 0

Test assertion: task gi show-state 0 returns GIended (state index 22).


Implementation notes

  • No containerization in this initial version. Docker/compose is in scope for WP 0.1 (separate task), not here.
  • Torch environment. Commands that invoke model training or aggregation must run under torchenv. The harness runner should switch environments or document which test groups require which venv.
  • Account index mapping. Hardhat dev accounts are indexed from 0. Accounts 11–22 are aggregators, 50–58 are auditors, 2–10 are clients. Account 0 is the DIN-Representative; account 1 is the model owner.
  • State assertions. Each phase should assert the GI state string returned by task gi show-state 0 matches the expected state from dincli/cli/utils.py::states.
  • Idempotency. Where possible, check whether a contract is already deployed before re-deploying. The harness should be re-runnable on a fresh Hardhat node without manual cleanup. if hardhat node is already running close it and restart.

Additional notes

all tests and commands within a test depends upon succesful execution of previous tests and previous commands, so upon failure it should quit and point to that failure command.

use ~/tempdir/dincli/ as temp_dir to output any test results to avoid clutter.

Deliverables

  • tests/dincli/ directory with test modules
  • Integration test runner script or pytest fixture that documents the required prerequisites
  • At minimum: deploy flow (Phase 1–2), registration flow (Phase 3), and GI state transitions (Phase 4 — open/close phases) covered with exit-code assertions
  • Notes file (tests/dincli/NOTES.md) identifying which command sequences are SDK candidates for P4 WP 1.2
  • notes in Documentation/technical/testing/dincli-testing-guide.md fo running the tests on your local hardhat node.