Skip to content

Latest commit

 

History

History
120 lines (83 loc) · 10.3 KB

task_240626_0a.md

File metadata and controls

120 lines (83 loc) · 10.3 KB

Task for — Santiago Rodriguez Cetran

ID: task_240626_0a
Assigned to: Santiago Rodriguez Cetran
Created: 2026-06-24
Status: Closed
Roadmap ref: P3 — Devnet Operator Baseline (validator-operations)
Target: dincli/docker/node/
PR: #12 (Santiagocetran:feature/din-node-container) — MERGED


1. Project Summary

DIN (InfiniteZero) is a federated-learning network coordinated by Solidity contracts on Optimism Sepolia. Participants run dincli, a Python/Typer CLI, to act as clients (local training), auditors (scoring), or aggregators (combining models). Raw training data never leaves a participant's machine — only model artifacts (pinned to IPFS) and on-chain coordination state are shared.

Each model owner supplies their own Python service code (training/scoring/aggregation logic), fetched from IPFS and executed locally by whoever is running dincli. Because that service code is supplied by a third party (the model owner), it is treated as untrusted — it must not get access to wallets, private keys, or the host filesystem beyond what a specific job needs.

2. What's Already Done

The team has already built the untrusted-execution piece:

  • dincli/cli/worker.py — builds/runs a Docker worker image (din-worker:dev), installs manifest-pinned requirements.txt per role into a shared package cache, writes a structured job file, runs the worker container with --network none, CPU/memory limits, read-only mounts (only specific subdirectories are writable), and reads back a structured result.json.
  • dincli/docker/worker/ — the worker image itself: a minimal Python entrypoint that loads the model owner's function and executes it inside the container.
  • dincli/cli/client.py, auditor.py, aggregator.py — all three roles (train-lms, lms-evaluation evaluate, aggregate-t1, aggregate-t2) already call into this worker layer to run untrusted training/scoring/aggregation code in isolated containers.

So: per-job sandboxing already exists and works. What's missing is the operator side — there is no packaged way to run dincli itself as a long-lived service with a sane start/stop/upgrade/log/volume story. Today, dincli runs preferably on host. However. based on feedback from other advisers/contributers, the best way to go is running everything in docker. Currently ~/.config/dincli / ~/.cache/dincli are managed by throgh dincli commands, but we want to move that into docker too.

Relevant docs (heads up — these are working drafts, not specs; they're known to be incomplete and in places inconsistent with the actual code, so treat the code as the source of truth and call out doc/reality mismatches you find):

  • Developer/issues/containerization.md
  • Developer/issues/validator-operations.md
  • Developer/CONTRIBUTING.md, Developer/DEVELOPMENT_SETUP.md

3. Roadmap Context

This work maps to Phase 1: Devnet Operator Baseline of the validator-operations roadmap item — the near-term goal of giving operators (clients/auditors/aggregators today, validators later) a real containerized run path instead of an ad-hoc local Python install. It's also a prerequisite for later DIN daemon (dind) work described in the P4 roadmap, which assumes a persistent host process exists to manage.

4. The Task

Build a din-node main container — a Docker image with dincli installed — plus an operator-facing run path around it (start/stop/upgrade/logs/volume cleanup), so a participant can run dincli as a containerized host process instead of installing Python locally.

Why this design

dincli already spawns short-lived worker containers (din-worker:dev) per job for untrusted client/auditor/aggregator service code (see §2). The din-node container you're building is the trusted host process — it holds config/wallet state and issues docker run commands for those worker containers as siblings, the same way dincli does today when run directly on a host. To make that work from inside a container, din-node needs access to a Docker daemon: mount the host's /var/run/docker.sock into the din-node container and install the docker CLI in its image. Worker containers it spawns will then run as siblings on the host's Docker daemon, not nested inside din-node. This is a deliberate simplification for devnet — document it as a known tradeoff (the din-node container effectively gets root-equivalent access to the host Docker daemon), not something to "solve" in this trial.

Required pieces

  1. din-node Docker image (e.g. dincli/docker/node/Dockerfile)

    • Installs dincli (editable or built install — your call, document which and why).
    • Installs the docker CLI (just the client binary, not a full daemon) so it can shell out to docker run/docker build exactly like dincli/cli/worker.py does today.
    • Non-root default user where practical (note any place you had to deviate, e.g. Docker socket group access).
    • Pin Python and dincli versions.
  2. Persistent volume layout — dincli already uses platformdirs for three directories (see dincli/cli/utils.py): CONFIG_DIR (wallet/config), CACHE_DIR (manifests/models/jobs), DOCKER_CACHE_DIR (worker package installs). Map these to named volumes or host bind mounts in your Compose file and document the mapping explicitly — this is the most important part of the deliverable, since getting it wrong either breaks persistence across upgrades or leaks state into the wrong place.

  3. Docker Compose file with:

    • The din-node service, with the Docker socket mounted (/var/run/docker.sock:/var/run/docker.sock).
    • Named volumes (or documented bind mounts) for config/cache/docker-cache.
    • One-command start, stop, upgrade flows — these can just be documented docker compose invocations (e.g. docker compose up -d, docker compose down, docker compose pull && docker compose up -d --build), they don't need custom scripting unless you find scripting genuinely clearer.
    • Documented log access (docker compose logs -f din-node).
    • Documented volume cleanup (what's safe to delete, what isn't — e.g. wallet/config should survive an upgrade, worker package cache can be safely wiped to reclaim disk).
  4. A short operator runbook (markdown, lives under Developer/ or wherever you think fits — your call, just say why) covering:

    • First-time setup (build/pull image, first dincli system configure-network / wallet setup inside the container).
    • Start/stop/upgrade/logs.
    • What state lives where and what survives an upgrade vs. a full teardown.
    • The Docker-socket tradeoff called out explicitly, with what it means for anyone deploying this (don't run din-node on a host you don't trust the operator of).
  5. Doc correction pass — while building this, you'll be reading Developer/issues/containerization.md and Developer/issues/validator-operations.md closely. Where you find concrete inaccuracies (e.g. references to mechanisms that don't match current code, or Phase 1 items that turn out to be already done elsewhere), call them out as a short list in your PR description or a small doc patch — whichever is less effort. We'd rather have a short accurate note than a large doc rewrite.

Explicitly out of scope

  • No changes to the worker container layer (dincli/cli/worker.py, dincli/docker/worker/) — that part already works.
  • No Solidity/contract changes.
  • No /health HTTP endpoint, systemd/launchd units, or vault/remote-signer integration — those are later phases.
  • No new automated tests are required for this task (it's primarily an image/Compose/docs deliverable), but if you add any small Python helper code (e.g. an entrypoint script) and it's easy to cover, a couple of tests are welcome — not required.

5. Setup Guide

# Fork https://github.com/InfiniteZeroFoundation/DevNet and clone your fork
git checkout develop
git pull
git checkout -b feature/din-node-container

# Local (non-container) baseline, to understand current behavior first
pip install -e .
dincli --help

Read, in this order, before writing any Docker/Compose code:

  1. Developer/issues/containerization.md (Phase 1 + Docker Packaging Requirements sections)
  2. Developer/issues/validator-operations.md (Blocking Requirements §1 + Phase 1)
  3. dincli/cli/worker.py and dincli/docker/worker/Dockerfile — this is the pattern to follow for the new din-node image.
  4. dincli/cli/utils.py — CONFIG_DIR, CACHE_DIR, DOCKER_CACHE_DIR definitions.

You'll need Docker installed locally to test the din-node image and Compose file end-to-end, including spawning a worker container from inside din-node (verify the docker.sock mount actually lets you do this — that's the core risk in this task).

6. Deliverables Checklist

  • din-node Dockerfile, builds cleanly — dincli/docker/node/Dockerfile
  • Docker Compose file wiring din-node + docker.sock + volumes — dincli/docker/node/docker-compose.yml
  • Verified: from inside the running din-node container, a dincli command that spawns a worker container actually launches a sibling container on the host Docker daemon
  • Volume layout documented (what maps to CONFIG_DIR/CACHE_DIR/DOCKER_CACHE_DIR, what's safe to wipe) — dincli/docker/node/README.md
  • Start/stop/upgrade/logs documented as docker compose commands — dincli/docker/node/README.md
  • Operator runbook (markdown) including the docker.sock tradeoff — dincli/docker/node/README.md
  • Short list of doc inaccuracies found in containerization.md / validator-operations.md, with a fix if it's a one-liner

7. Submission

When done:

  • Push your feature branch to your fork.
  • Open a pull request from your fork's feature/din-node-container branch into develop on https://github.com/InfiniteZeroFoundation/DevNet.
  • PR description: what you built, the docker.sock tradeoff and why you went with it, anything you'd do differently with more time, and the doc-inaccuracy notes from §6.
  • Send us the PR link (or the repo + branch link if you'd rather not open the PR until we've reviewed) once it's up.

If anything in this task is ambiguous or you think a different approach is better, say so in the PR or reach out first — we'd rather you push back on a bad assumption here than silently work around it.