Join our community of builders on Discord!

Run a Worker on Testnet

Workers are the supply side of the Lightchain AI network. A worker runs whitelisted models via Ollama alongside the Worker Sidecar (shipped as a Docker image), serves encrypted inference jobs through the Worker Gateway, and earns fees for every completed job. This guide walks through the end-to-end lifecycle on Testnet — from generating a worker key and funding it to registering on-chain, going live, and deregistering when you're done.

Prerequisites

  • Docker installed
  • GPU machine with enough VRAM for your model (8 GB+ for llama3-8b)
  • Ollama installed and running
  • Funder wallet holding at least 5001 LCAI (5000 stake + ~1 gas) — this is your existing wallet that pays to bring the worker online. It is NOT the worker key. You will generate a fresh worker key in Step 0 and send LCAI from the funder to it in Step 5.
  • Foundry installed (cast is used for key generation, balance checks, and contract reads)

Network reference

ServiceValue
RPC URLhttps://rpc.testnet.lightchain.ai
Chain ID8200
Beacon APIhttps://beacon.testnet.lightchain.ai
Worker Gatewayhttps://worker-gateway.testnet.lightchain.ai

Resolve testnet contract addresses

AIConfig and JobRegistry are deployed at runtime, so their addresses depend on the environment. Resolve them once from the predeployed WorkerRegistry and export them — the docker run steps below pick them up from your shell:
CodeBASH

Step 0: Generate a fresh worker key

Always use a dedicated, brand-new key for the worker. Do not reuse your funder key — the worker key sits in a Docker container with the keystore password, and should hold only the working capital (stake + small gas buffer) you're comfortable exposing to that machine.
CodeBASH
Copy the printed Address and Private key, then export them:
CodeBASH
Sanity check — the privkey must derive to the address you'll be funding and registering:
CodeBASH
The output must equal $WORKER_ADDR. If it doesn't, stop and re-export — anything sent to the wrong address is unrecoverable, and registering with mismatched keys locks the stake on the wrong account.
Do not set WORKER_PRIVKEY to your funder's private key. The two must be different. The funder pays from your existing wallet (Step 5); the worker is the new key from this step.

Step 1: Install Ollama and pull the model

CodeBASH

Step 2: Pull the worker image

CodeBASH

Step 3: Import the worker private key

Imports $WORKER_PRIVKEY (set in Step 0) into an encrypted keystore on disk:
CodeBASH
The Address: printed by the command must equal $WORKER_ADDR from Step 0. If they differ, stop — the wrong key was imported.

Step 4: Generate the ECDH encryption key

Every worker advertises an encryption public key on-chain so users can encrypt prompts for it — keygen produces that pair locally.
CodeBASH
The encryption private key stays on the machine running inference — it is what decrypts incoming prompts.

Step 5: Fund the worker from your funder wallet

Send LCAI from your funder wallet (the existing one mentioned in Prerequisites) to $WORKER_ADDR (the fresh address from Step 0). The worker needs at least 5001 LCAI: 5000 for the minimum stake plus ~1 for gas (register TX + per-job ack and complete TXs over its lifetime). 5005 LCAI gives a comfortable buffer. If your funder wallet is in MetaMask/Rabby, send the transfer through the wallet UI. If you have its private key locally and want to use Foundry:
CodeBASH
Verify the worker received the funds:
CodeBASH
Common mistake: setting FUNDER_PRIVKEY to the same value as WORKER_PRIVKEY. That sends LCAI from the worker to itself (a no-op minus gas) and the worker stays unfunded. Cross-check with cast wallet address --private-key "$FUNDER_PRIVKEY" — it must NOT equal $WORKER_ADDR.

Step 6: Register on-chain

CodeBASH
This will:
  • Stake 5000 LCAI (auto-queried from AIConfig)
  • Register your ECDH public key on-chain
  • Add llama3-8b to your supported models
You can only serve models that are currently whitelisted on AIConfig. Attempting to register for a delisted or non-existent model will revert.

Step 7: Run the worker

The --add-host flag below makes host.docker.internal resolve to the Docker host on Linux (where it isn't provided by default). On macOS and Windows it's a no-op — Docker Desktop already maps that hostname — so the same command works everywhere.
CodeBASH

Step 8: Verify it's working

CodeBASH
The worker emits structured JSON logs. A healthy startup shows roughly this sequence (timestamps and addresses elided for brevity):
CodeTEXT
If you see all of those — particularly worker registration validated, authenticated with worker-gateway, and websocket connected to gateway — the worker is fully online. Grep for the stable substrings if you don't want to read the full output:
CodeBASH
The worker is now:
  • Sending heartbeats every 10s via the gateway
  • Connected via WebSocket for instant job delivery
  • Ready to receive and process inference jobs
When a job lands, you'll see a multi-stage log sequence (ws_job_receivedstage 1 completestage 2 starting → … → job completed). Tail with:
CodeBASH

Rewards and fund handling

Per-job fees earned by the worker are paid out directly to the worker's wallet ($WORKER_ADDR from Step 0) as jobs complete. There is no separate payout address registered on-chain and no automatic forwarding to the funder wallet — earnings simply accumulate on the worker key. Because the worker key lives inside the Docker container alongside its keystore password, you should not treat it as long-term storage. Sweep accumulated fees to your own designated wallet (typically the funder, a hardware wallet, or any cold-storage address you control) on whatever cadence matches your risk tolerance. Check the worker's current balance:
CodeBASH
Sweep funds from the worker to your designated wallet, leaving a small gas buffer behind so the sidecar can keep paying for JobAcknowledged / JobCompleted transactions:
CodeBASH
Do not drain the worker wallet to zero while the worker is registered and running — it needs gas to ack and complete future jobs. Missed deadlines lead to slashing (see Slashing and jailing). Leaving ~1 LCAI behind is usually enough; top up from your funder if it dips.
The staked 5000 LCAI is held by WorkerRegistry, not by the worker wallet, and is only released when you deregister (see Deregister and withdraw stake).

Check registration status

CodeBASH

Slashing and jailing

Workers are held accountable for correctness and availability. See AIVM EL Architecture — Verification for the full model; in short:
  • Timeouts (missed job deadlines) → slashed stake and a temporary jail
  • Lost disputes (semantic similarity check indicates a bad response) → slashed stake
  • Repeat offenses → escalating slashing and eventual long-term jailing
Jailed workers can be un-jailed via WorkerUnjailed once the penalty window passes, assuming stake remains above the minimum.

Deregister and withdraw stake

Finish or time out any outstanding jobs first, then run:
CodeBASH
This removes your worker from the registry and returns your staked LCAI (minus any slashing penalties).

Stop the worker

CodeBASH

Testnet contract addresses

ContractAddress
WorkerRegistry0x0000000000000000000000000000000000001002 (predeploy)
AIConfigResolve from WorkerRegistry — see Resolve testnet contract addresses
JobRegistryResolve from WorkerRegistry — see Resolve testnet contract addresses
FeePool0x0000000000000000000000000000000000001004 (predeploy)