ssbc / ssb-ebt

secure scuttlebutt replication with epidemic-broadcast-trees
MIT License
18 stars 10 forks source link

Synchronous race conditions with ssb-friends #56

Open staltz opened 3 years ago

staltz commented 3 years ago

Context and problem

See #55

ssb-ebt / ssb-friends have always been in a fragile state where they barely work, and if you change something to be async (like via a Promise or just with a 1ms setTimeout), then they stop working.

Suppose there are three peers, Alice, Bob, and Carol. The network connections are set up as Alice <==> Carol <==> Bob, so that Carol is the intermediate.

  1. Alice publishes an new message that she is blocking Bob
  2. Carol receives that message via ssb-ebt
  3. Carol should process that message in ssb-friends and register in Carol's EBT that Alice blocks Bob
  4. Carol should update connected peers (i.e. Bob) about the new message, unless the connected peer should not receive it (because of blocks)

We need (3) to happen strictly before (4), and currently ssb-ebt is working fine, but this is a fragile situation, and any addition of asynchronous work in ssb-ebt or ssb-friends could potentially break this, causing (4) to happen before (3), and then causing Bob to receive Alice's msg, when he shouldn't.

Proposed solutions

We need to create explicit dependencies between these two computations, but it's a bit challenging because it's spread across many modules (ssb-db2, ssb-ebt, epidemic-broadcast-trees, ssb-friends, layered-graph, ssb-replication-scheduler).

Here's one possible solution:

Even with this proposed solution, we have to be careful that every ongoing sbot.ebt.block() (in case it has asynchronous tasks, like promises or whatnot) is completed before ebt.onAppend() is called.