Skip to content
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

feat/conflict-and-cro #4

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 8 additions & 18 deletions docs/get-started/conflict.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,18 @@ sidebar_position: 4

# Conflict

## TODO
- explain what a conflict is (operations that are concurrent but do not commute; be careful with the word "commute" because it's mathy)
- explain semantics
- provide a super simple example

---

## Old text
A CRO state can be affected by **concurrent operations** that are not **commutative** (_i.e._ different execution orders produce different results). To avoid this, the CRO must define its behavior in those situations, which we call **_concurrency semantics_**.

Let's considers this hash graph example:
The [**CRO**](./cro.md) state can be affected by [**concurrent**](./concurrency.md) **operations**. If applying these operations in any possible order produces the same state of the object, we do not have to worry about conflicts. Think about a CRO which accepts addition and multiplication as operations. If the initial state is _1_, and we have two **concurrent** operations as below, what is the state of the CRO after applying these operations?

<div align="center">
![alt text](/img/concurrency.png)

**Figure 2:** Hash graph for a register CRO that accepts addition and multiplication.

**Figure 1:** Hash graph for a single number register CRO that accepts addition and multiplication.
</div>
Different execution orders yield:
- ![](https://latex.codecogs.com/svg.latex?(1+7)\cdot3+2=26)
- ![](https://latex.codecogs.com/svg.latex?(1\cdot3)+7+2=12)

Since **addition** and **multiplication** do not commute, and if we define two different execution orders, we will have 2 different results. For example:

1. (1+7)\*3+2=26
2. (1\*3)+7+2=12
This means these operations are not commutative, and they cause a **conflict**. We must define the behavior of the CRO in those situations to make sure every honest replica will arrive at the same state after applying conflicting operations.
We need rules to determine what to do with the **conflicting** operations. Some of the operations might be dropped, the rest needs to be ordered in a replicable manner. This is what we call **_conflict resolution_**. In the above example we could define conflict resolution as "multiplication wins". This way, the final state will always be _12_.

To solve this we must define a concurrency semantic, for example, define that addition goes first in case of concurrency. With this, and considering the example above, every honest replica of this hash graph will arrive at 26 as its final state.
---
24 changes: 24 additions & 0 deletions docs/get-started/cro.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ sidebar_position: 5

# CRO

A **CRO** is a **Conflict-free Replicated Object**. It is a programmable object that can be updated concurrently in real-time and subscribed to as a **PubSub** group on an open P2P network.

Here is a snippet from the pseudocode of defining a CRO:
```
type CRO {
operations: string[];
semanticsType: SemanticsType = {pair-wise or group-wise};
resolveConflicts: (vertices: Vertex[]) returns ResolveConflictsType;
mergeCallback: (operations: Operation[])
}
```
Let's break it down.

Firstly, we need to define an array of operations that can be applied to the CRO. Then we need to specify the semantics ([conflict resolution rules](./conflict.md)) of the CRO. Currently there are two types of conflict resolution: pair-wise and group-wise.

Pair-wise conflict resolution always analyzes two conflicting operations at a time. Group-wise conflict resolution analyzes all conflicting operations at once. The choice of conflict resolution type depends on the application requirements.

The `resolveConflicts` function needs to be implemented and is used as the judge to handle conflicting operations. It takes an array of vertices and returns a `ResolveConflictsType` object. If the `semanticsType` is pair-wise, the array only has two elements. The `ResolveConflictsType` is essensially only useful for the group-wise semantics, as it holds the hashes of conflicting vertices to be reduced (discarded).

Lastly, we need to implement the `mergeCallback` function. The underlying data structure is the [hashgraph](./hashgraph.md). All merging is completed automatically by the hashgraph. The `mergeCallback` function is called after the hashgraph has merged the operations. It is used to notify the application that the merge has been completed, and the final state of the CRO has been updated.

Now let's take a look at a tangible example of **conflicting** operations in a CRO.
Let the CRO be a [pile of sand](https://blog.topology.gg/the-origins-of-topology-from-ledgers-to-sandcastles-part-2/)

## TODO
- explain the structure of a CRO
- state
Expand Down