upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpablof7z <pfer@me.com>2024-10-20 00:57:11 +0100
committerpablof7z <pfer@me.com>2024-10-20 00:57:11 +0100
commitb5774a1338dbe1e2d133105e22f79986518b8acd (patch)
tree19132993757604a3695a8eaa3528d9806e41a2c4
parent07de7ea7e5d2934afac1eb86db0cd0a0200039a0 (diff)
wip
-rw-r--r--22.md141
1 files changed, 141 insertions, 0 deletions
diff --git a/22.md b/22.md
new file mode 100644
index 0000000..02ff3ab
--- /dev/null
+++ b/22.md
@@ -0,0 +1,141 @@
1# NIP-22
2## Event Onion-routing
3`draft` `optional`
4
5This NIP defines a way to do onion-based routing for event publishing, optionally compensated with cashu where pubkeys (not necessarily relays) provide routing services.
6
7## Announcement
8A pubkey announces itself as willing to route by publishing an ephemeral event `kind:20690` in their outbox relays. Announcers should republish a new ephemeral event every few minutes to indicate they are still willing to route and online. The refresh rate depends on the relays where they are publishing (usually ~5 minutes).
9
10```jsonc
11{
12 "kind": 20690,
13 "tags": [
14 [ "relay", "wss://example1.com" ],
15 [ "relay", "wss://example2.com" ],
16 [ "fee", "1", "sat" ]
17 ],
18 "content": "",
19 "pubkey": <pubkey-of-router>
20}
21```
22
23Tags:
24`relay` -- relay(s) where the pubkey will be listening for requests.
25`fee` -- an optional fee indicating how much money the pubkey demands to be paid.
26
27## Routing request
28A sender publishes a series of `kind:2444` or `kind:20444` where the `payload` is the event that should be published by the pubkey of the current hop in the relays specified by the envelope. An optional proof can be included, this cashu proof is for the hop processing this route.
29
30```jsonc
31{
32 "kind": 20444,
33 "content": nip44_encrypt("{
34 'relays': [ 'wss://example1.com' ],
35 'event': { 'id': ...., sig: ..., }, // event the current routing pubkey should publish
36 'proof': <optional-unencoded-cashu-proof>,
37 'mint': 'https://mint.com',
38 'unit': 'sat'
39 }")
40 "tags": [
41 [ "p", "pubkey-of-next-hop" ]
42 ]
43}
44```
45
46Event `kind:2444` has the exact same format as the `kind:20444`, the only difference being that it's not ephemeral, so it can be used to route events that are expected to take longer to route. `kind:2444` events SHOULD include an [[NIP-40]] `expiration` tag.
47
48Routing pubkeys MUST look at the `created_at` of the event they need to publish and wait until at least that time before publishing.
49
50When a routing pubkey receives a routing request event it should decrypt the content, redeem the cashu and publish the event in the `event` field. If the cashu cannot be redeemed the routing pubkey MUST NOT publish the event. This is useful as a way to **cancel** a routing event where the sender uses a future `created_at` timestamps and chooses to cancel the publication.
51
52## Constructing a route
53The sender:
54
551. looks for `kind:20400` announcements and assembles a path
562. creates the event they want to publish and sign it with their normal pubkey
57
583. walks the path backwards (finish -> start), putting the event signed in the previous step in the `event` field of the `content` and the other fileds of the envelope
594. encrypts to the current hop and signs -- both operations with a new disposable key and `p`-tags the current hop.
603. repeat step #3 and #4 for the rest of the route until the first hop
614. sender publishes the resulting event to one of the relays the first hop indicated it's active on
62
63## Pseudocode implementation
64```ts
65// event to be published
66event = { "kind": 1, content: "This is an onion-routed event" }
67sign_event(event, my_private_key)
68outer_layer = assemble_onion_route(event, [ "pubkey-A", "pubkey-B", "pubkey-C" ])
69publish_event(outer_layer)
70
71function assemble_onion_route(final_event, path) {
72 current_event = final_event // Start with the event to be published by the final hop
73
74 // Walk the path backwards from "C" to "A"
75 for hop_pubkey in reverse(path): // path = ["A", "B", "C"], reversed to ["C", "B", "A"]
76 // Generate a new disposable key for this hop
77 disposable_key = generate_disposable_key()
78
79 // Create the payload for this hop
80 payload = {
81 "event": current_event // The event for the hop to publish
82 // ...
83 }
84
85 // Encrypt the payload for the current hop
86 encrypted_payload = nip44_encrypt(payload, hop_pubkey) // Encrypt with the hop's pubkey
87
88 // Create the routing event for this hop
89 routing_event = {
90 "kind": 20444, // Ephemeral routing request
91 "content": encrypted_payload, // The encrypted payload for this hop
92 "tags": [["p", hop_pubkey]] // Tag indicating the pubkey of the next hop
93 }
94
95 // Sign the event with the disposable key for this hop
96 sign_event(routing_event, disposable_key)
97
98 // Prepare for the next hop (wrap another layer)
99 current_event = routing_event
100 }
101
102 return current_event // Return the fully wrapped outermost event ready to be published
103}
104
105```
106
107## Example anatomy of a sequence of routing events
108
109```jsonc
110{
111 kind: 20444,
112 content: nip44_encrypt({
113 relays: [...],
114 event: {
115 "id": ...,
116 "kind": 20444,
117 "pubkey": "ephemeral-key-1",
118 "sig": ...,
119 content: nip44_encrypt({
120 relays: [....],
121 event: {
122 "id": ....,
123 "kind": 20444,
124 "pubkey": "ephemeral-key-2",
125 "sig": ...,
126 "content": nip44_encrypt({
127 relays: [ "wss://target-relay.com" ],
128 event: {
129 id: ...,
130 "kind": 1,
131 content: "This is an onion-routed event",
132 "pubkey": "real-pubkey",
133 "sig": ...,
134 }
135 })
136 }
137 })
138 }
139 }
140}
141```