nips icon indicating copy to clipboard operation
nips copied to clipboard

NIP-55: Unix Domain Sockets

Open ChristianChiarulli opened this issue 1 year ago • 18 comments

Example using unix domain sockets with two desktop apps where one is acting as a remote signer: https://twitter.com/chrisatmachine/status/1786549455967154312

ChristianChiarulli avatar May 04 '24 23:05 ChristianChiarulli

@mikedilger

fiatjaf avatar May 04 '24 23:05 fiatjaf

Nice! Let's go!

vitorpamplona avatar May 04 '24 23:05 vitorpamplona

Why the link to Twitter, though? :)

vitorpamplona avatar May 04 '24 23:05 vitorpamplona

Thanks @vitorpamplona, also I've had a lot of issues with kind 1 web clients.

ChristianChiarulli avatar May 05 '24 10:05 ChristianChiarulli

A few thoughts:

  • Should we define a message structure and encoding? I really like what NIP-46 uses for requests and responses, where they both share a designated kind, and the content field contains a NIP-04 encrypted JSON-RPC 2.0 request or response. When using JSON-RPC 2.0 over byte sockets, we also need a message delineation mechanism. See here for some possible options - I'd vote for the first option, shutdown after every request/response, for its simplicity.
  • Building on this, should we have socket namespaces? We could use /tmp/nip55-kind{kind number} instead of /tmp/nip55. This way there could be more than one server on a single device while also keeping the purpose of each one clear.

Also, here's a reference implementation in Rust containing a working server and client which uses the message structure and encoding mentioned above: https://crates.io/crates/nip-55

tvolk131 avatar May 06 '24 21:05 tvolk131

You can also use the Android Signer spec as a reference: https://github.com/nostr-protocol/nips/pull/868

The interesting part of the Android spec is that it has two modes: with UI and without it. It always tries to do the operation without transferring the user to the other app and only if it fails, it brings the signer UI up.

vitorpamplona avatar May 06 '24 21:05 vitorpamplona

Cool.

It's not nostr, because it's not websocket communication through relays.

Maybe nostr should be a layered specification, with the top event layer defined in one spec, relay-client messages in another lower spec, websocket transport in a lower yet spec. In that world, this demo would be using not just a different transport, but a different sub-event protocol.

mikedilger avatar May 09 '24 03:05 mikedilger

Maybe nostr should be a layered specification, with the top event layer defined in one spec, relay-client messages in another lower spec, websocket transport in a lower yet spec. In that world, this demo would be using not just a different transport, but a different sub-event protocol.

IMHO, it already is like that. The NIP description is just not up to speed. The real Nostr Protocol is only the event definition/sign/verify. Everything else is layer 2+.

vitorpamplona avatar May 09 '24 03:05 vitorpamplona

@mikedilger does that call into question the validity of nip-7 since it is not websocket communication through relays? I left the nip relatively open but I'm not necessarily suggesting we should send any and all events over the socket, for now just the utility methods from nip-46 that would provide a similar benefit as nip-7 but outside of a browser context and specifically native to the desktop.

ChristianChiarulli avatar May 12 '24 01:05 ChristianChiarulli

Yeah I think nip-7 and nip-6 too are not really nostr. It doesn't mean we can't put it in a nip, we are sloppy about a lot of things.

mikedilger avatar May 13 '24 21:05 mikedilger

Why not just do local http?

alexgleason avatar May 13 '24 21:05 alexgleason

@alexgleason one reason is that I don't want to deal with figuring out how to get the server and client to agree on a port.

@mikedilger right, maybe it's worth outlining some place in the future to put things like this nip, nip-7 etc, since standards like this allow more streamlined development for clients and greater security.

ChristianChiarulli avatar May 14 '24 02:05 ChristianChiarulli

Why not just do local http?

I see two reasons:

  1. For local communication, UDS is simpler and more performant.
  2. If we want socket namespaces like I mentioned above (/tmp/nip55-kind{kind number} instead of just /tmp/nip55) then I'm not sure how this would translate to HTTP. With UDS there are effectively port names rather than port numbers which allows for easy extensibility without the need for a discovery mechanism

tvolk131 avatar May 14 '24 13:05 tvolk131

It looks like Windows has supported UDS since 2017 when they added support for the SOCK_STREAM socket type (see here). We could include Named Pipes as an alternative/fallback for Windows (although I don't think that's necessary - I just figured it's worth mentioning).

SOCK_STREAM is analogous to TCP and is what we'd want to use for JSON-RPC 2.0 as I mentioned here.

tvolk131 avatar May 15 '24 17:05 tvolk131

I think maybe we should narrow it down to just passing the JSON defined in NIP-46. Maybe in the future other events could be passed via UDS but for now I think this is fine.

I'll think about multi user, I'm open to suggestions here.

This NIP does not apply to non Unix systems.

ChristianChiarulli avatar May 17 '24 14:05 ChristianChiarulli

I'll think about multi user, I'm open to suggestions here.

I would switch /tmp/... to a .nostrsigner.sock in the user's home directory. In that way, system apps can have access to it if you give the right permissions to the file. Otherwise, only the user's apps can interact with it.

vitorpamplona avatar May 17 '24 15:05 vitorpamplona

@vitorpamplona I think that's probably a good idea to manage it in the users home directory, maybe we could define two standard locations in this nip, one that is system wide and one user specific?

ChristianChiarulli avatar May 17 '24 15:05 ChristianChiarulli

would a concrete implementation in JS or Python be helpful to add to the nip?

ChristianChiarulli avatar May 17 '24 15:05 ChristianChiarulli