-
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-77: Negentropy syncing #1494
base: master
Are you sure you want to change the base?
Conversation
IMHO, In the long run, sync will have to become a mandatory part of the protocol. I just don't see Nostr taking over everything without robust syncing operations. Yes, we can sync via REQs but that is so bad that I don't actually consider it a viable solution. That means that the sync protocol must be extremely well defined such that we can actually have 100s of different implementations in all possible languages, with all possible database options, working together. We need to simplify and clarify this NIP to the extreme. It needs to become so good that it is fine if we add it to 01.md Libraries can help, but the ability to code it from near scratch is a MUST to me. |
|
||
```jsonc | ||
[ | ||
"NEG-ERR", |
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.
These new message types must be added to readme as well.
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.
Let's not do it for now.
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.
I hope so |
A great one to add, this will be great for mobile clients and for relay to relay syncing. Lots of potential. Let's go! :) |
It would be great to merge this so that we can start checking |
Something that could be helpful for these types of protocol extensions is a consistent machine readable response that indicates it isn't supported. Currently I'm getting several different NOTICE responses (not intended to be machine readable) from relays, such as:
|
https://github.com/fiatjaf/khatru supports this as of now, https://github.com/nbd-wtf/go-nostr has supported it from the client side for some weeks. You were interested in trying it, @gzuuus @barrydeen, so once you did let me know if it's broken. |
@hoytech what do you think of getting rid of the CLOSED and TOO_MANY_RESULTS error messages and reusing the other format that is already common on Nostr of an arbitrary string with a machine-readable prefix, like |
@fiatjaf - On the error message format: Good idea, this would be better. I will push a change shortly. |
As someone who just finished implementing the base negentropy protocol in C# (https://github.com/bezysoftware/negentropy.net) I have a few notes:
|
Added placeholder negentropy tracker nostrability/nostrability#125 |
I am coding in Kotlin at the moment and I am not going to lie. I hate this VarInt and the Query encoding part. Yeah, it's very optimized, but there is so much byte crunching and type overflows that we are going to have bugs everywhere on this. I wish we just made it a regular JSON object when transmitting messages between nodes to keep the Nostr theme of "not really the most optimal, but really easy to code without bugs" |
That was my thought too, all the VarInt and Bound encoding (and especially relative timestamps) is non trivial, but given the complexity of the algorithm overall, I think it's all or nothing. Either adopt Negentropy as it is, or not at all and use something like #1027 I still think it's worth it - invest in base libraries and you'll save a ton in bandwidth |
I don't think varint is saving a lot. Similar to the delta timestamps in the same message, which turns the algo stateful. Maybe I am wrong, but I think @hoytech could have used And yes, we desperately need static test cases. |
If a nostr app, or a nostr relay implements negentropy, is it backwards compatible? |
Kotlin PR is up: hoytech/negentropy#15 |
That depends on the size of the diff. For fun I gutted one of @hoytech's tests with around 40k items on both sides (with 9k mismatches both ways); once with delta timestamps + varints and once without those (numbers+dates encoded as longs - 8 bytes). The non-optimized query was 2x as large in the first round. |
That's the issue with the test cases... They generate But it's ok. We can keep it like that. |
I finally got parity with the C++ and JavaScript implementations on hoytech/negentropy#15 Pros:
Cons:
Meanwhile, something like #826 is: Pros:
Cons:
|
Thank you for this @vitorpamplona! I pretty much agree with your assessment, although I'll make a couple comments. I'm going to find a moment to merge your PR, hopefully this weekend.
The protocol is actually relatively forgiving of implementation differences. Yes, the test-suite is much stricter and does verify that they exactly conform, but this is mostly just to help developers detect bugs, and I could relax this if needed.
It depends. In theory, you could throw away the set of IDs after generating each message and re-run the query for each received message. The protocol is tolerant of changes to the ID set while messages are in flight. This would make it stateless at the expense of much higher CPU usage. Personally I think keeping state is the right tradeoff in most cases. For implementations with btree storage like strfry, queries for specific pre-selected filters (plus their variants with
Yes, this would be wonderful. I will add this to my TODO list and will make some (eventually!). |
I ran into many issues of "forever syncing" when fingerprints/bands didn't perfectly match (because of the bugs in my implementation). I do think a malicious actor can use the sync SPEC to keep relays busy, but my real concern is if there are too many slightly-off implementations of the protocol such that nothing would work and people just give up because of the lack of consistent support across the network. Libraries help, but the risk is still there. Let me know if you need any help running the kotlin/java stuff. |
|
||
Error reasons are the same format as in NIP-01. They should begin with a machine-readable single-word prefix, followed by a `:` and then a human-readable message with more information. | ||
|
||
The current suggested error reasons are |
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.
Should we also add something like invalid: unknown subscription id
? AFAIK there is no equivalent in NIP-01, since it's not needed. In case of CLOSE
message the client is not expecting any reply, so it's fine the relay doesn't send back an error, but in case of MSG
the client is actually waiting for a response, so it makes send to send appropriate error.
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.
Good question. Currently strfry sends closed: unknown subscription handle
in this case. It doesn't bother trying to differentiate between a subscription ID that was previously open but got closed (by a NEG-CLOSE
message, timeout, etc) and one that was never opened in the first place.
The relay portion of this is now implemented in Netstr running here: https://relay.netstr.io/ |
This is a copy of @hoytech's https://github.com/hoytech/strfry/blob/nextneg/docs/negentropy.md with some small tweaks in the text (not in the protocol) just to have it here somewhere.
https://github.com/nostr-protocol/nips/blob/negentropy/77.md