4. Evidence Graph Data Model

4.1 Graph Structure

The Evidence Graph is a directed, typed, temporally-anchored multigraph.

{
  "graphId":      "string         // Unique identifier",
  "claimRef":     "string         // ClaimId this graph was constructed for",
  "nodes":        "Node[]",
  "edges":        "Edge[]",
  "metadata": {
    "constructionTime": "string   // ISO 8601 (informational, not used in deterministic replay)",
    "nodeCount":        "number",
    "edgeCount":        "number",
    "expansionOps":     "number   // Total BFS expansion operations performed",
    "maxDepth":         "number   // Actual expansion depth reached",
    "scopeExhausted":   "boolean  // True if any deterministic scope limit was hit",
    "scopeConstraint":  "string | null  // Which constraint was hit: maxNodes | maxEdges | maxHops | maxExpansionOps"
  }
}

4.2 Node Types

NodeType = ACCOUNT | TOKEN | POOL | CONTRACT | TX
{
  "nodeId":       "string         // Canonical address or hash",
  "type":         "NodeType",
  "chain":        "ChainType",
  "properties": {
    "balance":    "u64 | null",
    "isContract": "boolean | null",
    "createdAt":  "number | null  // Block/slot of first appearance",
    "label":      "string | null  // 'CEX_HOT_WALLET' | 'DEX_ROUTER' | 'UNKNOWN'"
  },
  "evidence":     "string[]       // EvidenceUnit IDs supporting this node"
}

4.3 Edge Types

EdgeType = TRANSFER | FUNDING | DEPLOYMENT | SWAP | LP_ACTION | TEMPORAL_PROXIMITY
{
  "edgeId":       "string",
  "type":         "EdgeType",
  "source":       "string         // Source nodeId",
  "target":       "string         // Target nodeId",
  "properties": {
    "amount":     "u64 | null     // Transfer/swap amount",
    "block":      "number         // Block/slot of this interaction",
    "time":       "string         // ISO 8601",
    "txHash":     "string | null"
  },
  "evidence":     "string[]       // EvidenceUnit IDs supporting this edge"
}

4.4 Construction Algorithm

Graph construction is initiated for each claim evaluation and proceeds as follows:

Phase 1: Seed Resolution

  • Resolve the claim subject to one or more seed nodes
  • For TOKEN subjects: seed = the token mint account
  • For POOL subjects: seed = the pool address
  • For ACCOUNT subjects: seed = the wallet address

Phase 2: Expansion

  • Starting from seed nodes, expand outward following edges defined by the predicate's required evidence types
  • Respect scope constraints: maxHops, maxNodes, maxEdges, temporalLookback
  • At each hop, retrieve evidence for all discovered nodes within the context window

Phase 3: Annotation

  • Attach retrieved evidence units to nodes and edges
  • Label known entities (CEX wallets, DEX routers, bridge contracts) from the Entity Registry
  • Compute derived properties (funding paths, timing correlations)

Phase 4: Pruning

  • Remove nodes and edges outside the context window
  • Remove nodes unreachable from the seed within scope constraints
  • Record whether scope limits were exhausted (metadata.scopeExhausted)

Deterministic Complexity Bounds:

Parameter Default Description
Maximum nodes scope.maxNodes (10,000) Hard cap on graph node count
Maximum edges scope.maxEdges (50,000) Hard cap on graph edge count
Maximum depth scope.maxHops (5) Max BFS expansion depth
Maximum expansion ops scope.maxExpansionOps (20,000) Total node-expansion operations (each BFS dequeue counts as 1)

All complexity bounds are deterministic — they depend only on the graph structure being traversed, not on wall-clock time or hardware performance. This is critical for reproducible replay: a validator replaying graph construction from the same evidence MUST produce a byte-identical graph regardless of hardware speed.

Why no wall-clock timeout: Wall-clock timeouts and deterministic replay are fundamentally in tension. If an engine operator hits a timeout at 29.8 seconds and includes a node, but a validator's replay takes 30.1 seconds on different hardware and prunes that node, graph hashes diverge and replay fails. Therefore, construction bounds MUST be expressed solely in terms of graph-structural limits.

Operational Timeout (Non-Deterministic, Failure Only):

Implementations MAY enforce a wall-clock timeout (recommended: 30 seconds) as an operational safeguard. However, if the timeout is hit:

  1. Construction MUST be aborted entirely — no partial graph is produced
  2. The VO enters CONSTRUCTION_FAILED status, not QUALIFIED or UNQUALIFIED
  3. The failed construction is not submitted for attestation or replay
  4. The operator MAY retry with tighter scope parameters (lower maxNodes, maxHops, etc.)

This ensures wall-clock timeouts never influence the deterministic output. Either construction completes within all deterministic bounds (producing a replayable graph), or it fails and produces nothing.

4.5 Scope Enforcement

Scope is enforced strictly and deterministically. If construction would exceed any scope limit:

  1. Stop expansion at the boundary (do not process the operation that would exceed the limit)
  2. Set metadata.scopeExhausted = true
  3. Record which scope constraint was hit (one of: maxNodes, maxEdges, maxHops, maxExpansionOps)
  4. The engine MAY adjust qualification accordingly (Section 6.2)

BFS ordering determinism: Expansion follows canonical BFS order. At each depth level, nodes are expanded in lexicographic order of their nodeId (UTF-8 byte order, matching BCE field sorting from Appendix B). This ensures that when maxNodes or maxExpansionOps is reached mid-level, the same nodes are included regardless of implementation.

results matching ""

    No results matching ""