---
# System prepended metadata

title: DID DHT for tbDEX

---

# Background

[DID DHT](https://github.com/TBD54566975/did-dht/blob/main/README.md) is a new service that, among other things, allows a global way to broadcast DID-authenticated messages using [libp2p PubSub](https://docs.libp2p.io/concepts/pubsub/overview/).


# Gossip

DID DHT exposes a set of APIs that enable you to create and send messages to a gossip topic within the `diddht` namespace. This means anyone in the world can set up a libp2p gossipsub client and participate in listening to and broadcasting messages if they use the namespace and 'join' a common topic.

The service enforces a common message format across all topics:

```go
type SignedRecord struct {
    Payload map[string]any `json:"payload,omitempty"`
    JWS     string         `json:"jws,omitempty"`
}
```

The `payload` is any JSON object. The JWS is a [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515) compliant object using [compact serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.1). The data is canonicalized using [JCS](https://www.rfc-editor.org/rfc/rfc8785) before signing for consistency purposes. The `SignedRecord` object combines both the raw payload with the JWS, since the JWS contains claims, such as the `iss`, `iat`, and `jti` properties that are not necessary in the `payload` itself.

If this becomes too cumbersome we may explore a [detached payload option](https://datatracker.ietf.org/doc/html/rfc7515#appendix-F) in the future.

The `iss` of the JWS **MUST** be a DID, and the `kid` in the JWS's protected header must be the identifier of a [`verificationMethod`](https://www.w3.org/TR/did-core/#verification-methods) in the corresponding DID Document.


# Usage in tbDEX

The first usage of the DID DHT in tbDEX is to enable PFI discovery. PFI discovery means giving PFIs a way to broadcast that that they offer exchanges for certain currency pairs. 


## Writing to a Topic

For example, an example broadcast message within the `diddht/pfi` namespace may look as follows:

- A PUT to `/gossip` to create the topic `pfi`, with body. This enables listening from and posting to the topic:

```json
{
 "topic": "pfi"
}
```

- A PUT to `/gossip/pfi`  to message the topic, with body:


```json
{
  "payload": {
    "currencyPairs": [
      "BTC/USDT",
      "ETH/USDT"
    ],
    "endpoint": "https://tbdex.website",
    "pfiName": "tbDEX-PFI"
  },
  "jws": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbUkwUWtkSVdtUnRkelJCTWtGeE9USmhWRzh4VWkxaE1YTm5ka3QxVDFwMFRWOTRaMG8yTWxadlNHOGlMQ0poYkdjaU9pSkZaRVJUUVNKOSMwIiwidHlwIjoiSldUIn0.eyJjdXJyZW5jeVBhaXJzIjpbIkJUQy9VU0RUIiwiRVRIL1VTRFQiXSwiZW5kcG9pbnQiOiJodHRwczovL3RiZGV4LndlYnNpdGUiLCJpYXQiOjE2OTAyMzg4NTQsImlzcyI6ImRpZDpqd2s6ZXlKcmRIa2lPaUpQUzFBaUxDSmpjbllpT2lKRlpESTFOVEU1SWl3aWVDSTZJbUkwUWtkSVdtUnRkelJCTWtGeE9USmhWRzh4VWkxaE1YTm5ka3QxVDFwMFRWOTRaMG8yTWxadlNHOGlMQ0poYkdjaU9pSkZaRVJUUVNKOSIsInBmaU5hbWUiOiJ0YkRFWC1QRkkifQ.6DW4P4ZpVFaliWGjdnlPzmCjH9dNqMafDb2Lc7iIQNJrgcLcS-lgoYqJBzjQaT1WWnfIPNgIcUAkxq9PWzX9Cw"
}
```

The decoded JWS payload is as follows:

```json
{
  "alg": "EdDSA",
  "kid": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5IiwieCI6ImI0QkdIWmRtdzRBMkFxOTJhVG8xUi1hMXNndkt1T1p0TV94Z0o2MlZvSG8iLCJhbGciOiJFZERTQSJ9#0",
  "typ": "JWT"
}
```

```json
{
  "currencyPairs": [
    "BTC/USDT",
    "ETH/USDT"
  ],
  "endpoint": "https://tbdex.website",
  "iat": 1690238854,
  "iss": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5IiwieCI6ImI0QkdIWmRtdzRBMkFxOTJhVG8xUi1hMXNndkt1T1p0TV94Z0o2MlZvSG8iLCJhbGciOiJFZERTQSJ9",
  "pfiName": "tbDEX-PFI"
}
```

## Reading from a Topic

Any other DID DHT service, besides where the message was published AND any gossip client configured to listen to `diddht/pfi` will see the `SignedRecord` JSON payload.

Conformant clients will verify the JWS, resolving the DID from the `iss` property, and finding the associated `kid` from the protected header's `kid` property. If the JWS does not validate, the message will be dropped. 

## More Useful APIs

We can surface more useful APIs in the DID DHT service that can fulfill certain queries, such as answering _"Which PFIs are available for X trading pair?"_


A sample API may be...

- GET `/gossip/pfi?pair=USD-BTC`

A sensible response would be a list of PFIs and their associated information, which could be pulled from prior gossip messages and/or the DHT itself:

```json
{
    "pair": "USD-BTC",
    "pfis": [
        {
            "did": "did:jwk:eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5IiwieCI6ImI0QkdIWmRtdzRBMkFxOTJhVG8xUi1hMXNndkt1T1p0TV94Z0o2MlZvSG8iLCJhbGciOiJFZERTQSJ9"
            "pfiName": "tbDEX-PFI",
            "endpoint": "https://tbdex.website"
        },
        {
            "did": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp"
            "pfiName": "ACME PFI",
            "endpoint": "https://acme.inc"
        }
    ]
}
```