pub mod bloom;
pub mod cdn;
pub mod governance;
pub mod index;
pub mod keys;
pub mod micro;
pub mod mixnet;
pub mod stake;
use crate::error::PrivacyError;
use crate::types::{MeshNode, NodeKind, SphinxPacket};
extern crate alloc;
use alloc::{format, collections::BTreeMap, string::String, vec::Vec};
pub struct DW3BMesh {
nodes: BTreeMap<String, MeshNode>,
qstp_key: String,
}
impl DW3BMesh {
pub fn new(qstp_key: impl Into<String>) -> Self {
Self {
nodes: BTreeMap::new(),
qstp_key: qstp_key.into(),
}
}
pub fn register_node(&mut self, node: MeshNode) {
self.nodes.insert(node.id.clone(), node);
}
pub fn route_query(
&self,
data: &[u8],
node_kind: NodeKind,
chaos_seed: &[u8; 32],
) -> Result<SphinxPacket, PrivacyError> {
let _node = self.nodes.values()
.find(|n| n.kind == node_kind)
.ok_or_else(|| PrivacyError::NodeUnreachable(format!("{node_kind:?}")))?;
let config = mixnet::SphinxConfig {
hops: 7,
lambda: 10.0,
chaos_seed: *chaos_seed,
};
mixnet::build_sphinx_packet(data.to_vec(), &config, false)
}
pub fn nodes_of_kind(&self, kind: NodeKind) -> Vec<&MeshNode> {
self.nodes.values().filter(|n| n.kind == kind).collect()
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
pub fn qstp_key(&self) -> &str {
&self.qstp_key
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_and_route() {
let mut mesh = DW3BMesh::new("qstp-key-hex");
mesh.register_node(MeshNode {
id: "mixnet-1".into(),
kind: NodeKind::Mixnet,
endpoint: "127.0.0.1:9001".into(),
stake: 1000,
pubkey: "deadbeef".into(),
});
let seed = [0u8; 32];
let pkt = mesh.route_query(b"query", NodeKind::Mixnet, &seed).unwrap();
assert_eq!(pkt.hops, 7);
}
#[test]
fn test_node_not_found() {
let mesh = DW3BMesh::new("key");
let seed = [0u8; 32];
assert!(mesh.route_query(b"q", NodeKind::Governance, &seed).is_err());
}
}