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/
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:
- 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.
- 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 whendindneeds to automate the same flows without the Typer layer.
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) callssdk/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.
cd /path/to/devnet/hardhat
npx hardhat compileRun in a separate terminal and keep it alive for the duration of the test run:
cd /path/to/devnet/hardhat
npx hardhat nodeFor commands that do not require torch (most deploy/registry/wallet commands):
source ~/my_venvs/pyDIN/bin/activateFor commands that require torch (client training, aggregation, auditor evaluation):
source ~/my_venvs/torchenv/bin/activateCheck the configured provider:
from dincli.cli.utils import resolve_ipfs_config
config = resolve_ipfs_config()
# if config.provider == "env": start ipfs daemonIf the provider resolves to "env", start the IPFS daemon in a separate terminal:
ipfs daemontests/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.
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.jsonTest assertions: Each deploy command exits 0.
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 --taskAuditorpython -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 0python -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 0python -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 0python -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 0python -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 0python -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 0python -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 0python -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 0Test assertion: task gi show-state 0 returns GIended (state index 22).
- 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 0matches the expected state fromdincli/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.
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.
tests/dincli/directory with test modules- Integration test runner script or
pytestfixture 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.