Chain-anchored routing resolution
When relay needs to deliver to a did:solidus, it does not take your word for where that DID lives.
It resolves the DID against the Solidus chain and reads the DIDComm service entry out of the
on-chain document.
Scope, stated first, because the phrase invites over-reading: this is about resolving your
correspondents' DIDs. The mediator's own identity is a did:key and is not chain-anchored, see
did:key vs did:solidus for a mediator.
Why resolve on-chain at all
A routing key and endpoint tell a mediator where to send. If that pointer comes from whoever is asking, the mediator has no way to tell a legitimate update from a redirection. Resolving the DID from an anchored source means the answer comes from where the DID's controller published it, not from the requester.
The mechanism: an RPC call to solidus_didResolve, then extraction of the DIDCommMessaging service
entry, its uri, accept, and routingKeys.
The three outcomes, and why the third one is the honest part
A resolution can go three ways, and relay reports which one happened rather than flattening them:
source |
What it means |
|---|---|
on-chain |
Resolved live from the chain just now. |
cache |
The chain call failed or timed out, so the last cached value was served, carrying its original block height and resolution timestamp, not a fresh-looking one. |
failed |
The chain call failed and there was no cache. A genuine resolution failure. |
The cache row is the one worth pausing on. A cached answer is still an answer, and serving it is
usually right, but re-stamping it with the current time would tell an operator the routing was
confirmed just now when it was not. Relay preserves the original block and timestamp instead. Stale
data labelled stale is useful; stale data labelled fresh is a lie with a clean UI.
failed is a real state, not an empty result. It surfaces to the operator and fires a
resolution.failed webhook rather than silently degrading. See
webhooks and delivery logs.
Two design choices worth knowing about
A malformed service entry is treated as "no service found", never half-trusted. If the on-chain
document has a DIDCommMessaging entry that does not validate, relay does not salvage the parts it
recognises. A partially-understood routing instruction is exactly the kind of thing that delivers
somewhere unintended.
Block height is decorative and never blocking. Relay reads the current block for the operator view, but if that read fails the resolution still succeeds with a null block. A cosmetic number is not allowed to fail a delivery.
There is a bounded timeout on the chain call and a bounded cache lifetime; both exist so a slow chain
degrades into cache rather than into a hung request.
What this is not
- Not the mediator's own identity. Repeated because it is the likeliest misreading: relay
identifies itself with a
did:key. - Not an integrity proof of message contents. It anchors where to route, nothing about what is in the envelope.
- Not a privacy feature. Resolution says nothing about what relay observes while routing: that is what a mediator can and cannot see.
- Not audited. Nothing here has been externally reviewed.
Seeing it
Resolutions are exposed on the operator plane at /v1/resolutions, which is authenticated:
curl -s -o /dev/null -w '%{http_code}\n' https://relay.solidus.network/v1/mediations
# 401
Sign in at relay.solidus.network for a key. The console renders sample data and says so,
do not read the figures on it as real metrics.
Relay implements Coordinate Mediation 2.0 and Pickup 3.0; no independent DIDComm conformance suite has been run, so "implements" is the claim and "conformant" is not.