Goals
Non-Goals
+-------------------------+ +---------------------------+
| Issuers | | Relying Applications |
| (KYC, .edu, employer) | | ("score ≥ θ?" checks) |
+------------+------------+ +--------------+------------+
| |
v v
+------------+-------------------- P2P Fabric (libp2p) -----------------------+
| Topics: events/* revocations/* rules/* checkpoints/* blobs/* (CID fetch) |
+----+----------------+-------------------+------------------+------------------+
| | | |
v v v v
+----+----+ +-----+-----+ +-----+-----+ +----+-----+
| Wallet | | Full Node | | Log Node | | Scorer |
| Light | | Storage | | (Trillian)| | Node |
| Node | | + Proofs | | + Proofs | | (Determin.)|
+----+----+ +-----+-----+ +-----+-----+ +----+-----+
| | | |
+----------------+---------+---------+------------------+
|
v
+--------+--------+
| Checkpoint Comm |
| (BLS threshold)|
+-----------------+
did:key
(v1) for simplicity; add did:web
/did:ion
later.Vouch
: (from DID, to DID, ctx, epoch, weight_hint?, nonce)
Report
: (reporter, target, ctx, reason_code, evidenceCID?, nonce)
Appeal
: (appellant, case_id, new_evidenceCID?)
RevocationAnnounce
: (issuer, statuslistURI, epoch, bitmapCID)
{root, tree_id, epoch, signers[], threshold_sig}
produced every Δt (e.g., 10–30 min).Service | Responsibilities | Key libs |
---|---|---|
walletd |
DID/VC wallet; event signing; threshold proofs; proof retrieval | vc-go , jwx , Ed25519 |
p2p-gateway |
libp2p host; gossipsub; CID fetch; rate limits | go-libp2p , go-cid |
fullnode |
Blob store (RocksDB/FS); proof server; mirrors StatusLists/rules/checkpoints | gorocksdb , HTTP |
lognode |
Trillian personality: append event refs; inclusion/consistency proofs | google/trillian |
checkpointor |
Committee sampling (VRF/drand), BLS aggregation, checkpoint gossip | herumi bls-eth-go-binary |
scorer |
Deterministic score compute; diversity/decay; proof bundling | custom (pure Go) |
adjudicator |
Reviewer sampling, vote collection, verdicts → log | VRF client, BLS verify |
rules-registry |
Signed ruleset JSON hosting; versioning; time-lock | jwx |
issuer |
VC issuing; StatusList publishing; DID rotation | vc-go |
Deployment topologies
{
"type": "vouch|report|appeal|revocation_announce",
"from": "did:key:z6MksA...",
"to": "did:key:z6MkqB...", // omit for revocation_announce
"ctx": "general|commerce|hiring",
"epoch": "2025-09",
"payloadCID": "bafy... (optional)",
"nonce": "base64-12-bytes",
"issuedAt": "2025-09-12T19:12:45Z",
"sig": "ed25519(...)" // detached over canonical body
}
Canonicalization
{
"did": "did:key:z6MkqB...",
"ctx": "commerce",
"ruleset": {"id":"v1.3","hash":"sha256:...","validFrom":"2025-09-01"},
"checkpoint": {"root":"...","epoch":1024,"sig":"bls...","signers":["..."]},
"score": 73.40,
"factors": {
"K": "comm(PoP,KYC)", "A": "comm(.edu,employer)", "V": "comm(web_of_trust)",
"R": "comm(adjudications)", "T": "comm(time)"
},
"proofs": {
"inclusion": [{"cid":"...","path":["..."]}],
"consistency": [{"old":"...","new":"...","path":["..."]}],
"statuslists": [{"issuer":"did:web:kyc1","epoch":1024,"bitmapCID":"bafy..."}]
}
}
{
"id": "v1.3",
"weights": {"alpha":0.4,"beta":0.2,"gamma":0.25,"delta":0.1,"tau":0.05},
"caps": {"K":1.0,"A":0.8,"V":0.9,"R":0.9,"T":0.2},
"vouch": {
"budget_base": 2,
"budget_lambda": 1.2,
"agg": "sqrt",
"per_epoch": "monthly",
"bond": {"type":"reputation","decay_on_abuse":0.05}
},
"decay": {"half_life_days":{"V":120,"R":180,"T":90}},
"diversity": {"community_overlap_penalty":0.15,"min_clusters":3},
"adjudication": {"pool_size":9,"quorum":6,"appeal_window_days":14},
"signature": "jws(...)",
"validFrom": "2025-09-01T00:00:00Z",
"timeLockDays": 7
}
Wallet P2P FullNode LogNode Checkpointor Scorer
| | | | | |
1 | create evt | | | | |
2 | gossip --->|---> relay | | | |
3 | | | store blob | | |
4 | | | appendRef ---->| leaf+seq | |
5 | | |<-- receipt ----| | |
6 | | | |--- roots -----> | aggregate |
7 | | | |<-- checkpoint --- | broadcast |
8 | | | | |-- recompute |
9 |<---- score+proofs (from Scorer or FullNode on demand) ------ | publish |
Notes
Wallet -> gossip Report
Adjudicator: sample reviewers (VRF); collect signed votes; tally
Verdict -> log (Append); included in next checkpoint
Scorer applies: increase R(target); if malicious report: decrease reporter (slash bond/rep)
(ctx, θ, nonce)
S ≥ θ
(+ checkpoint ref), orFor user i in context c:
\[S_i^c = \alpha K_i^c + \beta A_i^c + \gamma \cdot \sqrt{\sum_{j \in \mathcal{V}_i^c} \min(S_j^c, cap) \cdot q_{ij}} - \delta R_i^c + \tau T_i^c\]Terms
K_i^c
(0..1): PoP/KYC credentials; weighted by issuer reputation w(issuer)
A_i^c
(0..1): other VCs (employment, .edu); clipped by caps and revocationV_i^c
: incoming vouches from set V_i
, aggregated concavely (sqrt); q_ij
adds:
R_i^c
: adjudicated reports (severity-weighted), decayed with half-life H_RT_i^c
: time component: bounded growth up to caps.T
, decays on inactivityVouch budget (per epoch)
b_i = b0 + λ * log(1 + S_i^c)
(non-transferable; non-rollover)V
contribution decays.Issuer reputation
w(issuer) ∈ [0.2, 1.0]
, initialized conservativelyParameterization
blob/<CID>
)PubSub: gossipsub v1.1 with:
mesh_n=8
, mesh_n_low=5
, mesh_n_high=12
Topics:
events/vouch
, events/report
, events/appeal
revocations/*
rules/active
checkpoints/epoch
RocksDB:
events:{cid} -> bytes
idx:by_to:{did}:{epoch} -> cid[]
idx:by_from:{did}:{epoch} -> cid[]
statuslist:{issuer}:{epoch} -> bitmapCID
checkpoint:{epoch} -> json
File store: large evidence blobs, mapped by CID
APIs:
QueueLeaves(Leaf)
→ seqNoGetInclusionProofByHash(hash, treeSize)
→ audit pathGetConsistencyProof(fromSize, toSize)
→ proof pathS ≥ θ_op
Protocol:
(tree_id, root, epoch)
with BLSS ≥ θ_rev
and diversity constraints (ASN/IP/country/graph partition balance)Incentives:
Outputs:
AdjudicationResult{case_id, target, reporter, outcome, severity, evidenceRefs[]}
→ appended to logS ≥ θ
without revealing factorsThreats & Mitigations
POST /v1/events
→ {cid, receipt}
Body: Event (signed)GET /v1/scores?did=&ctx=
→ Score Record + proofsPOST /v1/threshold-proof
→ {proof, checkpoint}
Body: {ctx, threshold, nonce}
GET /v1/blobs/{cid}
→ raw bytesGET /v1/proofs/inclusion?cid=&epoch=
→ inclusion proofGET /v1/proofs/consistency?from=&to=
→ consistency proofGET /v1/status/{issuer}/{epoch}
→ bitmap & mirror receiptGET /v1/rules/active
→ signed ruleset JSONGET /v1/rules/{id}
POST /v1/log/append
→ {seqNo, leafHash}
GET /v1/log/inclusion?hash=&size=
GET /v1/log/consistency?from=&to=
Auth: requests are either public (proofs) or signed (event submission). Rate limits by peer ID + DID.
Events:
b_i
per epoch enforced by wallet; network also limits ≤ 5/day if abuse detectedSLOs
AppendRef
latency < 800 ms (regional)InclusionProof
< 300 ms from nearest full nodeTelemetry
Assumptions:
Throughput
Phase 0 (Local Net)
Phase 1 (Pilot)
Phase 2 (Open Beta)
Phase 3 (Prod)
S ≥ θ
with max-staleness policyPeriodic scorer job:
Detections:
q_ij
weights, increase proof-of-work for implicated cluster’s reports, alert maintainers (no hard bans)/cmd
/walletd // CLI + gRPC/HTTP
/p2p-gateway // libp2p host
/fullnode // blob + proofs
/lognode // trillian personality
/checkpointor // bls aggregation
/scorer // score calculator
/adjudicator // reviewer pools
/rules-registry // signed rulesets
/internal
/didvc // vc-go adapters, sd-jwt
/events // schemas, canonicalization
/p2p // pubsub, dht, topics
/log // trillian client
/score // algorithms, decay, diversity
/proof // bundling; (zk circuits later)
/store // rocksdb, blob fs
/crypto // ed25519, bls, vrf
/api
/http // OpenAPI
/proto // gRPC defs
/deploy
/compose // local stack
/helm // k8s charts
/tests
/e2e // simulated networks
α=0.40, β=0.20, γ=0.25, δ=0.10, τ=0.05
K≤1.0, A≤0.8, V≤0.9, R≤0.9, T≤0.2
V=120d, R=180d, T=90d
b0=2/epoch, λ=1.2
; max vouch impact per sender per recipient per epoch: 0.05θ_rev=65
, pool 9, quorum 6, appeal window 14dK/A/V/R/T
(no diversity yet), simple decay