nostr-protocol / nips

Nostr Implementation Possibilities
2.35k stars 566 forks source link

Sequence of events #407

Closed Ungigdu closed 1 year ago

Ungigdu commented 1 year ago

Problem: Timestamp (created_at) is chosen by clients

The created_at field is filled by clients, which can lead to problems such as sending a message (via a dishonest client) to the past (like 10 mins ago), sending messages with the same created_at, etc. These issues can mess up the message timeline. Here is an example of DMs between two clients:

3===> the last message but uses the earliest timestamp (created_at)
2===> the second message using the middle timestamp (created_at)
1===> the first message but uses the latest timestamp (created_at)

In a word, created_at is not reliable.

NIP-03 exists, but it might be an overkill. Even if some clients (and relays) agree to use it, one client can still get OTS and hold the message, then send it an hour later. This message would also be inserted into the chat history.

Possible Solution?

Since there is no consensus layer in Nostr, the timeline issues can not be solved by clients themselves. One way to aline those events would be using arrival_time instead of created_at. The relay is the best place to record arrival_time. The relay can attach arrival_time on the event, with a signature from relay if needed. Or, The client may send a new kind of message type ["TIME", ] to query the arrival_time. This method needs to further trust relay.

Another way is event chaining. In scenarios like DM or group chat where events ordering matters, we can chain events by tags as in NIP-10, but with a special marker "pre":

{
  ...other fields
  "tags": [
    ["e", <event-id>, <relay-url>, "root"],
    ["e", <event-id>, <relay-url>, "pre"],
  ],
  "content": "this is a new message!",
  ...other fields
}

The "root" points to the event that starts this chat timeline, and the "pre" points to the last message a client thought was legitimate. Each client can believe its version of chat chain. Relay or other witnesses (can be a special client) can record using a replaceable event that tells which fork should all participants should follow.

Are those ideas good or stupid, worth writing a NIP? Or has someone already solved this problem? Please let me know.

peterzion45 commented 1 year ago

2a8234ef0454347fcff888f39dc52dfcd091f2de708d20f6afde984964b8433c

peterzion45 commented 1 year ago

2a8234ef0454347fcff888f39dc52dfcd091f2de708d20f6afde984964b8433c

Ungigdu commented 1 year ago

2a8234ef0454347fcff888f39dc52dfcd091f2de708d20f6afde984964b8433c

What is this meaning?

Egge21M commented 1 year ago

Clients can already protect themselves by only using relays with proper NIP22 for DMs. In that case the relay becomes the trusted source for timestamps.

Couldn't clients just include a reference to the last post they received? That would form a chain aswell

Ungigdu commented 1 year ago

Clients can already protect themselves by only using relays with proper NIP22 for DMs. In that case the relay becomes the trusted source for timestamps.

I think not, NIP22 can not protect against hacked messages that only have few seconds differ from NOW

Couldn't clients just include a reference to the last post they received? That would form a chain aswell

The "ref" is included by each client in the next message it shall send. Each client will choose its version of "ref". The witness tells clients that which version is the "best", so the clients can have a common chat history otherwise the clients may chat on their own fork.

hydrogenesis commented 1 year ago

npub1qjchhhhqx8t8nc5dnlhqnxd0dmdquj43ml9ddxrkhhu8g5fycvrqahmm2j

alexgleason commented 1 year ago

Same problem on the Fediverse, and the solution is to preserve the original event but add a "discovered_at" column in the database. Filters searching "since" and "until" should use the discovered_at date instead of the event date (and possibly reject events outside of a certain time range). Clients will never be able to solve this without the cooperation of relays.

mikedilger commented 1 year ago

Same problem on the Fediverse, and the solution is to preserve the original event but add a "discovered_at" column in the database. Filters searching "since" and "until" should use the discovered_at date instead of the event date (and possibly reject events outside of a certain time range). Clients will never be able to solve this without the cooperation of relays.

I suggested this back in November https://github.com/nostr-protocol/nips/pull/79 but I got hung up on this notion that if you add any new filters (rather than change the meaning of since and until), relays that don't know about those new filters because their code hasn't been updated would potentially ignore them and send every event (!). So I wanted to change NIP-01 to say that relays must ignore requests containing unknown filters. But then I thought it was too late to change NIP-01. Since that time I've realized nostr NIPs are not written in stone, but we must not break what is already out there.

milahu commented 1 year ago

Problem: Timestamp (created_at) is chosen by clients

The created_at field is filled by clients, which can lead to problems such as sending a message (via a dishonest client)

Possible Solution?

Since there is no consensus layer in Nostr, the timeline issues can not be solved by clients themselves. One way to aline those events would be using arrival_time instead of created_at. The relay is the best place to record arrival_time.

relays can be dishonest too

there is no way to enforce time in a decentral network

you can include "proof of freshness" data like bitcoin block hashes (https://github.com/nostr-protocol/nips/pull/296) (see also NIP-03: OpenTimestamps Attestations for Events)

but this works only in one direction: it is proof that your event was created after the other event. so you cannot fake past events, but you still can fake future events

similar: #569 (timeless sequence of events, chain of events)

nostronaut commented 1 year ago

the proposal sketched on #419 introduces the notion of previous and later messages by using vector/chained commitments of the past event history

thus although timestamps can't be trusted, one recovers partial temporal information by knowing the order of events

on the example above:

3===> the last message but uses the earliest timestamp (created_at)
2===> the second message using the middle timestamp (created_at)
1===> the first message but uses the latest timestamp (created_at)

when implementing #419, the cryptographic vector commitment attest the correct sequence of events, which explicitly contradicts the created_at data field.

thus, events 1 and 2 are included in event 3 commitments of its past history.

Ungigdu commented 1 year ago

thus, events 1 and 2 are included in event 3 commitments of its past history.

That is what I mean. There is no way to add exact timestamp for events, but may be we can manage the sequence. On the other side, nostr support kind-5 events to delete DMs, so the event chaining may fail in many situations. I will close this thread for now, thanks everyone.