-
Notifications
You must be signed in to change notification settings - Fork 411
MSC4353: Per-origin linear chain #4353
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,164 @@ | ||||||
# MSC4353: Per origin linear chain | ||||||
|
||||||
Currently, servers can produce events that are disconnected from the | ||||||
server's own causal history. This allows servers to produce events | ||||||
that are deteched or at conflict with their own decisions. This issue | ||||||
is exacerbated as servers can also create events concurrent with their | ||||||
own, and it is not actually possible to prove a given server is a | ||||||
byzantine traitor/equivocator. | ||||||
|
||||||
These conditions allow for servers to ignore their own causal history | ||||||
in order to erase or modify it, leaving other servers without proof of | ||||||
malice or inconsistency. | ||||||
|
||||||
## Example using today's room model | ||||||
|
||||||
 | ||||||
|
||||||
Consider A scenario where there are three servers in a room: Blue, | ||||||
Green, and Yellow. Consider that Blue immediately bans Yellow after | ||||||
Yellow joins the room and the ban event directly references Yellow's | ||||||
join in `prev_events`. Consider that concurrent to Blue's ban, | ||||||
Yellow sends a message. So that Yellow's join event has to known | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
causal successors, Blue's ban targetting Yellow, and Yellow's | ||||||
message. | ||||||
|
||||||
Now consider that Green sends an event referencing Yellow's message | ||||||
in `prev_events`, and forwards this to Blue. | ||||||
|
||||||
Now consider that Blue sends an event that references Green's event, | ||||||
indirectly tying up the diverging branch, but inadvertanly introducing | ||||||
Yellow's concurrent message into Blue's own recognised causal history. | ||||||
|
||||||
### Discussion | ||||||
|
||||||
This is a huge problem. Blue has inadvertently been tricked into referencing | ||||||
an event that it has likely soft failed (under partial sync). This example | ||||||
demonstrates that `prev_events` cannot be used as a causal frontier | ||||||
for a given server's understanding of causal history, because | ||||||
the server is not actually in control of its own history. | ||||||
|
||||||
Additionally, it is impossible to know whether Blue's ban on Yellow is | ||||||
an attempt to abuse the room model to erase Yellow's message | ||||||
retroactively. | ||||||
|
||||||
## Proposal | ||||||
|
||||||
We propose that a new field is added to the PDU, the | ||||||
`origin_predecessor`. | ||||||
|
||||||
This means that every event will reference either one or no | ||||||
predecessors from the same origin. | ||||||
|
||||||
This has some major advantages: | ||||||
|
||||||
- Intentional forks are explicit and detectable. Servers cannot create | ||||||
events concurrent to their own causal predecessors without | ||||||
explicitly ignoring their maintained forward extremity. The proposal | ||||||
does not prevent this, but it does mean that such an equivocation is | ||||||
detectable and provable. And so the sender's repuatation can become | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
tarnished as they are now known to be a byzantine traitor. | ||||||
|
||||||
- Within the context of the terminology from [MSC4349: Causal barriers | ||||||
and | ||||||
enforcement](https://github.com/matrix-org/matrix-spec-proposals/pull/4349), | ||||||
when servers abuse causal barriers (e.g. membership events) to erase | ||||||
either their own, or another server's history, this is now always | ||||||
detectable. | ||||||
|
||||||
In addition this enhances serveral other proposals both current and | ||||||
future: | ||||||
|
||||||
- In-DAG key based MSCs such as MSC4243 and MSC4345, and any | ||||||
psuedo-identity proposal: it is simplier to reason about key | ||||||
revocation or rotation when describing the causal frontier for which | ||||||
the key was valid. | ||||||
|
||||||
- Any attempt to specify an epoch based synchronisation for rooms | ||||||
would both be simplified through the use of linear chains and also | ||||||
and also more secure through equivocation detection. | ||||||
|
||||||
- Ban events would no longer be plagued by soft failure, as a future | ||||||
proposal could mandate that the ban is scoped to a target's | ||||||
predecessor. In order to canonicalise the events that the target | ||||||
sent before they were banned. | ||||||
|
||||||
### An example of bans with linear origin chain | ||||||
|
||||||
 | ||||||
|
||||||
Now with a linear origin chain in place, we can determine that Blue's | ||||||
ban on Yellow was not an attempt to erase Yellow. | ||||||
|
||||||
### An example of erasure with linear origin chain | ||||||
|
||||||
 | ||||||
|
||||||
If Blue does attempt to retroactively erase Yellow, it must explicitly | ||||||
create an event that is concurrent with its own origin chain. And thus | ||||||
it is observable to everyone that Blue is an equivocator/byzantine | ||||||
traitor. As Blue's own events will have multiple causal successors | ||||||
sent by Blue. | ||||||
Comment on lines
+93
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's still possible to erase history, it's just that doing so without creating a concurrent event requires you to explicitly acknowledge yellow's history as a part of the ban. And if bans are mandated to be scoped to a target's origin predecessor, it is then actually impossible to abuse to erase history. Since a condition for authorising the ban would be not to contradict your own causal frontier in auth rules. |
||||||
|
||||||
### Situations for which there is no `origin_predecessor` | ||||||
|
||||||
We specify the situations for which no `origin_predecessor` | ||||||
can be expected: | ||||||
|
||||||
1. The `m.room.create` event. | ||||||
2. Any `m.room.member` event with a membership of `join` or | ||||||
`knock`. | ||||||
|
||||||
This validation is enforced by authorization rules. | ||||||
|
||||||
Usually there will only be one `m.room.membership` event within a | ||||||
room's history per sender that has no `origin_predecessor` unless the | ||||||
sender is an equivocator. | ||||||
|
||||||
## Potential issues | ||||||
|
||||||
### Some current implementations may not synchronise within one room | ||||||
|
||||||
Some implementations may not currently synchronise within one room. We | ||||||
believe Synapse has a bug where forward extremities can be created | ||||||
through sequential use of `/send`. It's not understood by me | ||||||
whether this is a bug or an intentional design decision(?) | ||||||
|
||||||
### Recovery from downtime/db failure | ||||||
|
||||||
Extra care must be taken to ensure that implementations maintain | ||||||
knowledge of their forward_extremity. Currently it doesn't matter if a | ||||||
server sends events with only partial knowledge of their prior | ||||||
history. Implementations may need to query other servers and ensure | ||||||
they have complete knowledge of their own forward extremity. | ||||||
Comment on lines
+127
to
+133
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that if servers persist events before sending them, then the risk is limited to db recovery. While querying other servers for the extremity may be necessary in that scenario, equally the server key could be rotated within the context of #4345 instead. Which removes the risk entirely. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunatly it is entirely possible through a naive db restore that a server sends authorization events that conflict with its prior history that is now unknown to itself. So even if a definition of a traitor is liberalised it's still going to be possible to become one by accident. We don't actually propose that equivicators or inconsistent servers are noted or even acted upon in any way but it's still going to be important that we allow ways out (which key rotation seems to be the best of them). |
||||||
|
||||||
### Leaving, forgetting, and rejoining | ||||||
|
||||||
If knowledge of the final leave event is not maintained, a concurrent | ||||||
join event must be created. Mitigiating this through modification of | ||||||
the `/make_join` handshake may allow the trusted server to frame the | ||||||
joiner as an equivocator. | ||||||
|
||||||
## Alternatives | ||||||
|
||||||
### Putting the `origin_predecessor` in `prev_events` | ||||||
|
||||||
We could put the `origin_predecessor` in `prev_events` but: | ||||||
|
||||||
- Where to find the `origin_predecessor` is no longer deterministic. | ||||||
|
||||||
Instead we could also put it in the first element of `prev_events` but | ||||||
this seems inappropriate and allows for implementors to be | ||||||
accidentally ignorant of the reserved use. | ||||||
|
||||||
## Security considerations | ||||||
|
||||||
- None considered | ||||||
|
||||||
## Unstable prefix | ||||||
|
||||||
NA. | ||||||
|
||||||
## Dependencies | ||||||
|
||||||
None |
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.
Implementation requirements: