Relay Descriptor Core Object
Client–relay protocol · Core object index
RelayDescriptor
RelayDescriptor is a verifiable service identity declaration for a public relay, published through the client–relay interface and exchanged during the relay Noise handshake. It binds the on-chain relay_id, corresponding Neo public key, client endpoints, libp2p Peer ID, protocol capabilities, and validity period into one signed object. Clients use it to verify endpoint/relay-identity binding. Other relays directly verify the descriptor supplied in the handshake and use the current Registry record to confirm its binding to the connection's Peer ID. Relay network eligibility requires an active Registry record and a valid RelayDescriptor.
Peer ID is derived from the relay's libp2p Peer public key under libp2p rules and identifies its secure-connection identity. relay_id identifies its Neo account identity.
{
"$type": "meshline.relay.descriptor",
"relay_id": "0x1234567890abcdef1234567890abcdef12345678",
"public_key": "base64url...",
"endpoints": [
"https://relay.example.com/meshline/v1",
"wss://relay.example.com/meshline/v1",
"/dns4/relay.example.com/tcp/4201/p2p/12D3KooW..."
],
"capabilities": [
"channel.host.v1"
],
"expires_at": 1730086400,
"relay_signature": "base64url..."
}
| Field | Type | Required | Semantics and constraints |
|---|---|---|---|
$type |
string | Yes | Fixed as meshline.relay.descriptor |
relay_id |
string | Yes | Relay ID in the Registry record |
public_key |
string | Yes | 33-byte SEC1 compressed secp256r1 public key, unpadded base64url; MUST derive relay_id |
endpoints |
array<string> | Yes | Nonempty set of endpoint addresses; see Relay endpoint addresses |
capabilities |
array<string> | No | Published capability declarations; empty or omitted if none; at most 64 entries, each a nonempty string of at most 128 UTF-8 bytes; compare complete strings case-sensitively with no duplicates; order has no semantic meaning, and unknown names MUST be ignored |
expires_at |
integer | Yes | Expiry time; the descriptor is invalid once the current time reaches or exceeds it |
relay_signature |
string | Yes | 64-byte signature generated by the Neo N3 relay account corresponding to relay_id under Account signatures, unpadded base64url |
Signing excludes root relay_signature and constructs input under Network-bound JSON inputs.
Service Requirements and Capability Declarations
Public relays MUST fully provide relay discovery and identity authentication, the HTTPS base client API, device and profile state, account routes, DHT queries, inter-relay forwarding, message sending, bounded-retention account message timelines, and HTTP synchronization.
This specification defines these channel and group hosting capabilities:
| Capability identifier | Service and implementation requirements |
|---|---|
channel.host.v1 |
MUST be declared when offering channel hosting; requires all interfaces with HTTP forms in the Channel method index and verification of remote devices connecting directly to the channel relay under auth.device.verify; with a WSS endpoint, channel subscriptions and channel notifications are also required |
group.host.v1 |
MUST be declared when offering group hosting; requires all interfaces with HTTP forms in the Group method index and verification of remote devices connecting directly to the group relay under auth.device.verify; with a WSS endpoint, group subscriptions and group notifications are also required |
Relay Endpoint Addresses
Address Format and Validation
This protocol defines the following dialable address formats, each of which also determines its transport:
| Address format | Purpose |
|---|---|
https://... |
Base address for the public client HTTP API |
wss://... |
Complete client WebSocket connection address provided by a public relay |
libp2p multiaddr containing /tcp/ and /p2p/<peer-id> |
Inter-relay connections |
A public relay MUST provide at least one HTTPS address and one libp2p TCP multiaddr. A WSS address indicates complete support for the client WebSocket transport and notifications under WebSocket JSON-RPC; without one, that mechanism is unavailable.
Every HTTPS candidate MUST meet all format constraints of the Registry entry. WSS candidates use the wss scheme with the same remaining constraints. Both MUST be absolute URLs with valid hosts; even an empty query or fragment is forbidden. For HTTP URL construction and WSS connections, see Method and request mapping.
For the HTTPS, WSS, and libp2p TCP formats defined here, any malformed candidate invalidates the entire descriptor; such errors MUST NOT be ignored as unknown transports. Verifiers MUST NOT accept a descriptor after filling in paths, removing prohibited parts, or rewriting addresses; signature verification uses original addresses. Authentication origin is separately calculated under Relay origin and does not replace endpoint format checks.
For transports not defined here, verifiers MUST retain the original address and its array position for signature verification, but ignore it in this protocol. They MUST NOT connect to it or count it toward required addresses or Peer ID binding checks, and MUST NOT reject the whole descriptor solely because it is present.
Each address array item MUST be a nonempty string, with no duplicates. Array order carries no business semantics, but signatures preserve the actual order.
Candidate Selection and Retries
A transport may have multiple candidate addresses; business connections MUST pass that transport's identity and protocol checks. Once a server has returned a valid protocol response, whether another address may be tried depends on the method's error handling and duplicate-request rules. Callers MUST NOT automatically treat business errors as address connection failures.
After all candidates for one transport in a RelayDescriptor fail, callers are advised to refresh Registry state and RelayDescriptor to check for changed eligibility or service addresses. All candidates belong to the same relay_id; changing addresses does not change the target relay or imply a standby relay or service migration.
For writes that may already have been accepted, handling after an address change follows the method's duplicate-request and retry rules. When a method explicitly allows idempotent retries, a caller that meets identity and session requirements at the new endpoint may resubmit the unchanged request to the same relay; idempotency retention, current authorization, and other conditions still apply. Other methods continue to require their respective reads, synchronization, or status queries before deciding whether to proceed. Changing addresses does not itself authorize replay.
Relay Descriptor Validation Rules
Verifiers MUST:
- Derive the Neo single-signature account from
public_keyand confirm its script hash equalsrelay_id. - Verify the Neo account signature.
- Confirm that the corresponding Registry record has
statusequal toactive. - Validate
endpointsunder Relay endpoint addresses, ignoring unknown transports, and confirm at least one valid HTTPS address and one valid libp2p TCP multiaddr. - Confirm
RelayDescriptorhas not expired. - Confirm
capabilitiesmeets its field constraints, and confirm the relevant declaration before using an optional capability. - Confirm that all libp2p TCP multiaddrs contain a Peer ID and that all such Peer IDs are identical.
Clients using HTTPS or WSS MUST select candidates from endpoints that have passed these checks. Origin calculation, session binding, and authentication on new WSS connections follow Session authentication. After switching to another origin, clients MUST reauthenticate there in a mode allowed by the method before calling a session-requiring method.
Relays connecting to libp2p TCP addresses in this descriptor MUST complete handshake declarations and identity checks under Relay connections and identity authentication. Every candidate's Peer ID MUST match the actual secure connection's Peer ID, and the remote MUST support the Relay DHT protocol and Relay RPC protocol defined here. Connections that fail these conditions MUST reject protocol negotiation or close. Identity discovery beginning with DHT candidates follows that connection specification. For transport failure handling, descriptor refresh, and request replay constraints, see Relay endpoint addresses.