diff --git a/veilid-core/proto/veilid.capnp b/veilid-core/proto/veilid.capnp index 131ba3e8..c92af433 100644 --- a/veilid-core/proto/veilid.capnp +++ b/veilid-core/proto/veilid.capnp @@ -36,12 +36,12 @@ using ValueSeqNum = UInt32; # sequence numbers for v using ValueSchema = UInt32; # FOURCC code for schema (0 = freeform, SUB0 = subkey control v0) using Subkey = UInt32; # subkey index for dht -struct TypedKey { +struct TypedKey @0xe2d567a9f1e61b29 { kind @0 :CryptoKind; key @1 :PublicKey; } -struct TypedSignature { +struct TypedSignature @0x963170c7298e3884 { kind @0 :CryptoKind; signature @1 :Signature; } @@ -160,25 +160,6 @@ struct SafetyRoute @0xf554734d07cb5d59 { } } -# Values -############################## - -struct SubkeyRange { - start @0 :Subkey; # the start of a subkey range - end @1 :Subkey; # the end of a subkey range -} - -struct ValueKey @0xe64b0992c21a0736 { - publicKey @0 :TypedKey; # the location of the value - subkey @1 :Subkey; # the index of the subkey (0 for the default subkey) -} - -struct ValueData @0xb4b7416f169f2a3d { - seq @0 :ValueSeqNum; # sequence number of value - schema @1 :ValueSchema; # fourcc code of schema for value - data @2 :Data; # value or subvalue contents -} - # Operations ############################## @@ -249,8 +230,8 @@ struct NodeInfo @0xe125d847e3f9f419 { networkClass @0 :NetworkClass; # network class of this node outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound addressTypes @2 :AddressTypeSet; # address types supported - envelopeSupport @3 :UInt8; # minimum protocol version for rpc - maxVersion @4 :UInt8; # maximum protocol version for rpc + envelopeSupport @3 :List(UInt8); # supported envelope versions + cryptoSupport @4 :List(CryptoKind); # maximum protocol version for rpc dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node } @@ -262,7 +243,7 @@ struct SignedDirectNodeInfo @0xe0e7ea3e893a3dd7 { struct SignedRelayedNodeInfo @0xb39e8428ccd87cbb { nodeInfo @0 :NodeInfo; # node info - relayId @1 :List(TypedKey); # node ids for relay + relayIds @1 :List(TypedKey); # node ids for relay relayInfo @2 :SignedDirectNodeInfo; # signed node info for relay timestamp @3 :UInt64; # when signed node info was generated signatures @4 :List(TypedSignature); # signatures @@ -331,6 +312,17 @@ struct OperationAppMessage @0x9baf542d81b411f5 { message @0 :Data; # opaque message to application } +struct SubkeyRange { + start @0 :Subkey; # the start of a subkey range + end @1 :Subkey; # the end of a subkey range +} + +struct ValueData @0xb4b7416f169f2a3d { + seq @0 :ValueSeqNum; # sequence number of value + schema @1 :ValueSchema; # fourcc code of schema for value + data @2 :Data; # value or subvalue contents +} + struct OperationGetValueQ @0xf88a5b6da5eda5d0 { publicKey @0 :TypedKey; # the location of the value subkey @1 :Subkey; # the index of the subkey (0 for the default subkey) @@ -358,19 +350,19 @@ struct OperationSetValueA @0x9378d0732dc95be2 { struct OperationWatchValueQ @0xf9a5a6c547b9b228 { publicKey @0 :TypedKey; # key for value to watch - subkeys @1 :List(SubkeyRange) # subkey range to watch, if empty, watch everything + subkeys @1 :List(SubkeyRange); # subkey range to watch, if empty, watch everything expiration @2 :UInt64; # requested timestamp when this watch will expire in usec since epoch (can be return less, 0 for max) count @3 :UInt32; # requested number of changes to watch for (0 = continuous, 1 = single shot, 2+ = counter) } struct OperationWatchValueA @0xa726cab7064ba893 { expiration @0 :UInt64; # timestamp when this watch will expire in usec since epoch (0 if watch failed) - peers @2 :List(PeerInfo); # returned list of other nodes to ask that could propagate watches + peers @1 :List(PeerInfo); # returned list of other nodes to ask that could propagate watches } struct OperationValueChanged @0xd1c59ebdd8cc1bf6 { publicKey @0 :TypedKey; # key for value that changed - subkeys @1 :List(SubkeyRange) # subkey range that changed (up to 512 ranges at a time) + subkeys @1 :List(SubkeyRange); # subkey range that changed (up to 512 ranges at a time) count @2 :UInt32; # remaining changes left (0 means watch has expired) value @3 :ValueData; # first value that changed (the rest can be gotten with getvalue) } diff --git a/veilid-core/src/crypto/envelope.rs b/veilid-core/src/crypto/envelope.rs index d0ce16b6..1b2b0fbc 100644 --- a/veilid-core/src/crypto/envelope.rs +++ b/veilid-core/src/crypto/envelope.rs @@ -89,7 +89,7 @@ impl Envelope { } // Check crypto kind - let crypto_kind = CryptoKind( + let crypto_kind = FourCC( data[0x04..0x08] .try_into() .map_err(VeilidAPIError::internal)?, diff --git a/veilid-core/src/crypto/mod.rs b/veilid-core/src/crypto/mod.rs index d9f8ec49..952ee7d8 100644 --- a/veilid-core/src/crypto/mod.rs +++ b/veilid-core/src/crypto/mod.rs @@ -231,23 +231,22 @@ impl Crypto { /// Returns the set of signature cryptokinds that validate and are supported /// If any cryptokinds are supported and do not validate, the whole operation /// returns an error - pub fn verify_signatures( + pub fn verify_signatures( &self, + node_ids: &[TypedKey], data: &[u8], - signatures: &[TypedKeySignature], - transform: F, - ) -> Result, VeilidAPIError> - where - F: Fn(&TypedKeySignature) -> R, - { - let mut out = Vec::::with_capacity(signatures.len()); - for sig in signatures { - if let Some(vcrypto) = self.get(sig.kind) { - vcrypto.verify(&sig.key, data, &sig.signature)?; - out.push(transform(sig)); + typed_signatures: &[TypedSignature], + ) -> Result<(), VeilidAPIError> { + for sig in typed_signatures { + for nid in node_ids { + if nid.kind == sig.kind { + if let Some(vcrypto) = self.get(sig.kind) { + vcrypto.verify(&nid.key, data, &sig.signature)?; + } + } } } - Ok(out) + Ok(()) } /// Signature set generation @@ -256,14 +255,14 @@ impl Crypto { pub fn generate_signatures( &self, data: &[u8], - keypairs: &[TypedKeyPair], + typed_key_pairs: &[TypedKeyPair], transform: F, ) -> Result, VeilidAPIError> where F: Fn(&TypedKeyPair, Signature) -> R, { - let mut out = Vec::::with_capacity(keypairs.len()); - for kp in keypairs { + let mut out = Vec::::with_capacity(typed_key_pairs.len()); + for kp in typed_key_pairs { if let Some(vcrypto) = self.get(kp.kind) { let sig = vcrypto.sign(&kp.key, &kp.secret, data)?; out.push(transform(kp, sig)) diff --git a/veilid-core/src/crypto/receipt.rs b/veilid-core/src/crypto/receipt.rs index 1b82be5f..d33ec837 100644 --- a/veilid-core/src/crypto/receipt.rs +++ b/veilid-core/src/crypto/receipt.rs @@ -90,7 +90,7 @@ impl Receipt { } // Check crypto kind - let crypto_kind = CryptoKind( + let crypto_kind = FourCC( data[0x04..0x08] .try_into() .map_err(VeilidAPIError::internal)?, diff --git a/veilid-core/src/crypto/types.rs b/veilid-core/src/crypto/types.rs index 8e96e3ab..5e9c0332 100644 --- a/veilid-core/src/crypto/types.rs +++ b/veilid-core/src/crypto/types.rs @@ -1,61 +1,30 @@ use super::*; use core::cmp::{Eq, Ord, PartialEq, PartialOrd}; -use core::convert::{TryFrom, TryInto}; +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; + #[derive( + Clone, Copy, Debug, - Default, - Clone, - Hash, + Serialize, + Deserialize, PartialOrd, Ord, PartialEq, Eq, - Serialize, - Deserialize, + Hash, RkyvArchive, RkyvSerialize, RkyvDeserialize, )] -#[archive_attr(repr(C), derive(CheckBytes, PartialOrd, Ord, PartialEq, Eq))] -pub struct CryptoKind(pub [u8; 4]); - -impl From<[u8; 4]> for CryptoKind { - fn from(b: [u8; 4]) -> Self { - Self(b) - } -} -impl TryFrom<&[u8]> for CryptoKind { - type Error = VeilidAPIError; - fn try_from(b: &[u8]) -> Result { - Ok(Self(b.try_into().map_err(VeilidAPIError::generic)?)) - } -} - -impl fmt::Display for CryptoKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - write!(f, "{}", String::from_utf8_lossy(&self.0)) - } -} -impl FromStr for CryptoKind { - type Err = VeilidAPIError; - fn from_str(s: &str) -> Result { - Ok(Self( - s.as_bytes().try_into().map_err(VeilidAPIError::generic)?, - )) - } -} - -#[derive( - Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize, -)] #[archive_attr(repr(C), derive(CheckBytes))] pub struct TypedKey { pub kind: CryptoKind, @@ -87,7 +56,19 @@ impl FromStr for TypedKey { } #[derive( - Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize, + Clone, + Copy, + Debug, + PartialOrd, + Ord, + PartialEq, + Eq, + Hash, + Serialize, + Deserialize, + RkyvArchive, + RkyvSerialize, + RkyvDeserialize, )] #[archive_attr(repr(C), derive(CheckBytes))] pub struct TypedKeyPair { @@ -131,7 +112,19 @@ impl FromStr for TypedKeyPair { } #[derive( - Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize, + Clone, + Copy, + Debug, + PartialOrd, + Ord, + PartialEq, + Eq, + Hash, + Serialize, + Deserialize, + RkyvArchive, + RkyvSerialize, + RkyvDeserialize, )] #[archive_attr(repr(C), derive(CheckBytes))] pub struct TypedSignature { @@ -175,7 +168,19 @@ impl FromStr for TypedSignature { } #[derive( - Clone, Copy, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize, + Clone, + Copy, + Debug, + PartialOrd, + Ord, + PartialEq, + Eq, + Hash, + Serialize, + Deserialize, + RkyvArchive, + RkyvSerialize, + RkyvDeserialize, )] #[archive_attr(repr(C), derive(CheckBytes))] pub struct TypedKeySignature { diff --git a/veilid-core/src/crypto/vld0/mod.rs b/veilid-core/src/crypto/vld0/mod.rs index 94d78802..5d00589c 100644 --- a/veilid-core/src/crypto/vld0/mod.rs +++ b/veilid-core/src/crypto/vld0/mod.rs @@ -14,7 +14,7 @@ use ed25519_dalek as ed; use x25519_dalek as xd; const AEAD_OVERHEAD: usize = 16; -pub const CRYPTO_KIND_VLD0: CryptoKind = CryptoKind([b'V', b'L', b'D', b'0']); +pub const CRYPTO_KIND_VLD0: CryptoKind = FourCC([b'V', b'L', b'D', b'0']); fn ed25519_to_x25519_pk(key: &ed::PublicKey) -> Result { let bytes = key.to_bytes(); diff --git a/veilid-core/src/routing_table/bucket_entry.rs b/veilid-core/src/routing_table/bucket_entry.rs index 7da5f0bb..e5f3286b 100644 --- a/veilid-core/src/routing_table/bucket_entry.rs +++ b/veilid-core/src/routing_table/bucket_entry.rs @@ -219,7 +219,7 @@ impl BucketEntryInner { // See if we have an existing signed_node_info to update or not if let Some(current_sni) = opt_current_sni { // Always allow overwriting invalid/unsigned node - if current_sni.has_valid_signature() { + if current_sni.has_any_signature() { // If the timestamp hasn't changed or is less, ignore this update if signed_node_info.timestamp() <= current_sni.timestamp() { // If we received a node update with the same timestamp diff --git a/veilid-core/src/routing_table/node_ref.rs b/veilid-core/src/routing_table/node_ref.rs index bdd9b484..b981126e 100644 --- a/veilid-core/src/routing_table/node_ref.rs +++ b/veilid-core/src/routing_table/node_ref.rs @@ -136,7 +136,7 @@ pub trait NodeRefBase: Sized { fn signed_node_info_has_valid_signature(&self, routing_domain: RoutingDomain) -> bool { self.operate(|_rti, e| { e.signed_node_info(routing_domain) - .map(|sni| sni.has_valid_signature()) + .map(|sni| sni.has_any_signature()) .unwrap_or(false) }) } diff --git a/veilid-core/src/routing_table/routing_table_inner.rs b/veilid-core/src/routing_table/routing_table_inner.rs index 9065638f..fc7139e7 100644 --- a/veilid-core/src/routing_table/routing_table_inner.rs +++ b/veilid-core/src/routing_table/routing_table_inner.rs @@ -671,7 +671,7 @@ impl RoutingTableInner { } if !allow_invalid { // verify signature - if !signed_node_info.has_valid_signature() { + if !signed_node_info.has_any_signature() { log_rtab!(debug "signed node info for {} has invalid signature", node_id); return None; } @@ -812,7 +812,7 @@ impl RoutingTableInner { None => has_valid_own_node_info, Some(entry) => entry.with(self, |_rti, e| { e.signed_node_info(routing_domain.into()) - .map(|sni| sni.has_valid_signature()) + .map(|sni| sni.has_any_signature()) .unwrap_or(false) }), } diff --git a/veilid-core/src/rpc_processor/coders/dht_key.rs b/veilid-core/src/rpc_processor/coders/key256.rs similarity index 61% rename from veilid-core/src/rpc_processor/coders/dht_key.rs rename to veilid-core/src/rpc_processor/coders/key256.rs index 993801a2..41a02cc5 100644 --- a/veilid-core/src/rpc_processor/coders/dht_key.rs +++ b/veilid-core/src/rpc_processor/coders/key256.rs @@ -1,7 +1,7 @@ use super::*; use core::convert::TryInto; -pub fn decode_dht_key(public_key: &veilid_capnp::key256::Reader) -> PublicKey { +pub fn decode_key256(public_key: &veilid_capnp::key256::Reader) -> PublicKey { let u0 = public_key.get_u0().to_be_bytes(); let u1 = public_key.get_u1().to_be_bytes(); let u2 = public_key.get_u2().to_be_bytes(); @@ -16,29 +16,25 @@ pub fn decode_dht_key(public_key: &veilid_capnp::key256::Reader) -> PublicKey { PublicKey::new(x) } -pub fn encode_dht_key( - key: &PublicKey, - builder: &mut veilid_capnp::key256::Builder, -) -> Result<(), RPCError> { +pub fn encode_key256(key: &PublicKey, builder: &mut veilid_capnp::key256::Builder) { builder.set_u0(u64::from_be_bytes( key.bytes[0..8] .try_into() - .map_err(RPCError::map_protocol("slice with incorrect length"))?, + .expect("slice with incorrect length"), )); builder.set_u1(u64::from_be_bytes( key.bytes[8..16] .try_into() - .map_err(RPCError::map_protocol("slice with incorrect length"))?, + .expect("slice with incorrect length"), )); builder.set_u2(u64::from_be_bytes( key.bytes[16..24] .try_into() - .map_err(RPCError::map_protocol("slice with incorrect length"))?, + .expect("slice with incorrect length"), )); builder.set_u3(u64::from_be_bytes( key.bytes[24..32] .try_into() - .map_err(RPCError::map_protocol("slice with incorrect length"))?, + .expect("slice with incorrect length"), )); - Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/mod.rs b/veilid-core/src/rpc_processor/coders/mod.rs index dafc01f2..8c8ce160 100644 --- a/veilid-core/src/rpc_processor/coders/mod.rs +++ b/veilid-core/src/rpc_processor/coders/mod.rs @@ -1,10 +1,9 @@ mod address; mod address_type_set; -mod dht_key; -mod dht_signature; mod dial_info; mod dial_info_class; mod dial_info_detail; +mod key256; mod network_class; mod node_info; mod node_status; @@ -16,21 +15,22 @@ mod protocol_type_set; mod sender_info; mod sequencing; mod signal_info; +mod signature512; mod signed_direct_node_info; mod signed_node_info; mod signed_relayed_node_info; mod socket_address; mod tunnel; +mod typed_key; +mod typed_signature; mod value_data; -mod value_key; pub use address::*; pub use address_type_set::*; -pub use dht_key::*; -pub use dht_signature::*; pub use dial_info::*; pub use dial_info_class::*; pub use dial_info_detail::*; +pub use key256::*; pub use network_class::*; pub use node_info::*; pub use node_status::*; @@ -42,12 +42,14 @@ pub use protocol_type_set::*; pub use sender_info::*; pub use sequencing::*; pub use signal_info::*; +pub use signature512::*; pub use signed_direct_node_info::*; pub use signed_node_info::*; pub use signed_relayed_node_info::*; pub use socket_address::*; pub use tunnel::*; +pub use typed_key::*; +pub use typed_signature::*; pub use value_data::*; -pub use value_key::*; use super::*; diff --git a/veilid-core/src/rpc_processor/coders/node_info.rs b/veilid-core/src/rpc_processor/coders/node_info.rs index 14ab95b3..80893219 100644 --- a/veilid-core/src/rpc_processor/coders/node_info.rs +++ b/veilid-core/src/rpc_processor/coders/node_info.rs @@ -12,8 +12,24 @@ pub fn encode_node_info( let mut ats_builder = builder.reborrow().init_address_types(); encode_address_type_set(&node_info.address_types, &mut ats_builder)?; - builder.set_min_version(node_info.min_version); - builder.set_max_version(node_info.max_version); + let mut es_builder = builder + .reborrow() + .init_envelope_support(node_info.envelope_support.len() as u32); + if let Some(s) = es_builder.as_slice() { + s.clone_from_slice(&node_info.envelope_support); + } + + let mut cs_builder = builder + .reborrow() + .init_crypto_support(node_info.crypto_support.len() as u32); + if let Some(s) = cs_builder.as_slice() { + let csvec: Vec = node_info + .crypto_support + .iter() + .map(|x| u32::from_be_bytes(x.0)) + .collect(); + s.clone_from_slice(&csvec); + } let mut didl_builder = builder.reborrow().init_dial_info_detail_list( node_info @@ -55,8 +71,21 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result = reader + .reborrow() + .get_crypto_support() + .map_err(RPCError::protocol)? + .as_slice() + .map(|s| s.iter().map(|x| FourCC::from(x.to_be_bytes())).collect()) + .unwrap_or_default(); let didl_reader = reader .reborrow() @@ -76,8 +105,8 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result Nonce { let u1 = reader.get_u1().to_be_bytes(); let u2 = reader.get_u2().to_be_bytes(); - [ + Nonce::new([ u0[0], u0[1], u0[2], u0[3], u0[4], u0[5], u0[6], u0[7], // u0 u1[0], u1[1], u1[2], u1[3], u1[4], u1[5], u1[6], u1[7], // u1 u2[0], u2[1], u2[2], u2[3], u2[4], u2[5], u2[6], u2[7], // u2 - ] + ]) } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs b/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs index 1ffa25ca..18c917ce 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_find_block.rs @@ -10,7 +10,7 @@ impl RPCOperationFindBlockQ { reader: &veilid_capnp::operation_find_block_q::Reader, ) -> Result { let bi_reader = reader.get_block_id().map_err(RPCError::protocol)?; - let block_id = decode_dht_key(&bi_reader); + let block_id = decode_key256(&bi_reader); Ok(RPCOperationFindBlockQ { block_id }) } @@ -19,7 +19,7 @@ impl RPCOperationFindBlockQ { builder: &mut veilid_capnp::operation_find_block_q::Builder, ) -> Result<(), RPCError> { let mut bi_builder = builder.reborrow().init_block_id(); - encode_dht_key(&self.block_id, &mut bi_builder)?; + encode_key256(&self.block_id, &mut bi_builder)?; Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs b/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs index 8ef12534..2ad42a55 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs @@ -10,7 +10,7 @@ impl RPCOperationFindNodeQ { reader: &veilid_capnp::operation_find_node_q::Reader, ) -> Result { let ni_reader = reader.get_node_id().map_err(RPCError::protocol)?; - let node_id = decode_dht_key(&ni_reader); + let node_id = decode_key256(&ni_reader); Ok(RPCOperationFindNodeQ { node_id }) } pub fn encode( @@ -18,7 +18,7 @@ impl RPCOperationFindNodeQ { builder: &mut veilid_capnp::operation_find_node_q::Builder, ) -> Result<(), RPCError> { let mut ni_builder = builder.reborrow().init_node_id(); - encode_dht_key(&self.node_id, &mut ni_builder)?; + encode_key256(&self.node_id, &mut ni_builder)?; Ok(()) } } diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs b/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs index 535d91b0..2e606661 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_supply_block.rs @@ -10,7 +10,7 @@ impl RPCOperationSupplyBlockQ { reader: &veilid_capnp::operation_supply_block_q::Reader, ) -> Result { let bi_reader = reader.get_block_id().map_err(RPCError::protocol)?; - let block_id = decode_dht_key(&bi_reader); + let block_id = decode_key256(&bi_reader); Ok(RPCOperationSupplyBlockQ { block_id }) } @@ -19,7 +19,7 @@ impl RPCOperationSupplyBlockQ { builder: &mut veilid_capnp::operation_supply_block_q::Builder, ) -> Result<(), RPCError> { let mut bi_builder = builder.reborrow().init_block_id(); - encode_dht_key(&self.block_id, &mut bi_builder)?; + encode_key256(&self.block_id, &mut bi_builder)?; Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/peer_info.rs b/veilid-core/src/rpc_processor/coders/peer_info.rs index 5844b8ab..fc766d5c 100644 --- a/veilid-core/src/rpc_processor/coders/peer_info.rs +++ b/veilid-core/src/rpc_processor/coders/peer_info.rs @@ -5,28 +5,48 @@ pub fn encode_peer_info( builder: &mut veilid_capnp::peer_info::Builder, ) -> Result<(), RPCError> { // - let mut nid_builder = builder.reborrow().init_node_id(); - encode_dht_key(&peer_info.node_id.key, &mut nid_builder)?; + let mut nids_builder = builder.reborrow().init_node_ids( + peer_info + .node_ids + .len() + .try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ); + for (i, nid) in peer_info.node_ids.iter().enumerate() { + encode_typed_key( + nid, + &mut nids_builder.get( + i.try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ), + ); + } let mut sni_builder = builder.reborrow().init_signed_node_info(); encode_signed_node_info(&peer_info.signed_node_info, &mut sni_builder)?; Ok(()) } -pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result { - let nid_reader = reader +pub fn decode_peer_info( + reader: &veilid_capnp::peer_info::Reader, + crypto: Crypto, +) -> Result { + let nids_reader = reader .reborrow() - .get_node_id() + .get_node_ids() .map_err(RPCError::protocol)?; let sni_reader = reader .reborrow() .get_signed_node_info() .map_err(RPCError::protocol)?; - let node_id = NodeId::new(decode_dht_key(&nid_reader)); - let signed_node_info = decode_signed_node_info(&sni_reader, &node_id.key)?; + let node_ids = Vec::with_capacity(nids_reader.len() as usize); + for nid_reader in nids_reader.iter() { + node_ids.push(decode_typed_key(&nid_reader)?); + } + let signed_node_info = decode_signed_node_info(&sni_reader, crypto, &node_ids)?; Ok(PeerInfo { - node_id, + node_ids, signed_node_info, }) } diff --git a/veilid-core/src/rpc_processor/coders/private_safety_route.rs b/veilid-core/src/rpc_processor/coders/private_safety_route.rs index 1edbb9fd..8baf2450 100644 --- a/veilid-core/src/rpc_processor/coders/private_safety_route.rs +++ b/veilid-core/src/rpc_processor/coders/private_safety_route.rs @@ -53,7 +53,7 @@ pub fn encode_route_hop( match &route_hop.node { RouteNode::NodeId(ni) => { let mut ni_builder = node_builder.init_node_id(); - encode_dht_key(&ni.key, &mut ni_builder)?; + encode_key256(&ni.key, &mut ni_builder)?; } RouteNode::PeerInfo(pi) => { let mut pi_builder = node_builder.init_peer_info(); @@ -72,7 +72,7 @@ pub fn decode_route_hop(reader: &veilid_capnp::route_hop::Reader) -> Result { let ni_reader = ni.map_err(RPCError::protocol)?; - RouteNode::NodeId(NodeId::new(decode_dht_key(&ni_reader))) + RouteNode::NodeId(NodeId::new(decode_key256(&ni_reader))) } veilid_capnp::route_hop::node::Which::PeerInfo(pi) => { let pi_reader = pi.map_err(RPCError::protocol)?; @@ -101,7 +101,7 @@ pub fn encode_private_route( private_route: &PrivateRoute, builder: &mut veilid_capnp::private_route::Builder, ) -> Result<(), RPCError> { - encode_dht_key( + encode_key256( &private_route.public_key, &mut builder.reborrow().init_public_key(), )?; @@ -126,7 +126,7 @@ pub fn encode_private_route( pub fn decode_private_route( reader: &veilid_capnp::private_route::Reader, ) -> Result { - let public_key = decode_dht_key(&reader.get_public_key().map_err(RPCError::map_protocol( + let public_key = decode_key256(&reader.get_public_key().map_err(RPCError::map_protocol( "invalid public key in private route", ))?); let hop_count = reader.get_hop_count(); @@ -156,7 +156,7 @@ pub fn encode_safety_route( safety_route: &SafetyRoute, builder: &mut veilid_capnp::safety_route::Builder, ) -> Result<(), RPCError> { - encode_dht_key( + encode_key256( &safety_route.public_key, &mut builder.reborrow().init_public_key(), )?; @@ -179,7 +179,7 @@ pub fn encode_safety_route( pub fn decode_safety_route( reader: &veilid_capnp::safety_route::Reader, ) -> Result { - let public_key = decode_dht_key( + let public_key = decode_key256( &reader .get_public_key() .map_err(RPCError::map_protocol("invalid public key in safety route"))?, diff --git a/veilid-core/src/rpc_processor/coders/dht_signature.rs b/veilid-core/src/rpc_processor/coders/signature512.rs similarity index 91% rename from veilid-core/src/rpc_processor/coders/dht_signature.rs rename to veilid-core/src/rpc_processor/coders/signature512.rs index 8b10e7b9..25212fe6 100644 --- a/veilid-core/src/rpc_processor/coders/dht_signature.rs +++ b/veilid-core/src/rpc_processor/coders/signature512.rs @@ -1,6 +1,6 @@ use super::*; -pub fn encode_signature(sig: &Signature, builder: &mut veilid_capnp::signature512::Builder) { +pub fn encode_signature512(sig: &Signature, builder: &mut veilid_capnp::signature512::Builder) { let sig = &sig.bytes; builder.set_u0(u64::from_be_bytes( @@ -29,7 +29,7 @@ pub fn encode_signature(sig: &Signature, builder: &mut veilid_capnp::signature51 )); } -pub fn decode_signature(reader: &veilid_capnp::signature512::Reader) -> Signature { +pub fn decode_signature512(reader: &veilid_capnp::signature512::Reader) -> Signature { let u0 = reader.get_u0().to_be_bytes(); let u1 = reader.get_u1().to_be_bytes(); let u2 = reader.get_u2().to_be_bytes(); diff --git a/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs b/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs index c753d58a..cda84813 100644 --- a/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs +++ b/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs @@ -12,18 +12,30 @@ pub fn encode_signed_direct_node_info( .reborrow() .set_timestamp(signed_direct_node_info.timestamp.into()); - let mut sig_builder = builder.reborrow().init_signature(); - let Some(signature) = &signed_direct_node_info.signature else { - return Err(RPCError::internal("Should not encode SignedDirectNodeInfo without signature!")); - }; - encode_signature(signature, &mut sig_builder); + let mut sigs_builder = builder.reborrow().init_signatures( + signed_direct_node_info + .signatures + .len() + .try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ); + for (i, typed_signature) in signed_direct_node_info.signatures.iter().enumerate() { + encode_typed_signature( + typed_signature, + &mut sigs_builder.get( + i.try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ), + ); + } Ok(()) } pub fn decode_signed_direct_node_info( reader: &veilid_capnp::signed_direct_node_info::Reader, - node_id: &PublicKey, + crypto: Crypto, + node_ids: &[TypedKey], ) -> Result { let ni_reader = reader .reborrow() @@ -31,15 +43,19 @@ pub fn decode_signed_direct_node_info( .map_err(RPCError::protocol)?; let node_info = decode_node_info(&ni_reader)?; - let sig_reader = reader + let sigs_reader = reader .reborrow() - .get_signature() + .get_signatures() .map_err(RPCError::protocol)?; let timestamp = reader.reborrow().get_timestamp().into(); - let signature = decode_signature(&sig_reader); + let mut typed_signatures = Vec::with_capacity(sigs_reader.len() as usize); + for sig_reader in sigs_reader { + let typed_signature = decode_typed_signature(&sig_reader)?; + typed_signatures.push(typed_signature); + } - SignedDirectNodeInfo::new(NodeId::new(*node_id), node_info, timestamp, signature) + SignedDirectNodeInfo::new(crypto, node_ids, node_info, timestamp, typed_signatures) .map_err(RPCError::protocol) } diff --git a/veilid-core/src/rpc_processor/coders/signed_node_info.rs b/veilid-core/src/rpc_processor/coders/signed_node_info.rs index ed4f6564..37996c26 100644 --- a/veilid-core/src/rpc_processor/coders/signed_node_info.rs +++ b/veilid-core/src/rpc_processor/coders/signed_node_info.rs @@ -20,20 +20,21 @@ pub fn encode_signed_node_info( pub fn decode_signed_node_info( reader: &veilid_capnp::signed_node_info::Reader, - node_id: &PublicKey, + crypto: Crypto, + node_ids: &[TypedKey], ) -> Result { match reader .which() - .map_err(RPCError::map_internal("invalid signal operation"))? + .map_err(RPCError::map_internal("invalid signed node info"))? { veilid_capnp::signed_node_info::Direct(d) => { let d_reader = d.map_err(RPCError::protocol)?; - let sdni = decode_signed_direct_node_info(&d_reader, node_id)?; + let sdni = decode_signed_direct_node_info(&d_reader, crypto, node_ids)?; Ok(SignedNodeInfo::Direct(sdni)) } veilid_capnp::signed_node_info::Relayed(r) => { let r_reader = r.map_err(RPCError::protocol)?; - let srni = decode_signed_relayed_node_info(&r_reader, node_id)?; + let srni = decode_signed_relayed_node_info(&r_reader, crypto, node_ids)?; Ok(SignedNodeInfo::Relayed(srni)) } } diff --git a/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs b/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs index 0b3ac2be..3a259b1f 100644 --- a/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs +++ b/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs @@ -8,8 +8,22 @@ pub fn encode_signed_relayed_node_info( let mut ni_builder = builder.reborrow().init_node_info(); encode_node_info(&signed_relayed_node_info.node_info, &mut ni_builder)?; - let mut rid_builder = builder.reborrow().init_relay_id(); - encode_dht_key(&signed_relayed_node_info.relay_id.key, &mut rid_builder)?; + let mut rids_builder = builder.reborrow().init_relay_ids( + signed_relayed_node_info + .relay_ids + .len() + .try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ); + for (i, typed_key) in signed_relayed_node_info.relay_ids.iter().enumerate() { + encode_typed_key( + typed_key, + &mut rids_builder.get( + i.try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ), + ); + } let mut ri_builder = builder.reborrow().init_relay_info(); encode_signed_direct_node_info(&signed_relayed_node_info.relay_info, &mut ri_builder)?; @@ -18,15 +32,30 @@ pub fn encode_signed_relayed_node_info( .reborrow() .set_timestamp(signed_relayed_node_info.timestamp.into()); - let mut sig_builder = builder.reborrow().init_signature(); - encode_signature(&signed_relayed_node_info.signature, &mut sig_builder); + let mut sigs_builder = builder.reborrow().init_signatures( + signed_relayed_node_info + .signatures + .len() + .try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ); + for (i, typed_signature) in signed_relayed_node_info.signatures.iter().enumerate() { + encode_typed_signature( + typed_signature, + &mut sigs_builder.get( + i.try_into() + .map_err(RPCError::map_invalid_format("out of bound error"))?, + ), + ); + } Ok(()) } pub fn decode_signed_relayed_node_info( reader: &veilid_capnp::signed_relayed_node_info::Reader, - node_id: &PublicKey, + crypto: Crypto, + node_ids: &[TypedKey], ) -> Result { let ni_reader = reader .reborrow() @@ -34,33 +63,42 @@ pub fn decode_signed_relayed_node_info( .map_err(RPCError::protocol)?; let node_info = decode_node_info(&ni_reader)?; - let rid_reader = reader + let rids_reader = reader .reborrow() - .get_relay_id() + .get_relay_ids() .map_err(RPCError::protocol)?; - let relay_id = decode_dht_key(&rid_reader); + let mut relay_ids = Vec::with_capacity(rids_reader.len() as usize); + for rid_reader in rids_reader { + let relay_id = decode_typed_key(&rid_reader)?; + relay_ids.push(relay_id); + } let ri_reader = reader .reborrow() .get_relay_info() .map_err(RPCError::protocol)?; - let relay_info = decode_signed_direct_node_info(&ri_reader, &relay_id)?; + let relay_info = decode_signed_direct_node_info(&ri_reader, crypto, &relay_ids)?; - let sig_reader = reader + let sigs_reader = reader .reborrow() - .get_signature() + .get_signatures() .map_err(RPCError::protocol)?; + let timestamp = reader.reborrow().get_timestamp().into(); - let signature = decode_signature(&sig_reader); - + let mut typed_signatures = Vec::with_capacity(sigs_reader.len() as usize); + for sig_reader in sigs_reader { + let typed_signature = decode_typed_signature(&sig_reader)?; + typed_signatures.push(typed_signature); + } SignedRelayedNodeInfo::new( - NodeId::new(*node_id), + crypto, + node_ids, node_info, - NodeId::new(relay_id), + relay_ids, relay_info, timestamp, - signature, + typed_signatures, ) .map_err(RPCError::protocol) } diff --git a/veilid-core/src/rpc_processor/coders/typed_key.rs b/veilid-core/src/rpc_processor/coders/typed_key.rs new file mode 100644 index 00000000..ec186a0c --- /dev/null +++ b/veilid-core/src/rpc_processor/coders/typed_key.rs @@ -0,0 +1,19 @@ +use super::*; + +pub fn decode_typed_key(typed_key: &veilid_capnp::typed_key::Reader) -> Result { + let key_reader = typed_key + .get_key() + .map_err(RPCError::map_invalid_format("invalid typed key"))?; + let kind = typed_key.get_kind(); + + Ok(TypedKey::new( + CryptoKind::from(kind.to_be_bytes()), + decode_key256(&key_reader), + )) +} + +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)); + let mut key_builder = builder.init_key(); + encode_key256(&typed_key.key, &mut key_builder); +} diff --git a/veilid-core/src/rpc_processor/coders/typed_signature.rs b/veilid-core/src/rpc_processor/coders/typed_signature.rs new file mode 100644 index 00000000..8f1f3d59 --- /dev/null +++ b/veilid-core/src/rpc_processor/coders/typed_signature.rs @@ -0,0 +1,24 @@ +use super::*; + +pub fn decode_typed_signature( + typed_signature: &veilid_capnp::typed_signature::Reader, +) -> Result { + let sig_reader = typed_signature + .get_signature() + .map_err(RPCError::map_invalid_format("invalid typed signature"))?; + let kind = typed_signature.get_kind(); + + Ok(TypedSignature::new( + CryptoKind::from(kind.to_be_bytes()), + decode_signature512(&sig_reader), + )) +} + +pub fn encode_typed_signature( + typed_signature: &TypedSignature, + builder: &mut veilid_capnp::typed_signature::Builder, +) { + builder.set_kind(u32::from_be_bytes(typed_signature.kind.0)); + let mut sig_builder = builder.init_signature(); + encode_signature512(&typed_signature.signature, &mut sig_builder); +} diff --git a/veilid-core/src/rpc_processor/coders/value_key.rs b/veilid-core/src/rpc_processor/coders/value_key.rs deleted file mode 100644 index fcb1c0a2..00000000 --- a/veilid-core/src/rpc_processor/coders/value_key.rs +++ /dev/null @@ -1,25 +0,0 @@ -use super::*; - -pub fn encode_value_key( - value_key: &ValueKey, - builder: &mut veilid_capnp::value_key::Builder, -) -> Result<(), RPCError> { - let mut pk_builder = builder.reborrow().init_public_key(); - encode_dht_key(&value_key.key, &mut pk_builder)?; - if let Some(subkey) = &value_key.subkey { - builder.set_subkey(subkey); - } - Ok(()) -} - -pub fn decode_value_key(reader: &veilid_capnp::value_key::Reader) -> Result { - let pk_reader = reader.get_public_key().map_err(RPCError::protocol)?; - let key = decode_dht_key(&pk_reader); - let subkey = if !reader.has_subkey() { - None - } else { - let subkey = reader.get_subkey().map_err(RPCError::protocol)?; - Some(subkey.to_owned()) - }; - Ok(ValueKey { key, subkey }) -} diff --git a/veilid-core/src/veilid_api/error.rs b/veilid-core/src/veilid_api/error.rs index ddcc826c..62a89a83 100644 --- a/veilid-core/src/veilid_api/error.rs +++ b/veilid-core/src/veilid_api/error.rs @@ -112,7 +112,7 @@ pub enum VeilidAPIError { #[error("No connection: {message}")] NoConnection { message: String }, #[error("No peer info: {node_id}")] - NoPeerInfo { node_id: NodeId }, + NoPeerInfo { node_id: PublicKey }, #[error("Internal: {message}")] Internal { message: String }, #[error("Unimplemented: {message}")] @@ -155,7 +155,7 @@ impl VeilidAPIError { message: msg.to_string(), } } - pub fn no_peer_info(node_id: NodeId) -> Self { + pub fn no_peer_info(node_id: PublicKey) -> Self { Self::NoPeerInfo { node_id } } pub fn internal(msg: T) -> Self { diff --git a/veilid-core/src/veilid_api/routing_context.rs b/veilid-core/src/veilid_api/routing_context.rs index 100e8c55..6d0bc7c2 100644 --- a/veilid-core/src/veilid_api/routing_context.rs +++ b/veilid-core/src/veilid_api/routing_context.rs @@ -4,7 +4,7 @@ use super::*; #[derive(Clone, Debug)] pub enum Target { - NodeId(NodeId), + NodeId(PublicKey), PrivateRoute(PublicKey), } @@ -105,9 +105,9 @@ impl RoutingContext { match target { Target::NodeId(node_id) => { // Resolve node - let mut nr = match rpc_processor.resolve_node(node_id.key).await { + let mut nr = match rpc_processor.resolve_node(node_id).await { Ok(Some(nr)) => nr, - Ok(None) => apibail_key_not_found!(node_id.key), + Ok(None) => apibail_key_not_found!(node_id), Err(e) => return Err(e.into()), }; // Apply sequencing to match safety selection @@ -225,11 +225,11 @@ impl RoutingContext { /////////////////////////////////// /// Block Store - pub async fn find_block(&self, _block_id: BlockId) -> Result, VeilidAPIError> { + pub async fn find_block(&self, _block_id: TypedKey) -> Result, VeilidAPIError> { panic!("unimplemented"); } - pub async fn supply_block(&self, _block_id: BlockId) -> Result { + pub async fn supply_block(&self, _block_id: TypedKey) -> Result { panic!("unimplemented"); } } diff --git a/veilid-core/src/veilid_api/types.rs b/veilid-core/src/veilid_api/types.rs index 81522958..6d8d06b9 100644 --- a/veilid-core/src/veilid_api/types.rs +++ b/veilid-core/src/veilid_api/types.rs @@ -15,7 +15,56 @@ pub type OperationId = AlignedU64; pub type ByteCount = AlignedU64; /// Tunnel identifier pub type TunnelId = AlignedU64; +/// Value schema +pub type ValueSchema = FourCC; +/// FOURCC code +#[derive( + Copy, + Debug, + Default, + Clone, + Hash, + PartialOrd, + Ord, + PartialEq, + Eq, + Serialize, + Deserialize, + RkyvArchive, + RkyvSerialize, + RkyvDeserialize, +)] +#[archive_attr(repr(C), derive(CheckBytes, PartialOrd, Ord, PartialEq, Eq))] +pub struct FourCC(pub [u8; 4]); + +impl From<[u8; 4]> for FourCC { + fn from(b: [u8; 4]) -> Self { + Self(b) + } +} +impl TryFrom<&[u8]> for FourCC { + type Error = VeilidAPIError; + fn try_from(b: &[u8]) -> Result { + Ok(Self(b.try_into().map_err(VeilidAPIError::generic)?)) + } +} + +impl fmt::Display for FourCC { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}", String::from_utf8_lossy(&self.0)) + } +} +impl FromStr for FourCC { + type Err = VeilidAPIError; + fn from_str(s: &str) -> Result { + Ok(Self( + s.as_bytes().try_into().map_err(VeilidAPIError::generic)?, + )) + } +} + +/// Log level for VeilidCore #[derive( Debug, Clone, @@ -91,6 +140,7 @@ impl fmt::Display for VeilidLogLevel { } } +/// A VeilidCore log message with optional backtrace #[derive( Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize, )] @@ -101,6 +151,7 @@ pub struct VeilidLog { pub backtrace: Option, } +/// Direct statement blob passed to hosting application for processing #[derive( Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize, )] @@ -114,6 +165,7 @@ pub struct VeilidAppMessage { pub message: Vec, } +/// Direct question blob passed to hosting application for processing to send an eventual AppReply #[derive( Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize, )] @@ -130,6 +182,7 @@ pub struct VeilidAppCall { pub id: OperationId, } +/// Attachment abstraction for network 'signal strength' #[derive( Debug, PartialEq, @@ -263,31 +316,6 @@ pub struct VeilidState { ///////////////////////////////////////////////////////////////////////////////////////////////////// /// -#[derive( - Clone, - Debug, - Default, - PartialOrd, - PartialEq, - Eq, - Ord, - Serialize, - Deserialize, - RkyvArchive, - RkyvSerialize, - RkyvDeserialize, -)] -#[archive_attr(repr(C), derive(CheckBytes))] -pub struct ValueKey { - pub key: TypedKey, - pub subkey: u32, -} -impl ValueKey { - pub fn new(key: TypedKey, subkey: u32) -> Self { - Self { key, subkey } - } -} - #[derive( Clone, Debug, @@ -305,14 +333,19 @@ impl ValueKey { #[archive_attr(repr(C), derive(CheckBytes))] pub struct ValueData { pub data: Vec, + pub schema: ValueSchema, pub seq: u32, } impl ValueData { - pub fn new(data: Vec) -> Self { - Self { data, seq: 0 } + pub fn new(data: Vec, schema: ValueSchema) -> Self { + Self { + data, + schema, + seq: 0, + } } - pub fn new_with_seq(data: Vec, seq: u32) -> Self { - Self { data, seq } + pub fn new_with_seq(data: Vec, schema: ValueSchema, seq: u32) -> Self { + Self { data, schema, seq } } pub fn change(&mut self, data: Vec) { self.data = data; @@ -1820,39 +1853,38 @@ pub struct SignedDirectNodeInfo { impl SignedDirectNodeInfo { pub fn new( crypto: Crypto, + node_ids: &[TypedKey], node_info: NodeInfo, timestamp: Timestamp, - keyed_signatures: Vec, + typed_signatures: Vec, ) -> Result { let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?; - let signatures = crypto.verify_signatures( - &node_info_bytes, - &keyed_signatures, - TypedSignature::from_keyed, - )?; + + // Verify the signatures that we can + crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?; Ok(Self { node_info, timestamp, - signatures, + signatures: typed_signatures, }) } pub fn make_signatures( crypto: Crypto, + typed_key_pairs: Vec, node_info: NodeInfo, - keypairs: Vec, ) -> Result { let timestamp = get_aligned_timestamp(); let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?; - let signatures = crypto.generate_signatures( + let typed_signatures = crypto.generate_signatures( &node_info_bytes, - &keypairs, + &typed_key_pairs, TypedSignature::from_pair_sig, )?; Ok(Self { node_info, timestamp, - signatures, + signatures: typed_signatures, }) } @@ -1877,8 +1909,8 @@ impl SignedDirectNodeInfo { pub fn with_no_signature(node_info: NodeInfo) -> Self { Self { node_info, - signatures: Vec::new(), timestamp: get_aligned_timestamp(), + signatures: Vec::new(), } } @@ -1901,25 +1933,22 @@ pub struct SignedRelayedNodeInfo { impl SignedRelayedNodeInfo { pub fn new( crypto: Crypto, + node_ids: &[TypedKey], node_info: NodeInfo, relay_ids: Vec, relay_info: SignedDirectNodeInfo, timestamp: Timestamp, - keyed_signatures: Vec, + typed_signatures: Vec, ) -> Result { let node_info_bytes = Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?; - let signatures = crypto.verify_signatures( - &node_info_bytes, - &keyed_signatures, - TypedSignature::from_keyed, - )?; + crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?; Ok(Self { node_info, relay_ids, relay_info, timestamp, - signatures, + signatures: typed_signatures, }) } @@ -1928,22 +1957,22 @@ impl SignedRelayedNodeInfo { node_info: NodeInfo, relay_ids: Vec, relay_info: SignedDirectNodeInfo, - keypairs: Vec, + typed_key_pairs: Vec, ) -> Result { let timestamp = get_aligned_timestamp(); let node_info_bytes = Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?; - let signatures = crypto.generate_signatures( + let typed_signatures = crypto.generate_signatures( &node_info_bytes, - &keypairs, + &typed_key_pairs, TypedSignature::from_pair_sig, )?; Ok(Self { node_info, relay_ids, relay_info, - signatures, timestamp, + signatures: typed_signatures, }) } @@ -1962,10 +1991,12 @@ impl SignedRelayedNodeInfo { sig_bytes.append(&mut builder_to_vec(ni_msg).map_err(VeilidAPIError::internal)?); // Add relay ids to signature - let mut rid_msg = ::capnp::message::Builder::new_default(); - let mut rid_builder = rid_msg.init_root::(); - encode_dht_key(&relay_id.key, &mut rid_builder).map_err(VeilidAPIError::internal)?; - sig_bytes.append(&mut builder_to_vec(rid_msg).map_err(VeilidAPIError::internal)?); + for relay_id in relay_ids { + let mut rid_msg = ::capnp::message::Builder::new_default(); + let mut rid_builder = rid_msg.init_root::(); + encode_typed_key(relay_id, &mut rid_builder); + sig_bytes.append(&mut builder_to_vec(rid_msg).map_err(VeilidAPIError::internal)?); + } // Add relay info to signature let mut ri_msg = ::capnp::message::Builder::new_default(); @@ -1979,6 +2010,10 @@ impl SignedRelayedNodeInfo { Ok(sig_bytes) } + + pub fn has_any_signature(&self) -> bool { + !self.signatures.is_empty() + } } #[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] @@ -1989,10 +2024,10 @@ pub enum SignedNodeInfo { } impl SignedNodeInfo { - pub fn has_valid_signature(&self) -> bool { + pub fn has_any_signature(&self) -> bool { match self { SignedNodeInfo::Direct(d) => d.has_any_signature(), - SignedNodeInfo::Relayed(_) => true, + SignedNodeInfo::Relayed(r) => r.has_any_signature(), } } @@ -2325,8 +2360,9 @@ pub struct PeerStats { pub transfer: TransferStatsDownUp, // Stats for communications with the peer } -pub type ValueChangeCallback = - Arc) -> SendPinBoxFuture<()> + Send + Sync + 'static>; +pub type ValueChangeCallback = Arc< + dyn Fn(TypedKey, Vec<(u32, u32)>, u32, Vec) -> SendPinBoxFuture<()> + Send + Sync + 'static, +>; ///////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/veilid-core/src/veilid_config.rs b/veilid-core/src/veilid_config.rs index a312ccea..065340ee 100644 --- a/veilid-core/src/veilid_config.rs +++ b/veilid-core/src/veilid_config.rs @@ -672,7 +672,7 @@ impl VeilidConfig { get_config!(inner.network.client_whitelist_timeout_ms); get_config!(inner.network.reverse_connection_receipt_time_ms); get_config!(inner.network.hole_punch_receipt_time_ms); - for ck in &VALID_CRYPTO_KINDS { + 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); } @@ -951,7 +951,9 @@ impl VeilidConfig { protected_store: intf::ProtectedStore, ) -> Result<(), VeilidAPIError> { for ck in VALID_CRYPTO_KINDS { - let vcrypto = crypto.get(ck)?; + let vcrypto = crypto + .get(ck) + .expect("Valid crypto kind is not actually valid."); let mut node_id = self .inner @@ -975,15 +977,15 @@ impl VeilidConfig { if node_id.is_none() { debug!("pulling node_id_{} from storage", ck); if let Some(s) = protected_store - .load_user_secret_string(format!("node_id_v{}", version)) + .load_user_secret_string(format!("node_id_{}", ck)) .await .map_err(VeilidAPIError::internal)? { - debug!("node id v{} found in storage", version); + debug!("node_id_{} found in storage", ck); node_id = Some(PublicKey::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?); } else { - debug!("node id v{} not found in storage", version); + debug!("node_id_{} not found in storage", ck); } } @@ -991,15 +993,15 @@ impl VeilidConfig { if node_id_secret.is_none() { debug!("pulling node id secret from storage"); if let Some(s) = protected_store - .load_user_secret_string(format!("node_id_secret_v{}", version)) + .load_user_secret_string(format!("node_id_secret_{}", ck)) .await .map_err(VeilidAPIError::internal)? { - debug!("node id v{} secret found in storage", version); + debug!("node_id_secret_{} found in storage", ck); node_id_secret = Some(SecretKey::try_decode(s.as_str()).map_err(VeilidAPIError::internal)?); } else { - debug!("node id v{} secret not found in storage", version); + debug!("node_id_secret_{} not found in storage", ck); } } @@ -1009,39 +1011,39 @@ impl VeilidConfig { // Validate node id if !vcrypto.validate_keypair(&node_id, &node_id_secret) { apibail_generic!(format!( - "version {} node id secret and node id key don't match", - version + "node_id_secret_{} and node_id_key_{} don't match", + ck, ck )); } (node_id, node_id_secret) } else { // If we still don't have a valid node id, generate one - debug!("generating new node id v{}", version); + debug!("generating new node_id_{}", ck); vcrypto.generate_keypair() }; - info!("Node Id v{} is {}", version, node_id.encode()); + info!("Node Id ({}) is {}", ck, node_id.encode()); // Save the node id / secret in storage protected_store - .save_user_secret_string(format!("node_id_v{}", version), node_id.encode().as_str()) + .save_user_secret_string(format!("node_id_{}", ck), node_id.encode().as_str()) .await .map_err(VeilidAPIError::internal)?; protected_store .save_user_secret_string( - format!("node_id_secret_v{}", version), + format!("node_id_secret_{}", ck), node_id_secret.encode().as_str(), ) .await .map_err(VeilidAPIError::internal)?; self.with_mut(|c| { - let n = c.network.routing_table.node_ids.entry(version).or_default(); + let n = c.network.routing_table.node_ids.entry(ck).or_default(); n.node_id = Some(node_id); n.node_id_secret = Some(node_id_secret); Ok(()) })?; } - trace!("init_node_id complete"); + trace!("init_node_ids complete"); Ok(()) }