|
@@ -1,69 +1,82 @@
|
|
|
# Event Graph
|
|
# Event Graph
|
|
|
|
|
|
|
|
-The event graph represents sequential events in an asynchronous environment.
|
|
|
|
|
|
|
+Event graph is a syncing mechanism between nodes working asynchronously.
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
+
|
|
|
|
|
+The graph here is a DAG (Directed Acyclic Graph) in which the nodes
|
|
|
|
|
+(vertices) are user created and pushed events and the edges are the
|
|
|
|
|
+parent-child relation between the two endpoints.
|
|
|
|
|
|
|
|
-Events can form small forks which should be quickly reconciled as new nodes are
|
|
|
|
|
-added to the structure and pull them in.
|
|
|
|
|
|
|
+The main purpose of the graph is synchronization. This allows nodes in
|
|
|
|
|
+the network maintain a fully synced store of objects. How those objects
|
|
|
|
|
+are interpreted is up to the application.
|
|
|
|
|
|
|
|
-Ties are broken using the timestamps inside the events.
|
|
|
|
|
|
|
+Each node is read-only and this is an append-only data structure.
|
|
|
|
|
+However the application may wish to prune old data from the store to
|
|
|
|
|
+conserve memory.
|
|
|
|
|
|
|
|
-The main purpose of the graph is *synchronization*. This allows nodes in the network
|
|
|
|
|
-maintain a fully synced store of objects. How those objects are interpreted is up
|
|
|
|
|
-to the application.
|
|
|
|
|
|
|
+## Synchronization
|
|
|
|
|
|
|
|
-We add a little more information about the objects which is that they are events
|
|
|
|
|
-with a timestamp, which allows our algorithm to be more intelligent.
|
|
|
|
|
|
|
+When a new node joins the network it starts with a genesis event, and
|
|
|
|
|
+will:
|
|
|
|
|
+1. ask for all connected peers for their unreferenced events (tips).
|
|
|
|
|
+2. Compare received tips with local ones, identify which we are missing.
|
|
|
|
|
+3. Request missing tips from peers.
|
|
|
|
|
+4. Recursively request events backwards.
|
|
|
|
|
|
|
|
-Each node is read-only and this is an append-only data structure. However the
|
|
|
|
|
-application may wish to prune old data from the store to conserve memory.
|
|
|
|
|
|
|
+We always save the tree database so once we restart before next
|
|
|
|
|
+rotation we reload the tree and continue from where we left off
|
|
|
|
|
+(previous steps 1 through 4).
|
|
|
|
|
|
|
|
-## Synchronization
|
|
|
|
|
|
|
+We stay in sync while connected by properly handling a new recieved
|
|
|
|
|
+event, we insert it into our dag and mark it as seen, this new event
|
|
|
|
|
+will be a new unreferenced event to be referenced by a newer event
|
|
|
|
|
+if we for some reason didn't receive the event, we will be requesting
|
|
|
|
|
+it when reciveing newer events as we don't accept events unless we have
|
|
|
|
|
+their parents existing in our dag.
|
|
|
|
|
|
|
|
-Nodes in the event graph are active, whereas nodes not yet in the graph are orphans.
|
|
|
|
|
|
|
+Synchronization task should start as soon as we connect to the p2p network.
|
|
|
|
|
|
|
|
-When node A receives an event from node B, it will check whether all parents are in the
|
|
|
|
|
-active pool. If there are missing parents then:
|
|
|
|
|
|
|
+## Sorting events
|
|
|
|
|
|
|
|
-1. Check whether the missing parents exist in the orphans pool.
|
|
|
|
|
- 1. If they have missing parents (they should), then request their missing parent events
|
|
|
|
|
- from node B.
|
|
|
|
|
-2. If the missing parents are not in the orphans pool:
|
|
|
|
|
- 1. Add this event to the orphans pool.
|
|
|
|
|
- 2. Request the missing parent events from node B.
|
|
|
|
|
|
|
+We perform a topological order of the dag, where we convert the dag
|
|
|
|
|
+into a sequence starting from the erlier event (genesis) to the later.
|
|
|
|
|
|
|
|
-Once a node is successfully added to the active pool, and linked in the event graph, then
|
|
|
|
|
-we call `reorganize()`. This function loops through all the orphans, and tries to relink
|
|
|
|
|
-them with the active pool. If there are any missing parents, then they are added back to
|
|
|
|
|
-the orphan pool.
|
|
|
|
|
|
|
+Since events could have multiple parents, there is no uniqe ordering of
|
|
|
|
|
+this dag, meaning events in the same layer could switch places in the
|
|
|
|
|
+resulted sequence, to overcome this we introduce timestamps as metadata
|
|
|
|
|
+of the events, we do `Depth First Search` (DFS) of the graph for every
|
|
|
|
|
+unreferenced tip to ensure visiting every event and sort them based on
|
|
|
|
|
+thier timestamp.
|
|
|
|
|
+
|
|
|
|
|
+In case of a tie in timestamps we use event id to break the tie.
|
|
|
|
|
|
|
|
## Creating an Event
|
|
## Creating an Event
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
-In this example A creates a new event. Since the event is new, it is impossible for
|
|
|
|
|
-any nodes in the network to possess it, so A does not need to send an `inv`.
|
|
|
|
|
|
|
+Typically events are propagated through the network by rebroadcasting
|
|
|
|
|
+the received event to other connected peers.
|
|
|
|
|
|
|
|
-1. A creates a new event.
|
|
|
|
|
-2. A sends `event` to $B_1, \dots, B_n$
|
|
|
|
|
|
|
+In this example A creates a new event and boradcast it to its connected
|
|
|
|
|
+peers (B nodes), and those in turn rebroadcast it to their connected
|
|
|
|
|
+peers (C nodes), and so on, until every single node has received the
|
|
|
|
|
+event.
|
|
|
|
|
+1. `Node A` creates a new event.
|
|
|
|
|
+2. `Node A` sends `event` to $B_1, \dots, B_n$
|
|
|
3. For each $B_i$ in $\{B_1, \dots, B_n\}$:
|
|
3. For each $B_i$ in $\{B_1, \dots, B_n\}$:
|
|
|
- 1. Create an `inv` representing the event.
|
|
|
|
|
- 2. Broadcast to all connected nodes `p2p.broadcast(inv)`.
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-Upon receiving an `inv`:
|
|
|
|
|
-
|
|
|
|
|
-1. Check if we already have the event. If not then reply back with `getevent`.
|
|
|
|
|
-2. The node receives `getevent`, and sends `event` back.
|
|
|
|
|
-
|
|
|
|
|
-So in this diagram, A will send `event` to $B_1, \dots, B_6$. Each $B_i$ will respond
|
|
|
|
|
-back to A with `inv`. Each one of $C_1, \dots, C_3$ also receive `inv`,
|
|
|
|
|
-and since they don't have the event, they will send back to $B_3$,
|
|
|
|
|
-a `getevent` message. $B_3$ will send them the `event`.
|
|
|
|
|
|
|
+ 1. validate the event (is it older than genesis, time drifted, malicous or
|
|
|
|
|
+ not, etc..).
|
|
|
|
|
+ 2. Check if we already have the event. also check if we have all of
|
|
|
|
|
+ its parents.
|
|
|
|
|
+ 3. request missing parents if any and add them to the DAG.
|
|
|
|
|
+ 4. if all the checks pass we add the actual recieved event to the DAG.
|
|
|
|
|
+ 5. Relay the event to other peers.
|
|
|
|
|
|
|
|
## Genesis Event
|
|
## Genesis Event
|
|
|
|
|
|
|
|
-All nodes start with a single hardcoded genesis event in their graph. The application
|
|
|
|
|
-layer should ignore this event. This serves as the origin event for synchronization.
|
|
|
|
|
|
|
+All nodes start with a single hardcoded genesis event in their graph.
|
|
|
|
|
+The application layer should ignore this event. This serves as the
|
|
|
|
|
+origin event for synchronization.
|
|
|
|
|
|