feat: Introduce Hybrid Logical Clocks in protobuf, update architecture documentation, and add HLC test cases.
This commit is contained in:
@@ -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 }
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user