I found a nice introductory article on delta-state CRDTs here.
Their approach uses a map with a root version vector and tags each key with a "dot" list. The version vector is standard - a map from replica ids to version integers. A dot represents a single edit - represented by a pair (replica id, version)
. Each entry in the version vector summarizes a series of edits or "dots". I've seen several other approaches in various research papers that use a very similar approach to this.
To calculate a diff a replica will send its root version vector to a peer. The peer will walk through each key in its map, looking at the dot list for each of them. If any of the dots in this dot list are not "covered" by the incoming version vector, then the keys & values associated with those dots must be packaged and sent to the peer.
The CRDT map is composable, so a particular value could be implemented using a LWW (last-write-wins) register, a MVV register, a CRDT set, another CRDT map, etc.
There are three things that aren't clear to me.
[In the] old Remove Wins Map the tombstone was a single dot. With Add Wins Maps this is more complex, and that is the subject of my next post!
It's not clear to why anything special needs to be done to get add wins behavior. In my mind, each element in the set would be tagged with a single dot. When a remove occurs, the item is tagged with a tombstone and a single dot. Because the version vectors and dots will tell us when a concurrent update and remove occurred, we can simple discard the tombstone.
Thank you in advance for your help clearing up these questions.
I would recommend contacting the author for definite answers (the post is rather sparse), but here is my attempt at interpreting it:
The only example they show with multiple dots is actually a counter, not an LWW register. The traditional state-based vector counter always stores the most recent dot from each replica.
For the LWW register, they might need to store all dots to handle removals properly. This is definitely the case for Add-Wins removals [1], but I'm not sure for their Remove-Wins removals.
I agree, it seems like they are using a causal-overwrite rule (a new dot overwrites causally prior dots). Otherwise, I would expect the root in each figure to contain all causal dots that appear in the tree.
The traditional algorithm for Add-Wins removals is [2]:
I think this is what you are getting it; perhaps the author just considers it more complicated? Or, there could be complications involving the tree structure / diff procedure.
[1] "Assessing the understandability of a distributed algorithm by tweeting buggy pseudocode", Martin Kleppmann, https://doi.org/10.48456/tr-969
[2] "An optimized conflict-free replicated set", Annette Bieniusa et al., https://arxiv.org/abs/1210.3368