Przeglądaj źródła

event_graph spec

x 3 lat temu
rodzic
commit
84e82ebd6b

+ 2 - 0
doc/src/SUMMARY.md

@@ -25,6 +25,8 @@
   - [ircd](misc/ircd/ircd.md)
   	- [Specification](misc/ircd/specification.md)
   - [tau](misc/tau.md)
+  - [event_graph](misc/event_graph/event_graph.md)
+    - [Network Protocol](misc/event_graph/network_protocol.md)
   - [HashChain](misc/hashchain/hashchain.md)
   	- [Network Protocol](misc/hashchain/network_protocol.md)
   - [darkwiki](misc/darkwiki.md)

+ 65 - 0
doc/src/misc/event_graph/event_graph.md

@@ -0,0 +1,65 @@
+# Event Graph
+
+The event graph represents sequential events in an asynchronous environment.
+
+![](event_graph.png)
+
+Events can form small forks which should be quickly reconciled as new nodes are
+added to the structure and pull them in.
+
+Ties are broken using the timestamps inside the events.
+
+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.
+
+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.
+
+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.
+
+## Synchronization
+
+Nodes in the event graph are active, whereas nodes not yet in the graph are orphans.
+
+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:
+
+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.
+
+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.
+
+## Creating an Event
+
+![](p2p-network.png)
+
+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`.
+
+1. A creates a new event.
+2. A sends `event` to $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)`.
+4. A waits for 3 nodes to respond back with the `inv` confirming they received it.
+5. Until A receives the `inv` confirms, it will wait for 1 minute and then
+   resend the `event` message.
+
+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`, and A will stop sending `event`. 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`.

BIN
doc/src/misc/event_graph/event_graph.png


+ 229 - 0
doc/src/misc/event_graph/event_graph.svg

@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="210mm"
+   height="297mm"
+   viewBox="0 0 210 297"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+   sodipodi:docname="event_graph.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#000000"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="false"
+     inkscape:zoom="6.2217172"
+     inkscape:cx="245.67173"
+     inkscape:cy="319.52594"
+     inkscape:window-width="3838"
+     inkscape:window-height="2158"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1" />
+  <defs
+     id="defs2">
+    <marker
+       style="overflow:visible"
+       id="marker1772"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1Lstart"
+       inkscape:isstock="true">
+      <path
+         transform="scale(0.8) translate(12.5,0)"
+         style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path1770" />
+    </marker>
+    <marker
+       style="overflow:visible;"
+       id="Arrow1Mend"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mend"
+       inkscape:isstock="true">
+      <path
+         transform="scale(0.4) rotate(180) translate(10,0)"
+         style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path1109" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1Mstart"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mstart"
+       inkscape:isstock="true">
+      <path
+         transform="scale(0.4) translate(10,0)"
+         style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path1106" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1Lstart"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1Lstart"
+       inkscape:isstock="true">
+      <path
+         transform="scale(0.8) translate(12.5,0)"
+         style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path1100" />
+    </marker>
+    <marker
+       style="overflow:visible;"
+       id="Arrow1Lend"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1Lend"
+       inkscape:isstock="true">
+      <path
+         transform="scale(0.8) rotate(180) translate(12.5,0)"
+         style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path1103" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1Mstart-5"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mstart"
+       inkscape:isstock="true">
+      <path
+         transform="matrix(0.4,0,0,0.4,4,0)"
+         style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         id="path1106-6" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1Mend-2"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mend"
+       inkscape:isstock="true">
+      <path
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         id="path1109-9" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1Mstart-5-2"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mstart"
+       inkscape:isstock="true">
+      <path
+         transform="matrix(0.4,0,0,0.4,4,0)"
+         style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         id="path1106-6-7" />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1Mend-2-0"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mend"
+       inkscape:isstock="true">
+      <path
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         id="path1109-9-9" />
+    </marker>
+  </defs>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       style="fill:none;fill-rule:evenodd;stroke-width:0.264583;stroke:#ffffff;stroke-opacity:1"
+       id="rect31"
+       width="5.3849921"
+       height="5.3849921"
+       x="17.013466"
+       y="73.212929" />
+    <rect
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.264583;stroke-opacity:1"
+       id="rect31-7"
+       width="5.3849921"
+       height="5.3849921"
+       x="48.76347"
+       y="73.212929" />
+    <rect
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.264583;stroke-opacity:1"
+       id="rect31-3"
+       width="5.3849921"
+       height="5.3849921"
+       x="32.888466"
+       y="67.921265" />
+    <rect
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.264583;stroke-opacity:1"
+       id="rect31-3-6"
+       width="5.3849921"
+       height="5.3849921"
+       x="32.888466"
+       y="78.504593" />
+    <rect
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.264583;stroke-opacity:1"
+       id="rect31-3-5"
+       width="5.3849921"
+       height="5.3849921"
+       x="64.638474"
+       y="67.921265" />
+    <rect
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.264583;stroke-opacity:1"
+       id="rect31-3-6-3"
+       width="5.3849921"
+       height="5.3849921"
+       x="64.638474"
+       y="78.504593" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend)"
+       d="m 32.35073,70.422846 -9.823034,5.45393 9.749113,5.364727"
+       id="path1098"
+       sodipodi:nodetypes="ccc" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart-5);marker-end:url(#Arrow1Mend-2)"
+       d="m 64.100732,70.422846 -9.823034,5.45393 9.749113,5.364727"
+       id="path1098-1"
+       sodipodi:nodetypes="ccc" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart)"
+       d="M 48.45094,75.876776 38.36162,81.241503"
+       id="path2761" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="m 38.330225,70.422846 10.120715,5.45393"
+       id="path1098-1-3" />
+  </g>
+</svg>

+ 50 - 0
doc/src/misc/event_graph/network_protocol.md

@@ -0,0 +1,50 @@
+# Network Protocol
+
+## Common Structures
+
+### EventId
+
+```rust
+type EventId = [u8; 32];
+```
+
+## inv
+
+Inventory vectors are used for notifying other nodes about objects they have or data which is being requested.
+
+| Description   | Data Type      	   | Comments           		|
+|-------------- | -------------------- | -------------------------- |
+| invs	  	  	| `Vec<EventId>`       | Inventory items    		|
+
+Upon receiving an unknown inventory object, a node will issue `getevent`.
+
+## getevent
+
+Requests event data from a node.
+
+| Description   | Data Type      	   | Comments           		|
+|-------------- | -------------------- | -------------------------- |
+| invs	  	  	| `Vec<EventId>`       | Inventory items    		|
+
+## event
+
+Event object data. This is either sent when a new event is created, or in response to `getevent`.
+
+| Description   | Data Type      	   | Comments           		|
+|-------------- | -------------------- | -------------------------- |
+| parents	  	| `Vec<EventId>`       | Parent events      		|
+| timestamp 	| `u64`                | Event timestamp    		|
+| action    	| `u8`                 | Type of event      		|
+| data      	| `Vec<u8>`            | Event specific data		|
+
+## getheads
+
+This message is *only* sent the first time a node connects to the network.
+It uses this message to synchronize with the current network state.
+
+Once updated, a node uses the messages above to stay synchronized.
+
+| Description   | Data Type      	   | Comments           		|
+|-------------- | -------------------- | -------------------------- |
+| invs	  	  	| `Vec<EventId>`       | Inventory items    		|
+

BIN
doc/src/misc/event_graph/p2p-network.png


+ 412 - 0
doc/src/misc/event_graph/p2p-network.svg

@@ -0,0 +1,412 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="210mm"
+   height="297mm"
+   viewBox="0 0 210 297"
+   version="1.1"
+   id="svg3343"
+   inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+   sodipodi:docname="p2p-network.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview3345"
+     pagecolor="#000000"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="false"
+     inkscape:zoom="8"
+     inkscape:cx="436.6875"
+     inkscape:cy="420.875"
+     inkscape:window-width="3838"
+     inkscape:window-height="2158"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1" />
+  <defs
+     id="defs3340">
+    <marker
+       style="overflow:visible;"
+       id="Arrow1Mend"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mend"
+       inkscape:isstock="true">
+      <path
+         transform="scale(0.4) rotate(180) translate(10,0)"
+         style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path1109" />
+    </marker>
+    <marker
+       style="overflow:visible;"
+       id="Arrow1Lend"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1Lend"
+       inkscape:isstock="true">
+      <path
+         transform="scale(0.8) rotate(180) translate(12.5,0)"
+         style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path1103" />
+    </marker>
+  </defs>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.264999"
+       id="path3369"
+       cx="104.79392"
+       cy="113.9286"
+       r="5.5445471" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+       x="102.38235"
+       y="116.50036"
+       id="text4715"><tspan
+         sodipodi:role="line"
+         id="tspan4713"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+         x="102.38235"
+         y="116.50036">A</tspan></text>
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.211999"
+       id="path3369-9-4"
+       cx="120.66891"
+       cy="113.92859"
+       r="4.4356375" />
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.211999"
+       id="path3369-9-4-5"
+       cx="112.73141"
+       cy="129.80359"
+       r="4.4356375" />
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.211999"
+       id="path3369-9-4-5-4"
+       cx="96.856415"
+       cy="129.80359"
+       r="4.4356375" />
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.211999"
+       id="path3369-9-4-5-6"
+       cx="112.73141"
+       cy="98.053589"
+       r="4.4356375" />
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.211999"
+       id="path3369-9-4-5-4-4"
+       cx="96.856415"
+       cy="98.053589"
+       r="4.4356375" />
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.211999"
+       id="path3369-9-4-5-4-0"
+       cx="88.918915"
+       cy="113.92859"
+       r="4.4356375" />
+    <g
+       id="g25820"
+       transform="matrix(0.8,0,0,0.8,22.115767,19.554428)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="109.79068"
+         y="100.09619"
+         id="text4715-3-5-4-8"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="109.79068"
+           y="100.09619">B</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="114.1646"
+         y="101.29524"
+         id="text16855"><tspan
+           sodipodi:role="line"
+           id="tspan16853"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="114.1646"
+           y="101.29524">2</tspan></text>
+    </g>
+    <g
+       id="g25832"
+       transform="matrix(0.8,0,0,0.8,23.675027,22.709452)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="117.72816"
+         y="115.97119"
+         id="text4715-3-5-4-8-6"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-8"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="117.72816"
+           y="115.97119">B</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="122.1021"
+         y="117.17023"
+         id="text16855-9"><tspan
+           sodipodi:role="line"
+           id="tspan16853-2"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="122.1021"
+           y="117.17023">3</tspan></text>
+    </g>
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.1325"
+       id="path3369-9-4-7"
+       cx="128.60645"
+       cy="101.22859"
+       r="2.7722735" />
+    <g
+       id="g25832-2"
+       transform="matrix(0.5,0,0,0.5,67.985251,44.216629)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="117.72816"
+         y="115.97119"
+         id="text4715-3-5-4-8-6-2"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-8-61"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="117.72816"
+           y="115.97119">C</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="122.1021"
+         y="117.17023"
+         id="text16855-9-0"><tspan
+           sodipodi:role="line"
+           id="tspan16853-2-6"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="122.1021"
+           y="117.17023">1</tspan></text>
+    </g>
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.1325"
+       id="path3369-9-4-7-5"
+       cx="136.01476"
+       cy="113.92857"
+       r="2.7722735" />
+    <g
+       id="g25832-2-9"
+       transform="matrix(0.5,0,0,0.5,75.393573,56.916621)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="117.72816"
+         y="115.97119"
+         id="text4715-3-5-4-8-6-2-4"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-8-61-9"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="117.72816"
+           y="115.97119">C</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="122.1021"
+         y="117.17023"
+         id="text16855-9-0-0"><tspan
+           sodipodi:role="line"
+           id="tspan16853-2-6-9"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="122.1021"
+           y="117.17023">2</tspan></text>
+    </g>
+    <circle
+       style="fill:none;stroke:#ffffff;stroke-width:0.1325"
+       id="path3369-9-4-7-5-1"
+       cx="128.60645"
+       cy="126.62857"
+       r="2.7722735" />
+    <g
+       id="g25832-2-9-7"
+       transform="matrix(0.5,0,0,0.5,67.985251,69.61662)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="117.72816"
+         y="115.97119"
+         id="text4715-3-5-4-8-6-2-4-7"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-8-61-9-1"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="117.72816"
+           y="115.97119">C</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="122.1021"
+         y="117.17023"
+         id="text16855-9-0-0-1"><tspan
+           sodipodi:role="line"
+           id="tspan16853-2-6-9-5"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="122.1021"
+           y="117.17023">3</tspan></text>
+    </g>
+    <g
+       id="g25850"
+       transform="matrix(0.8,0,0,0.8,17.300912,22.709452)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="85.978165"
+         y="115.97119"
+         id="text4715-3-5-4-8-6-7"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-8-1"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="85.978165"
+           y="115.97119">B</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="90.352104"
+         y="117.17023"
+         id="text16855-9-7"><tspan
+           sodipodi:role="line"
+           id="tspan16853-2-2"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="90.352104"
+           y="117.17023">6</tspan></text>
+    </g>
+    <g
+       id="g25838"
+       transform="matrix(0.8,0,0,0.8,22.053755,25.904434)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="109.79066"
+         y="131.84619"
+         id="text4715-3-5-4-8-6-6"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-8-6"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="109.79066"
+           y="131.84619">B</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="114.16462"
+         y="133.04523"
+         id="text16855-9-4"><tspan
+           sodipodi:role="line"
+           id="tspan16853-2-9"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="114.16462"
+           y="133.04523">4</tspan></text>
+    </g>
+    <g
+       id="g25844"
+       transform="matrix(0.8,0,0,0.8,18.922851,25.884452)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="93.915665"
+         y="131.84619"
+         id="text4715-3-5-4-8-6-6-5"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-8-6-0"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="93.915665"
+           y="131.84619">B</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="98.289635"
+         y="133.04523"
+         id="text16855-9-4-4"><tspan
+           sodipodi:role="line"
+           id="tspan16853-2-9-8"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="98.289635"
+           y="133.04523">5</tspan></text>
+    </g>
+    <g
+       id="g25826"
+       transform="matrix(0.8,0,0,0.8,18.929741,19.554428)">
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="93.915695"
+         y="100.09619"
+         id="text4715-3-5-4-8-4"><tspan
+           sodipodi:role="line"
+           id="tspan4713-7-2-7-8-9"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.05556px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="93.915695"
+           y="100.09619">B</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+         x="98.289604"
+         y="101.29524"
+         id="text16855-2"><tspan
+           sodipodi:role="line"
+           id="tspan16853-0"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.264583"
+           x="98.289604"
+           y="101.29524">1</tspan></text>
+    </g>
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="m 107.67082,109.10652 3.49707,-6.9134"
+       id="path30982" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="m 110.29831,114.27933 5.86294,-0.14496"
+       id="path31318" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="m 107.48814,118.92633 3.13883,7.00616"
+       id="path31584" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       d="m 101.76691,118.50271 -3.033402,7.16933"
+       id="path31883" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="m 99.205054,113.63014 -5.672135,0.38047"
+       id="path32248" />
+    <path
+       style="fill:none;stroke:#e9ffff;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       d="m 102.28833,108.91984 -3.454828,-6.82581"
+       id="path32613" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="m 123.19041,110.31148 4.04666,-6.62298"
+       id="path32879" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       d="m 125.14649,113.98723 7.94254,-0.0614"
+       id="path33211" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="m 123.07595,117.75237 4.18941,6.33321"
+       id="path33477" />
+  </g>
+</svg>