Skip to content

DIN Node

umermjd11 edited this page Oct 5, 2026 · 5 revisions

DIN Node

🚧 This wiki describes DevNet 2.0, soon to be launched. It follows the contracts and dincli on the develop branch; the currently running DevNet may still use older contracts and commands. Pre-launch discussion: #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.

Trusted control plane, untrusted execution

The design splits dincli's work into two trust domains:

  • Trusted control plane — runs inside din-node. Holds the wallet and config, talks to the chain and IPFS, and decides what to submit.
  • Untrusted execution — never runs inside din-node. Every training/scoring/aggregation job executes the model owner's Python code, which is treated as hostile. Each job runs in a short-lived, sandboxed Worker Node container.

Because din-node must be able to spawn those workers, the host's Docker socket is mounted into it (the image ships only the Docker client). Workers therefore launch as siblings of din-node on the host daemon, not nested inside it:

        Host Docker daemon  ◄──────── /var/run/docker.sock (mounted into din-node)
          │            │                       │
          ▼            ▼                 ┌──────┴─────┐
   ┌────────────┐ ┌────────────┐         │  din-node  │  dincli runs `docker run`
   │ din-worker │ │ din-worker │ ◄───────┤  (dincli)  │  → host daemon → sibling
   └────────────┘ └────────────┘         └────────────┘

⚠️ Security tradeoff: the mounted Docker socket gives din-node root-equivalent control of the host's Docker daemon — anyone who compromises din-node effectively owns the host. This is a deliberate devnet simplification, accepted and documented, not a solved problem. Don't run din-node next to unrelated sensitive workloads. Hardening options (rootless Docker, socket proxy, Podman) are future work. The worker sandbox itself is unaffected by this tradeoff.

State: one directory, bind-mounted at the same path

All persistent state lives in a single host directory, DIN_STATE_DIR, bind-mounted into the container at the identical absolute path:

$DIN_STATE_DIR/
├── config/dincli/            wallets/, config.json      ← your keys — back this up
├── cache/dincli/             manifests, models, job files (re-downloadable)
└── cache/dincli-worker/      worker pip packages (safe to delete, can be large)

The identical-path bind mount is load-bearing, not cosmetic: when dincli spawns a worker via the host daemon, the host resolves the volume paths — so the path dincli knows inside the container must also be valid on the host. (A named volume would silently give workers empty mounts — a known constraint of the Docker-outside-of-Docker pattern.)

Because state lives on the host, container rebuilds and image upgrades never touch the wallet, config, or caches. The container also runs as the operator's own UID/GID, so all files stay owned by the operator.

Operating it

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
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

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) 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 for the shared layer that enables this.

Roadmap (validator operations)

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

Introduction

DIN Components

Network Roles

Clone this wiki locally