feat: Introduce Hybrid Logical Clocks in protobuf, update architecture documentation, and add HLC test cases.

This commit is contained in:
2025-12-20 14:29:03 +01:00
commit e1405bb910
20 changed files with 522 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
[package]
name = "lattice-core"
description = "Core types for Lattice: nodes, sigchains, entries, and vector clocks"
version.workspace = true
edition.workspace = true
license.workspace = true
[dependencies]
ed25519-dalek = { workspace = true }
rand = { workspace = true }
prost = { workspace = true }
thiserror = { workspace = true }
bytes = { workspace = true }
[dev-dependencies]
tokio-test = { workspace = true }
+9
View File
@@ -0,0 +1,9 @@
//! Log entries (atomic operations)
/// An atomic, batched operation in the sigchain.
///
/// Entries are the fundamental unit of change in Lattice.
/// The KV store is a "view" generated by replaying these entries.
pub struct Entry {
// TODO: operation data, signature, prev_hash
}
+17
View File
@@ -0,0 +1,17 @@
//! Lattice Core
//!
//! Core types for the Lattice distributed mesh:
//! - **Node**: Identity with Ed25519 keypair
//! - **SigChain**: Append-only cryptographically signed log
//! - **Entry**: Atomic operations in the log
//! - **VectorClock**: Causality tracking for reconciliation
pub mod node;
pub mod sigchain;
pub mod entry;
pub mod vector_clock;
pub use node::Node;
pub use sigchain::SigChain;
pub use entry::Entry;
pub use vector_clock::VectorClock;
+30
View File
@@ -0,0 +1,30 @@
//! Node identity and cryptographic keys
use ed25519_dalek::{SigningKey, VerifyingKey};
use rand::rngs::OsRng;
/// A node in the Lattice mesh.
///
/// Each node has an Ed25519 keypair used for signing sigchain entries
/// and establishing trust within the network.
pub struct Node {
signing_key: SigningKey,
}
impl Node {
/// Generate a new node with a random keypair.
pub fn generate() -> Self {
let signing_key = SigningKey::generate(&mut OsRng);
Self { signing_key }
}
/// Get the node's public key (identity).
pub fn public_key(&self) -> VerifyingKey {
self.signing_key.verifying_key()
}
/// Get the signing key for creating signatures.
pub fn signing_key(&self) -> &SigningKey {
&self.signing_key
}
}
+20
View File
@@ -0,0 +1,20 @@
//! Cryptographic SigChain (append-only signed log)
/// An append-only log where each entry is cryptographically signed
/// and hash-linked to the previous entry.
pub struct SigChain {
// TODO: entries, hash chain
}
impl SigChain {
/// Create a new empty sigchain.
pub fn new() -> Self {
Self {}
}
}
impl Default for SigChain {
fn default() -> Self {
Self::new()
}
}
+41
View File
@@ -0,0 +1,41 @@
//! Vector clocks for causality tracking
use std::collections::HashMap;
/// A vector clock for tracking "how much" of each node's log has been seen.
///
/// Used during reconciliation to identify missing entries between peers.
pub struct VectorClock {
clocks: HashMap<[u8; 32], u64>,
}
impl VectorClock {
/// Create a new empty vector clock.
pub fn new() -> Self {
Self {
clocks: HashMap::new(),
}
}
/// Get the clock value for a node (returns 0 if not present).
pub fn get(&self, node_id: &[u8; 32]) -> u64 {
self.clocks.get(node_id).copied().unwrap_or(0)
}
/// Set the clock value for a node.
pub fn set(&mut self, node_id: [u8; 32], value: u64) {
self.clocks.insert(node_id, value);
}
/// Increment the clock for a node.
pub fn increment(&mut self, node_id: [u8; 32]) {
let current = self.get(&node_id);
self.set(node_id, current + 1);
}
}
impl Default for VectorClock {
fn default() -> Self {
Self::new()
}
}