The Ontological Error in DePIN Supply Reporting

Decentralized Physical Infrastructure Networks (DePINs) have inherited a dangerous reporting convention from Web3: equate registration with deployment. Dashboard after dashboard, explorer after explorer, the headline metric is total registered nodes, total registered GPUs, total staked capacity. This is an ontological category error. Registration is a declaration of intent; deployment is a proof of work. The two are separated by an entire operational stack—provisioning, heartbeat verification, network NAT traversal, uptime maintenance, and demand-side matching.

At Kairos Signal, we instrument both sides of this gap. What we observe across every major DePIN network is a persistent and often widening delta between registered and active supply. This post provides a rigorous analysis of that delta, using io.net as a primary case study, and proposes a formal framework for cross-network utilization comparison that the ecosystem currently lacks.

---

Formal Definitions: The Supply Stack

Before analyzing data, we need precise definitions. DePIN supply is not monolithic—it exists in stratified states, each with distinct verification requirements and economic semantics.

┌─────────────────────────────────────────────────────┐
│                  SUPPLY STATE STACK                  │
├─────────────────────────────────────────────────────┤
│                                                     │
│  S_registered  ── On-chain identity + stake/commit  │
│       │                                             │
│       ▼                                             │
│  S_provisioned ── Hardware attestation passed       │
│       │           (TEE, PoH, device fingerprint)     │
│       ▼                                             │
│  S_heartbeat   ── Active network heartbeat within   │
│       │            telemetry window τ               │
│       ▼                                             │
│  S_matched     ── Matched to a demand order/lease   │
│       │                                             │
│       ▼                                             │
│  S_executing   ── Currently fulfilling workload     │
│                                                     │
└─────────────────────────────────────────────────────┘

Formally, for a given telemetry window $\tau$ (typically 1h, 24h, or 7d):

$$S_{registered}(\tau) = \{n_i \mid \text{Identity}(n_i) \in \text{Registry}(\tau)\}$$

$$S_{active}(\tau) = \{n_i \mid \text{Heartbeat}(n_i, \tau) = \text{True} \land \text{Attestation}(n_i) = \text{Valid}\}$$

$$S_{utilized}(\tau) = \{n_i \mid n_i \in S_{active}(\tau) \land \text{Lease}(n_i, \tau) \neq \emptyset\}$$

The utilization ratio at each layer transition is:

$$U_{reg \to active}(\tau) = \frac{|S_{active}(\tau)|}{|S_{registered}(\tau)|}$$

$$U_{active \to utilized}(\tau) = \frac{|S_{utilized}(\tau)|}{|S_{active}(\tau)|}$$

$$U_{e2e}(\tau) = U_{reg \to active} \times U_{active \to utilized} = \frac{|S_{utilized}(\tau)|}{|S_{registered}(\tau)|}$$

The end-to-end utilization ratio $U_{e2e}$ is the only metric that captures actual economic throughput relative to declared supply. Yet it is almost never reported.

---

Case Study: io.net's Registered vs. Active Divergence

Between October 28 and November 4, 2024, io.net's public dashboard reported the following aggregate supply figures:

| Metric | Oct 28 | Nov 4 | Δ | |---|---|---|---| | Registered GPUs | ~18,400 | ~23,200 | +26.1% | | Active GPUs (24h heartbeat) | ~4,100 | ~4,250 | +3.7% | | $U_{reg \to active}$ | 22.3% | 18.3% | −400 bps |

Registered capacity surged by nearly 4,800 GPUs in a single week. Active capacity budged by 150. The utilization ratio fell by 400 basis points despite—indeed, because of—the supply-side growth.

What's Happening to the Ghost Supply?

The 22,950 GPUs in the registered-but-inactive pool are not a monolith. Our telemetry decomposition reveals at least four distinct failure modes:

1. Provisioning Failure (~38%) The node registered on-chain, passed initial identity verification, but never completed hardware attestation. Common causes: misconfigured TEE enclaves on consumer GPUs, outdated driver versions incompatible with the io.net worker runtime, or simply abandoned setup processes. 2. NAT/Firewall Impenetrability (~27%) The node passed attestation locally but cannot maintain a stable WebSocket connection to the coordinator. Home NAT configurations, carrier-grade NAT (CGNAT) on mobile GPUs, and asymmetric routing break the heartbeat channel. 3. Intermittent Churn (~22%) The node appears in some heartbeat windows but not others. These are typically consumer machines that power down, enter sleep, or experience thermal throttling. Their $P(\text{heartbeat} \mid \tau)$ is probabilistic, not deterministic. 4. Economic Idle (~13%) The node is fully operational but has no matched lease. In io.net's case, this is partially obscured because the network does not publish a clean $S_{matched}$ count—only $S_{active}$ and a separate "jobs completed" counter.
# Ghost supply decomposition model
def decompose_ghost_supply(registered: int, active: int, 
                           heartbeat_traces: pd.DataFrame) -> dict:
    """
    Classify registered-but-inactive nodes into failure modes
    using heartbeat trace analysis over window tau.
    """
    ghost_ids = set(registered_ids) - set(active_ids)
    
    never_attested = {n for n in ghost_ids 
                      if attestation_log[attestation_log['node'] == n].empty}
    
    no_heartbeat = {n for n in ghost_ids - never_attested 
                    if heartbeat_traces[heartbeat_traces['node'] == n].empty}
    
    intermittent = {n for n in ghost_ids - never_attested - no_heartbeat
                    if heartbeat_traces[heartbeat_traces['node'] == n
                    ]['uptime_ratio'].max() < 0.8}
    
    economic_idle = ghost_ids - never_attested - no_heartbeat - intermittent
    
    return {
        'provisioning_failure': len(never_attested),
        'nat_firewall': len(no_heartbeat),
        'intermittent_churn': len(intermittent),
        'economic_idle': len(economic_idle),
        'total_ghost': len(ghost_ids)
    }

The critical insight: only 13% of the ghost supply represents economically idle but functional capacity. The remaining 87% represents structural friction—nodes that cannot participate even if demand existed. This distinction is essential for network valuation and demand modeling.

---

Cross-Network Comparison: The Metric Mapping Problem

If $U_{reg \to active}$ for io.net is 18.3%, what is it for Akash Network? For Render? For Filecoin? You cannot answer this question today, because no two networks define these states identically.

The Canonical Mapping Challenge

Consider the following comparison of state definitions across three GPU/compute DePINs:

| State | io.net | Akash | Render | |---|---|---|---| | Registered | On-chain identity + wallet connected | Provider attributes posted on-chain | Node registered in renderer registry | | Active | Heartbeat within 24h window | Provider has bid on an order in last 7d | Node responded to render poll in last 24h | | Utilized | Currently assigned to a job | Active lease exists | Currently rendering a frame |

The ontological mismatches are severe:

A Proposed Canonical Schema

To enable meaningful cross-network utilization analysis, we propose the following minimal canonical metric schema:

```yaml canonical_supply_metric: unit: "compute_unit" # e.g., GPU-hour, CPU-core-hour, TB-storage-hour states: registered: definition: "Identity exists in on-chain registry with valid stake/commit" verification: "On-chain query" required_fields: ["node_id", "register_timestamp", "stake_amount"] provisioned: definition: "Hardware attestation completed within last 7d" verification: "TEE/PoH attestation receipt" required_fields: ["attestation_hash", "hardware_spec", "attestation_timestamp"] heartbeat_active: definition: "At least 1 heartbeat received in telemetry window tau" verification: "Coordinator log with cryptographic heartbeat" required_fields: ["heartbeat_timestamp", "latency_ms", "connection_type"] parameters: tau: "1h | 24h | 7d" # MUST specify lease_matched: definition: "Compute unit has an active lease/order assignment" verification: "On-chain lease transaction" required_fields: ["lease_id", "demand_order_id", "lease_start", "lease_end"] workload_executing: definition: "Compute unit currently processing workload with proof" verification: "Execution proof (output hash, TEE receipt)" required_fields: ["execution_proof", "workload_id", "progress_pct"] utilization_ratios: - name: "registration_efficiency" numerator: "heartbeat_active" denominator: "registered" - name: "matching_efficiency" numerator: "lease_matched" denominator: "heartbeat_active" - name: "execution_efficiency" numerator