mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-07-22 14:40:54 -04:00
refactor
This commit is contained in:
parent
615158d54e
commit
562f9bb7f7
36 changed files with 943 additions and 784 deletions
|
@ -96,6 +96,9 @@ impl veilid_client::Server for VeilidClientImpl {
|
||||||
self.comproc.update_route(route);
|
self.comproc.update_route(route);
|
||||||
}
|
}
|
||||||
VeilidUpdate::Shutdown => self.comproc.update_shutdown(),
|
VeilidUpdate::Shutdown => self.comproc.update_shutdown(),
|
||||||
|
VeilidUpdate::ValueChange(value_change) => {
|
||||||
|
self.comproc.update_value_change(value_change);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
|
|
|
@ -424,6 +424,10 @@ reply - reply to an AppCall not handled directly by the server
|
||||||
self.inner().ui.add_node_event(out);
|
self.inner().ui.add_node_event(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn update_value_change(&mut self, value_change: veilid_core::VeilidValueChange) {
|
||||||
|
let out = format!("Value change: {:?}", value_change);
|
||||||
|
self.inner().ui.add_node_event(out);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_log(&mut self, log: veilid_core::VeilidLog) {
|
pub fn update_log(&mut self, log: veilid_core::VeilidLog) {
|
||||||
self.inner().ui.add_node_event(format!(
|
self.inner().ui.add_node_event(format!(
|
||||||
|
|
|
@ -50,7 +50,11 @@ fn format_bps(bps: ByteCount) -> String {
|
||||||
impl TableViewItem<PeerTableColumn> for PeerTableData {
|
impl TableViewItem<PeerTableColumn> for PeerTableData {
|
||||||
fn to_column(&self, column: PeerTableColumn) -> String {
|
fn to_column(&self, column: PeerTableColumn) -> String {
|
||||||
match column {
|
match column {
|
||||||
PeerTableColumn::NodeId => self.node_id.encode(),
|
PeerTableColumn::NodeId => self
|
||||||
|
.node_ids
|
||||||
|
.best()
|
||||||
|
.map(|n| n.value.encode())
|
||||||
|
.unwrap_or_else(|| "???".to_owned()),
|
||||||
PeerTableColumn::Address => format!(
|
PeerTableColumn::Address => format!(
|
||||||
"{:?}:{}",
|
"{:?}:{}",
|
||||||
self.peer_address.protocol_type(),
|
self.peer_address.protocol_type(),
|
||||||
|
@ -74,7 +78,21 @@ impl TableViewItem<PeerTableColumn> for PeerTableData {
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
match column {
|
match column {
|
||||||
PeerTableColumn::NodeId => self.node_id.cmp(&other.node_id),
|
PeerTableColumn::NodeId => {
|
||||||
|
let n1 = self
|
||||||
|
.node_ids
|
||||||
|
.best()
|
||||||
|
.map(|n| n.value.encode())
|
||||||
|
.unwrap_or_else(|| "???".to_owned());
|
||||||
|
|
||||||
|
let n2 = other
|
||||||
|
.node_ids
|
||||||
|
.best()
|
||||||
|
.map(|n| n.value.encode())
|
||||||
|
.unwrap_or_else(|| "???".to_owned());
|
||||||
|
|
||||||
|
n1.cmp(&n2)
|
||||||
|
}
|
||||||
PeerTableColumn::Address => self.to_column(column).cmp(&other.to_column(column)),
|
PeerTableColumn::Address => self.to_column(column).cmp(&other.to_column(column)),
|
||||||
PeerTableColumn::LatencyAvg => self
|
PeerTableColumn::LatencyAvg => self
|
||||||
.peer_stats
|
.peer_stats
|
||||||
|
|
|
@ -881,13 +881,17 @@ impl UI {
|
||||||
}
|
}
|
||||||
pub fn set_config(&mut self, config: VeilidConfigInner) {
|
pub fn set_config(&mut self, config: VeilidConfigInner) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
inner.ui_state.node_id.set(
|
|
||||||
config
|
let tkv: Vec<TypedKey> = config
|
||||||
.network
|
.network
|
||||||
.node_id
|
.routing_table
|
||||||
.map(|x| x.encode())
|
.node_ids
|
||||||
.unwrap_or("<unknown>".to_owned()),
|
.iter()
|
||||||
);
|
.filter_map(|(k, v)| v.node_id.map(|nid| TypedKey::new(*k, nid)))
|
||||||
|
.collect();
|
||||||
|
let tks = TypedKeySet::from(tkv);
|
||||||
|
|
||||||
|
inner.ui_state.node_id.set(tks.to_string());
|
||||||
}
|
}
|
||||||
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
|
|
@ -44,17 +44,29 @@ pub const SHARED_SECRET_LENGTH_ENCODED: usize = 43;
|
||||||
/// Length of a route id in bytes
|
/// Length of a route id in bytes
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const ROUTE_ID_LENGTH: usize = 32;
|
pub const ROUTE_ID_LENGTH: usize = 32;
|
||||||
|
/// Length of a route id in bytes afer encoding to base64url
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const ROUTE_ID_LENGTH_ENCODED: usize = 43;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub trait Encodable {
|
pub trait Encodable
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
fn encode(&self) -> String;
|
fn encode(&self) -> String;
|
||||||
|
fn encoded_len() -> usize;
|
||||||
|
fn try_decode<S: AsRef<str>>(input: S) -> Result<Self, VeilidAPIError> {
|
||||||
|
let b = input.as_ref().as_bytes();
|
||||||
|
Self::try_decode_bytes(b)
|
||||||
|
}
|
||||||
|
fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! byte_array_type {
|
macro_rules! byte_array_type {
|
||||||
($name:ident, $size:expr) => {
|
($name:ident, $size:expr, $encoded_size:expr) => {
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
Copy,
|
Copy,
|
||||||
|
@ -161,12 +173,16 @@ macro_rules! byte_array_type {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_decode<S: AsRef<str>>(input: S) -> Result<Self, VeilidAPIError> {
|
|
||||||
let b = input.as_ref().as_bytes();
|
|
||||||
Self::try_decode_bytes(b)
|
|
||||||
}
|
}
|
||||||
pub fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError> {
|
|
||||||
|
impl Encodable for $name {
|
||||||
|
fn encode(&self) -> String {
|
||||||
|
BASE64URL_NOPAD.encode(&self.bytes)
|
||||||
|
}
|
||||||
|
fn encoded_len() -> usize {
|
||||||
|
$encoded_size
|
||||||
|
}
|
||||||
|
fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError> {
|
||||||
let mut bytes = [0u8; $size];
|
let mut bytes = [0u8; $size];
|
||||||
let res = BASE64URL_NOPAD.decode_len(b.len());
|
let res = BASE64URL_NOPAD.decode_len(b.len());
|
||||||
match res {
|
match res {
|
||||||
|
@ -187,15 +203,8 @@ macro_rules! byte_array_type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encodable for $name {
|
|
||||||
fn encode(&self) -> String {
|
|
||||||
BASE64URL_NOPAD.encode(&self.bytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl fmt::Display for $name {
|
impl fmt::Display for $name {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
//write!(f, "{}", String::from(self))
|
|
||||||
write!(f, "{}", self.encode())
|
write!(f, "{}", self.encode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,12 +219,6 @@ macro_rules! byte_array_type {
|
||||||
|
|
||||||
impl From<&$name> for String {
|
impl From<&$name> for String {
|
||||||
fn from(value: &$name) -> Self {
|
fn from(value: &$name) -> Self {
|
||||||
// let mut s = String::new();
|
|
||||||
// for n in 0..($size / 8) {
|
|
||||||
// let b: [u8; 8] = value.bytes[n * 8..(n + 1) * 8].try_into().unwrap();
|
|
||||||
// s.push_str(hex::encode(b).as_str());
|
|
||||||
// }
|
|
||||||
// s
|
|
||||||
value.encode()
|
value.encode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,17 +241,6 @@ macro_rules! byte_array_type {
|
||||||
impl TryFrom<&str> for $name {
|
impl TryFrom<&str> for $name {
|
||||||
type Error = VeilidAPIError;
|
type Error = VeilidAPIError;
|
||||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
// let mut out = $name::default();
|
|
||||||
// if value == "" {
|
|
||||||
// return Ok(out);
|
|
||||||
// }
|
|
||||||
// if value.len() != ($size * 2) {
|
|
||||||
// apibail_generic!(concat!(stringify!($name), " is incorrect length"));
|
|
||||||
// }
|
|
||||||
// match hex::decode_to_slice(value, &mut out.bytes) {
|
|
||||||
// Ok(_) => Ok(out),
|
|
||||||
// Err(err) => Err(VeilidAPIError::generic(err)),
|
|
||||||
// }
|
|
||||||
Self::try_decode(value)
|
Self::try_decode(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,10 +249,18 @@ macro_rules! byte_array_type {
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
|
|
||||||
byte_array_type!(PublicKey, PUBLIC_KEY_LENGTH);
|
byte_array_type!(PublicKey, PUBLIC_KEY_LENGTH, PUBLIC_KEY_LENGTH_ENCODED);
|
||||||
byte_array_type!(SecretKey, SECRET_KEY_LENGTH);
|
byte_array_type!(SecretKey, SECRET_KEY_LENGTH, SECRET_KEY_LENGTH_ENCODED);
|
||||||
byte_array_type!(Signature, SIGNATURE_LENGTH);
|
byte_array_type!(Signature, SIGNATURE_LENGTH, SIGNATURE_LENGTH_ENCODED);
|
||||||
byte_array_type!(PublicKeyDistance, PUBLIC_KEY_LENGTH);
|
byte_array_type!(
|
||||||
byte_array_type!(Nonce, NONCE_LENGTH);
|
PublicKeyDistance,
|
||||||
byte_array_type!(SharedSecret, SHARED_SECRET_LENGTH);
|
PUBLIC_KEY_LENGTH,
|
||||||
byte_array_type!(RouteId, ROUTE_ID_LENGTH);
|
PUBLIC_KEY_LENGTH_ENCODED
|
||||||
|
);
|
||||||
|
byte_array_type!(Nonce, NONCE_LENGTH, NONCE_LENGTH_ENCODED);
|
||||||
|
byte_array_type!(
|
||||||
|
SharedSecret,
|
||||||
|
SHARED_SECRET_LENGTH,
|
||||||
|
SHARED_SECRET_LENGTH_ENCODED
|
||||||
|
);
|
||||||
|
byte_array_type!(RouteId, ROUTE_ID_LENGTH, ROUTE_ID_LENGTH_ENCODED);
|
||||||
|
|
|
@ -229,7 +229,7 @@ impl Crypto {
|
||||||
for nid in node_ids {
|
for nid in node_ids {
|
||||||
if nid.kind == sig.kind {
|
if nid.kind == sig.kind {
|
||||||
if let Some(vcrypto) = self.get(sig.kind) {
|
if let Some(vcrypto) = self.get(sig.kind) {
|
||||||
vcrypto.verify(&nid.key, data, &sig.signature)?;
|
vcrypto.verify(&nid.value, data, &sig.value)?;
|
||||||
out.push(nid.kind);
|
out.push(nid.kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ impl Crypto {
|
||||||
let mut out = Vec::<R>::with_capacity(typed_key_pairs.len());
|
let mut out = Vec::<R>::with_capacity(typed_key_pairs.len());
|
||||||
for kp in typed_key_pairs {
|
for kp in typed_key_pairs {
|
||||||
if let Some(vcrypto) = self.get(kp.kind) {
|
if let Some(vcrypto) = self.get(kp.kind) {
|
||||||
let sig = vcrypto.sign(&kp.key, &kp.secret, data)?;
|
let sig = vcrypto.sign(&kp.value.key, &kp.value.secret, data)?;
|
||||||
out.push(transform(kp, sig))
|
out.push(transform(kp, sig))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,548 +0,0 @@
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
|
|
||||||
use core::convert::TryInto;
|
|
||||||
use core::fmt;
|
|
||||||
use core::hash::Hash;
|
|
||||||
|
|
||||||
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
|
||||||
|
|
||||||
/// Cryptography version fourcc code
|
|
||||||
pub type CryptoKind = FourCC;
|
|
||||||
|
|
||||||
/// Sort best crypto kinds first
|
|
||||||
/// Better crypto kinds are 'less', ordered toward the front of a list
|
|
||||||
pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
|
|
||||||
let a_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == a);
|
|
||||||
let b_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == b);
|
|
||||||
if let Some(a_idx) = a_idx {
|
|
||||||
if let Some(b_idx) = b_idx {
|
|
||||||
// Both are valid, prefer better crypto kind
|
|
||||||
a_idx.cmp(&b_idx)
|
|
||||||
} else {
|
|
||||||
// A is valid, B is not
|
|
||||||
cmp::Ordering::Less
|
|
||||||
}
|
|
||||||
} else if b_idx.is_some() {
|
|
||||||
// B is valid, A is not
|
|
||||||
cmp::Ordering::Greater
|
|
||||||
} else {
|
|
||||||
// Both are invalid, so use lex comparison
|
|
||||||
a.cmp(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Intersection of crypto kind vectors
|
|
||||||
pub fn common_crypto_kinds(a: &[CryptoKind], b: &[CryptoKind]) -> Vec<CryptoKind> {
|
|
||||||
let mut out = Vec::new();
|
|
||||||
for ack in a {
|
|
||||||
if b.contains(ack) {
|
|
||||||
out.push(*ack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialOrd,
|
|
||||||
Ord,
|
|
||||||
PartialEq,
|
|
||||||
Eq,
|
|
||||||
Hash,
|
|
||||||
RkyvArchive,
|
|
||||||
RkyvSerialize,
|
|
||||||
RkyvDeserialize,
|
|
||||||
)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
|
||||||
pub struct KeyPair {
|
|
||||||
pub key: PublicKey,
|
|
||||||
pub secret: SecretKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyPair {
|
|
||||||
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
|
|
||||||
Self { key, secret }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xxx make default template version here for secretkey
|
|
||||||
and put Vec<TypedKey<SecretKey>> in settings
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
|
||||||
pub struct TypedKey {
|
|
||||||
pub kind: CryptoKind,
|
|
||||||
pub key: PublicKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypedKey {
|
|
||||||
pub fn new(kind: CryptoKind, key: PublicKey) -> Self {
|
|
||||||
Self { kind, key }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl PartialOrd for TypedKey {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for TypedKey {
|
|
||||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
||||||
let x = compare_crypto_kind(&self.kind, &other.kind);
|
|
||||||
if x != cmp::Ordering::Equal {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
self.key.cmp(&other.key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for TypedKey {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
||||||
write!(f, "{}:{}", self.kind, self.key.encode())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl FromStr for TypedKey {
|
|
||||||
type Err = VeilidAPIError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let b = s.as_bytes();
|
|
||||||
if b.len() != (5 + PUBLIC_KEY_LENGTH_ENCODED) || b[4..5] != b":"[..] {
|
|
||||||
apibail_parse_error!("invalid typed key", s);
|
|
||||||
}
|
|
||||||
let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert");
|
|
||||||
let key = PublicKey::try_decode_bytes(&b[5..])?;
|
|
||||||
Ok(Self { kind, key })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'de> Deserialize<'de> for TypedKey {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let s = <String as Deserialize>::deserialize(deserializer)?;
|
|
||||||
FromStr::from_str(&s).map_err(serde::de::Error::custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Serialize for TypedKey {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: serde::Serializer,
|
|
||||||
{
|
|
||||||
serializer.collect_str(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone,
|
|
||||||
Debug,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialOrd,
|
|
||||||
Ord,
|
|
||||||
PartialEq,
|
|
||||||
Eq,
|
|
||||||
Hash,
|
|
||||||
RkyvArchive,
|
|
||||||
RkyvSerialize,
|
|
||||||
RkyvDeserialize,
|
|
||||||
)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
|
||||||
#[serde(from = "Vec<TypedKey>", into = "Vec<TypedKey>")]
|
|
||||||
pub struct TypedKeySet {
|
|
||||||
items: Vec<TypedKey>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypedKeySet {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { items: Vec::new() }
|
|
||||||
}
|
|
||||||
pub fn with_capacity(cap: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
items: Vec::with_capacity(cap),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn kinds(&self) -> Vec<CryptoKind> {
|
|
||||||
let mut out = Vec::new();
|
|
||||||
for tk in &self.items {
|
|
||||||
out.push(tk.kind);
|
|
||||||
}
|
|
||||||
out.sort_by(compare_crypto_kind);
|
|
||||||
out
|
|
||||||
}
|
|
||||||
pub fn keys(&self) -> Vec<PublicKey> {
|
|
||||||
let mut out = Vec::new();
|
|
||||||
for tk in &self.items {
|
|
||||||
out.push(tk.key);
|
|
||||||
}
|
|
||||||
out
|
|
||||||
}
|
|
||||||
pub fn get(&self, kind: CryptoKind) -> Option<TypedKey> {
|
|
||||||
self.items.iter().find(|x| x.kind == kind).copied()
|
|
||||||
}
|
|
||||||
pub fn add(&mut self, typed_key: TypedKey) {
|
|
||||||
for x in &mut self.items {
|
|
||||||
if x.kind == typed_key.kind {
|
|
||||||
*x = typed_key;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.items.push(typed_key);
|
|
||||||
self.items.sort()
|
|
||||||
}
|
|
||||||
pub fn add_all(&mut self, typed_keys: &[TypedKey]) {
|
|
||||||
'outer: for typed_key in typed_keys {
|
|
||||||
for x in &mut self.items {
|
|
||||||
if x.kind == typed_key.kind {
|
|
||||||
*x = *typed_key;
|
|
||||||
continue 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.items.push(*typed_key);
|
|
||||||
}
|
|
||||||
self.items.sort()
|
|
||||||
}
|
|
||||||
pub fn remove(&mut self, kind: CryptoKind) {
|
|
||||||
if let Some(idx) = self.items.iter().position(|x| x.kind == kind) {
|
|
||||||
self.items.remove(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn remove_all(&mut self, kinds: &[CryptoKind]) {
|
|
||||||
for k in kinds {
|
|
||||||
self.remove(*k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Return preferred typed key of our supported crypto kinds
|
|
||||||
pub fn best(&self) -> Option<TypedKey> {
|
|
||||||
match self.items.first().copied() {
|
|
||||||
None => None,
|
|
||||||
Some(k) => {
|
|
||||||
if !VALID_CRYPTO_KINDS.contains(&k.kind) {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.items.len()
|
|
||||||
}
|
|
||||||
pub fn iter(&self) -> core::slice::Iter<'_, TypedKey> {
|
|
||||||
self.items.iter()
|
|
||||||
}
|
|
||||||
pub fn contains(&self, typed_key: &TypedKey) -> bool {
|
|
||||||
self.items.contains(typed_key)
|
|
||||||
}
|
|
||||||
pub fn contains_any(&self, typed_keys: &[TypedKey]) -> bool {
|
|
||||||
for typed_key in typed_keys {
|
|
||||||
if self.items.contains(typed_key) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
pub fn contains_key(&self, key: &PublicKey) -> bool {
|
|
||||||
for tk in &self.items {
|
|
||||||
if tk.key == *key {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::ops::Deref for TypedKeySet {
|
|
||||||
type Target = [TypedKey];
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn deref(&self) -> &[TypedKey] {
|
|
||||||
&self.items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for TypedKeySet {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
||||||
write!(f, "[")?;
|
|
||||||
let mut first = true;
|
|
||||||
for x in &self.items {
|
|
||||||
if !first {
|
|
||||||
write!(f, ",")?;
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
write!(f, "{}", x)?;
|
|
||||||
}
|
|
||||||
write!(f, "]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl FromStr for TypedKeySet {
|
|
||||||
type Err = VeilidAPIError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mut items = Vec::new();
|
|
||||||
if s.len() < 2 {
|
|
||||||
apibail_parse_error!("invalid length", s);
|
|
||||||
}
|
|
||||||
if &s[0..1] != "[" || &s[(s.len() - 1)..] != "]" {
|
|
||||||
apibail_parse_error!("invalid format", s);
|
|
||||||
}
|
|
||||||
for x in s[1..s.len() - 1].split(",") {
|
|
||||||
let tk = TypedKey::from_str(x.trim())?;
|
|
||||||
items.push(tk);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self { items })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<TypedKey> for TypedKeySet {
|
|
||||||
fn from(x: TypedKey) -> Self {
|
|
||||||
let mut tks = TypedKeySet::with_capacity(1);
|
|
||||||
tks.add(x);
|
|
||||||
tks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<Vec<TypedKey>> for TypedKeySet {
|
|
||||||
fn from(x: Vec<TypedKey>) -> Self {
|
|
||||||
let mut tks = TypedKeySet::with_capacity(x.len());
|
|
||||||
tks.add_all(&x);
|
|
||||||
tks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Into<Vec<TypedKey>> for TypedKeySet {
|
|
||||||
fn into(self) -> Vec<TypedKey> {
|
|
||||||
self.items
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
PartialEq,
|
|
||||||
Eq,
|
|
||||||
Hash,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
RkyvArchive,
|
|
||||||
RkyvSerialize,
|
|
||||||
RkyvDeserialize,
|
|
||||||
)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
|
||||||
pub struct TypedKeyPair {
|
|
||||||
pub kind: CryptoKind,
|
|
||||||
pub key: PublicKey,
|
|
||||||
pub secret: SecretKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypedKeyPair {
|
|
||||||
pub fn new(kind: CryptoKind, key: PublicKey, secret: SecretKey) -> Self {
|
|
||||||
Self { kind, key, secret }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for TypedKeyPair {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for TypedKeyPair {
|
|
||||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
||||||
let x = compare_crypto_kind(&self.kind, &other.kind);
|
|
||||||
if x != cmp::Ordering::Equal {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
let x = self.key.cmp(&other.key);
|
|
||||||
if x != cmp::Ordering::Equal {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
self.secret.cmp(&other.secret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for TypedKeyPair {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}:{}:{}",
|
|
||||||
self.kind,
|
|
||||||
self.key.encode(),
|
|
||||||
self.secret.encode()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl FromStr for TypedKeyPair {
|
|
||||||
type Err = VeilidAPIError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let b = s.as_bytes();
|
|
||||||
if b.len() != (5 + PUBLIC_KEY_LENGTH_ENCODED + 1 + SECRET_KEY_LENGTH_ENCODED)
|
|
||||||
|| b[4..5] != b":"[..]
|
|
||||||
|| b[5 + PUBLIC_KEY_LENGTH_ENCODED..6 + PUBLIC_KEY_LENGTH_ENCODED] != b":"[..]
|
|
||||||
{
|
|
||||||
apibail_parse_error!("invalid typed key pair", s);
|
|
||||||
}
|
|
||||||
let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert");
|
|
||||||
let key = PublicKey::try_decode_bytes(&b[5..5 + PUBLIC_KEY_LENGTH_ENCODED])?;
|
|
||||||
let secret = SecretKey::try_decode_bytes(&b[5 + PUBLIC_KEY_LENGTH_ENCODED + 1..])?;
|
|
||||||
Ok(Self { kind, key, secret })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
PartialEq,
|
|
||||||
Eq,
|
|
||||||
Hash,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
RkyvArchive,
|
|
||||||
RkyvSerialize,
|
|
||||||
RkyvDeserialize,
|
|
||||||
)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
|
||||||
pub struct TypedSignature {
|
|
||||||
pub kind: CryptoKind,
|
|
||||||
pub signature: Signature,
|
|
||||||
}
|
|
||||||
impl TypedSignature {
|
|
||||||
pub fn new(kind: CryptoKind, signature: Signature) -> Self {
|
|
||||||
Self { kind, signature }
|
|
||||||
}
|
|
||||||
pub fn from_keyed(tks: &TypedKeySignature) -> Self {
|
|
||||||
Self {
|
|
||||||
kind: tks.kind,
|
|
||||||
signature: tks.signature,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn from_pair_sig(tkp: &TypedKeyPair, sig: Signature) -> Self {
|
|
||||||
Self {
|
|
||||||
kind: tkp.kind,
|
|
||||||
signature: sig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for TypedSignature {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for TypedSignature {
|
|
||||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
||||||
let x = compare_crypto_kind(&self.kind, &other.kind);
|
|
||||||
if x != cmp::Ordering::Equal {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
self.signature.cmp(&other.signature)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for TypedSignature {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
||||||
write!(f, "{}:{}", self.kind, self.signature.encode())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl FromStr for TypedSignature {
|
|
||||||
type Err = VeilidAPIError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let b = s.as_bytes();
|
|
||||||
if b.len() != (5 + SIGNATURE_LENGTH_ENCODED) || b[4..5] != b":"[..] {
|
|
||||||
apibail_parse_error!("invalid typed signature", s);
|
|
||||||
}
|
|
||||||
let kind: CryptoKind = b[0..4].try_into()?;
|
|
||||||
let signature = Signature::try_decode_bytes(&b[5..])?;
|
|
||||||
Ok(Self { kind, signature })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone,
|
|
||||||
Copy,
|
|
||||||
Debug,
|
|
||||||
PartialEq,
|
|
||||||
Eq,
|
|
||||||
Hash,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
RkyvArchive,
|
|
||||||
RkyvSerialize,
|
|
||||||
RkyvDeserialize,
|
|
||||||
)]
|
|
||||||
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
|
||||||
pub struct TypedKeySignature {
|
|
||||||
pub kind: CryptoKind,
|
|
||||||
pub key: PublicKey,
|
|
||||||
pub signature: Signature,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypedKeySignature {
|
|
||||||
pub fn new(kind: CryptoKind, key: PublicKey, signature: Signature) -> Self {
|
|
||||||
Self {
|
|
||||||
kind,
|
|
||||||
key,
|
|
||||||
signature,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn as_typed_signature(&self) -> TypedSignature {
|
|
||||||
TypedSignature {
|
|
||||||
kind: self.kind,
|
|
||||||
signature: self.signature,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for TypedKeySignature {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for TypedKeySignature {
|
|
||||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
||||||
let x = compare_crypto_kind(&self.kind, &other.kind);
|
|
||||||
if x != cmp::Ordering::Equal {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
let x = self.key.cmp(&other.key);
|
|
||||||
if x != cmp::Ordering::Equal {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
self.signature.cmp(&other.signature)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for TypedKeySignature {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}:{}:{}",
|
|
||||||
self.kind,
|
|
||||||
self.key.encode(),
|
|
||||||
self.signature.encode()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl FromStr for TypedKeySignature {
|
|
||||||
type Err = VeilidAPIError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let b = s.as_bytes();
|
|
||||||
if b.len() != (5 + PUBLIC_KEY_LENGTH_ENCODED + 1 + SIGNATURE_LENGTH_ENCODED)
|
|
||||||
|| b[4] != b':'
|
|
||||||
|| b[5 + PUBLIC_KEY_LENGTH_ENCODED] != b':'
|
|
||||||
{
|
|
||||||
apibail_parse_error!("invalid typed key signature", s);
|
|
||||||
}
|
|
||||||
let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert");
|
|
||||||
let key = PublicKey::try_decode_bytes(&b[5..5 + PUBLIC_KEY_LENGTH_ENCODED])?;
|
|
||||||
let signature = Signature::try_decode_bytes(&b[5 + PUBLIC_KEY_LENGTH_ENCODED + 1..])?;
|
|
||||||
Ok(Self {
|
|
||||||
kind,
|
|
||||||
key,
|
|
||||||
signature,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
184
veilid-core/src/crypto/types/crypto_typed.rs
Normal file
184
veilid-core/src/crypto/types/crypto_typed.rs
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
|
||||||
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
|
pub struct CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
pub kind: CryptoKind,
|
||||||
|
pub value: K,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K> CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
pub fn new(kind: CryptoKind, value: K) -> Self {
|
||||||
|
Self { kind, value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<K> PartialOrd for CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K> Ord for CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||||
|
let x = compare_crypto_kind(&self.kind, &other.kind);
|
||||||
|
if x != cmp::Ordering::Equal {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
self.value.cmp(&other.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K> fmt::Display for CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
|
write!(f, "{}:{}", self.kind, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<K> FromStr for CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
type Err = VeilidAPIError;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let b = s.as_bytes();
|
||||||
|
if b.len() != (5 + K::encoded_len()) || b[4..5] != b":"[..] {
|
||||||
|
apibail_parse_error!("invalid typed key", s);
|
||||||
|
}
|
||||||
|
let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert");
|
||||||
|
let value = K::try_decode_bytes(&b[5..])?;
|
||||||
|
Ok(Self { kind, value })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'de, K> Deserialize<'de> for CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s = <String as Deserialize>::deserialize(deserializer)?;
|
||||||
|
FromStr::from_str(&s).map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<K> Serialize for CryptoTyped<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ Ord
|
||||||
|
+ PartialOrd
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
serializer.collect_str(self)
|
||||||
|
}
|
||||||
|
}
|
303
veilid-core/src/crypto/types/crypto_typed_set.rs
Normal file
303
veilid-core/src/crypto/types/crypto_typed_set.rs
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Debug,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
RkyvArchive,
|
||||||
|
RkyvSerialize,
|
||||||
|
RkyvDeserialize,
|
||||||
|
Default,
|
||||||
|
)]
|
||||||
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
|
#[serde(from = "Vec<CryptoTyped<K>>", into = "Vec<CryptoTyped<K>>")]
|
||||||
|
pub struct CryptoTypedSet<K = PublicKey>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
<Vec<CryptoTyped<K>> as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
items: Vec<CryptoTyped<K>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K> CryptoTypedSet<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { items: Vec::new() }
|
||||||
|
}
|
||||||
|
pub fn with_capacity(cap: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
items: Vec::with_capacity(cap),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn kinds(&self) -> Vec<CryptoKind> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for tk in &self.items {
|
||||||
|
out.push(tk.kind);
|
||||||
|
}
|
||||||
|
out.sort_by(compare_crypto_kind);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
pub fn keys(&self) -> Vec<K> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for tk in &self.items {
|
||||||
|
out.push(tk.value);
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
pub fn get(&self, kind: CryptoKind) -> Option<CryptoTyped<K>> {
|
||||||
|
self.items.iter().find(|x| x.kind == kind).copied()
|
||||||
|
}
|
||||||
|
pub fn add(&mut self, typed_key: CryptoTyped<K>) {
|
||||||
|
for x in &mut self.items {
|
||||||
|
if x.kind == typed_key.kind {
|
||||||
|
*x = typed_key;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.items.push(typed_key);
|
||||||
|
self.items.sort()
|
||||||
|
}
|
||||||
|
pub fn add_all(&mut self, typed_keys: &[CryptoTyped<K>]) {
|
||||||
|
'outer: for typed_key in typed_keys {
|
||||||
|
for x in &mut self.items {
|
||||||
|
if x.kind == typed_key.kind {
|
||||||
|
*x = *typed_key;
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.items.push(*typed_key);
|
||||||
|
}
|
||||||
|
self.items.sort()
|
||||||
|
}
|
||||||
|
pub fn remove(&mut self, kind: CryptoKind) {
|
||||||
|
if let Some(idx) = self.items.iter().position(|x| x.kind == kind) {
|
||||||
|
self.items.remove(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn remove_all(&mut self, kinds: &[CryptoKind]) {
|
||||||
|
for k in kinds {
|
||||||
|
self.remove(*k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Return preferred typed key of our supported crypto kinds
|
||||||
|
pub fn best(&self) -> Option<CryptoTyped<K>> {
|
||||||
|
match self.items.first().copied() {
|
||||||
|
None => None,
|
||||||
|
Some(k) => {
|
||||||
|
if !VALID_CRYPTO_KINDS.contains(&k.kind) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.items.len()
|
||||||
|
}
|
||||||
|
pub fn iter(&self) -> core::slice::Iter<'_, CryptoTyped<K>> {
|
||||||
|
self.items.iter()
|
||||||
|
}
|
||||||
|
pub fn contains(&self, typed_key: &CryptoTyped<K>) -> bool {
|
||||||
|
self.items.contains(typed_key)
|
||||||
|
}
|
||||||
|
pub fn contains_any(&self, typed_keys: &[CryptoTyped<K>]) -> bool {
|
||||||
|
for typed_key in typed_keys {
|
||||||
|
if self.items.contains(typed_key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
pub fn contains_key(&self, key: &K) -> bool {
|
||||||
|
for tk in &self.items {
|
||||||
|
if tk.value == *key {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K> core::ops::Deref for CryptoTypedSet<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
type Target = [CryptoTyped<K>];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deref(&self) -> &[CryptoTyped<K>] {
|
||||||
|
&self.items
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K> fmt::Display for CryptoTypedSet<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
|
write!(f, "[")?;
|
||||||
|
let mut first = true;
|
||||||
|
for x in &self.items {
|
||||||
|
if !first {
|
||||||
|
write!(f, ",")?;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
write!(f, "{}", x)?;
|
||||||
|
}
|
||||||
|
write!(f, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<K> FromStr for CryptoTypedSet<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
type Err = VeilidAPIError;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let mut items = Vec::new();
|
||||||
|
if s.len() < 2 {
|
||||||
|
apibail_parse_error!("invalid length", s);
|
||||||
|
}
|
||||||
|
if &s[0..1] != "[" || &s[(s.len() - 1)..] != "]" {
|
||||||
|
apibail_parse_error!("invalid format", s);
|
||||||
|
}
|
||||||
|
for x in s[1..s.len() - 1].split(",") {
|
||||||
|
let tk = CryptoTyped::<K>::from_str(x.trim())?;
|
||||||
|
items.push(tk);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self { items })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<K> From<CryptoTyped<K>> for CryptoTypedSet<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn from(x: CryptoTyped<K>) -> Self {
|
||||||
|
let mut tks = CryptoTypedSet::<K>::with_capacity(1);
|
||||||
|
tks.add(x);
|
||||||
|
tks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<K> From<Vec<CryptoTyped<K>>> for CryptoTypedSet<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn from(x: Vec<CryptoTyped<K>>) -> Self {
|
||||||
|
let mut tks = CryptoTypedSet::<K>::with_capacity(x.len());
|
||||||
|
tks.add_all(&x);
|
||||||
|
tks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<K> Into<Vec<CryptoTyped<K>>> for CryptoTypedSet<K>
|
||||||
|
where
|
||||||
|
K: Clone
|
||||||
|
+ Copy
|
||||||
|
+ fmt::Debug
|
||||||
|
+ fmt::Display
|
||||||
|
+ FromStr
|
||||||
|
+ PartialEq
|
||||||
|
+ Eq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Ord
|
||||||
|
+ Hash
|
||||||
|
+ RkyvArchive
|
||||||
|
+ Encodable,
|
||||||
|
<K as RkyvArchive>::Archived: Hash + PartialEq + Eq,
|
||||||
|
{
|
||||||
|
fn into(self) -> Vec<CryptoTyped<K>> {
|
||||||
|
self.items
|
||||||
|
}
|
||||||
|
}
|
85
veilid-core/src/crypto/types/keypair.rs
Normal file
85
veilid-core/src/crypto/types/keypair.rs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
RkyvArchive,
|
||||||
|
RkyvSerialize,
|
||||||
|
RkyvDeserialize,
|
||||||
|
)]
|
||||||
|
#[archive_attr(repr(C), derive(CheckBytes, Hash, PartialEq, Eq))]
|
||||||
|
pub struct KeyPair {
|
||||||
|
pub key: PublicKey,
|
||||||
|
pub secret: SecretKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyPair {
|
||||||
|
pub fn new(key: PublicKey, secret: SecretKey) -> Self {
|
||||||
|
Self { key, secret }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Encodable for KeyPair {
|
||||||
|
fn encode(&self) -> String {
|
||||||
|
format!("{}:{}", self.key.encode(), self.secret.encode())
|
||||||
|
}
|
||||||
|
fn encoded_len() -> usize {
|
||||||
|
PublicKey::encoded_len() + 1 + SecretKey::encoded_len()
|
||||||
|
}
|
||||||
|
fn try_decode_bytes(b: &[u8]) -> Result<Self, VeilidAPIError> {
|
||||||
|
if b.len() != Self::encoded_len() {
|
||||||
|
apibail_parse_error!("input has wrong encoded length", format!("len={}", b.len()));
|
||||||
|
}
|
||||||
|
let key = PublicKey::try_decode_bytes(&b[0..PublicKey::encoded_len()])?;
|
||||||
|
let secret = SecretKey::try_decode_bytes(&b[(PublicKey::encoded_len() + 1)..])?;
|
||||||
|
Ok(KeyPair { key, secret })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Display for KeyPair {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.encode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for KeyPair {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, concat!(stringify!($name), "("))?;
|
||||||
|
write!(f, "{}", self.encode())?;
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&KeyPair> for String {
|
||||||
|
fn from(value: &KeyPair) -> Self {
|
||||||
|
value.encode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for KeyPair {
|
||||||
|
type Err = VeilidAPIError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
KeyPair::try_from(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<String> for KeyPair {
|
||||||
|
type Error = VeilidAPIError;
|
||||||
|
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||||
|
KeyPair::try_from(value.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for KeyPair {
|
||||||
|
type Error = VeilidAPIError;
|
||||||
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
|
Self::try_decode(value)
|
||||||
|
}
|
||||||
|
}
|
59
veilid-core/src/crypto/types/mod.rs
Normal file
59
veilid-core/src/crypto/types/mod.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
|
||||||
|
use core::convert::TryInto;
|
||||||
|
use core::fmt;
|
||||||
|
use core::hash::Hash;
|
||||||
|
|
||||||
|
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||||
|
|
||||||
|
/// Cryptography version fourcc code
|
||||||
|
pub type CryptoKind = FourCC;
|
||||||
|
|
||||||
|
/// Sort best crypto kinds first
|
||||||
|
/// Better crypto kinds are 'less', ordered toward the front of a list
|
||||||
|
pub fn compare_crypto_kind(a: &CryptoKind, b: &CryptoKind) -> cmp::Ordering {
|
||||||
|
let a_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == a);
|
||||||
|
let b_idx = VALID_CRYPTO_KINDS.iter().position(|k| k == b);
|
||||||
|
if let Some(a_idx) = a_idx {
|
||||||
|
if let Some(b_idx) = b_idx {
|
||||||
|
// Both are valid, prefer better crypto kind
|
||||||
|
a_idx.cmp(&b_idx)
|
||||||
|
} else {
|
||||||
|
// A is valid, B is not
|
||||||
|
cmp::Ordering::Less
|
||||||
|
}
|
||||||
|
} else if b_idx.is_some() {
|
||||||
|
// B is valid, A is not
|
||||||
|
cmp::Ordering::Greater
|
||||||
|
} else {
|
||||||
|
// Both are invalid, so use lex comparison
|
||||||
|
a.cmp(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Intersection of crypto kind vectors
|
||||||
|
pub fn common_crypto_kinds(a: &[CryptoKind], b: &[CryptoKind]) -> Vec<CryptoKind> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for ack in a {
|
||||||
|
if b.contains(ack) {
|
||||||
|
out.push(*ack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
mod crypto_typed;
|
||||||
|
mod crypto_typed_set;
|
||||||
|
mod keypair;
|
||||||
|
|
||||||
|
pub use crypto_typed::*;
|
||||||
|
pub use crypto_typed_set::*;
|
||||||
|
pub use keypair::*;
|
||||||
|
|
||||||
|
pub type TypedKey = CryptoTyped<PublicKey>;
|
||||||
|
pub type TypedSecret = CryptoTyped<SecretKey>;
|
||||||
|
pub type TypedKeyPair = CryptoTyped<KeyPair>;
|
||||||
|
pub type TypedSignature = CryptoTyped<Signature>;
|
||||||
|
pub type TypedKeySet = CryptoTypedSet<PublicKey>;
|
||||||
|
pub type TypedSecretSet = CryptoTypedSet<SecretKey>;
|
|
@ -32,7 +32,16 @@ fn ed25519_to_x25519_sk(key: &ed::SecretKey) -> Result<xd::StaticSecret, VeilidA
|
||||||
Ok(xd::StaticSecret::from(lowbytes))
|
Ok(xd::StaticSecret::from(lowbytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// V1 CryptoSystem
|
pub fn vld0_generate_keypair() -> (PublicKey, SecretKey) {
|
||||||
|
let mut csprng = VeilidRng {};
|
||||||
|
let keypair = ed::Keypair::generate(&mut csprng);
|
||||||
|
let dht_key = PublicKey::new(keypair.public.to_bytes());
|
||||||
|
let dht_key_secret = SecretKey::new(keypair.secret.to_bytes());
|
||||||
|
|
||||||
|
(dht_key, dht_key_secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// V0 CryptoSystem
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CryptoSystemVLD0 {
|
pub struct CryptoSystemVLD0 {
|
||||||
crypto: Crypto,
|
crypto: Crypto,
|
||||||
|
@ -87,12 +96,7 @@ impl CryptoSystem for CryptoSystemVLD0 {
|
||||||
Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes()))
|
Ok(SharedSecret::new(sk_xd.diffie_hellman(&pk_xd).to_bytes()))
|
||||||
}
|
}
|
||||||
fn generate_keypair(&self) -> (PublicKey, SecretKey) {
|
fn generate_keypair(&self) -> (PublicKey, SecretKey) {
|
||||||
let mut csprng = VeilidRng {};
|
vld0_generate_keypair()
|
||||||
let keypair = ed::Keypair::generate(&mut csprng);
|
|
||||||
let dht_key = PublicKey::new(keypair.public.to_bytes());
|
|
||||||
let dht_key_secret = SecretKey::new(keypair.secret.to_bytes());
|
|
||||||
|
|
||||||
(dht_key, dht_key_secret)
|
|
||||||
}
|
}
|
||||||
fn generate_hash(&self, data: &[u8]) -> PublicKey {
|
fn generate_hash(&self, data: &[u8]) -> PublicKey {
|
||||||
PublicKey::new(*blake3::hash(data).as_bytes())
|
PublicKey::new(*blake3::hash(data).as_bytes())
|
||||||
|
|
|
@ -35,6 +35,7 @@ mod veilid_layer_filter;
|
||||||
|
|
||||||
pub use self::api_tracing_layer::ApiTracingLayer;
|
pub use self::api_tracing_layer::ApiTracingLayer;
|
||||||
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
|
pub use self::core_context::{api_startup, api_startup_json, UpdateCallback};
|
||||||
|
pub use self::crypto::vld0_generate_keypair;
|
||||||
pub use self::veilid_api::*;
|
pub use self::veilid_api::*;
|
||||||
pub use self::veilid_config::*;
|
pub use self::veilid_config::*;
|
||||||
pub use self::veilid_layer_filter::*;
|
pub use self::veilid_layer_filter::*;
|
||||||
|
|
|
@ -529,7 +529,7 @@ impl NetworkManager {
|
||||||
let node_id = routing_table.node_id(vcrypto.kind());
|
let node_id = routing_table.node_id(vcrypto.kind());
|
||||||
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
|
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
|
||||||
|
|
||||||
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.key, extra_data)?;
|
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
||||||
let out = receipt
|
let out = receipt
|
||||||
.to_signed_data(self.crypto(), &node_id_secret)
|
.to_signed_data(self.crypto(), &node_id_secret)
|
||||||
.wrap_err("failed to generate signed receipt")?;
|
.wrap_err("failed to generate signed receipt")?;
|
||||||
|
@ -558,7 +558,7 @@ impl NetworkManager {
|
||||||
let node_id = routing_table.node_id(vcrypto.kind());
|
let node_id = routing_table.node_id(vcrypto.kind());
|
||||||
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
|
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
|
||||||
|
|
||||||
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.key, extra_data)?;
|
let receipt = Receipt::try_new(best_envelope_version(), node_id.kind, nonce, node_id.value, extra_data)?;
|
||||||
let out = receipt
|
let out = receipt
|
||||||
.to_signed_data(self.crypto(), &node_id_secret)
|
.to_signed_data(self.crypto(), &node_id_secret)
|
||||||
.wrap_err("failed to generate signed receipt")?;
|
.wrap_err("failed to generate signed receipt")?;
|
||||||
|
@ -761,7 +761,7 @@ impl NetworkManager {
|
||||||
let nonce = vcrypto.random_nonce();
|
let nonce = vcrypto.random_nonce();
|
||||||
|
|
||||||
// Encode envelope
|
// Encode envelope
|
||||||
let envelope = Envelope::new(version, node_id.kind, ts, nonce, node_id.key, dest_node_id.key);
|
let envelope = Envelope::new(version, node_id.kind, ts, nonce, node_id.value, dest_node_id.value);
|
||||||
envelope
|
envelope
|
||||||
.to_encrypted_data(self.crypto(), body.as_ref(), &node_id_secret)
|
.to_encrypted_data(self.crypto(), body.as_ref(), &node_id_secret)
|
||||||
.wrap_err("envelope failed to encode")
|
.wrap_err("envelope failed to encode")
|
||||||
|
@ -1389,7 +1389,7 @@ impl NetworkManager {
|
||||||
|
|
||||||
let some_relay_nr = if self.check_client_whitelist(sender_id) {
|
let some_relay_nr = if self.check_client_whitelist(sender_id) {
|
||||||
// Full relay allowed, do a full resolve_node
|
// Full relay allowed, do a full resolve_node
|
||||||
match rpc.resolve_node(recipient_id.key).await {
|
match rpc.resolve_node(recipient_id.value).await {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log_net!(debug "failed to resolve recipient node for relay, dropping outbound relayed packet: {}" ,e);
|
log_net!(debug "failed to resolve recipient node for relay, dropping outbound relayed packet: {}" ,e);
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl RoutingTableUnlockedInner {
|
||||||
pub fn node_id_typed_key_pairs(&self) -> Vec<TypedKeyPair> {
|
pub fn node_id_typed_key_pairs(&self) -> Vec<TypedKeyPair> {
|
||||||
let mut tkps = Vec::new();
|
let mut tkps = Vec::new();
|
||||||
for (ck, v) in &self.node_id_keypairs {
|
for (ck, v) in &self.node_id_keypairs {
|
||||||
tkps.push(TypedKeyPair::new(*ck, v.key, v.secret));
|
tkps.push(TypedKeyPair::new(*ck, *v));
|
||||||
}
|
}
|
||||||
tkps
|
tkps
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ impl RoutingTableUnlockedInner {
|
||||||
pub fn matches_own_node_id(&self, node_ids: &[TypedKey]) -> bool {
|
pub fn matches_own_node_id(&self, node_ids: &[TypedKey]) -> bool {
|
||||||
for ni in node_ids {
|
for ni in node_ids {
|
||||||
if let Some(v) = self.node_id_keypairs.get(&ni.kind) {
|
if let Some(v) = self.node_id_keypairs.get(&ni.kind) {
|
||||||
if v.key == ni.key {
|
if v.key == ni.value {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ impl RoutingTableUnlockedInner {
|
||||||
(
|
(
|
||||||
node_id.kind,
|
node_id.kind,
|
||||||
vcrypto
|
vcrypto
|
||||||
.distance(&node_id.key, &self_node_id)
|
.distance(&node_id.value, &self_node_id)
|
||||||
.first_nonzero_bit()
|
.first_nonzero_bit()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl RouteSetSpecDetail {
|
||||||
tks
|
tks
|
||||||
}
|
}
|
||||||
pub fn get_best_route_set_key(&self) -> Option<PublicKey> {
|
pub fn get_best_route_set_key(&self) -> Option<PublicKey> {
|
||||||
self.get_route_set_keys().best().map(|k| k.key)
|
self.get_route_set_keys().best().map(|k| k.value)
|
||||||
}
|
}
|
||||||
pub fn set_hop_node_refs(&mut self, node_refs: Vec<NodeRef>) {
|
pub fn set_hop_node_refs(&mut self, node_refs: Vec<NodeRef>) {
|
||||||
self.hop_node_refs = node_refs;
|
self.hop_node_refs = node_refs;
|
||||||
|
@ -128,7 +128,7 @@ impl RouteSetSpecDetail {
|
||||||
let hops = &self.hop_node_refs;
|
let hops = &self.hop_node_refs;
|
||||||
let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * PUBLIC_KEY_LENGTH);
|
let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * PUBLIC_KEY_LENGTH);
|
||||||
for hop in hops {
|
for hop in hops {
|
||||||
cache.extend_from_slice(&hop.best_node_id().key.bytes);
|
cache.extend_from_slice(&hop.best_node_id().value.bytes);
|
||||||
}
|
}
|
||||||
cache
|
cache
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,7 +358,7 @@ impl RouteSpecStore {
|
||||||
fn route_permutation_to_hop_cache(rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]) -> Vec<u8> {
|
fn route_permutation_to_hop_cache(rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]) -> Vec<u8> {
|
||||||
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH);
|
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH);
|
||||||
for n in perm {
|
for n in perm {
|
||||||
cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().key.bytes)
|
cache.extend_from_slice(&nodes[*n].locked(rti).best_node_id().value.bytes)
|
||||||
}
|
}
|
||||||
cache
|
cache
|
||||||
}
|
}
|
||||||
|
@ -491,7 +491,7 @@ impl RouteSpecStore {
|
||||||
for crypto_kind in crypto_kinds.iter().copied() {
|
for crypto_kind in crypto_kinds.iter().copied() {
|
||||||
let vcrypto = self.unlocked_inner.routing_table.crypto().get(crypto_kind).unwrap();
|
let vcrypto = self.unlocked_inner.routing_table.crypto().get(crypto_kind).unwrap();
|
||||||
let (public_key, secret_key) = vcrypto.generate_keypair();
|
let (public_key, secret_key) = vcrypto.generate_keypair();
|
||||||
let hops: Vec<PublicKey> = route_nodes.iter().map(|v| nodes[*v].node_ids().get(crypto_kind).unwrap().key).collect();
|
let hops: Vec<PublicKey> = route_nodes.iter().map(|v| nodes[*v].node_ids().get(crypto_kind).unwrap().value).collect();
|
||||||
|
|
||||||
route_set.insert(public_key, RouteSpecDetail {
|
route_set.insert(public_key, RouteSpecDetail {
|
||||||
crypto_kind,
|
crypto_kind,
|
||||||
|
@ -543,16 +543,16 @@ impl RouteSpecStore {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(rsid) = inner.content.get_id_by_key(&public_key.key) else {
|
let Some(rsid) = inner.content.get_id_by_key(&public_key.value) else {
|
||||||
log_rpc!(debug "route id does not exist: {:?}", public_key.key);
|
log_rpc!(debug "route id does not exist: {:?}", public_key.value);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let Some(rssd) = inner.content.get_detail(&rsid) else {
|
let Some(rssd) = inner.content.get_detail(&rsid) else {
|
||||||
log_rpc!(debug "route detail does not exist: {:?}", rsid);
|
log_rpc!(debug "route detail does not exist: {:?}", rsid);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let Some(rsd) = rssd.get_route_by_key(&public_key.key) else {
|
let Some(rsd) = rssd.get_route_by_key(&public_key.value) else {
|
||||||
log_rpc!(debug "route set {:?} does not have key: {:?}", rsid, public_key.key);
|
log_rpc!(debug "route set {:?} does not have key: {:?}", rsid, public_key.value);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -694,7 +694,7 @@ impl RouteSpecStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a route id is remote or not
|
/// Check if a route id is remote or not
|
||||||
fn is_route_id_remote(&self, id: &RouteId) -> bool {
|
pub fn is_route_id_remote(&self, id: &RouteId) -> bool {
|
||||||
let inner = &mut *self.inner.lock();
|
let inner = &mut *self.inner.lock();
|
||||||
let cur_ts = get_aligned_timestamp();
|
let cur_ts = get_aligned_timestamp();
|
||||||
inner.cache.peek_remote_private_route_mut(cur_ts, &id).is_some()
|
inner.cache.peek_remote_private_route_mut(cur_ts, &id).is_some()
|
||||||
|
@ -847,7 +847,7 @@ impl RouteSpecStore {
|
||||||
let Some(vcrypto) = crypto.get(crypto_kind) else {
|
let Some(vcrypto) = crypto.get(crypto_kind) else {
|
||||||
bail!("crypto not supported for route");
|
bail!("crypto not supported for route");
|
||||||
};
|
};
|
||||||
let pr_pubkey = private_route.public_key.key;
|
let pr_pubkey = private_route.public_key.value;
|
||||||
let pr_hopcount = private_route.hop_count as usize;
|
let pr_hopcount = private_route.hop_count as usize;
|
||||||
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
||||||
|
|
||||||
|
@ -1092,7 +1092,7 @@ impl RouteSpecStore {
|
||||||
if let Some(preferred_key) = preferred_rssd.get_route_set_keys().get(crypto_kind) {
|
if let Some(preferred_key) = preferred_rssd.get_route_set_keys().get(crypto_kind) {
|
||||||
// Only use the preferred route if it doesn't contain the avoid nodes
|
// Only use the preferred route if it doesn't contain the avoid nodes
|
||||||
if !preferred_rssd.contains_nodes(avoid_nodes) {
|
if !preferred_rssd.contains_nodes(avoid_nodes) {
|
||||||
return Ok(Some(preferred_key.key));
|
return Ok(Some(preferred_key.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1131,7 +1131,7 @@ impl RouteSpecStore {
|
||||||
sr_route_id
|
sr_route_id
|
||||||
};
|
};
|
||||||
|
|
||||||
let sr_pubkey = inner.content.get_detail(&sr_route_id).unwrap().get_route_set_keys().get(crypto_kind).unwrap().key;
|
let sr_pubkey = inner.content.get_detail(&sr_route_id).unwrap().get_route_set_keys().get(crypto_kind).unwrap().value;
|
||||||
|
|
||||||
Ok(Some(sr_pubkey))
|
Ok(Some(sr_pubkey))
|
||||||
}
|
}
|
||||||
|
@ -1178,7 +1178,7 @@ impl RouteSpecStore {
|
||||||
let Some(node_id) = routing_table.node_ids().get(rsd.crypto_kind) else {
|
let Some(node_id) = routing_table.node_ids().get(rsd.crypto_kind) else {
|
||||||
bail!("missing node id for crypto kind");
|
bail!("missing node id for crypto kind");
|
||||||
};
|
};
|
||||||
RouteNode::NodeId(node_id.key)
|
RouteNode::NodeId(node_id.value)
|
||||||
} else {
|
} else {
|
||||||
let Some(pi) = rti.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
let Some(pi) = rti.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||||
bail!("can't make private routes until our node info is valid");
|
bail!("can't make private routes until our node info is valid");
|
||||||
|
@ -1319,7 +1319,7 @@ impl RouteSpecStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure this isn't also an allocated route
|
// ensure this isn't also an allocated route
|
||||||
if inner.content.get_id_by_key(&private_route.public_key.key).is_some() {
|
if inner.content.get_id_by_key(&private_route.public_key.value).is_some() {
|
||||||
bail!("should not import allocated route");
|
bail!("should not import allocated route");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1570,7 +1570,7 @@ impl RouteSpecStore {
|
||||||
if best_kind.is_none() || compare_crypto_kind(&tk.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less {
|
if best_kind.is_none() || compare_crypto_kind(&tk.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less {
|
||||||
best_kind = Some(tk.kind);
|
best_kind = Some(tk.kind);
|
||||||
}
|
}
|
||||||
idbytes.extend_from_slice(&tk.key.bytes);
|
idbytes.extend_from_slice(&tk.value.bytes);
|
||||||
}
|
}
|
||||||
let Some(best_kind) = best_kind else {
|
let Some(best_kind) = best_kind else {
|
||||||
bail!("no compatible crypto kinds in route");
|
bail!("no compatible crypto kinds in route");
|
||||||
|
@ -1591,7 +1591,7 @@ impl RouteSpecStore {
|
||||||
if best_kind.is_none() || compare_crypto_kind(&private_route.public_key.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less {
|
if best_kind.is_none() || compare_crypto_kind(&private_route.public_key.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less {
|
||||||
best_kind = Some(private_route.public_key.kind);
|
best_kind = Some(private_route.public_key.kind);
|
||||||
}
|
}
|
||||||
idbytes.extend_from_slice(&private_route.public_key.key.bytes);
|
idbytes.extend_from_slice(&private_route.public_key.value.bytes);
|
||||||
}
|
}
|
||||||
let Some(best_kind) = best_kind else {
|
let Some(best_kind) = best_kind else {
|
||||||
bail!("no compatible crypto kinds in route");
|
bail!("no compatible crypto kinds in route");
|
||||||
|
|
|
@ -114,14 +114,18 @@ impl RouteSpecStoreCache {
|
||||||
/// calculate how many times a node with a particular node id set has been used anywhere in the path of our allocated routes
|
/// calculate how many times a node with a particular node id set has been used anywhere in the path of our allocated routes
|
||||||
pub fn get_used_node_count(&self, node_ids: &TypedKeySet) -> usize {
|
pub fn get_used_node_count(&self, node_ids: &TypedKeySet) -> usize {
|
||||||
node_ids.iter().fold(0usize, |acc, k| {
|
node_ids.iter().fold(0usize, |acc, k| {
|
||||||
acc + self.used_nodes.get(&k.key).cloned().unwrap_or_default()
|
acc + self.used_nodes.get(&k.value).cloned().unwrap_or_default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// calculate how many times a node with a particular node id set has been used at the end of the path of our allocated routes
|
/// calculate how many times a node with a particular node id set has been used at the end of the path of our allocated routes
|
||||||
pub fn get_used_end_node_count(&self, node_ids: &TypedKeySet) -> usize {
|
pub fn get_used_end_node_count(&self, node_ids: &TypedKeySet) -> usize {
|
||||||
node_ids.iter().fold(0usize, |acc, k| {
|
node_ids.iter().fold(0usize, |acc, k| {
|
||||||
acc + self.used_end_nodes.get(&k.key).cloned().unwrap_or_default()
|
acc + self
|
||||||
|
.used_end_nodes
|
||||||
|
.get(&k.value)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +139,7 @@ impl RouteSpecStoreCache {
|
||||||
// also store in id by key table
|
// also store in id by key table
|
||||||
for private_route in rprinfo.get_private_routes() {
|
for private_route in rprinfo.get_private_routes() {
|
||||||
self.remote_private_routes_by_key
|
self.remote_private_routes_by_key
|
||||||
.insert(private_route.public_key.key, id.clone());
|
.insert(private_route.public_key.value, id.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dead = None;
|
let mut dead = None;
|
||||||
|
@ -149,9 +153,9 @@ impl RouteSpecStoreCache {
|
||||||
// Follow the same logic as 'remove_remote_private_route' here
|
// Follow the same logic as 'remove_remote_private_route' here
|
||||||
for dead_private_route in dead_rpri.get_private_routes() {
|
for dead_private_route in dead_rpri.get_private_routes() {
|
||||||
self.remote_private_routes_by_key
|
self.remote_private_routes_by_key
|
||||||
.remove(&dead_private_route.public_key.key)
|
.remove(&dead_private_route.public_key.value)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.invalidate_compiled_route_cache(&dead_private_route.public_key.key);
|
self.invalidate_compiled_route_cache(&dead_private_route.public_key.value);
|
||||||
}
|
}
|
||||||
self.dead_remote_routes.push(dead_id);
|
self.dead_remote_routes.push(dead_id);
|
||||||
}
|
}
|
||||||
|
@ -261,9 +265,9 @@ impl RouteSpecStoreCache {
|
||||||
};
|
};
|
||||||
for private_route in rprinfo.get_private_routes() {
|
for private_route in rprinfo.get_private_routes() {
|
||||||
self.remote_private_routes_by_key
|
self.remote_private_routes_by_key
|
||||||
.remove(&private_route.public_key.key)
|
.remove(&private_route.public_key.value)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.invalidate_compiled_route_cache(&private_route.public_key.key);
|
self.invalidate_compiled_route_cache(&private_route.public_key.value);
|
||||||
}
|
}
|
||||||
self.dead_remote_routes.push(id);
|
self.dead_remote_routes.push(id);
|
||||||
true
|
true
|
||||||
|
@ -272,7 +276,7 @@ impl RouteSpecStoreCache {
|
||||||
/// Stores a compiled 'safety + private' route so we don't have to compile it again later
|
/// Stores a compiled 'safety + private' route so we don't have to compile it again later
|
||||||
pub fn add_to_compiled_route_cache(&mut self, pr_pubkey: PublicKey, safety_route: SafetyRoute) {
|
pub fn add_to_compiled_route_cache(&mut self, pr_pubkey: PublicKey, safety_route: SafetyRoute) {
|
||||||
let key = CompiledRouteCacheKey {
|
let key = CompiledRouteCacheKey {
|
||||||
sr_pubkey: safety_route.public_key.key,
|
sr_pubkey: safety_route.public_key.value,
|
||||||
pr_pubkey,
|
pr_pubkey,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -605,14 +605,14 @@ impl RoutingTableInner {
|
||||||
// Remove any old node id for this crypto kind
|
// Remove any old node id for this crypto kind
|
||||||
let bucket_index = self.unlocked_inner.calculate_bucket_index(&old_node_id);
|
let bucket_index = self.unlocked_inner.calculate_bucket_index(&old_node_id);
|
||||||
let bucket = self.get_bucket_mut(bucket_index);
|
let bucket = self.get_bucket_mut(bucket_index);
|
||||||
bucket.remove_entry(&old_node_id.key);
|
bucket.remove_entry(&old_node_id.value);
|
||||||
self.unlocked_inner.kick_queue.lock().insert(bucket_index);
|
self.unlocked_inner.kick_queue.lock().insert(bucket_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bucket the entry appropriately
|
// Bucket the entry appropriately
|
||||||
let bucket_index = self.unlocked_inner.calculate_bucket_index(node_id);
|
let bucket_index = self.unlocked_inner.calculate_bucket_index(node_id);
|
||||||
let bucket = self.get_bucket_mut(bucket_index);
|
let bucket = self.get_bucket_mut(bucket_index);
|
||||||
bucket.add_existing_entry(node_id.key, entry.clone());
|
bucket.add_existing_entry(node_id.value, entry.clone());
|
||||||
|
|
||||||
// Kick bucket
|
// Kick bucket
|
||||||
self.unlocked_inner.kick_queue.lock().insert(bucket_index);
|
self.unlocked_inner.kick_queue.lock().insert(bucket_index);
|
||||||
|
@ -649,7 +649,7 @@ impl RoutingTableInner {
|
||||||
}
|
}
|
||||||
let bucket_index = self.unlocked_inner.calculate_bucket_index(node_id);
|
let bucket_index = self.unlocked_inner.calculate_bucket_index(node_id);
|
||||||
let bucket = self.get_bucket(bucket_index);
|
let bucket = self.get_bucket(bucket_index);
|
||||||
if let Some(entry) = bucket.entry(&node_id.key) {
|
if let Some(entry) = bucket.entry(&node_id.value) {
|
||||||
// Best entry is the first one in sorted order that exists from the node id list
|
// Best entry is the first one in sorted order that exists from the node id list
|
||||||
// Everything else that matches will be overwritten in the bucket and the
|
// Everything else that matches will be overwritten in the bucket and the
|
||||||
// existing noderefs will eventually unref and drop the old unindexed bucketentry
|
// existing noderefs will eventually unref and drop the old unindexed bucketentry
|
||||||
|
@ -680,7 +680,7 @@ impl RoutingTableInner {
|
||||||
let first_node_id = node_ids[0];
|
let first_node_id = node_ids[0];
|
||||||
let bucket_entry = self.unlocked_inner.calculate_bucket_index(&first_node_id);
|
let bucket_entry = self.unlocked_inner.calculate_bucket_index(&first_node_id);
|
||||||
let bucket = self.get_bucket_mut(bucket_entry);
|
let bucket = self.get_bucket_mut(bucket_entry);
|
||||||
let new_entry = bucket.add_new_entry(first_node_id.key);
|
let new_entry = bucket.add_new_entry(first_node_id.value);
|
||||||
self.unlocked_inner.kick_queue.lock().insert(bucket_entry);
|
self.unlocked_inner.kick_queue.lock().insert(bucket_entry);
|
||||||
|
|
||||||
// Update the other bucket entries with the remaining node ids
|
// Update the other bucket entries with the remaining node ids
|
||||||
|
@ -723,7 +723,7 @@ impl RoutingTableInner {
|
||||||
let bucket_index = self.unlocked_inner.calculate_bucket_index(&node_id);
|
let bucket_index = self.unlocked_inner.calculate_bucket_index(&node_id);
|
||||||
let bucket = self.get_bucket(bucket_index);
|
let bucket = self.get_bucket(bucket_index);
|
||||||
bucket
|
bucket
|
||||||
.entry(&node_id.key)
|
.entry(&node_id.value)
|
||||||
.map(|e| NodeRef::new(outer_self, e, None))
|
.map(|e| NodeRef::new(outer_self, e, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,7 +760,7 @@ impl RoutingTableInner {
|
||||||
}
|
}
|
||||||
let bucket_entry = self.unlocked_inner.calculate_bucket_index(&node_id);
|
let bucket_entry = self.unlocked_inner.calculate_bucket_index(&node_id);
|
||||||
let bucket = self.get_bucket(bucket_entry);
|
let bucket = self.get_bucket(bucket_entry);
|
||||||
bucket.entry(&node_id.key).map(f)
|
bucket.entry(&node_id.value).map(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shortcut function to add a node to our routing table if it doesn't exist
|
/// Shortcut function to add a node to our routing table if it doesn't exist
|
||||||
|
@ -1174,8 +1174,8 @@ impl RoutingTableInner {
|
||||||
// since multiple cryptosystems are in use, the distance for a key is the shortest
|
// since multiple cryptosystems are in use, the distance for a key is the shortest
|
||||||
// distance to that key over all supported cryptosystems
|
// distance to that key over all supported cryptosystems
|
||||||
|
|
||||||
let da = vcrypto.distance(&a_key.key, &node_id.key);
|
let da = vcrypto.distance(&a_key.value, &node_id.value);
|
||||||
let db = vcrypto.distance(&b_key.key, &node_id.key);
|
let db = vcrypto.distance(&b_key.value, &node_id.value);
|
||||||
da.cmp(&db)
|
da.cmp(&db)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,5 +15,5 @@ pub fn decode_typed_key(typed_key: &veilid_capnp::typed_key::Reader) -> Result<T
|
||||||
pub fn encode_typed_key(typed_key: &TypedKey, builder: &mut veilid_capnp::typed_key::Builder) {
|
pub fn encode_typed_key(typed_key: &TypedKey, builder: &mut veilid_capnp::typed_key::Builder) {
|
||||||
builder.set_kind(u32::from_be_bytes(typed_key.kind.0));
|
builder.set_kind(u32::from_be_bytes(typed_key.kind.0));
|
||||||
let mut key_builder = builder.reborrow().init_key();
|
let mut key_builder = builder.reborrow().init_key();
|
||||||
encode_key256(&typed_key.key, &mut key_builder);
|
encode_key256(&typed_key.value, &mut key_builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,5 @@ pub fn encode_typed_signature(
|
||||||
) {
|
) {
|
||||||
builder.set_kind(u32::from_be_bytes(typed_signature.kind.0));
|
builder.set_kind(u32::from_be_bytes(typed_signature.kind.0));
|
||||||
let mut sig_builder = builder.reborrow().init_signature();
|
let mut sig_builder = builder.reborrow().init_signature();
|
||||||
encode_signature512(&typed_signature.signature, &mut sig_builder);
|
encode_signature512(&typed_signature.value, &mut sig_builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,12 +223,12 @@ impl RPCProcessor {
|
||||||
|
|
||||||
// Determine if we can use optimized nodeinfo
|
// Determine if we can use optimized nodeinfo
|
||||||
let route_node = if rss
|
let route_node = if rss
|
||||||
.has_remote_private_route_seen_our_node_info(&private_route.public_key.key)
|
.has_remote_private_route_seen_our_node_info(&private_route.public_key.value)
|
||||||
{
|
{
|
||||||
if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) {
|
if !routing_table.has_valid_own_node_info(RoutingDomain::PublicInternet) {
|
||||||
return Ok(NetworkResult::no_connection_other("Own node info must be valid to use private route"));
|
return Ok(NetworkResult::no_connection_other("Own node info must be valid to use private route"));
|
||||||
}
|
}
|
||||||
RouteNode::NodeId(routing_table.node_id(crypto_kind).key)
|
RouteNode::NodeId(routing_table.node_id(crypto_kind).value)
|
||||||
} else {
|
} else {
|
||||||
let Some(own_peer_info) =
|
let Some(own_peer_info) =
|
||||||
routing_table.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
routing_table.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||||
|
@ -245,11 +245,11 @@ impl RPCProcessor {
|
||||||
// Sent to a private route via a safety route, respond to private route
|
// Sent to a private route via a safety route, respond to private route
|
||||||
|
|
||||||
// Check for loopback test
|
// Check for loopback test
|
||||||
let opt_private_route_id = rss.get_route_id_for_key(&private_route.public_key.key);
|
let opt_private_route_id = rss.get_route_id_for_key(&private_route.public_key.value);
|
||||||
let pr_key = if opt_private_route_id.is_some() && safety_spec.preferred_route == opt_private_route_id
|
let pr_key = if opt_private_route_id.is_some() && safety_spec.preferred_route == opt_private_route_id
|
||||||
{
|
{
|
||||||
// Private route is also safety route during loopback test
|
// Private route is also safety route during loopback test
|
||||||
private_route.public_key.key
|
private_route.public_key.value
|
||||||
} else {
|
} else {
|
||||||
// Get the private route to respond to that matches the safety route spec we sent the request with
|
// Get the private route to respond to that matches the safety route spec we sent the request with
|
||||||
let Some(pr_key) = rss
|
let Some(pr_key) = rss
|
||||||
|
|
|
@ -505,7 +505,7 @@ impl RPCProcessor {
|
||||||
// Get useful private route properties
|
// Get useful private route properties
|
||||||
let pr_is_stub = remote_private_route.is_stub();
|
let pr_is_stub = remote_private_route.is_stub();
|
||||||
let pr_hop_count = remote_private_route.hop_count;
|
let pr_hop_count = remote_private_route.hop_count;
|
||||||
let pr_pubkey = remote_private_route.public_key.key;
|
let pr_pubkey = remote_private_route.public_key.value;
|
||||||
let crypto_kind = remote_private_route.crypto_kind();
|
let crypto_kind = remote_private_route.crypto_kind();
|
||||||
let Some(vcrypto) = self.crypto.get(crypto_kind) else {
|
let Some(vcrypto) = self.crypto.get(crypto_kind) else {
|
||||||
return Err(RPCError::internal("crypto not available for selected private route"));
|
return Err(RPCError::internal("crypto not available for selected private route"));
|
||||||
|
@ -524,7 +524,7 @@ impl RPCProcessor {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let sr_is_stub = compiled_route.safety_route.is_stub();
|
let sr_is_stub = compiled_route.safety_route.is_stub();
|
||||||
let sr_pubkey = compiled_route.safety_route.public_key.key;
|
let sr_pubkey = compiled_route.safety_route.public_key.value;
|
||||||
|
|
||||||
// Encrypt routed operation
|
// Encrypt routed operation
|
||||||
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
|
||||||
|
@ -599,7 +599,7 @@ impl RPCProcessor {
|
||||||
let reply_private_route = match operation.kind() {
|
let reply_private_route = match operation.kind() {
|
||||||
RPCOperationKind::Question(q) => match q.respond_to() {
|
RPCOperationKind::Question(q) => match q.respond_to() {
|
||||||
RespondTo::Sender => None,
|
RespondTo::Sender => None,
|
||||||
RespondTo::PrivateRoute(pr) => Some(pr.public_key.key),
|
RespondTo::PrivateRoute(pr) => Some(pr.public_key.value),
|
||||||
},
|
},
|
||||||
RPCOperationKind::Statement(_) | RPCOperationKind::Answer(_) => None,
|
RPCOperationKind::Statement(_) | RPCOperationKind::Answer(_) => None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl RPCProcessor {
|
||||||
let sender = msg
|
let sender = msg
|
||||||
.opt_sender_nr
|
.opt_sender_nr
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().key);
|
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().value);
|
||||||
|
|
||||||
// Register a waiter for this app call
|
// Register a waiter for this app call
|
||||||
let id = msg.operation.op_id();
|
let id = msg.operation.op_id();
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl RPCProcessor {
|
||||||
let sender = msg
|
let sender = msg
|
||||||
.opt_sender_nr
|
.opt_sender_nr
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().key);
|
.map(|nr| nr.node_ids().get(crypto_kind).unwrap().value);
|
||||||
|
|
||||||
// Pass the message up through the update callback
|
// Pass the message up through the update callback
|
||||||
let message = app_message.message;
|
let message = app_message.message;
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl RPCProcessor {
|
||||||
// xxx: punish nodes that send messages that fail to decrypt eventually? How to do this for safety routes?
|
// xxx: punish nodes that send messages that fail to decrypt eventually? How to do this for safety routes?
|
||||||
let node_id_secret = self.routing_table.node_id_secret(remote_sr_pubkey.kind);
|
let node_id_secret = self.routing_table.node_id_secret(remote_sr_pubkey.kind);
|
||||||
let dh_secret = vcrypto
|
let dh_secret = vcrypto
|
||||||
.cached_dh(&remote_sr_pubkey.key, &node_id_secret)
|
.cached_dh(&remote_sr_pubkey.value, &node_id_secret)
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
let body = match vcrypto.decrypt_aead(
|
let body = match vcrypto.decrypt_aead(
|
||||||
&routed_operation.data,
|
&routed_operation.data,
|
||||||
|
@ -131,7 +131,7 @@ impl RPCProcessor {
|
||||||
// Pass message to RPC system
|
// Pass message to RPC system
|
||||||
self.enqueue_safety_routed_message(
|
self.enqueue_safety_routed_message(
|
||||||
detail,
|
detail,
|
||||||
remote_sr_pubkey.key,
|
remote_sr_pubkey.value,
|
||||||
routed_operation.sequencing,
|
routed_operation.sequencing,
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
|
@ -166,7 +166,7 @@ impl RPCProcessor {
|
||||||
(
|
(
|
||||||
rsd.secret_key,
|
rsd.secret_key,
|
||||||
SafetySpec {
|
SafetySpec {
|
||||||
preferred_route: rss.get_route_id_for_key(&pr_pubkey.key),
|
preferred_route: rss.get_route_id_for_key(&pr_pubkey.value),
|
||||||
hop_count: rssd.hop_count(),
|
hop_count: rssd.hop_count(),
|
||||||
stability: rssd.get_stability(),
|
stability: rssd.get_stability(),
|
||||||
sequencing: routed_operation.sequencing,
|
sequencing: routed_operation.sequencing,
|
||||||
|
@ -181,7 +181,7 @@ impl RPCProcessor {
|
||||||
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
||||||
// xxx: punish nodes that send messages that fail to decrypt eventually. How to do this for private routes?
|
// xxx: punish nodes that send messages that fail to decrypt eventually. How to do this for private routes?
|
||||||
let dh_secret = vcrypto
|
let dh_secret = vcrypto
|
||||||
.cached_dh(&remote_sr_pubkey.key, &secret_key)
|
.cached_dh(&remote_sr_pubkey.value, &secret_key)
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
let body = vcrypto
|
let body = vcrypto
|
||||||
.decrypt_aead(
|
.decrypt_aead(
|
||||||
|
@ -197,8 +197,8 @@ impl RPCProcessor {
|
||||||
// Pass message to RPC system
|
// Pass message to RPC system
|
||||||
self.enqueue_private_routed_message(
|
self.enqueue_private_routed_message(
|
||||||
detail,
|
detail,
|
||||||
remote_sr_pubkey.key,
|
remote_sr_pubkey.value,
|
||||||
pr_pubkey.key,
|
pr_pubkey.value,
|
||||||
safety_spec,
|
safety_spec,
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
|
@ -315,7 +315,7 @@ impl RPCProcessor {
|
||||||
// Decrypt the blob with DEC(nonce, DH(the PR's public key, this hop's secret)
|
// Decrypt the blob with DEC(nonce, DH(the PR's public key, this hop's secret)
|
||||||
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
||||||
let dh_secret = vcrypto
|
let dh_secret = vcrypto
|
||||||
.cached_dh(&pr_pubkey.key, &node_id_secret)
|
.cached_dh(&pr_pubkey.value, &node_id_secret)
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
let dec_blob_data = match vcrypto.decrypt_aead(
|
let dec_blob_data = match vcrypto.decrypt_aead(
|
||||||
&route_hop_data.blob,
|
&route_hop_data.blob,
|
||||||
|
@ -347,7 +347,7 @@ impl RPCProcessor {
|
||||||
let node_id = self.routing_table.node_id(crypto_kind);
|
let node_id = self.routing_table.node_id(crypto_kind);
|
||||||
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
||||||
let sig = vcrypto
|
let sig = vcrypto
|
||||||
.sign(&node_id.key, &node_id_secret, &route_operation.data)
|
.sign(&node_id.value, &node_id_secret, &route_operation.data)
|
||||||
.map_err(RPCError::internal)?;
|
.map_err(RPCError::internal)?;
|
||||||
route_operation.signatures.push(sig);
|
route_operation.signatures.push(sig);
|
||||||
}
|
}
|
||||||
|
@ -394,7 +394,7 @@ impl RPCProcessor {
|
||||||
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
||||||
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
|
||||||
let dh_secret = vcrypto
|
let dh_secret = vcrypto
|
||||||
.cached_dh(&route.safety_route.public_key.key, &node_id_secret)
|
.cached_dh(&route.safety_route.public_key.value, &node_id_secret)
|
||||||
.map_err(RPCError::protocol)?;
|
.map_err(RPCError::protocol)?;
|
||||||
let mut dec_blob_data = vcrypto
|
let mut dec_blob_data = vcrypto
|
||||||
.decrypt_aead(
|
.decrypt_aead(
|
||||||
|
|
|
@ -71,7 +71,7 @@ pub async fn test_signed_node_info() {
|
||||||
|
|
||||||
let sni = SignedDirectNodeInfo::make_signatures(
|
let sni = SignedDirectNodeInfo::make_signatures(
|
||||||
crypto.clone(),
|
crypto.clone(),
|
||||||
vec![TypedKeyPair::new(ck, pkey, skey)],
|
vec![TypedKeyPair::new(ck, KeyPair::new(pkey, skey))],
|
||||||
node_info.clone(),
|
node_info.clone(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -107,7 +107,7 @@ pub async fn test_signed_node_info() {
|
||||||
|
|
||||||
let sni2 = SignedRelayedNodeInfo::make_signatures(
|
let sni2 = SignedRelayedNodeInfo::make_signatures(
|
||||||
crypto.clone(),
|
crypto.clone(),
|
||||||
vec![TypedKeyPair::new(ck, pkey2, skey2)],
|
vec![TypedKeyPair::new(ck, KeyPair::new(pkey2, skey2))],
|
||||||
node_info2.clone(),
|
node_info2.clone(),
|
||||||
tks.clone(),
|
tks.clone(),
|
||||||
sni.clone(),
|
sni.clone(),
|
||||||
|
|
|
@ -1902,11 +1902,10 @@ impl SignedDirectNodeInfo {
|
||||||
) -> Result<Self, VeilidAPIError> {
|
) -> Result<Self, VeilidAPIError> {
|
||||||
let timestamp = get_aligned_timestamp();
|
let timestamp = get_aligned_timestamp();
|
||||||
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
|
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
|
||||||
let typed_signatures = crypto.generate_signatures(
|
let typed_signatures =
|
||||||
&node_info_bytes,
|
crypto.generate_signatures(&node_info_bytes, &typed_key_pairs, |kp, s| {
|
||||||
&typed_key_pairs,
|
TypedSignature::new(kp.kind, s)
|
||||||
TypedSignature::from_pair_sig,
|
})?;
|
||||||
)?;
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
node_info,
|
node_info,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
@ -1997,11 +1996,10 @@ impl SignedRelayedNodeInfo {
|
||||||
let timestamp = get_aligned_timestamp();
|
let timestamp = get_aligned_timestamp();
|
||||||
let node_info_bytes =
|
let node_info_bytes =
|
||||||
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
|
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
|
||||||
let typed_signatures = crypto.generate_signatures(
|
let typed_signatures =
|
||||||
&node_info_bytes,
|
crypto.generate_signatures(&node_info_bytes, &typed_key_pairs, |kp, s| {
|
||||||
&typed_key_pairs,
|
TypedSignature::new(kp.kind, s)
|
||||||
TypedSignature::from_pair_sig,
|
})?;
|
||||||
)?;
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
node_info,
|
node_info,
|
||||||
relay_ids,
|
relay_ids,
|
||||||
|
|
|
@ -613,6 +613,9 @@ impl VeilidConfig {
|
||||||
cb: ConfigCallback,
|
cb: ConfigCallback,
|
||||||
update_cb: UpdateCallback,
|
update_cb: UpdateCallback,
|
||||||
) -> Result<(), VeilidAPIError> {
|
) -> Result<(), VeilidAPIError> {
|
||||||
|
self.update_cb = Some(update_cb);
|
||||||
|
self.with_mut(|inner| {
|
||||||
|
// Simple config transformation
|
||||||
macro_rules! get_config {
|
macro_rules! get_config {
|
||||||
($key:expr) => {
|
($key:expr) => {
|
||||||
let keyname = &stringify!($key)[6..];
|
let keyname = &stringify!($key)[6..];
|
||||||
|
@ -625,26 +628,55 @@ impl VeilidConfig {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
macro_rules! get_config_indexed {
|
// More complicated optional fields for node ids
|
||||||
($key:expr, $index:expr, $subkey:tt) => {
|
macro_rules! get_config_node_ids {
|
||||||
let keyname = format!(
|
() => {
|
||||||
"{}[{}].{}",
|
let keys = cb("network.routing_table.node_id".to_owned())?;
|
||||||
&stringify!($key)[6..],
|
let keys: Option<TypedKeySet> = match keys.downcast() {
|
||||||
$index,
|
|
||||||
&stringify!($subkey)
|
|
||||||
);
|
|
||||||
let v = cb(keyname.to_owned())?;
|
|
||||||
$key.entry($index).or_default().$subkey = match v.downcast() {
|
|
||||||
Ok(v) => *v,
|
Ok(v) => *v,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
apibail_generic!(format!("incorrect type for key {}", keyname))
|
apibail_generic!(
|
||||||
|
"incorrect type for key 'network.routing_table.node_id'".to_owned()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let keys = keys.unwrap_or_default();
|
||||||
|
|
||||||
|
let secrets = cb("network.routing_table.node_id_secret".to_owned())?;
|
||||||
|
let secrets: Option<TypedSecretSet> = match secrets.downcast() {
|
||||||
|
Ok(v) => *v,
|
||||||
|
Err(_) => {
|
||||||
|
apibail_generic!(
|
||||||
|
"incorrect type for key 'network.routing_table.node_id_secret'"
|
||||||
|
.to_owned()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let secrets = secrets.unwrap_or_default();
|
||||||
|
|
||||||
|
for ck in VALID_CRYPTO_KINDS {
|
||||||
|
if let Some(key) = keys.get(ck) {
|
||||||
|
inner
|
||||||
|
.network
|
||||||
|
.routing_table
|
||||||
|
.node_ids
|
||||||
|
.entry(ck)
|
||||||
|
.or_default()
|
||||||
|
.node_id = Some(key.value);
|
||||||
|
}
|
||||||
|
if let Some(secret) = secrets.get(ck) {
|
||||||
|
inner
|
||||||
|
.network
|
||||||
|
.routing_table
|
||||||
|
.node_ids
|
||||||
|
.entry(ck)
|
||||||
|
.or_default()
|
||||||
|
.node_id_secret = Some(secret.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_cb = Some(update_cb);
|
|
||||||
self.with_mut(|inner| {
|
|
||||||
get_config!(inner.program_name);
|
get_config!(inner.program_name);
|
||||||
get_config!(inner.namespace);
|
get_config!(inner.namespace);
|
||||||
get_config!(inner.capabilities.protocol_udp);
|
get_config!(inner.capabilities.protocol_udp);
|
||||||
|
@ -670,11 +702,7 @@ impl VeilidConfig {
|
||||||
get_config!(inner.network.max_connection_frequency_per_min);
|
get_config!(inner.network.max_connection_frequency_per_min);
|
||||||
get_config!(inner.network.client_whitelist_timeout_ms);
|
get_config!(inner.network.client_whitelist_timeout_ms);
|
||||||
get_config!(inner.network.reverse_connection_receipt_time_ms);
|
get_config!(inner.network.reverse_connection_receipt_time_ms);
|
||||||
get_config!(inner.network.hole_punch_receipt_time_ms);
|
get_config_node_ids!();
|
||||||
for ck in VALID_CRYPTO_KINDS {
|
|
||||||
get_config_indexed!(inner.network.routing_table.node_ids, ck, node_id);
|
|
||||||
get_config_indexed!(inner.network.routing_table.node_ids, ck, node_id_secret);
|
|
||||||
}
|
|
||||||
get_config!(inner.network.routing_table.bootstrap);
|
get_config!(inner.network.routing_table.bootstrap);
|
||||||
get_config!(inner.network.routing_table.limit_over_attached);
|
get_config!(inner.network.routing_table.limit_over_attached);
|
||||||
get_config!(inner.network.routing_table.limit_fully_attached);
|
get_config!(inner.network.routing_table.limit_fully_attached);
|
||||||
|
|
|
@ -1818,19 +1818,19 @@ Sequencing sequencingFromJson(String j) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
/// KeyBlob
|
/// RouteBlob
|
||||||
class KeyBlob {
|
class RouteBlob {
|
||||||
final String key;
|
final String routeId;
|
||||||
final Uint8List blob;
|
final Uint8List blob;
|
||||||
|
|
||||||
KeyBlob(this.key, this.blob);
|
RouteBlob(this.routeId, this.blob);
|
||||||
|
|
||||||
KeyBlob.fromJson(dynamic json)
|
RouteBlob.fromJson(dynamic json)
|
||||||
: key = json['key'],
|
: routeId = json['route_id'],
|
||||||
blob = base64UrlNoPadDecode(json['blob']);
|
blob = base64UrlNoPadDecode(json['blob']);
|
||||||
|
|
||||||
Map<String, dynamic> get json {
|
Map<String, dynamic> get json {
|
||||||
return {'key': key, 'blob': base64UrlNoPadEncode(blob)};
|
return {'route_id': routeId, 'blob': base64UrlNoPadEncode(blob)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1918,8 +1918,8 @@ abstract class Veilid {
|
||||||
Future<VeilidRoutingContext> routingContext();
|
Future<VeilidRoutingContext> routingContext();
|
||||||
|
|
||||||
// Private route allocation
|
// Private route allocation
|
||||||
Future<KeyBlob> newPrivateRoute();
|
Future<RouteBlob> newPrivateRoute();
|
||||||
Future<KeyBlob> newCustomPrivateRoute(
|
Future<RouteBlob> newCustomPrivateRoute(
|
||||||
Stability stability, Sequencing sequencing);
|
Stability stability, Sequencing sequencing);
|
||||||
Future<String> importRemotePrivateRoute(Uint8List blob);
|
Future<String> importRemotePrivateRoute(Uint8List blob);
|
||||||
Future<void> releasePrivateRoute(String key);
|
Future<void> releasePrivateRoute(String key);
|
||||||
|
|
|
@ -847,21 +847,21 @@ class VeilidFFI implements Veilid {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<KeyBlob> newPrivateRoute() {
|
Future<RouteBlob> newPrivateRoute() {
|
||||||
final recvPort = ReceivePort("new_private_route");
|
final recvPort = ReceivePort("new_private_route");
|
||||||
final sendPort = recvPort.sendPort;
|
final sendPort = recvPort.sendPort;
|
||||||
_newPrivateRoute(sendPort.nativePort);
|
_newPrivateRoute(sendPort.nativePort);
|
||||||
return processFutureJson(KeyBlob.fromJson, recvPort.first);
|
return processFutureJson(RouteBlob.fromJson, recvPort.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<KeyBlob> newCustomPrivateRoute(
|
Future<RouteBlob> newCustomPrivateRoute(
|
||||||
Stability stability, Sequencing sequencing) async {
|
Stability stability, Sequencing sequencing) async {
|
||||||
final recvPort = ReceivePort("new_custom_private_route");
|
final recvPort = ReceivePort("new_custom_private_route");
|
||||||
final sendPort = recvPort.sendPort;
|
final sendPort = recvPort.sendPort;
|
||||||
_newCustomPrivateRoute(sendPort.nativePort, stability.json.toNativeUtf8(),
|
_newCustomPrivateRoute(sendPort.nativePort, stability.json.toNativeUtf8(),
|
||||||
sequencing.json.toNativeUtf8());
|
sequencing.json.toNativeUtf8());
|
||||||
final keyblob = await processFutureJson(KeyBlob.fromJson, recvPort.first);
|
final keyblob = await processFutureJson(RouteBlob.fromJson, recvPort.first);
|
||||||
return keyblob;
|
return keyblob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,15 +65,15 @@ class VeilidRoutingContextJS implements VeilidRoutingContext {
|
||||||
var encodedRequest = base64UrlNoPadEncode(request);
|
var encodedRequest = base64UrlNoPadEncode(request);
|
||||||
|
|
||||||
return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod(
|
return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod(
|
||||||
wasm, "routing_context_app_call", [_ctx.id, encodedRequest])));
|
wasm, "routing_context_app_call", [_ctx.id, target, encodedRequest])));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> appMessage(String target, Uint8List message) {
|
Future<void> appMessage(String target, Uint8List message) {
|
||||||
var encodedMessage = base64UrlNoPadEncode(message);
|
var encodedMessage = base64UrlNoPadEncode(message);
|
||||||
|
|
||||||
return _wrapApiPromise(js_util.callMethod(
|
return _wrapApiPromise(js_util.callMethod(wasm,
|
||||||
wasm, "routing_context_app_message", [_ctx.id, encodedMessage]));
|
"routing_context_app_message", [_ctx.id, target, encodedMessage]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,14 +267,14 @@ class VeilidJS implements Veilid {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<KeyBlob> newPrivateRoute() async {
|
Future<RouteBlob> newPrivateRoute() async {
|
||||||
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(
|
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(
|
||||||
js_util.callMethod(wasm, "new_private_route", [])));
|
js_util.callMethod(wasm, "new_private_route", [])));
|
||||||
return KeyBlob.fromJson(blobJson);
|
return RouteBlob.fromJson(blobJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<KeyBlob> newCustomPrivateRoute(
|
Future<RouteBlob> newCustomPrivateRoute(
|
||||||
Stability stability, Sequencing sequencing) async {
|
Stability stability, Sequencing sequencing) async {
|
||||||
var stabilityString =
|
var stabilityString =
|
||||||
jsonEncode(stability, toEncodable: veilidApiToEncodable);
|
jsonEncode(stability, toEncodable: veilidApiToEncodable);
|
||||||
|
@ -284,7 +284,7 @@ class VeilidJS implements Veilid {
|
||||||
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(js_util
|
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(js_util
|
||||||
.callMethod(
|
.callMethod(
|
||||||
wasm, "new_private_route", [stabilityString, sequencingString])));
|
wasm, "new_private_route", [stabilityString, sequencingString])));
|
||||||
return KeyBlob.fromJson(blobJson);
|
return RouteBlob.fromJson(blobJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -10,12 +10,14 @@ use opentelemetry::*;
|
||||||
use opentelemetry_otlp::WithExportConfig;
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use serde::*;
|
use serde::*;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::*;
|
use tracing::*;
|
||||||
use tracing_subscriber::prelude::*;
|
use tracing_subscriber::prelude::*;
|
||||||
use tracing_subscriber::*;
|
use tracing_subscriber::*;
|
||||||
|
use veilid_core::Encodable as _;
|
||||||
|
|
||||||
// Globals
|
// Globals
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -56,6 +58,29 @@ define_string_destructor!(free_string);
|
||||||
type APIResult<T> = Result<T, veilid_core::VeilidAPIError>;
|
type APIResult<T> = Result<T, veilid_core::VeilidAPIError>;
|
||||||
const APIRESULT_VOID: APIResult<()> = APIResult::Ok(());
|
const APIRESULT_VOID: APIResult<()> = APIResult::Ok(());
|
||||||
|
|
||||||
|
// Parse target
|
||||||
|
async fn parse_target(s: String) -> APIResult<veilid_core::Target> {
|
||||||
|
|
||||||
|
// Is this a route id?
|
||||||
|
if let Ok(rrid) = veilid_core::RouteId::from_str(&s) {
|
||||||
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
let routing_table = veilid_api.routing_table()?;
|
||||||
|
let rss = routing_table.route_spec_store();
|
||||||
|
|
||||||
|
// Is this a valid remote route id? (can't target allocated routes)
|
||||||
|
if rss.is_route_id_remote(&rrid) {
|
||||||
|
return Ok(veilid_core::Target::PrivateRoute(rrid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this a node id?
|
||||||
|
if let Ok(nid) = veilid_core::PublicKey::from_str(&s) {
|
||||||
|
return Ok(veilid_core::Target::NodeId(nid));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(veilid_core::VeilidAPIError::invalid_target())
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/////////////////////////////////////////
|
||||||
// FFI-specific
|
// FFI-specific
|
||||||
|
|
||||||
|
@ -92,8 +117,8 @@ pub struct VeilidFFIConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct VeilidFFIKeyBlob {
|
pub struct VeilidFFIRouteBlob {
|
||||||
pub key: veilid_core::TypedKey,
|
pub route_id: veilid_core::RouteId,
|
||||||
#[serde(with = "veilid_core::json_as_base64")]
|
#[serde(with = "veilid_core::json_as_base64")]
|
||||||
pub blob: Vec<u8>,
|
pub blob: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
@ -415,10 +440,10 @@ pub extern "C" fn routing_context_with_sequencing(id: u32, sequencing: FfiStr) -
|
||||||
new_id
|
new_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) {
|
pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) {
|
||||||
let target: veilid_core::TypedKey =
|
let target_string: String = target.into_opt_string().unwrap();
|
||||||
veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap();
|
|
||||||
let request: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
let request: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
.decode(
|
.decode(
|
||||||
request.into_opt_string()
|
request.into_opt_string()
|
||||||
|
@ -427,10 +452,6 @@ pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, r
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||||
let veilid_api = get_veilid_api().await?;
|
|
||||||
let routing_table = veilid_api.routing_table()?;
|
|
||||||
let rss = routing_table.route_spec_store();
|
|
||||||
|
|
||||||
let routing_context = {
|
let routing_context = {
|
||||||
let rc = ROUTING_CONTEXTS.lock();
|
let rc = ROUTING_CONTEXTS.lock();
|
||||||
let Some(routing_context) = rc.get(&id) else {
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
|
@ -439,12 +460,7 @@ pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, r
|
||||||
routing_context.clone()
|
routing_context.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = if rss.get_remote_private_route(&target).is_some() {
|
let target = parse_target(target_string).await?;
|
||||||
veilid_core::Target::PrivateRoute(target)
|
|
||||||
} else {
|
|
||||||
veilid_core::Target::NodeId(veilid_core::NodeId::new(target))
|
|
||||||
};
|
|
||||||
|
|
||||||
let answer = routing_context.app_call(target, request).await?;
|
let answer = routing_context.app_call(target, request).await?;
|
||||||
let answer = data_encoding::BASE64URL_NOPAD.encode(&answer);
|
let answer = data_encoding::BASE64URL_NOPAD.encode(&answer);
|
||||||
APIResult::Ok(answer)
|
APIResult::Ok(answer)
|
||||||
|
@ -453,8 +469,7 @@ pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, r
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr, message: FfiStr) {
|
pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr, message: FfiStr) {
|
||||||
let target: veilid_core::TypedKey =
|
let target_string: String = target.into_opt_string().unwrap();
|
||||||
veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap();
|
|
||||||
let message: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
let message: Vec<u8> = data_encoding::BASE64URL_NOPAD
|
||||||
.decode(
|
.decode(
|
||||||
message.into_opt_string()
|
message.into_opt_string()
|
||||||
|
@ -463,10 +478,6 @@ pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||||
let veilid_api = get_veilid_api().await?;
|
|
||||||
let routing_table = veilid_api.routing_table()?;
|
|
||||||
let rss = routing_table.route_spec_store();
|
|
||||||
|
|
||||||
let routing_context = {
|
let routing_context = {
|
||||||
let rc = ROUTING_CONTEXTS.lock();
|
let rc = ROUTING_CONTEXTS.lock();
|
||||||
let Some(routing_context) = rc.get(&id) else {
|
let Some(routing_context) = rc.get(&id) else {
|
||||||
|
@ -475,12 +486,7 @@ pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr
|
||||||
routing_context.clone()
|
routing_context.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = if rss.get_remote_private_route(&target).is_some() {
|
let target = parse_target(target_string).await?;
|
||||||
veilid_core::Target::PrivateRoute(target)
|
|
||||||
} else {
|
|
||||||
veilid_core::Target::NodeId(veilid_core::NodeId::new(target))
|
|
||||||
};
|
|
||||||
|
|
||||||
routing_context.app_message(target, message).await?;
|
routing_context.app_message(target, message).await?;
|
||||||
APIRESULT_VOID
|
APIRESULT_VOID
|
||||||
});
|
});
|
||||||
|
@ -491,9 +497,9 @@ pub extern "C" fn new_private_route(port: i64) {
|
||||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
let veilid_api = get_veilid_api().await?;
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
|
||||||
let (key, blob) = veilid_api.new_private_route().await?;
|
let (route_id, blob) = veilid_api.new_private_route().await?;
|
||||||
|
|
||||||
let keyblob = VeilidFFIKeyBlob { key, blob };
|
let keyblob = VeilidFFIRouteBlob { route_id, blob };
|
||||||
|
|
||||||
APIResult::Ok(keyblob)
|
APIResult::Ok(keyblob)
|
||||||
});
|
});
|
||||||
|
@ -509,11 +515,11 @@ pub extern "C" fn new_custom_private_route(port: i64, stability: FfiStr, sequenc
|
||||||
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
DartIsolateWrapper::new(port).spawn_result_json(async move {
|
||||||
let veilid_api = get_veilid_api().await?;
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
|
||||||
let (key, blob) = veilid_api
|
let (route_id, blob) = veilid_api
|
||||||
.new_custom_private_route(stability, sequencing)
|
.new_custom_private_route(&veilid_core::VALID_CRYPTO_KINDS, stability, sequencing)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let keyblob = VeilidFFIKeyBlob { key, blob };
|
let keyblob = VeilidFFIRouteBlob { route_id, blob };
|
||||||
|
|
||||||
APIResult::Ok(keyblob)
|
APIResult::Ok(keyblob)
|
||||||
});
|
});
|
||||||
|
@ -531,19 +537,19 @@ pub extern "C" fn import_remote_private_route(port: i64, blob: FfiStr) {
|
||||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||||
let veilid_api = get_veilid_api().await?;
|
let veilid_api = get_veilid_api().await?;
|
||||||
|
|
||||||
let key = veilid_api.import_remote_private_route(blob)?;
|
let route_id = veilid_api.import_remote_private_route(blob)?;
|
||||||
|
|
||||||
APIResult::Ok(key.encode())
|
APIResult::Ok(route_id.encode())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn release_private_route(port: i64, key: FfiStr) {
|
pub extern "C" fn release_private_route(port: i64, key: FfiStr) {
|
||||||
let key: veilid_core::TypedKey =
|
let route_id: veilid_core::RouteId =
|
||||||
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap();
|
||||||
DartIsolateWrapper::new(port).spawn_result(async move {
|
DartIsolateWrapper::new(port).spawn_result(async move {
|
||||||
let veilid_api = get_veilid_api().await?;
|
let veilid_api = get_veilid_api().await?;
|
||||||
veilid_api.release_private_route(&key)?;
|
veilid_api.release_private_route(route_id)?;
|
||||||
APIRESULT_VOID
|
APIRESULT_VOID
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use clap::{Arg, ArgMatches, Command};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use veilid_core::{SecretKey, TypedKeySet};
|
use veilid_core::{TypedKeySet, TypedSecretSet};
|
||||||
|
|
||||||
fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap::Error> {
|
fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap::Error> {
|
||||||
let matches = Command::new("veilid-server")
|
let matches = Command::new("veilid-server")
|
||||||
|
@ -78,17 +78,21 @@ fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap
|
||||||
.help("Run as an extra daemon on the same machine for testing purposes, specify a number greater than zero to offset the listening ports"),
|
.help("Run as an extra daemon on the same machine for testing purposes, specify a number greater than zero to offset the listening ports"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("generate-dht-key")
|
Arg::new("generate-key-pair")
|
||||||
.long("generate-dht-key")
|
.long("generate-key-pair")
|
||||||
.help("Only generate a new dht key and print it"),
|
.takes_value(true)
|
||||||
|
.value_name("crypto_kind")
|
||||||
|
.default_missing_value("VLD0")
|
||||||
|
.help("Only generate a new keypair and print it")
|
||||||
|
.long_help("Generate a new keypair for a specific crypto kind and print both the key and its secret to the terminal, then exit immediately."),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("set-node-id")
|
Arg::new("set-node-id")
|
||||||
.long("set-node-id")
|
.long("set-node-id")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("ID")
|
.value_name("key_set")
|
||||||
.help("Set the node id and secret key")
|
.help("Set the node ids and secret keys")
|
||||||
.long_help("To specify both node id and secret key on the command line, use a ID:SECRET syntax with a colon, like:\n zsVXz5aTU98vZxwTcDmvpcnO5g1B2jRO3wpdNiDrRgw:gJzQLmzuBvA-dFvEmLcYvLoO5bh7hzCWFzfpJHapZKg\nIf no colon is used, the node id is specified, and a prompt appears to enter the secret key interactively.")
|
.long_help("Specify node ids in typed key set format ('[VLD0:xxxx,VLD1:xxxx]') on the command line, a prompt appears to enter the secret key set interactively.")
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("delete-protected-store")
|
Arg::new("delete-protected-store")
|
||||||
|
@ -239,13 +243,13 @@ pub fn process_command_line() -> EyreResult<(Settings, ArgMatches)> {
|
||||||
let tks =
|
let tks =
|
||||||
TypedKeySet::from_str(v).wrap_err("failed to decode node id set from command line")?;
|
TypedKeySet::from_str(v).wrap_err("failed to decode node id set from command line")?;
|
||||||
|
|
||||||
let buffer = rpassword::prompt_password("Enter secret key (will not echo): ")
|
let buffer = rpassword::prompt_password("Enter secret key set (will not echo): ")
|
||||||
.wrap_err("invalid secret key")?;
|
.wrap_err("invalid secret key")?;
|
||||||
let buffer = buffer.trim().to_string();
|
let buffer = buffer.trim().to_string();
|
||||||
let s = SecretKey::try_decode(&buffer)?;
|
let tss = TypedSecretSet::from_str(&buffer).wrap_err("failed to decode secret set")?;
|
||||||
|
|
||||||
settingsrw.core.network.node_id = Some(k);
|
settingsrw.core.network.routing_table.node_id = Some(tks);
|
||||||
settingsrw.core.network.node_id_secret = Some(s);
|
settingsrw.core.network.routing_table.node_id_secret = Some(tss);
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches.occurrences_of("bootstrap") != 0 {
|
if matches.occurrences_of("bootstrap") != 0 {
|
||||||
|
@ -264,7 +268,7 @@ pub fn process_command_line() -> EyreResult<(Settings, ArgMatches)> {
|
||||||
bail!("value not specified for bootstrap");
|
bail!("value not specified for bootstrap");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
settingsrw.core.network.bootstrap = bootstrap_list;
|
settingsrw.core.network.routing_table.bootstrap = bootstrap_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rt-tokio")]
|
#[cfg(feature = "rt-tokio")]
|
||||||
|
|
|
@ -20,6 +20,7 @@ use color_eyre::eyre::{bail, ensure, eyre, Result as EyreResult, WrapErr};
|
||||||
use server::*;
|
use server::*;
|
||||||
use tools::*;
|
use tools::*;
|
||||||
use tracing::*;
|
use tracing::*;
|
||||||
|
use veilid_core::Encodable as _;
|
||||||
use veilid_logs::*;
|
use veilid_logs::*;
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
@ -42,8 +43,8 @@ fn main() -> EyreResult<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Generate DHT Key ---
|
// --- Generate DHT Key ---
|
||||||
if matches.occurrences_of("generate-dht-key") != 0 {
|
if matches.occurrences_of("generate-key-pair") != 0 {
|
||||||
let (key, secret) = veilid_core::generate_secret();
|
let (key, secret) = veilid_core::vld0_generate_keypair();
|
||||||
println!("Public: {}\nSecret: {}", key.encode(), secret.encode());
|
println!("Public: {}\nSecret: {}", key.encode(), secret.encode());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,7 +517,7 @@ pub struct Dht {
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct RoutingTable {
|
pub struct RoutingTable {
|
||||||
pub node_id: Option<veilid_core::TypedKeySet>,
|
pub node_id: Option<veilid_core::TypedKeySet>,
|
||||||
pub node_id_secret: Option<veilid_core::SecretKey>,
|
pub node_id_secret: Option<veilid_core::TypedSecretSet>,
|
||||||
pub bootstrap: Vec<String>,
|
pub bootstrap: Vec<String>,
|
||||||
pub limit_over_attached: u32,
|
pub limit_over_attached: u32,
|
||||||
pub limit_fully_attached: u32,
|
pub limit_fully_attached: u32,
|
||||||
|
@ -857,6 +857,7 @@ impl Settings {
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
set_config_value!(inner.daemon.enabled, value);
|
set_config_value!(inner.daemon.enabled, value);
|
||||||
set_config_value!(inner.client_api.enabled, value);
|
set_config_value!(inner.client_api.enabled, value);
|
||||||
set_config_value!(inner.client_api.listen_address, value);
|
set_config_value!(inner.client_api.listen_address, value);
|
||||||
|
@ -1057,11 +1058,11 @@ impl Settings {
|
||||||
Ok(Box::new(inner.core.network.hole_punch_receipt_time_ms))
|
Ok(Box::new(inner.core.network.hole_punch_receipt_time_ms))
|
||||||
}
|
}
|
||||||
"network.routing_table.node_id" => {
|
"network.routing_table.node_id" => {
|
||||||
Ok(Box::new(inner.core.network.routing_table.node_id))
|
Ok(Box::new(inner.core.network.routing_table.node_id.clone()))
|
||||||
}
|
|
||||||
"network.routing_table.node_id_secret" => {
|
|
||||||
Ok(Box::new(inner.core.network.routing_table.node_id_secret))
|
|
||||||
}
|
}
|
||||||
|
"network.routing_table.node_id_secret" => Ok(Box::new(
|
||||||
|
inner.core.network.routing_table.node_id_secret.clone(),
|
||||||
|
)),
|
||||||
"network.routing_table.bootstrap" => {
|
"network.routing_table.bootstrap" => {
|
||||||
Ok(Box::new(inner.core.network.routing_table.bootstrap.clone()))
|
Ok(Box::new(inner.core.network.routing_table.bootstrap.clone()))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue