-
Notifications
You must be signed in to change notification settings - Fork 602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NIP-44 Geospatial Types #136
Open
rossbates
wants to merge
7
commits into
nostr-protocol:master
Choose a base branch
from
rossbates:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 6 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
d3ffa27
First draft of NIP-44
rossbates 6abc7ec
typos and clean up
rossbates 5e654ad
tid bit more
rossbates ab21106
kind-of-a typo
rossbates 77e85b4
remove opinions not related to protocol
rossbates f76c78a
RFC link. Content string/object question resolved
rossbates 95d9ba8
Remove section on content field
rossbates File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
NIP-44 | ||
====== | ||
|
||
Geospatial Types | ||
------------------------- | ||
|
||
`draft` `optional` `author:rossbates` `author:milesbates` | ||
|
||
## Description | ||
|
||
An event of `kind 4326` is a geospatial note supporting various location-based clients such as transportation, travel, home automation, and social media applications. The data for this event is stored in the `content` field and should contain only valid [GeoJSON](https://www.rfc-editor.org/rfc/rfc7946) objects. | ||
|
||
This proposal recommends storing geographic features in standalone events that reference other `e` and `p` tags, similar to how `kind 7` responses work. By requiring geographic features to link to related keys and events, rather than embedding location data within events, collections of notes in nostr will remain composable. Using GeoJSON as the geospatial data type for nostr supports interoperability with existing web standards and designating it type `kind 4326` provides a standard method for future nostr kinds to integrate it in their applications. | ||
|
||
For example, developers might implement notes that represent objects such as calendar events, restaurant reviews, or concert tickets - in this situation each of these notes would have a convenient way to integrate existing location data using `e` and `p` tags linked to `kind 4326` notes. If no useable data exists, they can create new `kind 4326` notes. All of this would be fully backwards compatible with the nostr protocol. | ||
|
||
An object represented by `p` could potentially be a fixed location such as a building, a shape boundary such as a geofence or border, or a moving object such as a truck or a nostr user. Each of these potentially has geospatial data that can be represented using GeoJSON. There are no minimum or maximum number of `kind 4326` notes that can be associated with a given `p`, nor are there restrictions on who can create them. This provides the most freedom for relays and clients to build solutions for making nostr objects spatially aware while adhering to the existing protocol standards. | ||
|
||
|
||
## Example | ||
|
||
Here is an example of how the use of `kind 4326` notes could be used in a real world example. In this scenario there are 3 nostr users (A,B,C) attending a nostr developer meetup in the evening who would like to privately share their location with their trusted contacts so they can coordinate dinner and transportation. They'll do this using the same nostr mobile app they use to communicate with a wider group of people. | ||
|
||
The meetup is taking place at a building in downtown Austin represented by the following note. | ||
|
||
```json | ||
["EVENT", { | ||
"id": "2953ae40dfc6c814cabef08a34e917e9886ffe3b11be54e0f14e0e76d1692197", | ||
"pubkey": "90f415eb9dd25616185f252f1565d9cfc0392906e4e2638d13fda1242aa00b09", | ||
"created_at": 1671975000, | ||
"kind": 4326, | ||
"tags": [], | ||
"content": "{'type': 'Point','coordinates': [-97.74274456131394,30.268100484614934]}", | ||
"sig": "0ecf4b5649366ab7f99123ff6ae9767bca988d8545300e545f09e1d9a956a0fa2e013ab12360c7abb4bbfa56338477f7ce5513754b06f472f5cc3eb40f6f2cab" | ||
}] | ||
``` | ||
|
||
|
||
At 5:30pm User A posts a kind 1 note using their nostr app reminding everyone about the event. In this note they tagged both the location as well as the 2 friends who will also be attending. This was done using the `e` tag for the location and the `p` of the contacts. | ||
|
||
|
||
```json | ||
["EVENT", { | ||
"id": "f040fc0ba2620264efb19d2764ceaa7978977256034594c9af5b4a5be356c797", | ||
"pubkey": "c403fbbc3808913bccdc4460986dd09f3985376ecf07d4b471d18644075d0c4c", | ||
"created_at": 1674603000, | ||
"kind": 1, | ||
"tags": [ | ||
["e", "2953ae40dfc6c814cabef08a34e917e9886ffe3b11be54e0f14e0e76d1692197", "wss...", "root"], | ||
["p", "3c8d410ef11ae8abbc541783cacecbb35075b93d23837fa59d59c3610c1c580c"], | ||
["p", "24226e17fcecdab9277218ab126ee882192c6ae3f1fec5689924e77754f00c11"] | ||
], | ||
"content": "Excited to see everyone this evening at the ATX nostr dev meetup.", | ||
"sig": "8a2228542bb69ab7b9a12824cd0df88eafd27e4993eec990c107b79a519754a436c1f5114188db254d8499cc6b7b5095ea34ade9173a8903739845da6d4a2815" | ||
}] | ||
``` | ||
|
||
In the same post User A chooses the option to attach their current location (created as `kind 4326`) to the note. The app generates an event referencing the original `kind 1` note which goes to all public relays, while both events also get posted to a private relay. | ||
|
||
```json | ||
["EVENT", { | ||
"id": "9850551d116a4c2c69b7d084a6b27aa95e0ba6ddf8b04cac33145ab290465733", | ||
"pubkey": "c403fbbc3808913bccdc4460986dd09f3985376ecf07d4b471d18644075d0c4c", | ||
"created_at": 1674603000, | ||
"kind": 4326, | ||
"tags": [ | ||
["e", "f040fc0ba2620264efb19d2764ceaa7978977256034594c9af5b4a5be356c797", "wss...", "reply"] | ||
], | ||
"content": "{'type': 'Point','coordinates': [-97.73995249685214, 30.282439538024022]}", | ||
"sig": "026174991b8e956a4ef591c08bb69e506d5f42a07aa652d6af106a33a83017f646ed37f85e010aa0cd7b1e0beb0fc546c0acdb564a8daff84047d437e358f7e2" | ||
}] | ||
``` | ||
|
||
Users A, B and C all share access to the same private relay which supports receiving and responding to `kind 4326` messages. Each client is also still able to filter for all public and private responses to the `kind 1` note using the same interface. When user A sends a `kind 4326` note that references `p` tags the relay can automatically generate a `kind 1` note for all parties to prompt or alert them. This however is just an example, the client developers can customize the experience however it best suits the users. | ||
|
||
Here user B & C decide to acknowldge and respond using only a `kind 4326` note sent over the same private relay. These responses can include their current location coordinates, as well as other any other related `p` tags such as the Coffee Shop or Park they're currently at. The location data is the response. | ||
|
||
User B Response: | ||
|
||
```json | ||
["EVENT", { | ||
"id": "49734138379434153a4af1275fe6afcc18937a326ff950875a0c7165ac2be123", | ||
"pubkey": "3c8d410ef11ae8abbc541783cacecbb35075b93d23837fa59d59c3610c1c580c", | ||
"created_at": 1674603213, | ||
"kind": 4326, | ||
"tags": [ | ||
["e", "9850551d116a4c2c69b7d084a6b27aa95e0ba6ddf8b04cac33145ab290465733", "wss...", "reply"] | ||
], | ||
"content": "{'type': 'Point','coordinates': [-97.7491855918345, 30.251096509429328]}", | ||
"sig": "b9889b3ae92ed5942a7270b6322b80d55230b256bd416d25e519ea07989a8eea8d105b0debb2d30366c70cd479b638453e16b2b9e8a016991b7f941fff553f05" | ||
}] | ||
``` | ||
|
||
User C Response: | ||
|
||
```json | ||
["EVENT", { | ||
"id": "36fbb58a1dcd30aa3420eb456306435d4b06be4b804987fe000be8b58b2efed1", | ||
"pubkey": "24226e17fcecdab9277218ab126ee882192c6ae3f1fec5689924e77754f00c11", | ||
"created_at": 1674603321, | ||
"kind": 4326, | ||
"tags": [ | ||
["e", "9850551d116a4c2c69b7d084a6b27aa95e0ba6ddf8b04cac33145ab290465733", "wss...", "reply"] | ||
], | ||
"content": "{'type': 'Point','coordinates': [-97.75077606389179, 30.26308185185999]}", | ||
"sig": "230f53ea5aa2c9a979badbb400f31edafa227ae526f019c1ffadf69ec257b21c360ca6ef779ea592a4eb7ffa7e8cedd6b5877c99ff202d1ecbdca99f76137d4c" | ||
}] | ||
``` | ||
|
||
This is a basic example to demonstrate the `kind 4326` data structures and for showing how an initial handshake between peers over public and private relays would work. From this point forward the clients and the private relay now have everything needed to work in coordinatation - potentially executing geofence and nearby queries on the notes, generating arrival estimates, status updates, routing suggestions, ride-share integration, etc.... There are many possibilties for client experiences that go beyond the scope of the NIP. | ||
|
||
|
||
## Summary of Benefits | ||
|
||
|
||
**Privacy Controls**: notes with `kind 4326` can be routed separately to private and/or user specified relays for handling. This provides users with options to protect their private data if they choose, and it provides client developers a solution for combining public and private data into composite events. | ||
|
||
**Proof of Location**: This design makes it so anyone is free to build validation and attestation services that an event took place in a physical location. For example, users could check-in at a concert using any nostr client to receive a special badge. Attestation and issuance could originate from any number of trusted sources, such as the artist and/and venue, without requiring users to be running a specific application or platform. Attestation could come from sources such as nostr peers, payment systems, photos or QR codes - or a combination of these using nostr multi-sig. Location proofs could be provided for any valid event, by any signer, with no barriers to entry. | ||
|
||
**Decentralized Data Providers**: Support for nostr data types such as `kind 4326` will open up opportunities for nostr relay operators to serve as data service providers. A `kind 4326` event can be any valid geometry including buildings, geofences, and points of interest. This is similar to the concept of linked data URIs, but it's much simpler - `p` can represent any location on earth. Relay operators could charge for custom key/data management services. | ||
|
||
**Relay Performance**: By separating data types and content using this approach, relays can route events without the need for content inspection. Notes with `kind 4326` can be forwarded to backend indexing services which respond with new events when conditions are met. As the network grows, some relays may be dedicated solely to routing events based on their type. | ||
|
||
## Open Issues | ||
|
||
### NIP-16 | ||
|
||
What is the desired behavior when it's reasonable for an event to be either a Regular event (`1000 <= n < 10000`), Replaceable event (`10000 <= n < 20000`), or Ephemeral (`20000 <= n < 30000`) event as defined by NIP-16? Take for example a bus tracking application where the users are checking on the status of their bus identified by. | ||
|
||
```json | ||
["p", "b68cf380888a13fab39afb144fb9e9502a8560af85943fa0cdcf1e3e130a109d"] | ||
``` | ||
|
||
As the bus travels it's route it will generate a series of location updates. One solution could be a new type created such as `kind 14326` or `kind 24326` for use as the "current status" location. If however the client app is also tracking the history of the bus then `kind 14326` is basically equal to the most recent `kind 4326`. Should this be something defined by the protocol, or left up to the developers? | ||
|
||
To be clear, this decision is not a technical challenge, but as types in nostr begin to increase some guidelines for how these types are assigned and used will need to be figured out. For now this NIP proposes using only `kind 4326` | ||
|
||
### Content Field | ||
|
||
The most common event on the network is `kind 1` which relays assume will have a string in the `content` field. The `event` object itself is already valid JSON, so allowing for valid JSON to be sent in the `content` would be more efficient for client developers because they would not need to wrap/unwrap and validate JSON content. This could be a complexity trade-off for relays because they would need to support both strings and objects in the content field. Because the `event` must already be valid JSON, and the purpose of the event is that it's entire contents are verifiable by it's signature, it would be reasonable to require relays to support valid JSON in the object field. | ||
|
||
*update*: Not wrapping the content would break existing code for things such as event signatures and validation. Continuing to treat all `content` as a string and not an object is the only reasonable path forward right now. | ||
|
||
|
||
## Other Notes | ||
|
||
- The value `4326` was selected because it is the default coordinate reference system (CRS) for the GeoJSON specification. If a client or relay wants to use another reference system the GeoJSON spec fully supports including it as a tag. | ||
|
||
- There have been suggestions about using a more compact binary encoding scheme to improve efficiency over the wire. This would require a format to be chosen which would inherently have implications for developers. Plain text ensures notes of this type can be exchanged by all relays and client no matter what languages or platforms they're using. | ||
|
||
- A proof-of-concept has been developed using a fork of Damus iOS as the client and a fork of Dave St. Germain's nostr_relay as the server. This will be made available at geonostr.org for people who want to participate testing. Reach out to `rossbates` on nostr if interested: | ||
|
||
`npub1u656f7znujcagfhtgngvtkcflhzptnj38enyzx85da0lh63sfj7qva332p` | ||
|
||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi this is unnecessary, there will never be non-string values for content
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok not a problem, I've removed it. I originally left it in there as a reference in case someone in the future had a similar question. You are right though in that it's not necessary in the context of this document.