Why Nostr? What is Njump?
2025-04-30 19:32:17

dolu on Nostr: I just published an article about data versioning issue on Nostr ...

I just published an article about data versioning issue on Nostr

Nostr is a decentralized protocol designed to be censorship-resistant.
However, this resilience can sometimes make data synchronization between relays more difficult—though not impossible.

In my opinion, Nostr still lacks a few key features to ensure consistent and reliable operation, especially regarding data versioning.

Profile Versions

When I log in to a new Nostr client using my private key, I might end up with an outdated version of my profile, depending on how the client is built or configured.

Why does this happen?
The client fetches my profile data (kind:0 - NIP 1) from its own list of selected relays.
If I didn’t publish the latest version of my profile on those specific relays, the client will only display an older version.

Relay List Metadata

The same issue occurs with the relay list metadata (kind:10002 - NIP 65).
When switching to a new client, it’s common that my configured relay list isn’t properly carried over because it also depends on where the data is fetched.

Protocol Change Proposal

I believe the protocol should evolve, specifically regarding how kind:0 (user metadata) and kind:10002 (relay list metadata) events are distributed to relays.

Relays should be able to build a list of public relays automatically (via autodiscovery), and forward all received kind:0 and kind:10002 events to every relay in that list.

This would create a ripple effect:

Relay A relay list: [Relay B, Relay C]  
Relay B relay list: [Relay A, Relay C]  
Relay C relay list: [Relay A, Relay B]  

User A sends kind:0 to Relay A  
→ Relay A forwards kind:0 to Relay B  
→ Relay A forwards kind:0 to Relay C  
→ Relay B forwards kind:0 to Relay A  
→ Relay B forwards kind:0 to Relay C
→ Relay A forwards kind:0 to Relay B  
→ etc.

Solution: Event Encapsulation

To avoid infinite replication loops, the solution could be to wrap the user’s signed event inside a new event signed by the relay, using a dedicated kind (e.g., kind:9999).

When Relay B receives a kind:9999 event from Relay A, it extracts the original event, checks whether it already exists or if a newer version is present. If not, it adds the event to its database.

Here is an example of such encapsulated data:

{
  "content": "{\"content\":\"{\\\"lud16\\\":\\\"dolu@npub.cash\\\",\\\"name\\\":\\\"dolu\\\",\\\"nip05\\\":\\\"dolu@dolu.dev\\\",\\\"picture\\\":\\\"!(image)[!(image)[https://pbs.twimg.com/profile_images/1577320325158682626/igGerO9A_400x400.jpg]]\\\",\\\"pubkey\\\":\\\"59b96df8d8b5e66b3b95a3e1ba159750a6edd69bcbba1857aeb652a5b208bd59\\\",\\\"npub\\\":\\\"npub1txukm7xckhnxkwu450sm59vh2znwm45mewaps4awkef2tvsgh4vsf7phrl\\\",\\\"created_at\\\":1688312044}\",\"created_at\":1728233747,\"id\":\"afc3629314aad00f8786af97877115de30c184a25a48440a480bff590a0f9ba8\",\"kind\":0,\"pubkey\":\"59b96df8d8b5e66b3b95a3e1ba159750a6edd69bcbba1857aeb652a5b208bd59\",\"sig\":\"989b250f7fd5d4cfc9a6ee567594c81ee0a91f972e76b61332005fb02aa1343854104fdbcb6c4f77ae8896acd886ab4188043c383e32a6bba509fd78fedb984a\",\"tags\":[]}",
  "created_at": 1746036589,
  "id": "efe7fa5844c5c4428fb06d1657bf663d8b256b60c793b5a2c5a426ec773c745c",
  "kind": 9999,
  "pubkey": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
  "sig": "219f8bc840d12969ceb0093fb62f314a1f2e19a0cbe3e34b481bdfdf82d8238e1f00362791d17801548839f511533461f10dd45cd0aa4e264d71db6844f5e97c",
  "tags": []
}
Author Public Key
npub1txukm7xckhnxkwu450sm59vh2znwm45mewaps4awkef2tvsgh4vsf7phrl