crdt-graph
An op-based 2P2P-Graph CRDT implementation in Rust.
Based on the 2P2P-Graph specification from Shapiro et al., "A comprehensive study of Convergent and Commutative Replicated Data Types" (2011).
Overview
A 2P2P-Graph (Two-Phase Two-Phase Graph) is a conflict-free replicated data type that models a directed graph with add and remove operations for both vertices and edges. Each replica maintains four sets:
| Set | Description |
|---|---|
V_A |
Vertices added |
V_R |
Vertices removed |
E_A |
Edges added |
E_R |
Edges removed |
Updates follow the op-based CRDT model with two phases:
- atSource — Precondition checks executed only on the originating replica.
- downstream — State mutations applied on all replicas (including the source).
Features
- Three built-in graph variants — ID-only (
simple), binary payload (bytes), and string payload (string). - FlatBuffers serialization — Compact binary encoding with 16-byte inline UUID structs (zero-copy).
- UUID v7 identifiers — Time-ordered, globally unique IDs via
uuid::Uuid. petgraphintegration — Convert CRDT state to a standardDiGraphfor graph algorithms.- Convenience traits —
Default,PartialEq,Eq,Hash,Fromconversions on all operation types. - State inspection —
vertex_count(),edge_count(),is_empty(),vertices(),edges()iterators.
Quick Start
Using the built-in simple types (UUID-based, no payload):
use ;
use ;
use Uuid;
#
Custom Types
You can also define your own types by implementing the required traits:
use ;
type Id = u64;
#
Built-in Graph Variants
| Module | Payload | FlatBuffers File ID |
|---|---|---|
types::simple |
None | "CRDT" |
types::bytes |
Option<Vec<u8>> |
"CRD2" |
types::string |
Option<String> |
"CRD3" |
Each variant provides: AddVertex, AddEdge, Graph (type alias), Operation (type alias).
RemoveVertex and RemoveEdge are shared across all variants (crdt_graph::types::{RemoveVertex, RemoveEdge}).
FlatBuffers Serialization
use ;
use simple as fb;
use Uuid;
#
Batch encoding/decoding is also supported via encode_operation_log() / decode_operation_log().
API
| Method | Description |
|---|---|
prepare(op) |
Executes atSource checks, applies locally, and returns the operation to broadcast. |
apply_downstream(op) |
Applies an operation received from a remote replica. |
update_operation(op) |
Convenience wrapper around prepare that discards the return value. |
lookup_vertex(id) |
Returns true if the vertex is in V_A \ V_R. |
vertex_count() |
Number of active (non-removed) vertices. |
edge_count() |
Number of active (non-removed) edges. |
is_empty() |
true if no active vertices or edges. |
vertices() |
Iterator over active vertices. |
edges() |
Iterator over active edges. |
generate_petgraph() |
Converts the current state into a petgraph::DiGraph. |
Preconditions
| Operation | atSource | downstream |
|---|---|---|
addVertex(w) |
— | — |
addEdge(u, v) |
lookup(u) ∧ lookup(v) |
— |
removeVertex(w) |
lookup(w), no active edges |
addVertex(w) delivered |
removeEdge(u, v) |
lookup((u, v)) |
addEdge(u, v) delivered |