Skip to content

Instantly share code, notes, and snippets.

@fiatjaf
Last active September 30, 2023 05:48
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fiatjaf/ea7d21e81359e1eb8abcb8805306adaa to your computer and use it in GitHub Desktop.
Save fiatjaf/ea7d21e81359e1eb8abcb8805306adaa to your computer and use it in GitHub Desktop.
ActivityPub bridge Nostr relay bounty

ActivityPub bridge Nostr relay

tl;dr 5M sat bounty to make https://github.com/fiatjaf/no-fed work.

The idea

ActivityPub communication is between servers. A server talks to another server, pushing and pulling data. Identities live on servers. Nostr communication is between clients and servers.

The idea of https://github.com/fiatjaf/no-fed is to make a server that can act both as an ActivityPub server, and thus be the home of AP accounts, and as a Nostr relay, and thus serve events to those who ask for them.

From the ActivityPub side, it would work as a server that has accounts like npub1az6g0srekrm8c626umzvy4f2glec4haz2v7vtynt6tqs99p0mjmsna8xse@no-fed.com and works normally as that, fetching (and caching) stuff from the broader Nostr network when necessary to build the AP profile of Nostr accounts.

From the Nostr side it will be a relay from which posts from any ActivityPub account can be queried, and also a NIP05 provider for all these, so one can use their Nostr client to add lukedashjr_at_bitcoinhackers.org@no-fed.com and that will return a "virtual" public key generated deterministically from the target AP account id (which is an URL like https://bitcoinhackers.org/users/lukedashjr).

It shouldn't send data from AP to other Nostr relays because that would be unnecessarily spammy, Nostr clients that want to interact with AP accounts should learn how to follow this relay, and this could be an incentive for Nostr clients to build smarter flows around relay selection and usage.

It also should not actively query other Nostr relays in order to get updates that may interest external AP users. Instead, it should accept direct events submitted from Nostr clients and cache these if they are directly interesting to external AP followers of Nostr accounts or replies to external AP notes.

The implementation

All the pieces are in place in the https://github.com/fiatjaf/no-fed codebase, and it kinda works, at least from the AP side: it is possible for a Mastodon or Pleroma user to see the profile of a Nostr account given by <hex key>@nofedtestdomain.com. The Nostr side is untested and probably incomplete.

I've given up getting it working because I have no time and AP is very annoying to test with and I am probably missing some fundamentals, but it would be a waste to throw away this initiative and past work.

However, if you believe this project would better be done using some other language or framework or approach, please reach out and maybe we can adjust the bounty.

The bounty

The fiatjaf Nostr Fund is pledging 5 million satoshis to whoever can complete this task. See comments below to check if this bounty is still up for grabs or has been reserved to someone who may be working on it. The bounty can be adjusted upwards if this proves to be very time-consuming or harder work than initially thought.

@silverpill
Copy link

ActivityPub communication is between servers. A server talks to another server, pushing and pulling data. Identities live on servers.

Actually, ActivityPub protocol has two parts: Server-to-Server (S2S) and Client-to-Server (C2S). Identities can live on clients too - there's nothing in the protocol specification that prohibits that.

Bridging Nostr relays and AP servers seems to be the easiest way, but I think it is also possible to create a client that supports both Nostr protocol and ActivityPub C2S. I'm not interested in this particular bounty, but if anyone wants to build such client, I could provide a compatible AP server.

@makinTheStuff
Copy link

makinTheStuff commented Jan 5, 2023

Hey guys, I thought I would take a crack at trying to get this running. I will need a few pointers to help with testing it out and it depends on litepub changes on master that haven't been released (as opposed to it's latest tag given some recent changes); but it seems to fire up now

fiatjaf/litepub@v1.1.2...master

# github.com/fiatjaf/no-fed

# errors that seem related to recent changes not yet released for litepub

./main.go:34:33: undefined: litepub.GeneratePrivateKey
./pub.go:52:10: litepub.OrderedCollectionPage is not a generic type
./pub.go:72:16: cannot use json.RawMessage(jpage) (value of type "encoding/json".RawMessage) as type litepub.OrderedCollectionPage in struct literal
./pub.go:103:10: litepub.OrderedCollectionPage is not a generic type
./pub.go:123:16: cannot use json.RawMessage(jpage) (value of type "encoding/json".RawMessage) as type litepub.OrderedCollectionPage in struct literal
./pub.go:150:20: litepub.Create is not a generic type
./pub.go:156:10: litepub.OrderedCollectionPage is not a generic type
./pub.go:172:15: cannot use json.RawMessage(jpage) (value of type "encoding/json".RawMessage) as type litepub.OrderedCollectionPage in struct literal
./storage.go:38:25: undefined: litepub.FetchNote
./storage.go:68:26: undefined: litepub.FetchNotes
./storage.go:68:26: too many errors

Any feedback is always welcome. Here are my latest changes if anyone has a chance to take a look

makinTheStuff/no-fed@bec6e32

@fiatjaf
Copy link
Author

fiatjaf commented Jan 5, 2023

Oops, sorry for that, @makinTheStuff. I've pushed a fix resolving all these dependencies things.
By the way, if you want to contact me, try https://t.me/fiatjaf (Nostr DMs still do not work well for me, but we'll get there).

@garydevenay
Copy link

If available, I'll reserve this and get to work on it. Happy to put a 7-day limit on the reservation.

@makinTheStuff
Copy link

@garydevenay I'm good with that if you want to check it out. If my changes help your more then welcome to use them. I got it to run but I wasnt sure how to test it so I'm not sure whats left. Thanks for offering to help! Let me know if you need a hand

@garydevenay
Copy link

Update on this— Currently testing the changes and functionality I've added. As mentioned in the original bounty, AP sucks to test. I'm thinking of writing a set of tests that will parse and send mock AP events through the handlers, but unsure how far to go once the functionality is working.

This will need a degree of "in-the-wild" testing to have confidence that all cases are handled as expected.

@fiatjaf
Copy link
Author

fiatjaf commented Jan 18, 2023

I was running Mastodon locally to try to test. It wasn't hard to get it running, but I didn't make much progress after that so I don't know if it would have been useful.

@alexgleason
Copy link

alexgleason commented Feb 10, 2023

The main problem I see is that Nostr has no equivalent to a "Follow" activity. ActivityPub servers aren't meant to be queried, they push events to their followers. So the AP server needs to know that a Nostr user is following them.

Best we have is REQ (if this bridge is a relay and not a client). On the AP side they'd see "npubxxx has followed you". But then semantically a CLOSE should correspond to an Unfollow, which would be very annoying on the AP side to see the same people following and unfollowing you whenever their client reconnects.

(Personally I think the bridge makes more sense as an ActivityPub server that's also a Nostr client, but we need a way to inform other AP servers to push events to it regardless.)

Edit: I still think something can be done with ActivityPub relays... but it's going to be wacky!

@alexgleason
Copy link

Good evening, a bridge between ActivityPub and Nostr just dropped: https://soapbox.pub/blog/mostr-fediverse-nostr-bridge/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment