Eschaton (eacc-swarm) — design
Brand: Eschaton / $ESC, "Immanentize the model." (`NAMING.md`). Internal names stay eacc-swarm. $ESC's trading fees fund node rewards; e/acc is only the stake token.
Status: v1 (2026-10-06). Owner: train. The cross-component contract (PDAs, account layouts, instructions, merkle format, the §7 coordinator API, ports, keys) lives in `INTERFACES.md` and is not repeated here. This document covers (1) how eacc-swarm maps onto Pluralis Protocol Learning / Node0, (2) the token layer on top of it, and (3) the train-internal interfaces (node ↔ coordinator ↔ trainer ↔ seed) that are additive to INTERFACES.md §7. Research and sources: `RESEARCH.md`.
1. One-paragraph summary
eacc-swarm is a fork of Pluralis Research's open-source Node0 client (Apache-2.0) with Pluralis's hosted services (auth server, seeds, monitor, trainers) re-implemented locally and a Solana token layer added. A LLaMA-style model is cut into pipeline stages (head / body / tail). Each GPU node holds one stage only, announces it in a hivemind (libp2p) DHT, and serves forward/backward RPCs. Replicas of a stage average their gradients/parameters among themselves (stage-wise data parallelism). Activations and activation gradients that cross a stage boundary are compressed with Protocol Models' subspace projection. Instead of a Hugging Face login, a node proves it controls the hot key registered to a staked e/acc NodeAccount. Trainers attest the compute every worker performed, spot-checks catch workers that return garbage, and at each epoch the coordinator publishes per-owner points; settlement turns them into a merkle root on-chain, and owners claim their pro-rata share of the SOL in the reward vault. That SOL comes from the trading fees of the project's own token, $ESC: its pump.fun creator-fee sharing pays 9,000 bps to the ["reward_vault"] PDA and 1,000 bps to ["eacc_lock"], fixed in the launch transaction, which also revokes the sharing admin (see `FEES.md`, `TOKENOMICS.md`). e/acc's own fees play no role. Production settlement streams PAYOUT_FRACTION = 1/60 of the vault per 24 h epoch; localnet demos pay out 1.
2. Pluralis → eacc-swarm mapping
| Pluralis (Node0 / Agora) | eacc-swarm | Same / deviation |
|---|---|---|
| Node0 client (`node0` package, hivemind fork-point `4d5c414`) | vendored in `node/` (`node0` package name kept), same hivemind commit | same code; diffs listed in `node/NOTICE` and file headers |
| LLaMA blocks (`models/llama/layers.py`): RMSNorm, RoPE, GQA, SwiGLU, QK-norm, `norm_reorder` | unchanged | same |
| Head / body / tail experts, one stage per GPU, uids `head.0.N`, `body{i}.0.N`, `tail.0.N` | unchanged | same |
| `llama_8B_C`: 32 stages × 1 block, d=4096, compression 100× | shipped unchanged (16 GB+ CUDA tier) | same |
| Subspace compression: `rcv` (d×k orthonormal) + fixed high-rank token embedding, `ss_regularize` after each optimizer step | unchanged math; `rcv` / fixed embedding are generated deterministically from the run seed instead of downloaded from Pluralis's CDN | deviation: no Pluralis CDN; same construction |
| Grassmann subspace drift (Protocol Models arXiv 2506.01260 §4.5, §6, Eq. 11): accumulate S = (1/K) Σ GᵀG of last-compressed-layer gradients, Riemannian step on −2SU, QR retraction, "per every 500 iterations, and transmit to all the layers" | partial: the step is in `node0.eacc.subspace_drift` (tested: stays orthonormal, converges to the gradient subspace); not wired, no flag | gap: not in Node0's or Agora's public code (both keep `rcv` frozen after `load_comp`). The paper leaves η (it reuses the learning-rate symbol) and K open, and also how projected weights, the fixed embedding and AdamW moments are re-expressed after U moves, and how replicas agree on U |
| hivemind `Optimizer` + PowerSGD gradient averager (`power_sgd_averager_mac` on macOS), sparse state averaging, `max_allowed_stale` | unchanged | same |
| AsyncSPARTA (Agora, Pluralis-8B): local optimizer step every collaborative epoch, no gradient all-reduce; every `average_state_every` epochs a background SPARTA round averages a seeded 5% partition (moments share their parameter's partition), weighted by samples, applied by the delta rule `x ← x + (x̄ − x_snapshot)` (λ = 1); optional β^k correction of moment deltas; `exp_avg_sq` clamped ≥ 0 | ported from `PluralisResearch/agora@37d29a9` (`state_averager_sparta.py`, `optimizer_sparta_async_nstep.py`) into `node0/server/`, plus the `_save_pre_averaging_state` hook and optimizer lock in the vendored state averager. Flag `async_sparta` (+ `sparse_avg`, `average_state_every`, `beta_k_correction`). Off by default everywhere. `llama_8B_C` documents the Pluralis-8B values (0.05, every 20, β^k off, plain gradient averager) as an opt-in. `laptop_demo_async` turns it on for the verification demo | same code. Not ported: Agora's ghost-mode join (phases 1/2) and load-state block window; joining keeps Node0's logic. Replicas legitimately diverge between rounds (honest pairs at rel_err ≈ 0.9), so these runs verify by self-replay and route-loss anomaly instead of duplicate-forward (§6). Deviation: off in `llama_8B_C` until those thresholds are calibrated on GPUs, because the run pays rewards |
| Async pipeline optimization with Nesterov correction (ICML 2025, AsyncPP) | `laptop_demo`: `torch.optim.NAdam(betas=(0.99, 0.999), decoupled_weight_decay=True)`, the paper's own instantiation; `llama_8B_C` keeps Node0's AdamW | deviation for the demo tier: both Node0 (AdamW) and Agora's Pluralis-8B (AdamW β=(0.9, 0.95) + AsyncSPARTA) ship AdamW; the Nesterov optimizer is Pluralis's research result for the asynchronous-pipeline staleness that our trainer exhibits, and it is one yaml line to switch back. AsyncPP's main recipe is unmodified torch NAdam (lr 3e-4, β=(0.99, 0.999), decoupled wd 0.01) with PipeDream weight stashing. Node0's `ModuleCollab.backward` recomputes with current weights, i.e. the paper's *no-stash* regime (§3.2, SWARM experiment), whose optional per-stage β1 and learning-rate discount are in `node0.eacc.optim` but not enabled by default |
| Trainer routing (Agora §3.4): per-stage min-heap keyed by virtual runtime charged as task size ÷ measured throughput; new workers enter level with the most-loaded; backward follows the forward path; failed workers temporarily banned; DHT re-scan ≈30 s | same policy | same (clean-room) |
| Auth server `auth.pluralis.ai/api/join`: HF token, RSA peer key, integrity hash, port test → signed expiring credential + stage assignment | coordinator `/api/auth/challenge` + `/api/auth/verify`: ed25519 challenge by the staked node's hot key + on-chain stake check → same signed expiring hivemind credential + stage assignment | deviation: stake replaces the HF login; integrity check is a gap (below) |
| Integrity check: `verify_integrity(private_key)` from a closed, Linux-only `integrity_check.cpython-311-x86_64-linux-gnu.so` (Node0 `src/node0/security/`, Agora `agora/src/agora/security/`); its hash goes into the join request (`integrity_hash`, Agora `authorizer.py:93`) and is checked server-side | not ported; `authorization.py` imports the binary only if present and the coordinator does not ask for a hash | gap: no public algorithm (client or server), so nothing to port faithfully. An open hash of our own sources would add no assurance, because a modified client can report any hash |
| Seeds (4 Pluralis DHT peers) publishing signed `{stage}_paramstore` run parameters | `node0.eacc.seed`: operator DHT peer that publishes the same signed paramstore | same role, run locally |
| Trainers (Pluralis-hosted, not in the Node0 repo; Agora §3) routing each microbatch through one worker per stage, one batch in flight per trainer | `node0.eacc.trainer`: clean-room from the Agora report, using hivemind `RemoteExpert` | reimplementation (no public code) |
| Monitor / dashboard.pluralis.ai: signed `WorkerMetricsV1 {num_flop, active_time}` | worker metrics also POSTed to the coordinator; dashboard reads `/api/*` | same metrics, different sink |
| Contribution ledger (FLOPs per participant, power-law) | points = trainer-attested GFLOPs per epoch; on-chain `lifetime_points` = cumulative points (informational; no ownership or revenue rights) | extension: credited only when attested by a trainer and not failed a spot-check |
| Verification: integrity check now; Sentinel (EMA/IQR monitoring of inter-stage signals) published 2026 | duplicate-dispatch spot-checks + Sentinel-style EMA/IQR tie-break | extension; see §6 |
| Unextractable Protocol Models (arXiv 2605.23464): time-varying invertible transforms folded into the weights at stage boundaries, sent from stage i to i+1, then discarded | partial: `node0.eacc.upm` has the Haar and scaled-SVD transforms (§3.2, Eqs. 65–66, fp64), the boundary fold (§3.1) and the momentum rule (§3.3, App. F); tested for function preservation, invertibility, time variation and gradient equivariance. Not wired, no flag | gap: no public code. The paper gives no rule for replicas of a stage to agree on T and none for Adam's second moment (App. F.1; Node0 and Pluralis-8B use AdamW). It is also silent on Protocol Models' shared subspace, which a rotated residual stream leaves. It was shown only for a single NanoGPT pipeline with Muon |3. Roles and processes
| Role | Process | Who runs it | Key | |---|---|---|---| | worker | `python -m node0.run_server` (Node0's entry point, auth swapped) | any staker | `NODE_KEYPAIR` (hot key registered in `NodeAccount.node_key`) + a libp2p RSA identity (`private.key`, as in Node0) | | trainer | `python -m node0.eacc.trainer` | operator | operator credential via `X-Admin-Token` | | seed | `python -m node0.eacc.seed` | operator | operator credential via `X-Admin-Token` | | coordinator | `python -m coordinator` (FastAPI, port 8787) | operator | `COORDINATOR_KEYPAIR` is used only by settlement; the coordinator's RSA authority key lives at `coordinator/data/authority.pem` (generated, gitignored) |
Workers never talk to each other's raw sockets except through hivemind/libp2p (DHT, averaging, expert RPC). The coordinator is never on the activation path: it only admits peers, receives reports, and scores epochs.
4. Node join handshake (worker)
Mirrors node0.security.authorization.PluralisAuthorizer._join_experiment, with the HF bearer replaced by a signature:
- ›Node loads
NODE_KEYPAIR(Solana JSON) andNODE_OWNER(the owner wallet's public key; the owner's secret key never touches the GPU machine). It loads or creates its libp2p RSA identity (private.key). - ›
POST /api/auth/challenge {owner, node_key}→{nonce, expires_at}(nonce: 32 random bytes, hex; TTL 120 s; single use). - ›
POST /api/auth/verifywith the §7 fields plus these additive ones:peer_id(libp2p PeerID, base58),peer_public_key(RSAPublicKey.to_bytes().decode()),role("worker"),device,gpu_memory_gb,ram_gb,run_config(name, e.g.laptop_demo). - ›Coordinator checks: nonce valid and unused; ed25519 signature over
"eacc-swarm-auth:" + nonce; reads Config["config"]and NodeAccount["node", owner]over RPC (STAKE_CHECK=rpc;mockfor offline tests), decodes by INTERFACES.md §4 offsets, requiresnode.node_key == node_keyand the §4 eligibility rule; capability check against the run's hardware tier (§9); apeer_idmay be bound to one owner only (Node0: "This peer_id is already used by another user"). - ›Success → the §7 fields
{access_token, expires_at, stage}plus additive: - ›
stage_type: Node0 stage string,head-0,body-<i>,tail-<n-1> - ›
peer_token:{username, public_key, expiration_time, signature}, a hivemindAccessTokenwhereusername = owner,public_key = peer_public_key,expiration_time= ISO-8601 aware datetime andsignature = authority.sign(peer_token_bytes(...))(hivemindRSAPrivateKey.sign, base64 text).peer_token_bytesisnode0.eacc.protocol.peer_token_bytes; it reproduces Node0's_token_to_bytes. - ›
auth_server_public_key: the coordinator authority'sRSAPublicKey.to_bytes().decode() - ›
run:{run_id, run_config, experiment_prefix, initial_peers: [multiaddr], num_stages} - ›The node builds hivemind's
AccessToken, passes the authorizer toDHT(...), and every libp2p request is then authenticated peer-to-peer exactly as in Node0/Agora (the coordinator is off the data path). Tokens last 10 min (PEER_TOKEN_TTL); hivemind callsget_token()to refresh, which re-runs steps 2–5, so un-staking or jailing revokes access at the next refresh (Agora: revocation by non-renewal).
Stage assignment: the least-provisioned stage among online workers (ties → lowest index), as Agora's Authorizer does. A returning (owner, peer_id) keeps its previous stage.
Operators (trainer, seed) use POST /api/auth/operator with X-Admin-Token and {peer_id, peer_public_key, role} and get the same peer_token / auth_server_public_key / run / access_token fields.
5. Points (the unit of verified work)
Pluralis's Agora leaderboard (docs) scores compute PFLOPs processed + 1 PFLOP of "presence" per hour a peer is active, summed over up to 5 peers per Hugging Face account, from node self-reports to its metrics server, with no financial reward attached. We keep both terms and the FLOP unit, but make compute *attested* (it now carries money):
flops(microbatch on worker w at stage s) = tokens × (flop_per_token_fwd(s) + flop_per_token_bwd(s)) # node0.utils.flops
compute_w = Σ trainer-attested flops / 1e9 # GFLOPs
presence_w = presence_points_per_hour × hours w was online (heartbeat gaps > 90 s not counted)
and had ≥ 1 attested microbatch in the same 10-minute window
points_w(epoch) = floor(compute_w + presence_w) if w passed every spot-check in the epoch, else 01 point = 1 GFLOP = 10⁻⁶ Pluralis PFLOP. presence_points_per_hour is 1 000 000 (1 PFLOP, Pluralis's value) for llama_8B_C and 500 for laptop_demo, about the same ≈0.5 % of a typical node's hourly compute in each tier. Presence requires attested work in the same window, so an idle staked node earns nothing. One peer per owner, because NodeAccount binds a single node_key (Pluralis allows 5 per account).
- ›Only trainer receipts count. A worker's self-reported metrics (
/api/report/worker, the Node0WorkerMetricsV1analogue) are shown on the dashboard but never credited, so inflating them earns nothing. - ›A microbatch counts once its backward pass through that worker has returned; duplicate spot-check forwards are verification overhead and are not credited.
- ›Points accrue to the stake owner (
NodeAccount.owner), one node per owner. - ›At epoch close, owners that are ineligible on-chain (§4 rule) are dropped (settlement re-checks).
- ›
claimadds the epoch's points toNodeAccount.lifetime_points, a cumulative record of contribution. Points are a ledger for fee payouts: each epoch's points decide that epoch's share of the $ESC trading fees in the reward vault. They give no ownership of the model and no revenue rights (TOKENOMICS §7).
Rewards are contribution-weighted: stake gates entry, prices sybils, and is the slashing collateral, but it does not multiply rewards (a whale with one GPU earns the same as a minnow with one GPU). Rationale: Protocol Learning credits compute contributed; stake-weighting would reward capital, not training.
6. Verification: spot-checks
Pluralis's public Node0 run relied on code-integrity checks; their 2026 Sentinel paper monitors inter-stage activations/gradients statistically. We combine redundancy (Gensyn-style refereed comparison, Psyche-style duplicated work) with a Sentinel-style statistical tie-break:
- ›With probability
SPOT_CHECK_RATE(demo 0.05–0.10), the trainer sends a microbatch's stage input to a second, different worker of the same stage (forward only) and compares the two outputs:rel_err = ‖a − b‖ / max(‖a‖, ‖b‖); pass ifrel_err ≤ SPOT_CHECK_TOL(default 0.05). Same-stage replicas apply the same averaged update every collaborative epoch, so honest outputs differ only by float nondeterminism and bounded staleness (max_allowed_stale). - ›On a mismatch, each output is scored against the trainer's per-stage running statistics (EMA of the per-token RMS norm and mean). The output outside the IQR fence (
Q1 − k·IQR, Q3 + k·IQR, k = 3, over the last 200 observations) fails; the other passes. With a third replica online, a majority vote decides instead. If inconclusive, nothing is credited for that microbatch and the check is logged asinconclusive. - ›A failure is reported in
/api/report/trainerspot_checks[]and opens a case for the owner (POLICY.md §4.1). One verdict never slashes: - ›First failure. The peer is banned from routing. The node is jailed at the coordinator, scores 0 for the epoch and stops getting its peer token renewed. A re-check by a different trainer is scheduled.
- ›Unconfirmed. A case not confirmed within
RECHECK_SECONDS(6 h) becomesunconfirmedand loses no stake. The node stays jailed until an admin unjails it. - ›Confirmed. Only an unambiguous failure from a different trainer confirms (POLICY.md §4.3), and only a confirmed case becomes a slash proposal (
GET /api/slash-proposals).
Severity (POLICY.md §4.4), as a share of the node's stake (staked + pending unstake):
- ›Fault, reason 4: 25%. Every confirmed case, unless all the fraud conditions hold.
- ›Fraud, reason 5: 100%. Only for a confirmed repeat by the same owner within 30 days (
FRAUD_REPEAT_DAYS), with independent, direct evidence. On-chain it goes above 25% only if the admin multisig approves it (slash-approve) during the 48 h slash delay; otherwise it executes at the 25% fault cap.
The coordinator runs SLASH_CMD (e.g. swarmctl slash --owner {owner} --amount {amount} --reason {reason}), appending --live only when SLASH_LIVE=1, and then follows the on-chain lifecycle: pending, approved, executed, cancelled (POLICY.md §4.5–4.7). Scheduling the slash also jails the node on-chain. Reason codes 1–3 (spot-check mismatch, statistical outlier, manual) remain valid on-chain for manual slashes with an explicit amount.
- ›The demo node has
--cheat {noise,zero,scale}to show this path end to end. - ›AsyncSPARTA. Duplicate-forward checks assume replicas of a stage hold (nearly) the same weights. Under
async_spartathey don't: each replica takes local steps and only 5% of entries are averaged per round. Onlaptop_demo, honest pairs reached rel_err ≈ 0.9 and one was falsely failed. Those runs use two other checks instead (node0.eacc.verify): - ›Self-replay (catches noise and random outputs). With probability
--replay_rate(0.1; every call for a late joiner on probation) a stage call is recorded and its input re-sent to the same worker 1–4 microbatches later. Measured onlaptop_demo_async(CPU/MPS), honest replays at unchanged weights reproduce exactly: 0.0000 in about 95% of cases, at most 0.0194 (small sparse-averaging slices). Across a weight update they drift 0.14–1.04, which overlaps noise (≈ 0.96), so no single tolerance separates the two. The rule is therefore: pass if rel_err ≤REPLAY_TOL= 0.02; otherwise re-send twice, back to back. A worker whose weights moved reproduces its own new output (inconclusive, not evidence). Fail only if three sends in a row disagree. - ›Route-loss anomaly (catches consistent cheaters: zeros, scaled or substitute outputs).
- ›Model: over the last 160 microbatches,
loss ≈ time bucket + Σ_stage effect[worker], fitted by median polish, so a cheater isn't blamed on the honest workers it shared routes with. - ›Flag: a worker whose effect differs from its stage median by ≥ max(0.5 nats, 0.15 × median loss) at robust |z| ≥ 6.
- ›Upstream of the tail, only a higher loss counts. A tie between two workers is resolved in favour of the trusted one.
- ›Probation ends only after 3 passing replays and one clean evaluation, since replay alone would clear a deterministic cheater.
- ›Margin: honest tail replicas differ consistently by up to 0.235 nats from the stage median (z 4.5), so the effect floor is about 2× that.
- ›Confirmation probes. After any first failure (including duplicate-forward), the trainer bans the suspect from routing but probes it: on the next 6 microbatches its output on the training input is passed through the same downstream workers, and the losses are compared pairwise. A failure needs a median diff ≥ max(0.5, 0.15 × loss) with 5 of 6 in the same direction (honest replicas measured up to +0.37 nats). Each probe is also recorded for a replay.
- ›Results on `laptop_demo_async`. No honest worker failed in three runs (≈ 2,400 replays, ≈ 1,000 route-loss evaluations). A late
--cheat noisetail was failed by both trainers (rel_err 0.95–0.97) and confirmed by a second replay over a disjoint window. A late--cheat zerotail was flagged 6 s after joining (effect −0.92/−0.96 nats, z ≈ −70) and confirmed by paired probes (−1.93 nats). - ›Not covered. A cheater that caches outputs by input hash defeats replay; one that detects forward-only calls can answer probes honestly; a substitute model within 0.5 nats of honest replicas isn't flagged. The thresholds are calibrated at laptop scale on CPU/MPS only.
llama_8B_Ctherefore ships withasync_sparta: False(Node0's synchronous averaging and duplicate-forward checks) until a GPU calibration run confirms bf16 replay reproducibility and honest loss gaps. A trainer refusesasync_spartawith--replay_rate 0. - ›Verdict fields. Every
spot_checks[]entry carries: - ›
method:duplicate_forward,self_replayorloss_anomaly; - ›
score(rel_err or nats) andthreshold; - ›
confirmed: true when this trainer holds two independent failures (different methods, or the same method over disjoint tick windows); - ›
evidence: the confirming pair, each with{method, score, threshold, window, verdict}.
rel_err stays for duplicate-forward and replay entries, and is null for loss anomalies. Replay drift across an update is reported as inconclusive. The coordinator jails on a first failure and proposes a slash only for a confirmed case, which needs a failure from a different trainer (step 3). The trainer's confirmed/evidence are kept as supporting evidence; on their own they are still one trainer's verdict.
7. Epochs
Epoch ids start at 1 and equal on-chain ids. The current epoch opens when the coordinator starts (or the previous one closes) and closes at EPOCH_SECONDS (demo: 300; prod: 86 400) or on POST /api/epochs/close. Closed epochs are immutable and served at /api/epochs/{id}/scores (settlement input). Coordinator state persists in coordinator/data/state.json so a restart does not lose points.
8. Train-internal coordinator API (additive to INTERFACES.md §7)
Auth: Authorization: Bearer <access_token> (from verify / operator auth). Quantities as in §7: u64 → decimal strings.
- ›
POST /api/auth/operator(headerX-Admin-Token){peer_id, peer_public_key, role: "trainer"|"seed"}→ as §4 step 5. - ›
POST /api/run/seed(operator bearer, role seed){maddrs: [multiaddr]}→ stores the DHT bootstrap addresses returned inrun.initial_peers. - ›
POST /api/report/worker(worker bearer) — Node0WorkerMetricsV1analogue, every ≤ 30 s, also the heartbeat:{peer_id, stage, local_epoch, samples, tokens, flops, active_time, device}(cumulative counters, numbers). - ›
POST /api/report/trainer(trainer bearer), every ≤ 10 s:{step, loss, tokens, ts, work: [{peer_id, stage, microbatches, tokens, flops}], spot_checks: [{stage, peers: [a, b], rel_err, verdict: {<peer_id>: "pass"|"fail"|"inconclusive"}, reason}]}workandspot_checksare deltas since the previous report;lossis the mean token loss of the microbatches since the previous report;stepis the trainer's global microbatch counter. - ›
GET /api/run→{run_id, run_config, experiment_prefix, initial_peers, num_stages, model}(no auth). - ›
GET /api/slash-proposals→[{ts, owner, peer_id, epoch_id, reason, amount, cmd, status, …}]; the v2 lifecycle statuses and fields are in POLICY.md §4.5.
9. Run configs and hardware tiers
| Config | Model | Stages | Min hardware (Node0 tiers) | Use | |---|---|---|---|---| | `llama_8B_C` (Node0 original) | LLaMA d=4096, 32 heads / 8 KV, 1 block per stage, compression 100× | 32 | NVIDIA 16 GB VRAM, 32 GB RAM, 80 GB disk, Linux/WSL2 | real run | | `llama_1B_C` | d=2048, 2 blocks per stage | 8 | NVIDIA 8 GB VRAM, 16 GB RAM | small GPUs | | `laptop_demo` | d=256, 8 heads / 4 KV, 2 blocks per stage, byte vocab, seq 128, compression 16× | 2 | Apple Silicon (MPS) or CPU, 8 GB RAM | local demo / CI |
The coordinator enforces the tier at auth (Agora's capability check); laptop_demo admits CPU/MPS.
10. Deviations from Pluralis, and why
- ›Stake instead of Hugging Face login: the token gates entry and prices sybils; HF accounts are free.
- ›No integrity binary: Node0 ships a closed, Linux-only
integrity_check.so; we rely on spot-checks and statistical monitoring instead (stake makes cheating costly). - ›Operator-run trainer and seed: as in Node0's public run (Pluralis hosted both); decentralizing them is roadmap.
- ›Deterministic subspace components: Pluralis distributes
rcvand the fixed embedding from its CDN; we derive both from(run_seed, d, k, vocab)so every stage reconstructs the same subspace offline. - ›No unextractability transforms yet: per-stage weights are still held only by that stage's replicas, and the coordinator holds no weights. UPM's transform math is ported, but rotating it during training is roadmap: the paper does not cover replicas, AdamW, or the shared subspace (§2).
- ›Inherited upstream gaps (pre-mainnet): only DHT RPCs check peer tokens; expert forward/backward RPCs are unauthenticated, so spot-checks are the only defense on the compute path. Any authorized peer can overwrite the parameter store during averaging. An honest late joiner whose state download fails looks like an outlier, and upstream's "catching up" bumps the epoch without loading state.