use crate::{get_blob, Address, NodeId, Request, SendError};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Identity {
pub name: NodeId,
pub networking_key: String,
pub routing: NodeRouting,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NodeRouting {
Routers(Vec<NodeId>),
Direct {
ip: String,
ports: BTreeMap<String, u16>,
},
}
impl Identity {
pub fn is_direct(&self) -> bool {
matches!(&self.routing, NodeRouting::Direct { .. })
}
pub fn get_protocol_port(&self, protocol: &str) -> Option<u16> {
match &self.routing {
NodeRouting::Routers(_) => None,
NodeRouting::Direct { ports, .. } => ports.get(protocol).cloned(),
}
}
pub fn routers(&self) -> Option<&Vec<NodeId>> {
match &self.routing {
NodeRouting::Routers(routers) => Some(routers),
NodeRouting::Direct { .. } => None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetAction {
ConnectionRequest(NodeId),
KnsUpdate(KnsUpdate),
KnsBatchUpdate(Vec<KnsUpdate>),
GetPeers,
GetPeer(String),
GetDiagnostics,
Sign,
Verify { from: Address, signature: Vec<u8> },
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetResponse {
Accepted(NodeId),
Rejected(NodeId),
Peers(Vec<Identity>),
Peer(Option<Identity>),
Diagnostics(String),
Signed,
Verified(bool),
}
#[derive(Debug, Serialize, Deserialize)]
pub enum IndexerRequests {
NamehashToName(NamehashToNameRequest),
}
#[derive(Clone, Debug, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub struct NamehashToNameRequest {
pub hash: String,
pub block: u64,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum IndexerResponses {
Name(Option<String>),
}
#[derive(Clone, Debug, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub struct KnsUpdate {
pub name: String,
pub public_key: String,
pub ips: Vec<String>,
pub ports: BTreeMap<String, u16>,
pub routers: Vec<String>,
}
impl KnsUpdate {
pub fn get_protocol_port(&self, protocol: &str) -> u16 {
self.ports.get(protocol).cloned().unwrap_or(0)
}
}
pub fn sign<T>(message: T) -> Result<Vec<u8>, SendError>
where
T: Into<Vec<u8>>,
{
Request::to(("our", "net", "distro", "sys"))
.body(rmp_serde::to_vec(&NetAction::Sign).unwrap())
.blob_bytes(message.into())
.send_and_await_response(30)
.unwrap()
.map(|_resp| get_blob().unwrap().bytes)
}
pub fn verify<T, U, V>(from: T, message: U, signature: V) -> Result<bool, SendError>
where
T: Into<Address>,
U: Into<Vec<u8>>,
V: Into<Vec<u8>>,
{
Request::to(("our", "net", "distro", "sys"))
.body(
rmp_serde::to_vec(&NetAction::Verify {
from: from.into(),
signature: signature.into(),
})
.unwrap(),
)
.blob_bytes(message.into())
.send_and_await_response(30)
.unwrap()
.map(|resp| {
let Ok(NetResponse::Verified(valid)) =
rmp_serde::from_slice::<NetResponse>(resp.body())
else {
return false;
};
valid
})
}
pub fn get_name<T>(namehash: T, block: Option<u64>, timeout: Option<u64>) -> Option<String>
where
T: Into<String>,
{
let res = Request::to(("our", "kns-indexer", "kns-indexer", "sys"))
.body(
serde_json::to_vec(&IndexerRequests::NamehashToName(NamehashToNameRequest {
hash: namehash.into(),
block: block.unwrap_or(0),
}))
.unwrap(),
)
.send_and_await_response(timeout.unwrap_or(30))
.unwrap()
.ok()?;
let Ok(IndexerResponses::Name(maybe_name)) =
serde_json::from_slice::<IndexerResponses>(res.body())
else {
return None;
};
maybe_name
}