refactor rpc validation

This commit is contained in:
John Smith 2023-04-20 11:47:54 -04:00
parent b4a071170d
commit 7f909a06b9
52 changed files with 729 additions and 430 deletions

View File

@ -367,7 +367,7 @@ struct OperationSetValueQ @0xbac06191ff8bdbc5 {
struct OperationSetValueA @0x9378d0732dc95be2 { struct OperationSetValueA @0x9378d0732dc95be2 {
union { union {
schemaError @0 :Void; # Either the schema is not available at the node, or the data does not match the schema that is there schemaError @0 :Void; # Either the schema is not available at the node, or the data does not match the schema that is there
value @1 :ValueDetail; # the new value if successful, may be a different value than what was set if the seq number was lower or equal value @1 :ValueDetail; # the new value if successful, may be a different value than what was set if the seq number was lower or equal
peers @2 :List(PeerInfo); # returned 'closer peer' information if this node is refusing to store the key peers @2 :List(PeerInfo); # returned 'closer peer' information if this node is refusing to store the key
} }
} }

View File

@ -282,6 +282,28 @@ where
tks tks
} }
} }
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(x.len());
tks.add_all(x);
tks
}
}
impl<K> Into<Vec<CryptoTyped<K>>> for CryptoTypedSet<K> impl<K> Into<Vec<CryptoTyped<K>>> for CryptoTypedSet<K>
where where
K: Clone K: Clone

View File

@ -58,3 +58,5 @@ pub type TypedSignature = CryptoTyped<Signature>;
pub type TypedKeySet = CryptoTypedSet<PublicKey>; pub type TypedKeySet = CryptoTypedSet<PublicKey>;
pub type TypedSecretSet = CryptoTypedSet<SecretKey>; pub type TypedSecretSet = CryptoTypedSet<SecretKey>;
pub type TypedKeyPairSet = CryptoTypedSet<KeyPair>;
pub type TypedSignatureSet = CryptoTypedSet<Signature>;

View File

@ -463,7 +463,7 @@ impl NetworkManager {
will_validate_dial_info: false, will_validate_dial_info: false,
}; };
}; };
let own_node_info = own_peer_info.signed_node_info.node_info(); let own_node_info = own_peer_info.signed_node_info().node_info();
let will_route = own_node_info.can_inbound_relay(); // xxx: eventually this may have more criteria added let will_route = own_node_info.can_inbound_relay(); // xxx: eventually this may have more criteria added
let will_tunnel = own_node_info.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point let will_tunnel = own_node_info.can_inbound_relay(); // xxx: we may want to restrict by battery life and network bandwidth at some point
@ -490,7 +490,7 @@ impl NetworkManager {
}; };
}; };
let own_node_info = own_peer_info.signed_node_info.node_info(); let own_node_info = own_peer_info.signed_node_info().node_info();
let will_relay = own_node_info.can_inbound_relay(); let will_relay = own_node_info.can_inbound_relay();
let will_validate_dial_info = own_node_info.can_validate_dial_info(); let will_validate_dial_info = own_node_info.can_validate_dial_info();

View File

@ -34,50 +34,39 @@ pub async fn test_signed_node_info() {
node_info.clone(), node_info.clone(),
) )
.unwrap(); .unwrap();
let mut tks: TypedKeySet = TypedKey::new(ck, keypair.key).into(); let tks: TypedKeySet = TypedKey::new(ck, keypair.key).into();
let oldtkslen = tks.len(); let oldtkslen = tks.len();
let _ = SignedDirectNodeInfo::new( let sdni = SignedDirectNodeInfo::new(
crypto.clone(),
&mut tks,
node_info.clone(), node_info.clone(),
sni.timestamp, sni.timestamp(),
sni.signatures.clone(), sni.signatures().to_vec(),
) );
.unwrap(); let tks_validated = sdni.validate(&tks, crypto.clone()).unwrap();
assert_eq!(tks.len(), oldtkslen); assert_eq!(tks_validated.len(), oldtkslen);
assert_eq!(tks.len(), sni.signatures.len()); assert_eq!(tks_validated.len(), sni.signatures().len());
// Test incorrect validation // Test incorrect validation
let keypair1 = vcrypto.generate_keypair(); let keypair1 = vcrypto.generate_keypair();
let mut tks1: TypedKeySet = TypedKey::new(ck, keypair1.key).into(); let tks1: TypedKeySet = TypedKey::new(ck, keypair1.key).into();
let oldtks1len = tks1.len(); let oldtks1len = tks1.len();
let _ = SignedDirectNodeInfo::new( let sdni = SignedDirectNodeInfo::new(
crypto.clone(),
&mut tks1,
node_info.clone(), node_info.clone(),
sni.timestamp, sni.timestamp(),
sni.signatures.clone(), sni.signatures().to_vec(),
) );
.unwrap_err(); sdni.validate(&tks1, crypto.clone()).unwrap_err();
assert_eq!(tks1.len(), oldtks1len);
assert_eq!(tks1.len(), sni.signatures.len());
// Test unsupported cryptosystem validation // Test unsupported cryptosystem validation
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]); let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
let mut tksfake: TypedKeySet = TypedKey::new(fake_crypto_kind, PublicKey::default()).into(); let mut tksfake: TypedKeySet = TypedKey::new(fake_crypto_kind, PublicKey::default()).into();
let mut sigsfake = sni.signatures.clone(); let mut sigsfake = sni.signatures().to_vec();
sigsfake.push(TypedSignature::new(fake_crypto_kind, Signature::default())); sigsfake.push(TypedSignature::new(fake_crypto_kind, Signature::default()));
tksfake.add(TypedKey::new(ck, keypair.key)); tksfake.add(TypedKey::new(ck, keypair.key));
let sdnifake = SignedDirectNodeInfo::new( let sdnifake =
crypto.clone(), SignedDirectNodeInfo::new(node_info.clone(), sni.timestamp(), sigsfake.clone());
&mut tksfake, let tksfake_validated = sdnifake.validate(&tksfake, crypto.clone()).unwrap();
node_info.clone(), assert_eq!(tksfake_validated.len(), 1);
sni.timestamp, assert_eq!(sdnifake.signatures().len(), sigsfake.len());
sigsfake.clone(),
)
.unwrap();
assert_eq!(tksfake.len(), 1);
assert_eq!(sdnifake.signatures.len(), sigsfake.len());
// Test relayed // Test relayed
let node_info2 = NodeInfo { let node_info2 = NodeInfo {
@ -94,7 +83,7 @@ pub async fn test_signed_node_info() {
// Test correct validation // Test correct validation
let keypair2 = vcrypto.generate_keypair(); let keypair2 = vcrypto.generate_keypair();
let mut tks2: TypedKeySet = TypedKey::new(ck, keypair2.key).into(); let tks2: TypedKeySet = TypedKey::new(ck, keypair2.key).into();
let oldtks2len = tks2.len(); let oldtks2len = tks2.len();
let sni2 = SignedRelayedNodeInfo::make_signatures( let sni2 = SignedRelayedNodeInfo::make_signatures(
@ -105,58 +94,49 @@ pub async fn test_signed_node_info() {
sni.clone(), sni.clone(),
) )
.unwrap(); .unwrap();
let _ = SignedRelayedNodeInfo::new( let srni = SignedRelayedNodeInfo::new(
crypto.clone(),
&mut tks2,
node_info2.clone(), node_info2.clone(),
tks.clone(), tks.clone(),
sni.clone(), sni.clone(),
sni2.timestamp, sni2.timestamp(),
sni2.signatures.clone(), sni2.signatures().to_vec(),
) );
.unwrap(); let tks2_validated = srni.validate(&tks2, crypto.clone()).unwrap();
assert_eq!(tks2.len(), oldtks2len); assert_eq!(tks2_validated.len(), oldtks2len);
assert_eq!(tks2.len(), sni2.signatures.len()); assert_eq!(tks2_validated.len(), sni2.signatures().len());
// Test incorrect validation // Test incorrect validation
let keypair3 = vcrypto.generate_keypair(); let keypair3 = vcrypto.generate_keypair();
let mut tks3: TypedKeySet = TypedKey::new(ck, keypair3.key).into(); let tks3: TypedKeySet = TypedKey::new(ck, keypair3.key).into();
let oldtks3len = tks3.len(); let oldtks3len = tks3.len();
let _ = SignedRelayedNodeInfo::new( let srni = SignedRelayedNodeInfo::new(
crypto.clone(),
&mut tks3,
node_info2.clone(), node_info2.clone(),
tks.clone(), tks.clone(),
sni.clone(), sni.clone(),
sni2.timestamp, sni2.timestamp(),
sni2.signatures.clone(), sni2.signatures().to_vec(),
) );
.unwrap_err(); srni.validate(&tks3, crypto.clone()).unwrap_err();
assert_eq!(tks3.len(), oldtks3len);
assert_eq!(tks3.len(), sni2.signatures.len());
// Test unsupported cryptosystem validation // Test unsupported cryptosystem validation
let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]); let fake_crypto_kind: CryptoKind = FourCC::from([0, 1, 2, 3]);
let mut tksfake3: TypedKeySet = let mut tksfake3: TypedKeySet =
TypedKey::new(fake_crypto_kind, PublicKey::default()).into(); TypedKey::new(fake_crypto_kind, PublicKey::default()).into();
let mut sigsfake3 = sni2.signatures.clone(); let mut sigsfake3 = sni2.signatures().to_vec();
sigsfake3.push(TypedSignature::new(fake_crypto_kind, Signature::default())); sigsfake3.push(TypedSignature::new(fake_crypto_kind, Signature::default()));
tksfake3.add(TypedKey::new(ck, keypair2.key)); tksfake3.add(TypedKey::new(ck, keypair2.key));
let srnifake = SignedRelayedNodeInfo::new( let srnifake = SignedRelayedNodeInfo::new(
crypto.clone(),
&mut tksfake3,
node_info2.clone(), node_info2.clone(),
tks.clone(), tks.clone(),
sni.clone(), sni.clone(),
sni2.timestamp, sni2.timestamp(),
sigsfake3.clone(), sigsfake3.clone(),
) );
.unwrap(); let tksfake3_validated = srnifake.validate(&tksfake3, crypto.clone()).unwrap();
assert_eq!(tksfake3.len(), 1); assert_eq!(tksfake3_validated.len(), 1);
assert_eq!(srnifake.signatures.len(), sigsfake3.len()); assert_eq!(srnifake.signatures().len(), sigsfake3.len());
} }
api.shutdown().await; api.shutdown().await;

View File

@ -73,7 +73,9 @@ pub struct BucketEntryLocalNetwork {
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct BucketEntryInner { pub struct BucketEntryInner {
/// The node ids matching this bucket entry, with the cryptography versions supported by this node as the 'kind' field /// The node ids matching this bucket entry, with the cryptography versions supported by this node as the 'kind' field
node_ids: TypedKeySet, validated_node_ids: TypedKeySet,
/// The node ids claimed by the remote node that use cryptography versions we do not support
unsupported_node_ids: TypedKeySet,
/// The set of envelope versions supported by the node inclusive of the requirements of any relay the node may be using /// The set of envelope versions supported by the node inclusive of the requirements of any relay the node may be using
envelope_support: Vec<u8>, envelope_support: Vec<u8>,
/// If this node has updated it's SignedNodeInfo since our network /// If this node has updated it's SignedNodeInfo since our network
@ -122,9 +124,11 @@ impl BucketEntryInner {
self.node_ref_tracks.remove(&track_id); self.node_ref_tracks.remove(&track_id);
} }
/// Get node ids /// Get all node ids
pub fn node_ids(&self) -> TypedKeySet { pub fn node_ids(&self) -> TypedKeySet {
self.node_ids.clone() let mut node_ids = self.validated_node_ids.clone();
node_ids.add_all(&self.unsupported_node_ids);
node_ids
} }
/// Add a node id for a particular crypto kind. /// Add a node id for a particular crypto kind.
@ -132,33 +136,39 @@ impl BucketEntryInner {
/// Returns Ok(None) if no previous existing node id was associated with that crypto kind /// Returns Ok(None) if no previous existing node id was associated with that crypto kind
/// Results Err() if this operation would add more crypto kinds than we support /// Results Err() if this operation would add more crypto kinds than we support
pub fn add_node_id(&mut self, node_id: TypedKey) -> EyreResult<Option<TypedKey>> { pub fn add_node_id(&mut self, node_id: TypedKey) -> EyreResult<Option<TypedKey>> {
if let Some(old_node_id) = self.node_ids.get(node_id.kind) { let node_ids = if VALID_CRYPTO_KINDS.contains(&node_id.kind) {
&mut self.validated_node_ids
} else {
&mut self.unsupported_node_ids
};
if let Some(old_node_id) = node_ids.get(node_id.kind) {
// If this was already there we do nothing // If this was already there we do nothing
if old_node_id == node_id { if old_node_id == node_id {
return Ok(None); return Ok(None);
} }
// Won't change number of crypto kinds // Won't change number of crypto kinds
self.node_ids.add(node_id); node_ids.add(node_id);
return Ok(Some(old_node_id)); return Ok(Some(old_node_id));
} }
// Check to ensure we aren't adding more crypto kinds than we support // Check to ensure we aren't adding more crypto kinds than we support
if self.node_ids.len() == MAX_CRYPTO_KINDS { if self.validated_node_ids.len() + self.unsupported_node_ids.len() == MAX_CRYPTO_KINDS {
bail!("too many crypto kinds for this node"); bail!("too many crypto kinds for this node");
} }
self.node_ids.add(node_id); node_ids.add(node_id);
Ok(None) Ok(None)
} }
pub fn best_node_id(&self) -> TypedKey { pub fn best_node_id(&self) -> TypedKey {
self.node_ids.best().unwrap() self.validated_node_ids.best().unwrap()
} }
/// Get crypto kinds /// Get crypto kinds
pub fn crypto_kinds(&self) -> Vec<CryptoKind> { pub fn crypto_kinds(&self) -> Vec<CryptoKind> {
self.node_ids.kinds() self.validated_node_ids.kinds()
} }
/// Compare sets of crypto kinds /// Compare sets of crypto kinds
pub fn common_crypto_kinds(&self, other: &[CryptoKind]) -> Vec<CryptoKind> { pub fn common_crypto_kinds(&self, other: &[CryptoKind]) -> Vec<CryptoKind> {
common_crypto_kinds(&self.node_ids.kinds(), other) common_crypto_kinds(&self.validated_node_ids.kinds(), other)
} }
@ -270,7 +280,7 @@ impl BucketEntryInner {
} }
// Update the envelope version support we have to use // Update the envelope version support we have to use
let envelope_support = signed_node_info.node_info().envelope_support.clone(); let envelope_support = signed_node_info.node_info().envelope_support().to_vec();
// Update the signed node info // Update the signed node info
*opt_current_sni = Some(Box::new(signed_node_info)); *opt_current_sni = Some(Box::new(signed_node_info));
@ -333,8 +343,10 @@ impl BucketEntryInner {
RoutingDomain::LocalNetwork => &self.local_network.signed_node_info, RoutingDomain::LocalNetwork => &self.local_network.signed_node_info,
RoutingDomain::PublicInternet => &self.public_internet.signed_node_info, RoutingDomain::PublicInternet => &self.public_internet.signed_node_info,
}; };
// Peer info includes all node ids, even unvalidated ones
let node_ids = self.node_ids();
opt_current_sni.as_ref().map(|s| PeerInfo { opt_current_sni.as_ref().map(|s| PeerInfo {
node_ids: self.node_ids.clone(), node_ids,
signed_node_info: *s.clone(), signed_node_info: *s.clone(),
}) })
} }
@ -781,11 +793,13 @@ pub struct BucketEntry {
impl BucketEntry { impl BucketEntry {
pub(super) fn new(first_node_id: TypedKey) -> Self { pub(super) fn new(first_node_id: TypedKey) -> Self {
let now = get_aligned_timestamp(); let now = get_aligned_timestamp();
let mut node_ids = TypedKeySet::new(); let mut validated_node_ids = TypedKeySet::new();
node_ids.add(first_node_id); let mut unsupported_node_ids = TypedKeySet::new();
validated_node_ids.add(first_node_id);
let inner = BucketEntryInner { let inner = BucketEntryInner {
node_ids, validated_node_ids,
unsupported_node_ids,
envelope_support: Vec::new(), envelope_support: Vec::new(),
updated_since_last_network_change: false, updated_since_last_network_change: false,
last_connections: BTreeMap::new(), last_connections: BTreeMap::new(),

View File

@ -792,8 +792,8 @@ impl RoutingTable {
e.with(rti, |_rti, e| { e.with(rti, |_rti, e| {
if let Some(ni) = e.node_info(routing_domain) { if let Some(ni) = e.node_info(routing_domain) {
let dif = DialInfoFilter::all() let dif = DialInfoFilter::all()
.with_protocol_type_set(ni.outbound_protocols) .with_protocol_type_set(ni.outbound_protocols())
.with_address_type_set(ni.address_types); .with_address_type_set(ni.address_types());
if dial_info.matches_filter(&dif) { if dial_info.matches_filter(&dif) {
return true; return true;
} }
@ -851,7 +851,7 @@ impl RoutingTable {
// does it have some dial info we need? // does it have some dial info we need?
let filter = |n: &NodeInfo| { let filter = |n: &NodeInfo| {
let mut keep = false; let mut keep = false;
for did in &n.dial_info_detail_list { for did in n.dial_info_detail_list() {
if matches!(did.dial_info.address_type(), AddressType::IPV4) { if matches!(did.dial_info.address_type(), AddressType::IPV4) {
for (n, protocol_type) in protocol_types.iter().enumerate() { for (n, protocol_type) in protocol_types.iter().enumerate() {
if nodes_proto_v4[n] < max_per_type if nodes_proto_v4[n] < max_per_type
@ -974,12 +974,12 @@ impl RoutingTable {
let mut out = Vec::<NodeRef>::with_capacity(peers.len()); let mut out = Vec::<NodeRef>::with_capacity(peers.len());
for p in peers { for p in peers {
// Ensure we're getting back nodes we asked for // Ensure we're getting back nodes we asked for
if !p.node_ids.kinds().contains(&crypto_kind) { if !p.node_ids().kinds().contains(&crypto_kind) {
continue; continue;
} }
// Don't register our own node // Don't register our own node
if self.matches_own_node_id(&p.node_ids) { if self.matches_own_node_id(p.node_ids()) {
continue; continue;
} }

View File

@ -174,13 +174,13 @@ pub trait NodeRefBase: Sized {
self.operate_mut(|_rti, e| e.set_our_node_info_ts(routing_domain, seen_ts)); self.operate_mut(|_rti, e| e.set_our_node_info_ts(routing_domain, seen_ts));
} }
fn network_class(&self, routing_domain: RoutingDomain) -> Option<NetworkClass> { fn network_class(&self, routing_domain: RoutingDomain) -> Option<NetworkClass> {
self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.network_class)) self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.network_class()))
} }
fn outbound_protocols(&self, routing_domain: RoutingDomain) -> Option<ProtocolTypeSet> { fn outbound_protocols(&self, routing_domain: RoutingDomain) -> Option<ProtocolTypeSet> {
self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.outbound_protocols)) self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.outbound_protocols()))
} }
fn address_types(&self, routing_domain: RoutingDomain) -> Option<AddressTypeSet> { fn address_types(&self, routing_domain: RoutingDomain) -> Option<AddressTypeSet> {
self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.address_types)) self.operate(|_rt, e| e.node_info(routing_domain).map(|n| n.address_types()))
} }
fn node_info_outbound_filter(&self, routing_domain: RoutingDomain) -> DialInfoFilter { fn node_info_outbound_filter(&self, routing_domain: RoutingDomain) -> DialInfoFilter {
let mut dif = DialInfoFilter::all(); let mut dif = DialInfoFilter::all();
@ -199,7 +199,7 @@ pub trait NodeRefBase: Sized {
.and_then(|rpi| { .and_then(|rpi| {
// If relay is ourselves, then return None, because we can't relay through ourselves // If relay is ourselves, then return None, because we can't relay through ourselves
// and to contact this node we should have had an existing inbound connection // and to contact this node we should have had an existing inbound connection
if rti.unlocked_inner.matches_own_node_id(&rpi.node_ids) { if rti.unlocked_inner.matches_own_node_id(rpi.node_ids()) {
return None; return None;
} }

View File

@ -22,6 +22,19 @@ pub enum RouteNode {
} }
impl RouteNode { impl RouteNode {
pub fn validate(&self, crypto: Crypto) -> Result<(), VeilidAPIError> {
match self {
RouteNode::NodeId(_) => Ok(()),
RouteNode::PeerInfo(pi) => {
let validated_node_ids = pi.validate(crypto)?;
if validated_node_ids.is_empty() {
apibail_generic!("no validated node ids for route node");
}
Ok(())
}
}
}
pub fn node_ref( pub fn node_ref(
&self, &self,
routing_table: RoutingTable, routing_table: RoutingTable,
@ -48,10 +61,10 @@ impl RouteNode {
RouteNode::NodeId(id) => { RouteNode::NodeId(id) => {
format!("{}", TypedKey::new(crypto_kind, *id)) format!("{}", TypedKey::new(crypto_kind, *id))
} }
RouteNode::PeerInfo(pi) => match pi.node_ids.get(crypto_kind) { RouteNode::PeerInfo(pi) => match pi.node_ids().get(crypto_kind) {
Some(id) => format!("{}", id), Some(id) => format!("{}", id),
None => { None => {
format!("({})?{}", crypto_kind, pi.node_ids) format!("({})?{}", crypto_kind, pi.node_ids())
} }
}, },
} }
@ -66,6 +79,11 @@ pub struct RouteHop {
/// The encrypted blob to pass to the next hop as its data (None for stubs) /// The encrypted blob to pass to the next hop as its data (None for stubs)
pub next_hop: Option<RouteHopData>, pub next_hop: Option<RouteHopData>,
} }
impl RouteHop {
pub fn validate(&self, crypto: Crypto) -> Result<(), VeilidAPIError> {
self.node.validate(crypto)
}
}
/// The kind of hops a private route can have /// The kind of hops a private route can have
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -78,6 +96,15 @@ pub enum PrivateRouteHops {
Empty, Empty,
} }
impl PrivateRouteHops {
pub fn validate(&self, crypto: Crypto) -> Result<(), VeilidAPIError> {
match self {
PrivateRouteHops::FirstHop(rh) => rh.validate(crypto),
PrivateRouteHops::Data(_) => Ok(()),
PrivateRouteHops::Empty => Ok(()),
}
}
}
/// A private route for receiver privacy /// A private route for receiver privacy
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct PrivateRoute { pub struct PrivateRoute {
@ -108,6 +135,10 @@ impl PrivateRoute {
} }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), VeilidAPIError> {
self.hops.validate(crypto)
}
/// Check if this is a stub route /// Check if this is a stub route
pub fn is_stub(&self) -> bool { pub fn is_stub(&self) -> bool {
if let PrivateRouteHops::FirstHop(first_hop) = &self.hops { if let PrivateRouteHops::FirstHop(first_hop) = &self.hops {
@ -155,7 +186,7 @@ impl PrivateRoute {
// Get the safety route to use from the spec // Get the safety route to use from the spec
Some(match &pr_first_hop.node { Some(match &pr_first_hop.node {
RouteNode::NodeId(n) => TypedKey::new(self.public_key.kind, *n), RouteNode::NodeId(n) => TypedKey::new(self.public_key.kind, *n),
RouteNode::PeerInfo(p) => p.node_ids.get(self.public_key.kind).unwrap(), RouteNode::PeerInfo(p) => p.node_ids().get(self.public_key.kind).unwrap(),
}) })
} }
} }

View File

@ -1550,7 +1550,9 @@ impl RouteSpecStore {
.get_root::<veilid_capnp::private_route::Reader>() .get_root::<veilid_capnp::private_route::Reader>()
.map_err(RPCError::internal) .map_err(RPCError::internal)
.wrap_err("failed to make reader for private_route")?; .wrap_err("failed to make reader for private_route")?;
let private_route = decode_private_route(&pr_reader, crypto.clone()).wrap_err("failed to decode private route")?; let private_route = decode_private_route(&pr_reader).wrap_err("failed to decode private route")?;
private_route.validate(crypto.clone()).wrap_err("failed to validate private route")?;
out.push(private_route); out.push(private_route);
} }

View File

@ -102,14 +102,14 @@ impl RoutingDomainDetailCommon {
} }
fn make_peer_info(&self, rti: &RoutingTableInner) -> PeerInfo { fn make_peer_info(&self, rti: &RoutingTableInner) -> PeerInfo {
let node_info = NodeInfo { let node_info = NodeInfo::new(
network_class: self.network_class.unwrap_or(NetworkClass::Invalid), self.network_class.unwrap_or(NetworkClass::Invalid),
outbound_protocols: self.outbound_protocols, self.outbound_protocols,
address_types: self.address_types, self.address_types,
envelope_support: VALID_ENVELOPE_VERSIONS.to_vec(), VALID_ENVELOPE_VERSIONS.to_vec(),
crypto_support: VALID_CRYPTO_KINDS.to_vec(), VALID_CRYPTO_KINDS.to_vec(),
dial_info_detail_list: self.dial_info_details.clone(), self.dial_info_details.clone()
}; );
let relay_info = self let relay_info = self
.relay_node .relay_node
@ -117,8 +117,9 @@ impl RoutingDomainDetailCommon {
.and_then(|rn| { .and_then(|rn| {
let opt_relay_pi = rn.locked(rti).make_peer_info(self.routing_domain); let opt_relay_pi = rn.locked(rti).make_peer_info(self.routing_domain);
if let Some(relay_pi) = opt_relay_pi { if let Some(relay_pi) = opt_relay_pi {
match relay_pi.signed_node_info { let (relay_ids, relay_sni) = relay_pi.into_fields();
SignedNodeInfo::Direct(d) => Some((relay_pi.node_ids, d)), match relay_sni {
SignedNodeInfo::Direct(d) => Some((relay_ids, d)),
SignedNodeInfo::Relayed(_) => { SignedNodeInfo::Relayed(_) => {
warn!("relay node should not have a relay itself! if this happens, a relay updated its signed node info and became a relay, which should cause the relay to be dropped"); warn!("relay node should not have a relay itself! if this happens, a relay updated its signed node info and became a relay, which should cause the relay to be dropped");
None None
@ -230,8 +231,8 @@ fn first_filtered_dial_info_detail(
) -> Option<DialInfoDetail> { ) -> Option<DialInfoDetail> {
let dial_info_filter = dial_info_filter.clone().filtered( let dial_info_filter = dial_info_filter.clone().filtered(
&DialInfoFilter::all() &DialInfoFilter::all()
.with_address_type_set(from_node.address_types) .with_address_type_set(from_node.address_types())
.with_protocol_type_set(from_node.outbound_protocols), .with_protocol_type_set(from_node.outbound_protocols()),
); );
// Get first filtered dialinfo // Get first filtered dialinfo
@ -278,18 +279,18 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
sequencing: Sequencing, sequencing: Sequencing,
) -> ContactMethod { ) -> ContactMethod {
// Get the nodeinfos for convenience // Get the nodeinfos for convenience
let node_a = peer_a.signed_node_info.node_info(); let node_a = peer_a.signed_node_info().node_info();
let node_b = peer_b.signed_node_info.node_info(); let node_b = peer_b.signed_node_info().node_info();
// Get the node ids that would be used between these peers // Get the node ids that would be used between these peers
let cck = common_crypto_kinds(&peer_a.node_ids.kinds(), &peer_b.node_ids.kinds()); let cck = common_crypto_kinds(&peer_a.node_ids().kinds(), &peer_b.node_ids().kinds());
let Some(best_ck) = cck.first().copied() else { let Some(best_ck) = cck.first().copied() else {
// No common crypto kinds between these nodes, can't contact // No common crypto kinds between these nodes, can't contact
return ContactMethod::Unreachable; return ContactMethod::Unreachable;
}; };
//let node_a_id = peer_a.node_ids.get(best_ck).unwrap(); //let node_a_id = peer_a.node_ids().get(best_ck).unwrap();
let node_b_id = peer_b.node_ids.get(best_ck).unwrap(); let node_b_id = peer_b.node_ids().get(best_ck).unwrap();
// Get the best match dial info for node B if we have it // Get the best match dial info for node B if we have it
if let Some(target_did) = if let Some(target_did) =
@ -302,17 +303,17 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
} }
// Get the target's inbound relay, it must have one or it is not reachable // Get the target's inbound relay, it must have one or it is not reachable
if let Some(node_b_relay) = peer_b.signed_node_info.relay_info() { if let Some(node_b_relay) = peer_b.signed_node_info().relay_info() {
// Note that relay_peer_info could be node_a, in which case a connection already exists // Note that relay_peer_info could be node_a, in which case a connection already exists
// and we only get here if the connection had dropped, in which case node_a is unreachable until // and we only get here if the connection had dropped, in which case node_a is unreachable until
// it gets a new relay connection up // it gets a new relay connection up
if peer_b.signed_node_info.relay_ids().contains_any(&peer_a.node_ids) { if peer_b.signed_node_info().relay_ids().contains_any(peer_a.node_ids()) {
return ContactMethod::Existing; return ContactMethod::Existing;
} }
// Get best node id to contact relay with // Get best node id to contact relay with
let Some(node_b_relay_id) = peer_b.signed_node_info.relay_ids().get(best_ck) else { let Some(node_b_relay_id) = peer_b.signed_node_info().relay_ids().get(best_ck) else {
// No best relay id // No best relay id
return ContactMethod::Unreachable; return ContactMethod::Unreachable;
}; };
@ -327,7 +328,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
.is_some() .is_some()
{ {
// Can node A receive anything inbound ever? // Can node A receive anything inbound ever?
if matches!(node_a.network_class, NetworkClass::InboundCapable) { if matches!(node_a.network_class(), NetworkClass::InboundCapable) {
///////// Reverse connection ///////// Reverse connection
// Get the best match dial info for an reverse inbound connection from node B to node A // Get the best match dial info for an reverse inbound connection from node B to node A
@ -390,17 +391,17 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
} }
} }
// If the node B has no direct dial info, it needs to have an inbound relay // If the node B has no direct dial info, it needs to have an inbound relay
else if let Some(node_b_relay) = peer_b.signed_node_info.relay_info() { else if let Some(node_b_relay) = peer_b.signed_node_info().relay_info() {
// Note that relay_peer_info could be node_a, in which case a connection already exists // Note that relay_peer_info could be node_a, in which case a connection already exists
// and we only get here if the connection had dropped, in which case node_a is unreachable until // and we only get here if the connection had dropped, in which case node_a is unreachable until
// it gets a new relay connection up // it gets a new relay connection up
if peer_b.signed_node_info.relay_ids().contains_any(&peer_a.node_ids) { if peer_b.signed_node_info().relay_ids().contains_any(peer_a.node_ids()) {
return ContactMethod::Existing; return ContactMethod::Existing;
} }
// Get best node id to contact relay with // Get best node id to contact relay with
let Some(node_b_relay_id) = peer_b.signed_node_info.relay_ids().get(best_ck) else { let Some(node_b_relay_id) = peer_b.signed_node_info().relay_ids().get(best_ck) else {
// No best relay id // No best relay id
return ContactMethod::Unreachable; return ContactMethod::Unreachable;
}; };
@ -419,7 +420,7 @@ impl RoutingDomainDetail for PublicInternetRoutingDomainDetail {
} }
// If node A can't reach the node by other means, it may need to use its own relay // If node A can't reach the node by other means, it may need to use its own relay
if let Some(node_a_relay_id) = peer_a.signed_node_info.relay_ids().get(best_ck) { if let Some(node_a_relay_id) = peer_a.signed_node_info().relay_ids().get(best_ck) {
return ContactMethod::OutboundRelay(node_a_relay_id); return ContactMethod::OutboundRelay(node_a_relay_id);
} }
@ -484,8 +485,8 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
// Scope the filter down to protocols node A can do outbound // Scope the filter down to protocols node A can do outbound
let dial_info_filter = dial_info_filter.filtered( let dial_info_filter = dial_info_filter.filtered(
&DialInfoFilter::all() &DialInfoFilter::all()
.with_address_type_set(peer_a.signed_node_info.node_info().address_types) .with_address_type_set(peer_a.signed_node_info().node_info().address_types())
.with_protocol_type_set(peer_a.signed_node_info.node_info().outbound_protocols), .with_protocol_type_set(peer_a.signed_node_info().node_info().outbound_protocols()),
); );
// Get first filtered dialinfo // Get first filtered dialinfo
@ -509,7 +510,7 @@ impl RoutingDomainDetail for LocalNetworkRoutingDomainDetail {
let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter); let filter = |did: &DialInfoDetail| did.matches_filter(&dial_info_filter);
let opt_target_did = peer_b.signed_node_info.node_info().first_filtered_dial_info_detail(sort, filter); let opt_target_did = peer_b.signed_node_info().node_info().first_filtered_dial_info_detail(sort, filter);
if let Some(target_did) = opt_target_did { if let Some(target_did) = opt_target_did {
return ContactMethod::Direct(target_did.dial_info); return ContactMethod::Direct(target_did.dial_info);
} }

View File

@ -171,11 +171,11 @@ impl RoutingTableInner {
node_info: &NodeInfo, node_info: &NodeInfo,
) -> bool { ) -> bool {
// Should not be passing around nodeinfo with an invalid network class // Should not be passing around nodeinfo with an invalid network class
if matches!(node_info.network_class, NetworkClass::Invalid) { if matches!(node_info.network_class(), NetworkClass::Invalid) {
return false; return false;
} }
// Ensure all of the dial info works in this routing domain // Ensure all of the dial info works in this routing domain
for did in &node_info.dial_info_detail_list { for did in node_info.dial_info_detail_list() {
if !self.ensure_dial_info_is_valid(routing_domain, &did.dial_info) { if !self.ensure_dial_info_is_valid(routing_domain, &did.dial_info) {
return false; return false;
} }
@ -258,7 +258,7 @@ impl RoutingTableInner {
} else { } else {
Some( Some(
rdd.common() rdd.common()
.with_peer_info(self, |pi| pi.signed_node_info.timestamp()), .with_peer_info(self, |pi| pi.signed_node_info().timestamp()),
) )
} }
}) })
@ -804,13 +804,16 @@ impl RoutingTableInner {
allow_invalid: bool, allow_invalid: bool,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
// if our own node if is in the list then ignore it, as we don't add ourselves to our own routing table // if our own node if is in the list then ignore it, as we don't add ourselves to our own routing table
if self.unlocked_inner.matches_own_node_id(&peer_info.node_ids) { if self
.unlocked_inner
.matches_own_node_id(peer_info.node_ids())
{
log_rtab!(debug "can't register own node id in routing table"); log_rtab!(debug "can't register own node id in routing table");
return None; return None;
} }
// node can not be its own relay // node can not be its own relay
let rids = peer_info.signed_node_info.relay_ids(); let rids = peer_info.signed_node_info().relay_ids();
if self.unlocked_inner.matches_own_node_id(&rids) { if self.unlocked_inner.matches_own_node_id(&rids) {
log_rtab!(debug "node can not be its own relay"); log_rtab!(debug "node can not be its own relay");
return None; return None;
@ -818,22 +821,22 @@ impl RoutingTableInner {
if !allow_invalid { if !allow_invalid {
// verify signature // verify signature
if !peer_info.signed_node_info.has_any_signature() { if !peer_info.signed_node_info().has_any_signature() {
log_rtab!(debug "signed node info for {:?} has invalid signature", &peer_info.node_ids); log_rtab!(debug "signed node info for {:?} has no valid signature", peer_info.node_ids());
return None; return None;
} }
// verify signed node info is valid in this routing domain // verify signed node info is valid in this routing domain
if !self.signed_node_info_is_valid_in_routing_domain( if !self.signed_node_info_is_valid_in_routing_domain(
routing_domain, routing_domain,
&peer_info.signed_node_info, peer_info.signed_node_info(),
) { ) {
log_rtab!(debug "signed node info for {:?} not valid in the {:?} routing domain", peer_info.node_ids, routing_domain); log_rtab!(debug "signed node info for {:?} not valid in the {:?} routing domain", peer_info.node_ids(), routing_domain);
return None; return None;
} }
} }
self.create_node_ref(outer_self, &peer_info.node_ids, |_rti, e| { self.create_node_ref(outer_self, peer_info.node_ids(), |_rti, e| {
e.update_signed_node_info(routing_domain, peer_info.signed_node_info); e.update_signed_node_info(routing_domain, peer_info.into_signed_node_info());
}) })
.map(|mut nr| { .map(|mut nr| {
nr.set_filter(Some( nr.set_filter(Some(

View File

@ -13,8 +13,8 @@ impl RoutingTable {
let Some(own_peer_info) = self.get_own_peer_info(RoutingDomain::PublicInternet) else { let Some(own_peer_info) = self.get_own_peer_info(RoutingDomain::PublicInternet) else {
return Ok(()); return Ok(());
}; };
let own_node_info = own_peer_info.signed_node_info.node_info(); let own_node_info = own_peer_info.signed_node_info().node_info();
let network_class = own_node_info.network_class; let network_class = own_node_info.network_class();
// Get routing domain editor // Get routing domain editor
let mut editor = self.edit_routing_domain(RoutingDomain::PublicInternet); let mut editor = self.edit_routing_domain(RoutingDomain::PublicInternet);

View File

@ -1,19 +1,58 @@
use super::*; use super::*;
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(
Clone, Default, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct NodeInfo { pub struct NodeInfo {
pub network_class: NetworkClass, network_class: NetworkClass,
#[with(RkyvEnumSet)] #[with(RkyvEnumSet)]
pub outbound_protocols: ProtocolTypeSet, outbound_protocols: ProtocolTypeSet,
#[with(RkyvEnumSet)] #[with(RkyvEnumSet)]
pub address_types: AddressTypeSet, address_types: AddressTypeSet,
pub envelope_support: Vec<u8>, envelope_support: Vec<u8>,
pub crypto_support: Vec<CryptoKind>, crypto_support: Vec<CryptoKind>,
pub dial_info_detail_list: Vec<DialInfoDetail>, dial_info_detail_list: Vec<DialInfoDetail>,
} }
impl NodeInfo { impl NodeInfo {
pub fn new(
network_class: NetworkClass,
outbound_protocols: ProtocolTypeSet,
address_types: AddressTypeSet,
envelope_support: Vec<u8>,
crypto_support: Vec<CryptoKind>,
dial_info_detail_list: Vec<DialInfoDetail>,
) -> Self {
Self {
network_class,
outbound_protocols,
address_types,
envelope_support,
crypto_support,
dial_info_detail_list,
}
}
pub fn network_class(&self) -> NetworkClass {
self.network_class
}
pub fn outbound_protocols(&self) -> ProtocolTypeSet {
self.outbound_protocols
}
pub fn address_types(&self) -> AddressTypeSet {
self.address_types
}
pub fn envelope_support(&self) -> &[u8] {
&self.envelope_support
}
pub fn crypto_support(&self) -> &[CryptoKind] {
&self.crypto_support
}
pub fn dial_info_detail_list(&self) -> &[DialInfoDetail] {
&self.dial_info_detail_list
}
pub fn first_filtered_dial_info_detail<S, F>( pub fn first_filtered_dial_info_detail<S, F>(
&self, &self,
sort: Option<S>, sort: Option<S>,

View File

@ -3,8 +3,8 @@ use super::*;
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct PeerInfo { pub struct PeerInfo {
pub node_ids: TypedKeySet, node_ids: TypedKeySet,
pub signed_node_info: SignedNodeInfo, signed_node_info: SignedNodeInfo,
} }
impl PeerInfo { impl PeerInfo {
@ -15,4 +15,21 @@ impl PeerInfo {
signed_node_info, signed_node_info,
} }
} }
pub fn validate(&self, crypto: Crypto) -> Result<TypedKeySet, VeilidAPIError> {
self.signed_node_info.validate(&self.node_ids, crypto)
}
pub fn node_ids(&self) -> &TypedKeySet {
&self.node_ids
}
pub fn signed_node_info(&self) -> &SignedNodeInfo {
&self.signed_node_info
}
pub fn into_signed_node_info(self) -> SignedNodeInfo {
self.signed_node_info
}
pub fn into_fields(self) -> (TypedKeySet, SignedNodeInfo) {
(self.node_ids, self.signed_node_info)
}
} }

View File

@ -4,36 +4,37 @@ use super::*;
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct SignedDirectNodeInfo { pub struct SignedDirectNodeInfo {
pub node_info: NodeInfo, node_info: NodeInfo,
pub timestamp: Timestamp, timestamp: Timestamp,
pub signatures: Vec<TypedSignature>, signatures: Vec<TypedSignature>,
} }
impl SignedDirectNodeInfo { impl SignedDirectNodeInfo {
/// Returns a new SignedDirectNodeInfo that has its signatures validated. /// Returns a new SignedDirectNodeInfo that has its signatures validated.
/// On success, this will modify the node_ids set to only include node_ids whose signatures validate. /// On success, this will modify the node_ids set to only include node_ids whose signatures validate.
/// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures. /// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures.
pub fn new( pub fn new(node_info: NodeInfo, timestamp: Timestamp, signatures: Vec<TypedSignature>) -> Self {
Self {
node_info,
timestamp,
signatures,
}
}
pub fn validate(
&self,
node_ids: &TypedKeySet,
crypto: Crypto, crypto: Crypto,
node_ids: &mut TypedKeySet, ) -> Result<TypedKeySet, VeilidAPIError> {
node_info: NodeInfo, let node_info_bytes = Self::make_signature_bytes(&self.node_info, self.timestamp)?;
timestamp: Timestamp,
typed_signatures: Vec<TypedSignature>,
) -> Result<Self, VeilidAPIError> {
let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?;
// Verify the signatures that we can // Verify the signatures that we can
let validated_node_ids = let validated_node_ids =
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?; crypto.verify_signatures(node_ids, &node_info_bytes, &self.signatures)?;
*node_ids = validated_node_ids; if validated_node_ids.len() == 0 {
if node_ids.len() == 0 {
apibail_generic!("no valid node ids in direct node info"); apibail_generic!("no valid node ids in direct node info");
} }
Ok(Self { Ok(validated_node_ids)
node_info,
timestamp,
signatures: typed_signatures,
})
} }
pub fn make_signatures( pub fn make_signatures(
@ -83,4 +84,14 @@ impl SignedDirectNodeInfo {
pub fn has_any_signature(&self) -> bool { pub fn has_any_signature(&self) -> bool {
!self.signatures.is_empty() !self.signatures.is_empty()
} }
pub fn node_info(&self) -> &NodeInfo {
&self.node_info
}
pub fn timestamp(&self) -> Timestamp {
self.timestamp
}
pub fn signatures(&self) -> &[TypedSignature] {
&self.signatures
}
} }

View File

@ -8,6 +8,17 @@ pub enum SignedNodeInfo {
} }
impl SignedNodeInfo { impl SignedNodeInfo {
pub fn validate(
&self,
node_ids: &TypedKeySet,
crypto: Crypto,
) -> Result<TypedKeySet, VeilidAPIError> {
match self {
SignedNodeInfo::Direct(d) => d.validate(node_ids, crypto),
SignedNodeInfo::Relayed(r) => r.validate(node_ids, crypto),
}
}
pub fn has_any_signature(&self) -> bool { pub fn has_any_signature(&self) -> bool {
match self { match self {
SignedNodeInfo::Direct(d) => d.has_any_signature(), SignedNodeInfo::Direct(d) => d.has_any_signature(),
@ -17,34 +28,34 @@ impl SignedNodeInfo {
pub fn timestamp(&self) -> Timestamp { pub fn timestamp(&self) -> Timestamp {
match self { match self {
SignedNodeInfo::Direct(d) => d.timestamp, SignedNodeInfo::Direct(d) => d.timestamp(),
SignedNodeInfo::Relayed(r) => r.timestamp, SignedNodeInfo::Relayed(r) => r.timestamp(),
} }
} }
pub fn node_info(&self) -> &NodeInfo { pub fn node_info(&self) -> &NodeInfo {
match self { match self {
SignedNodeInfo::Direct(d) => &d.node_info, SignedNodeInfo::Direct(d) => &d.node_info(),
SignedNodeInfo::Relayed(r) => &r.node_info, SignedNodeInfo::Relayed(r) => &r.node_info(),
} }
} }
pub fn relay_ids(&self) -> TypedKeySet { pub fn relay_ids(&self) -> TypedKeySet {
match self { match self {
SignedNodeInfo::Direct(_) => TypedKeySet::new(), SignedNodeInfo::Direct(_) => TypedKeySet::new(),
SignedNodeInfo::Relayed(r) => r.relay_ids.clone(), SignedNodeInfo::Relayed(r) => r.relay_ids().clone(),
} }
} }
pub fn relay_info(&self) -> Option<&NodeInfo> { pub fn relay_info(&self) -> Option<&NodeInfo> {
match self { match self {
SignedNodeInfo::Direct(_) => None, SignedNodeInfo::Direct(_) => None,
SignedNodeInfo::Relayed(r) => Some(&r.relay_info.node_info), SignedNodeInfo::Relayed(r) => Some(r.relay_info().node_info()),
} }
} }
pub fn relay_peer_info(&self) -> Option<PeerInfo> { pub fn relay_peer_info(&self) -> Option<PeerInfo> {
match self { match self {
SignedNodeInfo::Direct(_) => None, SignedNodeInfo::Direct(_) => None,
SignedNodeInfo::Relayed(r) => Some(PeerInfo::new( SignedNodeInfo::Relayed(r) => Some(PeerInfo::new(
r.relay_ids.clone(), r.relay_ids().clone(),
SignedNodeInfo::Direct(r.relay_info.clone()), SignedNodeInfo::Direct(r.relay_info().clone()),
)), )),
} }
} }
@ -58,7 +69,7 @@ impl SignedNodeInfo {
pub fn has_sequencing_matched_dial_info(&self, sequencing: Sequencing) -> bool { pub fn has_sequencing_matched_dial_info(&self, sequencing: Sequencing) -> bool {
// Check our dial info // Check our dial info
for did in &self.node_info().dial_info_detail_list { for did in self.node_info().dial_info_detail_list() {
match sequencing { match sequencing {
Sequencing::NoPreference | Sequencing::PreferOrdered => return true, Sequencing::NoPreference | Sequencing::PreferOrdered => return true,
Sequencing::EnsureOrdered => { Sequencing::EnsureOrdered => {
@ -72,7 +83,7 @@ impl SignedNodeInfo {
return self return self
.relay_info() .relay_info()
.map(|relay_ni| { .map(|relay_ni| {
for did in &relay_ni.dial_info_detail_list { for did in relay_ni.dial_info_detail_list() {
match sequencing { match sequencing {
Sequencing::NoPreference | Sequencing::PreferOrdered => return true, Sequencing::NoPreference | Sequencing::PreferOrdered => return true,
Sequencing::EnsureOrdered => { Sequencing::EnsureOrdered => {

View File

@ -4,11 +4,11 @@ use super::*;
#[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)] #[derive(Clone, Debug, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))] #[archive_attr(repr(C), derive(CheckBytes))]
pub struct SignedRelayedNodeInfo { pub struct SignedRelayedNodeInfo {
pub node_info: NodeInfo, node_info: NodeInfo,
pub relay_ids: TypedKeySet, relay_ids: TypedKeySet,
pub relay_info: SignedDirectNodeInfo, relay_info: SignedDirectNodeInfo,
pub timestamp: Timestamp, timestamp: Timestamp,
pub signatures: Vec<TypedSignature>, signatures: Vec<TypedSignature>,
} }
impl SignedRelayedNodeInfo { impl SignedRelayedNodeInfo {
@ -16,30 +16,50 @@ impl SignedRelayedNodeInfo {
/// On success, this will modify the node_ids set to only include node_ids whose signatures validate. /// On success, this will modify the node_ids set to only include node_ids whose signatures validate.
/// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures. /// All signatures are stored however, as this can be passed to other nodes that may be able to validate those signatures.
pub fn new( pub fn new(
crypto: Crypto,
node_ids: &mut TypedKeySet,
node_info: NodeInfo, node_info: NodeInfo,
relay_ids: TypedKeySet, relay_ids: TypedKeySet,
relay_info: SignedDirectNodeInfo, relay_info: SignedDirectNodeInfo,
timestamp: Timestamp, timestamp: Timestamp,
typed_signatures: Vec<TypedSignature>, signatures: Vec<TypedSignature>,
) -> Result<Self, VeilidAPIError> { ) -> Self {
let node_info_bytes = Self {
Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?;
let validated_node_ids =
crypto.verify_signatures(node_ids, &node_info_bytes, &typed_signatures)?;
*node_ids = validated_node_ids;
if node_ids.len() == 0 {
apibail_generic!("no valid node ids in relayed node info");
}
Ok(Self {
node_info, node_info,
relay_ids, relay_ids,
relay_info, relay_info,
timestamp, timestamp,
signatures: typed_signatures, signatures,
}) }
}
pub fn validate(
&self,
node_ids: &TypedKeySet,
crypto: Crypto,
) -> Result<TypedKeySet, VeilidAPIError> {
// Ensure the relay info for the node has a superset of the crypto kinds of the node it is relaying
if common_crypto_kinds(
self.node_info.crypto_support(),
self.relay_info.node_info().crypto_support(),
)
.len()
!= self.node_info.crypto_support().len()
{
apibail_generic!("relay should have superset of node crypto kinds");
}
// Verify signatures
let node_info_bytes = Self::make_signature_bytes(
&self.node_info,
&self.relay_ids,
&self.relay_info,
self.timestamp,
)?;
let validated_node_ids =
crypto.verify_signatures(node_ids, &node_info_bytes, &self.signatures)?;
if validated_node_ids.len() == 0 {
apibail_generic!("no valid node ids in relayed node info");
}
Ok(validated_node_ids)
} }
pub fn make_signatures( pub fn make_signatures(
@ -103,4 +123,20 @@ impl SignedRelayedNodeInfo {
pub fn has_any_signature(&self) -> bool { pub fn has_any_signature(&self) -> bool {
!self.signatures.is_empty() !self.signatures.is_empty()
} }
pub fn node_info(&self) -> &NodeInfo {
&self.node_info
}
pub fn timestamp(&self) -> Timestamp {
self.timestamp
}
pub fn relay_ids(&self) -> &TypedKeySet {
&self.relay_ids
}
pub fn relay_info(&self) -> &SignedDirectNodeInfo {
&self.relay_info
}
pub fn signatures(&self) -> &[TypedSignature] {
&self.signatures
}
} }

View File

@ -4,27 +4,27 @@ pub fn encode_node_info(
node_info: &NodeInfo, node_info: &NodeInfo,
builder: &mut veilid_capnp::node_info::Builder, builder: &mut veilid_capnp::node_info::Builder,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
builder.set_network_class(encode_network_class(node_info.network_class)); builder.set_network_class(encode_network_class(node_info.network_class()));
let mut ps_builder = builder.reborrow().init_outbound_protocols(); let mut ps_builder = builder.reborrow().init_outbound_protocols();
encode_protocol_type_set(&node_info.outbound_protocols, &mut ps_builder)?; encode_protocol_type_set(&node_info.outbound_protocols(), &mut ps_builder)?;
let mut ats_builder = builder.reborrow().init_address_types(); let mut ats_builder = builder.reborrow().init_address_types();
encode_address_type_set(&node_info.address_types, &mut ats_builder)?; encode_address_type_set(&node_info.address_types(), &mut ats_builder)?;
let mut es_builder = builder let mut es_builder = builder
.reborrow() .reborrow()
.init_envelope_support(node_info.envelope_support.len() as u32); .init_envelope_support(node_info.envelope_support().len() as u32);
if let Some(s) = es_builder.as_slice() { if let Some(s) = es_builder.as_slice() {
s.clone_from_slice(&node_info.envelope_support); s.clone_from_slice(&node_info.envelope_support());
} }
let mut cs_builder = builder let mut cs_builder = builder
.reborrow() .reborrow()
.init_crypto_support(node_info.crypto_support.len() as u32); .init_crypto_support(node_info.crypto_support().len() as u32);
if let Some(s) = cs_builder.as_slice() { if let Some(s) = cs_builder.as_slice() {
let csvec: Vec<u32> = node_info let csvec: Vec<u32> = node_info
.crypto_support .crypto_support()
.iter() .iter()
.map(|x| u32::from_be_bytes(x.0)) .map(|x| u32::from_be_bytes(x.0))
.collect(); .collect();
@ -33,7 +33,7 @@ pub fn encode_node_info(
let mut didl_builder = builder.reborrow().init_dial_info_detail_list( let mut didl_builder = builder.reborrow().init_dial_info_detail_list(
node_info node_info
.dial_info_detail_list .dial_info_detail_list()
.len() .len()
.try_into() .try_into()
.map_err(RPCError::map_protocol( .map_err(RPCError::map_protocol(
@ -41,9 +41,9 @@ pub fn encode_node_info(
))?, ))?,
); );
for idx in 0..node_info.dial_info_detail_list.len() { for idx in 0..node_info.dial_info_detail_list().len() {
let mut did_builder = didl_builder.reborrow().get(idx as u32); let mut did_builder = didl_builder.reborrow().get(idx as u32);
encode_dial_info_detail(&node_info.dial_info_detail_list[idx], &mut did_builder)?; encode_dial_info_detail(&node_info.dial_info_detail_list()[idx], &mut did_builder)?;
} }
Ok(()) Ok(())
@ -131,12 +131,12 @@ pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<Node
dial_info_detail_list.push(decode_dial_info_detail(&did)?) dial_info_detail_list.push(decode_dial_info_detail(&did)?)
} }
Ok(NodeInfo { Ok(NodeInfo::new(
network_class, network_class,
outbound_protocols, outbound_protocols,
address_types, address_types,
envelope_support, envelope_support,
crypto_support, crypto_support,
dial_info_detail_list, dial_info_detail_list,
}) ))
} }

View File

@ -9,18 +9,18 @@ impl RPCAnswer {
pub fn new(detail: RPCAnswerDetail) -> Self { pub fn new(detail: RPCAnswerDetail) -> Self {
Self { detail } Self { detail }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
self.detail.validate(crypto)
}
pub fn into_detail(self) -> RPCAnswerDetail { pub fn into_detail(self) -> RPCAnswerDetail {
self.detail self.detail
} }
pub fn desc(&self) -> &'static str { pub fn desc(&self) -> &'static str {
self.detail.desc() self.detail.desc()
} }
pub fn decode( pub fn decode(reader: &veilid_capnp::answer::Reader) -> Result<RPCAnswer, RPCError> {
reader: &veilid_capnp::answer::Reader,
crypto: Crypto,
) -> Result<RPCAnswer, RPCError> {
let d_reader = reader.get_detail(); let d_reader = reader.get_detail();
let detail = RPCAnswerDetail::decode(&d_reader, crypto)?; let detail = RPCAnswerDetail::decode(&d_reader)?;
Ok(RPCAnswer { detail }) Ok(RPCAnswer { detail })
} }
pub fn encode(&self, builder: &mut veilid_capnp::answer::Builder) -> Result<(), RPCError> { pub fn encode(&self, builder: &mut veilid_capnp::answer::Builder) -> Result<(), RPCError> {
@ -60,10 +60,23 @@ impl RPCAnswerDetail {
RPCAnswerDetail::CancelTunnelA(_) => "CancelTunnelA", RPCAnswerDetail::CancelTunnelA(_) => "CancelTunnelA",
} }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
match self {
RPCAnswerDetail::StatusA(r) => r.validate(crypto),
RPCAnswerDetail::FindNodeA(r) => r.validate(crypto),
RPCAnswerDetail::AppCallA(r) => r.validate(crypto),
RPCAnswerDetail::GetValueA(r) => r.validate(crypto),
RPCAnswerDetail::SetValueA(r) => r.validate(crypto),
RPCAnswerDetail::WatchValueA(r) => r.validate(crypto),
RPCAnswerDetail::SupplyBlockA(r) => r.validate(crypto),
RPCAnswerDetail::FindBlockA(r) => r.validate(crypto),
RPCAnswerDetail::StartTunnelA(r) => r.validate(crypto),
RPCAnswerDetail::CompleteTunnelA(r) => r.validate(crypto),
RPCAnswerDetail::CancelTunnelA(r) => r.validate(crypto),
}
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::answer::detail::Reader, reader: &veilid_capnp::answer::detail::Reader,
crypto: Crypto,
) -> Result<RPCAnswerDetail, RPCError> { ) -> Result<RPCAnswerDetail, RPCError> {
let which_reader = reader.which().map_err(RPCError::protocol)?; let which_reader = reader.which().map_err(RPCError::protocol)?;
let out = match which_reader { let out = match which_reader {
@ -74,7 +87,7 @@ impl RPCAnswerDetail {
} }
veilid_capnp::answer::detail::FindNodeA(r) => { veilid_capnp::answer::detail::FindNodeA(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationFindNodeA::decode(&op_reader, crypto)?; let out = RPCOperationFindNodeA::decode(&op_reader)?;
RPCAnswerDetail::FindNodeA(out) RPCAnswerDetail::FindNodeA(out)
} }
veilid_capnp::answer::detail::AppCallA(r) => { veilid_capnp::answer::detail::AppCallA(r) => {
@ -84,27 +97,27 @@ impl RPCAnswerDetail {
} }
veilid_capnp::answer::detail::GetValueA(r) => { veilid_capnp::answer::detail::GetValueA(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationGetValueA::decode(&op_reader, crypto)?; let out = RPCOperationGetValueA::decode(&op_reader)?;
RPCAnswerDetail::GetValueA(out) RPCAnswerDetail::GetValueA(out)
} }
veilid_capnp::answer::detail::SetValueA(r) => { veilid_capnp::answer::detail::SetValueA(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationSetValueA::decode(&op_reader, crypto)?; let out = RPCOperationSetValueA::decode(&op_reader)?;
RPCAnswerDetail::SetValueA(out) RPCAnswerDetail::SetValueA(out)
} }
veilid_capnp::answer::detail::WatchValueA(r) => { veilid_capnp::answer::detail::WatchValueA(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationWatchValueA::decode(&op_reader, crypto)?; let out = RPCOperationWatchValueA::decode(&op_reader)?;
RPCAnswerDetail::WatchValueA(out) RPCAnswerDetail::WatchValueA(out)
} }
veilid_capnp::answer::detail::SupplyBlockA(r) => { veilid_capnp::answer::detail::SupplyBlockA(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationSupplyBlockA::decode(&op_reader, crypto)?; let out = RPCOperationSupplyBlockA::decode(&op_reader)?;
RPCAnswerDetail::SupplyBlockA(out) RPCAnswerDetail::SupplyBlockA(out)
} }
veilid_capnp::answer::detail::FindBlockA(r) => { veilid_capnp::answer::detail::FindBlockA(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationFindBlockA::decode(&op_reader, crypto)?; let out = RPCOperationFindBlockA::decode(&op_reader)?;
RPCAnswerDetail::FindBlockA(out) RPCAnswerDetail::FindBlockA(out)
} }
veilid_capnp::answer::detail::StartTunnelA(r) => { veilid_capnp::answer::detail::StartTunnelA(r) => {

View File

@ -16,25 +16,30 @@ impl RPCOperationKind {
} }
} }
pub fn decode( pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
kind_reader: &veilid_capnp::operation::kind::Reader, match self {
crypto: Crypto, RPCOperationKind::Question(r) => r.validate(crypto),
) -> Result<Self, RPCError> { RPCOperationKind::Statement(r) => r.validate(crypto),
RPCOperationKind::Answer(r) => r.validate(crypto),
}
}
pub fn decode(kind_reader: &veilid_capnp::operation::kind::Reader) -> Result<Self, RPCError> {
let which_reader = kind_reader.which().map_err(RPCError::protocol)?; let which_reader = kind_reader.which().map_err(RPCError::protocol)?;
let out = match which_reader { let out = match which_reader {
veilid_capnp::operation::kind::Which::Question(r) => { veilid_capnp::operation::kind::Which::Question(r) => {
let q_reader = r.map_err(RPCError::protocol)?; let q_reader = r.map_err(RPCError::protocol)?;
let out = RPCQuestion::decode(&q_reader, crypto)?; let out = RPCQuestion::decode(&q_reader)?;
RPCOperationKind::Question(out) RPCOperationKind::Question(out)
} }
veilid_capnp::operation::kind::Which::Statement(r) => { veilid_capnp::operation::kind::Which::Statement(r) => {
let q_reader = r.map_err(RPCError::protocol)?; let q_reader = r.map_err(RPCError::protocol)?;
let out = RPCStatement::decode(&q_reader, crypto)?; let out = RPCStatement::decode(&q_reader)?;
RPCOperationKind::Statement(out) RPCOperationKind::Statement(out)
} }
veilid_capnp::operation::kind::Which::Answer(r) => { veilid_capnp::operation::kind::Which::Answer(r) => {
let q_reader = r.map_err(RPCError::protocol)?; let q_reader = r.map_err(RPCError::protocol)?;
let out = RPCAnswer::decode(&q_reader, crypto)?; let out = RPCAnswer::decode(&q_reader)?;
RPCOperationKind::Answer(out) RPCOperationKind::Answer(out)
} }
}; };
@ -93,6 +98,15 @@ impl RPCOperation {
} }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
// Validate sender peer info
if let Some(sender_peer_info) = &self.opt_sender_peer_info {
sender_peer_info.validate(crypto.clone())?;
}
// Validate operation kind
self.kind.validate(crypto)
}
pub fn op_id(&self) -> OperationId { pub fn op_id(&self) -> OperationId {
self.op_id self.op_id
} }
@ -112,17 +126,14 @@ impl RPCOperation {
self.kind self.kind
} }
pub fn decode( pub fn decode(operation_reader: &veilid_capnp::operation::Reader) -> Result<Self, RPCError> {
operation_reader: &veilid_capnp::operation::Reader,
crypto: Crypto,
) -> Result<Self, RPCError> {
let op_id = OperationId::new(operation_reader.get_op_id()); let op_id = OperationId::new(operation_reader.get_op_id());
let sender_peer_info = if operation_reader.has_sender_peer_info() { let sender_peer_info = if operation_reader.has_sender_peer_info() {
let pi_reader = operation_reader let pi_reader = operation_reader
.get_sender_peer_info() .get_sender_peer_info()
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
let pi = decode_peer_info(&pi_reader, crypto.clone())?; let pi = decode_peer_info(&pi_reader)?;
Some(pi) Some(pi)
} else { } else {
None None
@ -131,7 +142,7 @@ impl RPCOperation {
let target_node_info_ts = Timestamp::new(operation_reader.get_target_node_info_ts()); let target_node_info_ts = Timestamp::new(operation_reader.get_target_node_info_ts());
let kind_reader = operation_reader.get_kind(); let kind_reader = operation_reader.get_kind();
let kind = RPCOperationKind::decode(&kind_reader, crypto)?; let kind = RPCOperationKind::decode(&kind_reader)?;
Ok(RPCOperation { Ok(RPCOperation {
op_id, op_id,

View File

@ -6,6 +6,10 @@ pub struct RPCOperationAppCallQ {
} }
impl RPCOperationAppCallQ { impl RPCOperationAppCallQ {
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
xxx length should be checked in decode verify this
Ok(())
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_app_call_q::Reader, reader: &veilid_capnp::operation_app_call_q::Reader,
) -> Result<RPCOperationAppCallQ, RPCError> { ) -> Result<RPCOperationAppCallQ, RPCError> {

View File

@ -35,7 +35,6 @@ pub struct RPCOperationFindBlockA {
impl RPCOperationFindBlockA { impl RPCOperationFindBlockA {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_find_block_a::Reader, reader: &veilid_capnp::operation_find_block_a::Reader,
crypto: Crypto,
) -> Result<RPCOperationFindBlockA, RPCError> { ) -> Result<RPCOperationFindBlockA, RPCError> {
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec(); let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
@ -47,7 +46,7 @@ impl RPCOperationFindBlockA {
.map_err(RPCError::map_internal("too many suppliers"))?, .map_err(RPCError::map_internal("too many suppliers"))?,
); );
for s in suppliers_reader.iter() { for s in suppliers_reader.iter() {
let peer_info = decode_peer_info(&s, crypto.clone())?; let peer_info = decode_peer_info(&s)?;
suppliers.push(peer_info); suppliers.push(peer_info);
} }
@ -59,7 +58,7 @@ impl RPCOperationFindBlockA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, crypto.clone())?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -6,6 +6,9 @@ pub struct RPCOperationFindNodeQ {
} }
impl RPCOperationFindNodeQ { impl RPCOperationFindNodeQ {
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
Ok(())
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_find_node_q::Reader, reader: &veilid_capnp::operation_find_node_q::Reader,
) -> Result<RPCOperationFindNodeQ, RPCError> { ) -> Result<RPCOperationFindNodeQ, RPCError> {
@ -29,9 +32,14 @@ pub struct RPCOperationFindNodeA {
} }
impl RPCOperationFindNodeA { impl RPCOperationFindNodeA {
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
for pi in &self.peers {
pi.validate(crypto.clone()).map_err(RPCError::protocol)?;
}
Ok(())
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_find_node_a::Reader, reader: &veilid_capnp::operation_find_node_a::Reader,
crypto: Crypto,
) -> Result<RPCOperationFindNodeA, RPCError> { ) -> Result<RPCOperationFindNodeA, RPCError> {
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?; let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
let mut peers = Vec::<PeerInfo>::with_capacity( let mut peers = Vec::<PeerInfo>::with_capacity(
@ -41,7 +49,7 @@ impl RPCOperationFindNodeA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, crypto.clone())?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -4,16 +4,22 @@ use super::*;
pub struct RPCOperationGetValueQ { pub struct RPCOperationGetValueQ {
pub key: TypedKey, pub key: TypedKey,
pub subkey: ValueSubkey, pub subkey: ValueSubkey,
pub want_descriptor: bool,
} }
impl RPCOperationGetValueQ { impl RPCOperationGetValueQ {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_get_value_q::Reader, reader: &veilid_capnp::operation_get_value_q::Reader,
) -> Result<RPCOperationGetValueQ, RPCError> { ) -> Result<RPCOperationGetValueQ, RPCError> {
let k_reader = reader.get_key().map_err(RPCError::protocol)?; let k_reader = reader.reborrow().get_key().map_err(RPCError::protocol)?;
let key = decode_typed_key(&k_reader)?; let key = decode_typed_key(&k_reader)?;
let subkey = reader.get_subkey(); let subkey = reader.reborrow().get_subkey();
Ok(RPCOperationGetValueQ { key, subkey }) let want_descriptor = reader.reborrow().get_want_descriptor();
Ok(RPCOperationGetValueQ {
key,
subkey,
want_descriptor,
})
} }
pub fn encode( pub fn encode(
&self, &self,
@ -22,24 +28,24 @@ impl RPCOperationGetValueQ {
let mut k_builder = builder.reborrow().init_key(); let mut k_builder = builder.reborrow().init_key();
encode_typed_key(&self.key, &mut k_builder); encode_typed_key(&self.key, &mut k_builder);
builder.set_subkey(self.subkey); builder.set_subkey(self.subkey);
builder.set_want_descriptor(self.want_descriptor);
Ok(()) Ok(())
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum RPCOperationGetValueA { pub enum RPCOperationGetValueA {
Data(ValueData), Value(ValueDetail),
Peers(Vec<PeerInfo>), Peers(Vec<PeerInfo>),
} }
impl RPCOperationGetValueA { impl RPCOperationGetValueA {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_get_value_a::Reader, reader: &veilid_capnp::operation_get_value_a::Reader,
crypto: Crypto,
) -> Result<RPCOperationGetValueA, RPCError> { ) -> Result<RPCOperationGetValueA, RPCError> {
match reader.which().map_err(RPCError::protocol)? { match reader.which().map_err(RPCError::protocol)? {
veilid_capnp::operation_get_value_a::Which::Data(r) => { veilid_capnp::operation_get_value_a::Which::Value(r) => {
let data = decode_value_data(&r.map_err(RPCError::protocol)?)?; let value_detail = decode_value_detail(&r.map_err(RPCError::protocol)?)?;
Ok(RPCOperationGetValueA::Data(data)) Ok(RPCOperationGetValueA::Data(data))
} }
veilid_capnp::operation_get_value_a::Which::Peers(r) => { veilid_capnp::operation_get_value_a::Which::Peers(r) => {
@ -51,7 +57,7 @@ impl RPCOperationGetValueA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, crypto.clone())?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -80,10 +80,9 @@ pub struct RPCOperationRoute {
impl RPCOperationRoute { impl RPCOperationRoute {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_route::Reader, reader: &veilid_capnp::operation_route::Reader,
crypto: Crypto,
) -> Result<RPCOperationRoute, RPCError> { ) -> Result<RPCOperationRoute, RPCError> {
let sr_reader = reader.get_safety_route().map_err(RPCError::protocol)?; let sr_reader = reader.get_safety_route().map_err(RPCError::protocol)?;
let safety_route = decode_safety_route(&sr_reader, crypto)?; let safety_route = decode_safety_route(&sr_reader)?;
let o_reader = reader.get_operation().map_err(RPCError::protocol)?; let o_reader = reader.get_operation().map_err(RPCError::protocol)?;
let operation = RoutedOperation::decode(&o_reader)?; let operation = RoutedOperation::decode(&o_reader)?;

View File

@ -40,7 +40,6 @@ pub enum RPCOperationSetValueA {
impl RPCOperationSetValueA { impl RPCOperationSetValueA {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_set_value_a::Reader, reader: &veilid_capnp::operation_set_value_a::Reader,
crypto: Crypto,
) -> Result<RPCOperationSetValueA, RPCError> { ) -> Result<RPCOperationSetValueA, RPCError> {
match reader.which().map_err(RPCError::protocol)? { match reader.which().map_err(RPCError::protocol)? {
veilid_capnp::operation_set_value_a::Which::Data(r) => { veilid_capnp::operation_set_value_a::Which::Data(r) => {
@ -56,7 +55,7 @@ impl RPCOperationSetValueA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, crypto.clone())?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -8,9 +8,8 @@ pub struct RPCOperationSignal {
impl RPCOperationSignal { impl RPCOperationSignal {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_signal::Reader, reader: &veilid_capnp::operation_signal::Reader,
crypto: Crypto,
) -> Result<RPCOperationSignal, RPCError> { ) -> Result<RPCOperationSignal, RPCError> {
let signal_info = decode_signal_info(reader, crypto)?; let signal_info = decode_signal_info(reader)?;
Ok(RPCOperationSignal { signal_info }) Ok(RPCOperationSignal { signal_info })
} }
pub fn encode( pub fn encode(

View File

@ -6,6 +6,10 @@ pub struct RPCOperationStatusQ {
} }
impl RPCOperationStatusQ { impl RPCOperationStatusQ {
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
Ok(())
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_status_q::Reader, reader: &veilid_capnp::operation_status_q::Reader,
) -> Result<RPCOperationStatusQ, RPCError> { ) -> Result<RPCOperationStatusQ, RPCError> {
@ -37,6 +41,9 @@ pub struct RPCOperationStatusA {
} }
impl RPCOperationStatusA { impl RPCOperationStatusA {
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
Ok(())
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_status_a::Reader, reader: &veilid_capnp::operation_status_a::Reader,
) -> Result<RPCOperationStatusA, RPCError> { ) -> Result<RPCOperationStatusA, RPCError> {

View File

@ -34,8 +34,7 @@ pub enum RPCOperationSupplyBlockA {
impl RPCOperationSupplyBlockA { impl RPCOperationSupplyBlockA {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_supply_block_a::Reader, reader: &veilid_capnp::operation_supply_block_a::Reader,
crypto: Crypto, = ) -> Result<RPCOperationSupplyBlockA, RPCError> {
) -> Result<RPCOperationSupplyBlockA, RPCError> {
match reader.which().map_err(RPCError::protocol)? { match reader.which().map_err(RPCError::protocol)? {
veilid_capnp::operation_supply_block_a::Which::Expiration(r) => { veilid_capnp::operation_supply_block_a::Which::Expiration(r) => {
Ok(RPCOperationSupplyBlockA::Expiration(r)) Ok(RPCOperationSupplyBlockA::Expiration(r))
@ -49,7 +48,7 @@ impl RPCOperationSupplyBlockA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, crypto.clone())?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -80,7 +80,6 @@ pub struct RPCOperationWatchValueA {
impl RPCOperationWatchValueA { impl RPCOperationWatchValueA {
pub fn decode( pub fn decode(
reader: &veilid_capnp::operation_watch_value_a::Reader, reader: &veilid_capnp::operation_watch_value_a::Reader,
crypto: Crypto,
) -> Result<RPCOperationWatchValueA, RPCError> { ) -> Result<RPCOperationWatchValueA, RPCError> {
let expiration = reader.get_expiration(); let expiration = reader.get_expiration();
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?; let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
@ -91,7 +90,7 @@ impl RPCOperationWatchValueA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, crypto.clone())?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -10,6 +10,10 @@ impl RPCQuestion {
pub fn new(respond_to: RespondTo, detail: RPCQuestionDetail) -> Self { pub fn new(respond_to: RespondTo, detail: RPCQuestionDetail) -> Self {
Self { respond_to, detail } Self { respond_to, detail }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
self.respond_to.validate(crypto.clone())?;
self.detail.validate(crypto)
}
pub fn respond_to(&self) -> &RespondTo { pub fn respond_to(&self) -> &RespondTo {
&self.respond_to &self.respond_to
} }
@ -19,12 +23,9 @@ impl RPCQuestion {
pub fn desc(&self) -> &'static str { pub fn desc(&self) -> &'static str {
self.detail.desc() self.detail.desc()
} }
pub fn decode( pub fn decode(reader: &veilid_capnp::question::Reader) -> Result<RPCQuestion, RPCError> {
reader: &veilid_capnp::question::Reader,
crypto: Crypto,
) -> Result<RPCQuestion, RPCError> {
let rt_reader = reader.get_respond_to(); let rt_reader = reader.get_respond_to();
let respond_to = RespondTo::decode(&rt_reader, crypto)?; let respond_to = RespondTo::decode(&rt_reader)?;
let d_reader = reader.get_detail(); let d_reader = reader.get_detail();
let detail = RPCQuestionDetail::decode(&d_reader)?; let detail = RPCQuestionDetail::decode(&d_reader)?;
Ok(RPCQuestion { respond_to, detail }) Ok(RPCQuestion { respond_to, detail })
@ -68,6 +69,21 @@ impl RPCQuestionDetail {
RPCQuestionDetail::CancelTunnelQ(_) => "CancelTunnelQ", RPCQuestionDetail::CancelTunnelQ(_) => "CancelTunnelQ",
} }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
match self {
RPCQuestionDetail::StatusQ(r) => r.validate(crypto),
RPCQuestionDetail::FindNodeQ(r) => r.validate(crypto),
RPCQuestionDetail::AppCallQ(r) => r.validate(crypto),
RPCQuestionDetail::GetValueQ(r) => r.validate(crypto),
RPCQuestionDetail::SetValueQ(r) => r.validate(crypto),
RPCQuestionDetail::WatchValueQ(r) => r.validate(crypto),
RPCQuestionDetail::SupplyBlockQ(r) => r.validate(crypto),
RPCQuestionDetail::FindBlockQ(r) => r.validate(crypto),
RPCQuestionDetail::StartTunnelQ(r) => r.validate(crypto),
RPCQuestionDetail::CompleteTunnelQ(r) => r.validate(crypto),
RPCQuestionDetail::CancelTunnelQ(r) => r.validate(crypto),
}
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::question::detail::Reader, reader: &veilid_capnp::question::detail::Reader,

View File

@ -7,6 +7,13 @@ pub enum RespondTo {
} }
impl RespondTo { impl RespondTo {
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
match self {
RespondTo::Sender => Ok(()),
RespondTo::PrivateRoute(pr) => pr.validate(crypto).map_err(RPCError::protocol),
}
}
pub fn encode( pub fn encode(
&self, &self,
builder: &mut veilid_capnp::question::respond_to::Builder, builder: &mut veilid_capnp::question::respond_to::Builder,
@ -23,15 +30,12 @@ impl RespondTo {
Ok(()) Ok(())
} }
pub fn decode( pub fn decode(reader: &veilid_capnp::question::respond_to::Reader) -> Result<Self, RPCError> {
reader: &veilid_capnp::question::respond_to::Reader,
crypto: Crypto,
) -> Result<Self, RPCError> {
let respond_to = match reader.which().map_err(RPCError::protocol)? { let respond_to = match reader.which().map_err(RPCError::protocol)? {
veilid_capnp::question::respond_to::Sender(()) => RespondTo::Sender, veilid_capnp::question::respond_to::Sender(()) => RespondTo::Sender,
veilid_capnp::question::respond_to::PrivateRoute(pr_reader) => { veilid_capnp::question::respond_to::PrivateRoute(pr_reader) => {
let pr_reader = pr_reader.map_err(RPCError::protocol)?; let pr_reader = pr_reader.map_err(RPCError::protocol)?;
let pr = decode_private_route(&pr_reader, crypto)?; let pr = decode_private_route(&pr_reader)?;
RespondTo::PrivateRoute(pr) RespondTo::PrivateRoute(pr)
} }
}; };

View File

@ -9,6 +9,9 @@ impl RPCStatement {
pub fn new(detail: RPCStatementDetail) -> Self { pub fn new(detail: RPCStatementDetail) -> Self {
Self { detail } Self { detail }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
self.detail.validate(crypto)
}
pub fn detail(&self) -> &RPCStatementDetail { pub fn detail(&self) -> &RPCStatementDetail {
&self.detail &self.detail
} }
@ -18,12 +21,9 @@ impl RPCStatement {
pub fn desc(&self) -> &'static str { pub fn desc(&self) -> &'static str {
self.detail.desc() self.detail.desc()
} }
pub fn decode( pub fn decode(reader: &veilid_capnp::statement::Reader) -> Result<RPCStatement, RPCError> {
reader: &veilid_capnp::statement::Reader,
crypto: Crypto,
) -> Result<RPCStatement, RPCError> {
let d_reader = reader.get_detail(); let d_reader = reader.get_detail();
let detail = RPCStatementDetail::decode(&d_reader, crypto)?; let detail = RPCStatementDetail::decode(&d_reader)?;
Ok(RPCStatement { detail }) Ok(RPCStatement { detail })
} }
pub fn encode(&self, builder: &mut veilid_capnp::statement::Builder) -> Result<(), RPCError> { pub fn encode(&self, builder: &mut veilid_capnp::statement::Builder) -> Result<(), RPCError> {
@ -53,9 +53,18 @@ impl RPCStatementDetail {
RPCStatementDetail::AppMessage(_) => "AppMessage", RPCStatementDetail::AppMessage(_) => "AppMessage",
} }
} }
pub fn validate(&self, crypto: Crypto) -> Result<(), RPCError> {
match self {
RPCStatementDetail::ValidateDialInfo(r) => r.validate(crypto),
RPCStatementDetail::Route(r) => r.validate(crypto),
RPCStatementDetail::ValueChanged(r) => r.validate(crypto),
RPCStatementDetail::Signal(r) => r.validate(crypto),
RPCStatementDetail::ReturnReceipt(r) => r.validate(crypto),
RPCStatementDetail::AppMessage(r) => r.validate(crypto),
}
}
pub fn decode( pub fn decode(
reader: &veilid_capnp::statement::detail::Reader, reader: &veilid_capnp::statement::detail::Reader,
crypto: Crypto,
) -> Result<RPCStatementDetail, RPCError> { ) -> Result<RPCStatementDetail, RPCError> {
let which_reader = reader.which().map_err(RPCError::protocol)?; let which_reader = reader.which().map_err(RPCError::protocol)?;
let out = match which_reader { let out = match which_reader {
@ -66,7 +75,7 @@ impl RPCStatementDetail {
} }
veilid_capnp::statement::detail::Route(r) => { veilid_capnp::statement::detail::Route(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationRoute::decode(&op_reader, crypto)?; let out = RPCOperationRoute::decode(&op_reader)?;
RPCStatementDetail::Route(out) RPCStatementDetail::Route(out)
} }
veilid_capnp::statement::detail::ValueChanged(r) => { veilid_capnp::statement::detail::ValueChanged(r) => {
@ -76,7 +85,7 @@ impl RPCStatementDetail {
} }
veilid_capnp::statement::detail::Signal(r) => { veilid_capnp::statement::detail::Signal(r) => {
let op_reader = r.map_err(RPCError::protocol)?; let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationSignal::decode(&op_reader, crypto)?; let out = RPCOperationSignal::decode(&op_reader)?;
RPCStatementDetail::Signal(out) RPCStatementDetail::Signal(out)
} }
veilid_capnp::statement::detail::ReturnReceipt(r) => { veilid_capnp::statement::detail::ReturnReceipt(r) => {

View File

@ -7,12 +7,12 @@ pub fn encode_peer_info(
// //
let mut nids_builder = builder.reborrow().init_node_ids( let mut nids_builder = builder.reborrow().init_node_ids(
peer_info peer_info
.node_ids .node_ids()
.len() .len()
.try_into() .try_into()
.map_err(RPCError::map_invalid_format("out of bound error"))?, .map_err(RPCError::map_invalid_format("out of bound error"))?,
); );
for (i, nid) in peer_info.node_ids.iter().enumerate() { for (i, nid) in peer_info.node_ids().iter().enumerate() {
encode_typed_key( encode_typed_key(
nid, nid,
&mut nids_builder.reborrow().get( &mut nids_builder.reborrow().get(
@ -22,15 +22,12 @@ pub fn encode_peer_info(
); );
} }
let mut sni_builder = builder.reborrow().init_signed_node_info(); let mut sni_builder = builder.reborrow().init_signed_node_info();
encode_signed_node_info(&peer_info.signed_node_info, &mut sni_builder)?; encode_signed_node_info(peer_info.signed_node_info(), &mut sni_builder)?;
Ok(()) Ok(())
} }
pub fn decode_peer_info( pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result<PeerInfo, RPCError> {
reader: &veilid_capnp::peer_info::Reader,
crypto: Crypto,
) -> Result<PeerInfo, RPCError> {
let nids_reader = reader let nids_reader = reader
.reborrow() .reborrow()
.get_node_ids() .get_node_ids()
@ -43,7 +40,7 @@ pub fn decode_peer_info(
for nid_reader in nids_reader.iter() { for nid_reader in nids_reader.iter() {
node_ids.add(decode_typed_key(&nid_reader)?); node_ids.add(decode_typed_key(&nid_reader)?);
} }
let signed_node_info = decode_signed_node_info(&sni_reader, crypto, &mut node_ids)?; let signed_node_info = decode_signed_node_info(&sni_reader)?;
if node_ids.len() == 0 { if node_ids.len() == 0 {
return Err(RPCError::protocol("no verified node ids")); return Err(RPCError::protocol("no verified node ids"));
} }

View File

@ -67,10 +67,7 @@ pub fn encode_route_hop(
Ok(()) Ok(())
} }
pub fn decode_route_hop( pub fn decode_route_hop(reader: &veilid_capnp::route_hop::Reader) -> Result<RouteHop, RPCError> {
reader: &veilid_capnp::route_hop::Reader,
crypto: Crypto,
) -> Result<RouteHop, RPCError> {
let n_reader = reader.reborrow().get_node(); let n_reader = reader.reborrow().get_node();
let node = match n_reader.which().map_err(RPCError::protocol)? { let node = match n_reader.which().map_err(RPCError::protocol)? {
veilid_capnp::route_hop::node::Which::NodeId(ni) => { veilid_capnp::route_hop::node::Which::NodeId(ni) => {
@ -80,7 +77,7 @@ pub fn decode_route_hop(
veilid_capnp::route_hop::node::Which::PeerInfo(pi) => { veilid_capnp::route_hop::node::Which::PeerInfo(pi) => {
let pi_reader = pi.map_err(RPCError::protocol)?; let pi_reader = pi.map_err(RPCError::protocol)?;
RouteNode::PeerInfo( RouteNode::PeerInfo(
decode_peer_info(&pi_reader, crypto) decode_peer_info(&pi_reader)
.map_err(RPCError::map_protocol("invalid peer info in route hop"))?, .map_err(RPCError::map_protocol("invalid peer info in route hop"))?,
) )
} }
@ -128,7 +125,6 @@ pub fn encode_private_route(
pub fn decode_private_route( pub fn decode_private_route(
reader: &veilid_capnp::private_route::Reader, reader: &veilid_capnp::private_route::Reader,
crypto: Crypto,
) -> Result<PrivateRoute, RPCError> { ) -> Result<PrivateRoute, RPCError> {
let public_key = decode_typed_key(&reader.get_public_key().map_err( let public_key = decode_typed_key(&reader.get_public_key().map_err(
RPCError::map_protocol("invalid public key in private route"), RPCError::map_protocol("invalid public key in private route"),
@ -138,7 +134,7 @@ pub fn decode_private_route(
let hops = match reader.get_hops().which().map_err(RPCError::protocol)? { let hops = match reader.get_hops().which().map_err(RPCError::protocol)? {
veilid_capnp::private_route::hops::Which::FirstHop(rh_reader) => { veilid_capnp::private_route::hops::Which::FirstHop(rh_reader) => {
let rh_reader = rh_reader.map_err(RPCError::protocol)?; let rh_reader = rh_reader.map_err(RPCError::protocol)?;
PrivateRouteHops::FirstHop(decode_route_hop(&rh_reader, crypto)?) PrivateRouteHops::FirstHop(decode_route_hop(&rh_reader)?)
} }
veilid_capnp::private_route::hops::Which::Data(rhd_reader) => { veilid_capnp::private_route::hops::Which::Data(rhd_reader) => {
let rhd_reader = rhd_reader.map_err(RPCError::protocol)?; let rhd_reader = rhd_reader.map_err(RPCError::protocol)?;
@ -182,7 +178,6 @@ pub fn encode_safety_route(
pub fn decode_safety_route( pub fn decode_safety_route(
reader: &veilid_capnp::safety_route::Reader, reader: &veilid_capnp::safety_route::Reader,
crypto: Crypto,
) -> Result<SafetyRoute, RPCError> { ) -> Result<SafetyRoute, RPCError> {
let public_key = decode_typed_key( let public_key = decode_typed_key(
&reader &reader
@ -197,7 +192,7 @@ pub fn decode_safety_route(
} }
veilid_capnp::safety_route::hops::Which::Private(pr_reader) => { veilid_capnp::safety_route::hops::Which::Private(pr_reader) => {
let pr_reader = pr_reader.map_err(RPCError::protocol)?; let pr_reader = pr_reader.map_err(RPCError::protocol)?;
SafetyRouteHops::Private(decode_private_route(&pr_reader, crypto)?) SafetyRouteHops::Private(decode_private_route(&pr_reader)?)
} }
}; };

View File

@ -34,7 +34,6 @@ pub fn encode_signal_info(
pub fn decode_signal_info( pub fn decode_signal_info(
reader: &veilid_capnp::operation_signal::Reader, reader: &veilid_capnp::operation_signal::Reader,
crypto: Crypto,
) -> Result<SignalInfo, RPCError> { ) -> Result<SignalInfo, RPCError> {
Ok( Ok(
match reader match reader
@ -53,7 +52,7 @@ pub fn decode_signal_info(
let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol( let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol(
"invalid peer info in hole punch signal info", "invalid peer info in hole punch signal info",
))?; ))?;
let peer_info = decode_peer_info(&pi_reader, crypto)?; let peer_info = decode_peer_info(&pi_reader)?;
SignalInfo::HolePunch { receipt, peer_info } SignalInfo::HolePunch { receipt, peer_info }
} }
@ -69,7 +68,7 @@ pub fn decode_signal_info(
let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol( let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol(
"invalid peer info in reverse connect signal info", "invalid peer info in reverse connect signal info",
))?; ))?;
let peer_info = decode_peer_info(&pi_reader, crypto)?; let peer_info = decode_peer_info(&pi_reader)?;
SignalInfo::ReverseConnect { receipt, peer_info } SignalInfo::ReverseConnect { receipt, peer_info }
} }

View File

@ -6,20 +6,20 @@ pub fn encode_signed_direct_node_info(
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
// //
let mut ni_builder = builder.reborrow().init_node_info(); let mut ni_builder = builder.reborrow().init_node_info();
encode_node_info(&signed_direct_node_info.node_info, &mut ni_builder)?; encode_node_info(signed_direct_node_info.node_info(), &mut ni_builder)?;
builder builder
.reborrow() .reborrow()
.set_timestamp(signed_direct_node_info.timestamp.into()); .set_timestamp(signed_direct_node_info.timestamp().into());
let mut sigs_builder = builder.reborrow().init_signatures( let mut sigs_builder = builder.reborrow().init_signatures(
signed_direct_node_info signed_direct_node_info
.signatures .signatures()
.len() .len()
.try_into() .try_into()
.map_err(RPCError::map_invalid_format("out of bound error"))?, .map_err(RPCError::map_invalid_format("out of bound error"))?,
); );
for (i, typed_signature) in signed_direct_node_info.signatures.iter().enumerate() { for (i, typed_signature) in signed_direct_node_info.signatures().iter().enumerate() {
encode_typed_signature( encode_typed_signature(
typed_signature, typed_signature,
&mut sigs_builder.reborrow().get( &mut sigs_builder.reborrow().get(
@ -34,8 +34,6 @@ pub fn encode_signed_direct_node_info(
pub fn decode_signed_direct_node_info( pub fn decode_signed_direct_node_info(
reader: &veilid_capnp::signed_direct_node_info::Reader, reader: &veilid_capnp::signed_direct_node_info::Reader,
crypto: Crypto,
node_ids: &mut TypedKeySet,
) -> Result<SignedDirectNodeInfo, RPCError> { ) -> Result<SignedDirectNodeInfo, RPCError> {
let ni_reader = reader let ni_reader = reader
.reborrow() .reborrow()
@ -61,6 +59,9 @@ pub fn decode_signed_direct_node_info(
typed_signatures.push(typed_signature); typed_signatures.push(typed_signature);
} }
SignedDirectNodeInfo::new(crypto, node_ids, node_info, timestamp, typed_signatures) Ok(SignedDirectNodeInfo::new(
.map_err(RPCError::protocol) node_info,
timestamp,
typed_signatures,
))
} }

View File

@ -20,8 +20,6 @@ pub fn encode_signed_node_info(
pub fn decode_signed_node_info( pub fn decode_signed_node_info(
reader: &veilid_capnp::signed_node_info::Reader, reader: &veilid_capnp::signed_node_info::Reader,
crypto: Crypto,
node_ids: &mut TypedKeySet,
) -> Result<SignedNodeInfo, RPCError> { ) -> Result<SignedNodeInfo, RPCError> {
match reader match reader
.which() .which()
@ -29,12 +27,12 @@ pub fn decode_signed_node_info(
{ {
veilid_capnp::signed_node_info::Direct(d) => { veilid_capnp::signed_node_info::Direct(d) => {
let d_reader = d.map_err(RPCError::protocol)?; let d_reader = d.map_err(RPCError::protocol)?;
let sdni = decode_signed_direct_node_info(&d_reader, crypto, node_ids)?; let sdni = decode_signed_direct_node_info(&d_reader)?;
Ok(SignedNodeInfo::Direct(sdni)) Ok(SignedNodeInfo::Direct(sdni))
} }
veilid_capnp::signed_node_info::Relayed(r) => { veilid_capnp::signed_node_info::Relayed(r) => {
let r_reader = r.map_err(RPCError::protocol)?; let r_reader = r.map_err(RPCError::protocol)?;
let srni = decode_signed_relayed_node_info(&r_reader, crypto, node_ids)?; let srni = decode_signed_relayed_node_info(&r_reader)?;
Ok(SignedNodeInfo::Relayed(srni)) Ok(SignedNodeInfo::Relayed(srni))
} }
} }

View File

@ -6,16 +6,16 @@ pub fn encode_signed_relayed_node_info(
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
// //
let mut ni_builder = builder.reborrow().init_node_info(); let mut ni_builder = builder.reborrow().init_node_info();
encode_node_info(&signed_relayed_node_info.node_info, &mut ni_builder)?; encode_node_info(signed_relayed_node_info.node_info(), &mut ni_builder)?;
let mut rids_builder = builder.reborrow().init_relay_ids( let mut rids_builder = builder.reborrow().init_relay_ids(
signed_relayed_node_info signed_relayed_node_info
.relay_ids .relay_ids()
.len() .len()
.try_into() .try_into()
.map_err(RPCError::map_invalid_format("out of bound error"))?, .map_err(RPCError::map_invalid_format("out of bound error"))?,
); );
for (i, typed_key) in signed_relayed_node_info.relay_ids.iter().enumerate() { for (i, typed_key) in signed_relayed_node_info.relay_ids().iter().enumerate() {
encode_typed_key( encode_typed_key(
typed_key, typed_key,
&mut rids_builder.reborrow().get( &mut rids_builder.reborrow().get(
@ -26,20 +26,20 @@ pub fn encode_signed_relayed_node_info(
} }
let mut ri_builder = builder.reborrow().init_relay_info(); let mut ri_builder = builder.reborrow().init_relay_info();
encode_signed_direct_node_info(&signed_relayed_node_info.relay_info, &mut ri_builder)?; encode_signed_direct_node_info(signed_relayed_node_info.relay_info(), &mut ri_builder)?;
builder builder
.reborrow() .reborrow()
.set_timestamp(signed_relayed_node_info.timestamp.into()); .set_timestamp(signed_relayed_node_info.timestamp().into());
let mut sigs_builder = builder.reborrow().init_signatures( let mut sigs_builder = builder.reborrow().init_signatures(
signed_relayed_node_info signed_relayed_node_info
.signatures .signatures()
.len() .len()
.try_into() .try_into()
.map_err(RPCError::map_invalid_format("out of bound error"))?, .map_err(RPCError::map_invalid_format("out of bound error"))?,
); );
for (i, typed_signature) in signed_relayed_node_info.signatures.iter().enumerate() { for (i, typed_signature) in signed_relayed_node_info.signatures().iter().enumerate() {
encode_typed_signature( encode_typed_signature(
typed_signature, typed_signature,
&mut sigs_builder.reborrow().get( &mut sigs_builder.reborrow().get(
@ -54,8 +54,6 @@ pub fn encode_signed_relayed_node_info(
pub fn decode_signed_relayed_node_info( pub fn decode_signed_relayed_node_info(
reader: &veilid_capnp::signed_relayed_node_info::Reader, reader: &veilid_capnp::signed_relayed_node_info::Reader,
crypto: Crypto,
node_ids: &mut TypedKeySet,
) -> Result<SignedRelayedNodeInfo, RPCError> { ) -> Result<SignedRelayedNodeInfo, RPCError> {
let ni_reader = reader let ni_reader = reader
.reborrow() .reborrow()
@ -81,20 +79,7 @@ pub fn decode_signed_relayed_node_info(
.reborrow() .reborrow()
.get_relay_info() .get_relay_info()
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
let relay_info = decode_signed_direct_node_info(&ri_reader, crypto.clone(), &mut relay_ids)?; let relay_info = decode_signed_direct_node_info(&ri_reader)?;
// Ensure the relay info for the node has a superset of the crypto kinds of the node it is relaying
if common_crypto_kinds(
&node_info.crypto_support,
&relay_info.node_info.crypto_support,
)
.len()
!= node_info.crypto_support.len()
{
return Err(RPCError::protocol(
"relay should have superset of node crypto kinds",
));
}
let timestamp = reader.reborrow().get_timestamp().into(); let timestamp = reader.reborrow().get_timestamp().into();
@ -113,14 +98,11 @@ pub fn decode_signed_relayed_node_info(
let typed_signature = decode_typed_signature(&sig_reader)?; let typed_signature = decode_typed_signature(&sig_reader)?;
typed_signatures.push(typed_signature); typed_signatures.push(typed_signature);
} }
SignedRelayedNodeInfo::new( Ok(SignedRelayedNodeInfo::new(
crypto,
node_ids,
node_info, node_info,
relay_ids, relay_ids,
relay_info, relay_info,
timestamp, timestamp,
typed_signatures, typed_signatures,
) ))
.map_err(RPCError::protocol)
} }

View File

@ -16,7 +16,7 @@ pub fn encode_signed_value_data(
pub fn decode_signed_value_data( pub fn decode_signed_value_data(
reader: &veilid_capnp::signed_value_data::Reader, reader: &veilid_capnp::signed_value_data::Reader,
) -> Result<ValueData, RPCError> { ) -> Result<SignedValueData, RPCError> {
let seq = reader.get_seq(); let seq = reader.get_seq();
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec(); let data = reader.get_data().map_err(RPCError::protocol)?.to_vec();
let wr = reader.get_writer().map_err(RPCError::protocol)?; let wr = reader.get_writer().map_err(RPCError::protocol)?;
@ -24,8 +24,8 @@ pub fn decode_signed_value_data(
let sr = reader.get_signature().map_err(RPCError::protocol)?; let sr = reader.get_signature().map_err(RPCError::protocol)?;
let signature = decode_signature512(&sr); let signature = decode_signature512(&sr);
Ok(SignedValueData { Ok(SignedValueData::new(
value_data: ValueData { seq, data, writer }, ValueData::new_with_seq(seq, data, writer),
signature, signature,
}) ))
} }

View File

@ -7,7 +7,7 @@ pub fn encode_signed_value_descriptor(
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
let mut ob = builder.reborrow().init_owner(); let mut ob = builder.reborrow().init_owner();
encode_key256(signed_value_descriptor.owner(), &mut ob); encode_key256(signed_value_descriptor.owner(), &mut ob);
builder.set_data(signed_value_descriptor.data()); builder.set_schema_data(signed_value_descriptor.schema_data());
let mut sb = builder.reborrow().init_signature(); let mut sb = builder.reborrow().init_signature();
encode_signature512(signed_value_descriptor.signature(), &mut sb); encode_signature512(signed_value_descriptor.signature(), &mut sb);
Ok(()) Ok(())
@ -15,12 +15,14 @@ pub fn encode_signed_value_descriptor(
pub fn decode_signed_value_descriptor( pub fn decode_signed_value_descriptor(
reader: &veilid_capnp::signed_value_descriptor::Reader, reader: &veilid_capnp::signed_value_descriptor::Reader,
vcrypto: CryptoSystemVersion,
) -> Result<SignedValueDescriptor, RPCError> { ) -> Result<SignedValueDescriptor, RPCError> {
let or = reader.get_owner().map_err(RPCError::protocol)?; let or = reader.get_owner().map_err(RPCError::protocol)?;
let owner = decode_key256(&or); let owner = decode_key256(&or);
let data = reader.get_data().map_err(RPCError::protocol)?.to_vec(); let schema_data = reader
.get_schema_data()
.map_err(RPCError::protocol)?
.to_vec();
let sr = reader.get_signature().map_err(RPCError::protocol)?; let sr = reader.get_signature().map_err(RPCError::protocol)?;
let signature = decode_signature512(&sr); let signature = decode_signature512(&sr);
Ok(SignedValueDescriptor::new(owner, data, signature, vcrypto).map_err(RPCError::protocol)?) Ok(SignedValueDescriptor::new(owner, schema_data, signature))
} }

View File

@ -6,13 +6,31 @@ pub fn encode_value_detail(
builder: &mut veilid_capnp::value_detail::Builder, builder: &mut veilid_capnp::value_detail::Builder,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
let mut svdb = builder.reborrow().init_signed_value_data(); let mut svdb = builder.reborrow().init_signed_value_data();
encode_signed_value_data(value_detail.signed_value_data(), &mut svdb)?;
if let Some(descriptor) = value_detail.descriptor() {
let mut db = builder.reborrow().init_descriptor();
encode_signed_value_descriptor(descriptor, &mut db)?;
}
Ok(()) Ok(())
} }
pub fn decode_value_detail( pub fn decode_value_detail(
reader: &veilid_capnp::value_detail::Reader, reader: &veilid_capnp::value_detail::Reader,
) -> Result<ValueDetail, RPCError> { ) -> Result<ValueDetail, RPCError> {
let svdr = reader.get_signed_value_data().map_err(RPCError::protocol)?;
let signed_value_data = decode_signed_value_data(&svdr)?;
let descriptor = if reader.has_descriptor() {
let dr = reader
.reborrow()
.get_descriptor()
.map_err(RPCError::protocol)?;
let descriptor = decode_signed_value_descriptor(&dr)?;
Some(descriptor)
} else {
None
};
Ok(ValueDetail { Ok(ValueDetail {
signed_value_data, signed_value_data,
descriptor, descriptor,

View File

@ -753,7 +753,7 @@ impl RPCProcessor {
}; };
// Get our node info timestamp // Get our node info timestamp
let our_node_info_ts = own_peer_info.signed_node_info.timestamp(); let our_node_info_ts = own_peer_info.signed_node_info().timestamp();
// If the target has seen our node info already don't send it again // If the target has seen our node info already don't send it again
if target.has_seen_our_node_info_ts(routing_domain, our_node_info_ts) { if target.has_seen_our_node_info_ts(routing_domain, our_node_info_ts) {
@ -1214,16 +1214,19 @@ impl RPCProcessor {
.get_root::<veilid_capnp::operation::Reader>() .get_root::<veilid_capnp::operation::Reader>()
.map_err(RPCError::protocol) .map_err(RPCError::protocol)
.map_err(logthru_rpc!())?; .map_err(logthru_rpc!())?;
RPCOperation::decode(&op_reader, self.crypto.clone())? RPCOperation::decode(&op_reader)?
}; };
// Validate the RPC operation
operation.validate(self.crypto.clone())?;
// Get the sender noderef, incorporating sender's peer info // Get the sender noderef, incorporating sender's peer info
let mut opt_sender_nr: Option<NodeRef> = None; let mut opt_sender_nr: Option<NodeRef> = None;
if let Some(sender_peer_info) = operation.sender_peer_info() { if let Some(sender_peer_info) = operation.sender_peer_info() {
// Ensure the sender peer info is for the actual sender specified in the envelope // Ensure the sender peer info is for the actual sender specified in the envelope
// Sender PeerInfo was specified, update our routing table with it // Sender PeerInfo was specified, update our routing table with it
if !self.filter_node_info(routing_domain, &sender_peer_info.signed_node_info) { if !self.filter_node_info(routing_domain, sender_peer_info.signed_node_info()) {
return Err(RPCError::invalid_format( return Err(RPCError::invalid_format(
"sender peerinfo has invalid peer scope", "sender peerinfo has invalid peer scope",
)); ));
@ -1261,9 +1264,12 @@ impl RPCProcessor {
.get_root::<veilid_capnp::operation::Reader>() .get_root::<veilid_capnp::operation::Reader>()
.map_err(RPCError::protocol) .map_err(RPCError::protocol)
.map_err(logthru_rpc!())?; .map_err(logthru_rpc!())?;
RPCOperation::decode(&op_reader, self.crypto.clone())? RPCOperation::decode(&op_reader)?
}; };
// Validate the RPC operation
operation.validate(self.crypto.clone())?;
// Make the RPC message // Make the RPC message
RPCMessage { RPCMessage {
header: encoded_msg.header, header: encoded_msg.header,

View File

@ -52,7 +52,7 @@ impl RPCProcessor {
// Verify peers are in the correct peer scope // Verify peers are in the correct peer scope
for peer_info in &find_node_a.peers { for peer_info in &find_node_a.peers {
if !self.filter_node_info(RoutingDomain::PublicInternet, &peer_info.signed_node_info) { if !self.filter_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
return Err(RPCError::invalid_format( return Err(RPCError::invalid_format(
"find_node response has invalid peer scope", "find_node response has invalid peer scope",
)); ));

View File

@ -341,8 +341,11 @@ impl RPCProcessor {
let rh_reader = dec_blob_reader let rh_reader = dec_blob_reader
.get_root::<veilid_capnp::route_hop::Reader>() .get_root::<veilid_capnp::route_hop::Reader>()
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
decode_route_hop(&rh_reader, self.crypto.clone())? decode_route_hop(&rh_reader)?
}; };
// Validate the RouteHop
route_hop.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
// Sign the operation if this is not our last hop // Sign the operation if this is not our last hop
// as the last hop is already signed by the envelope // as the last hop is already signed by the envelope
@ -422,8 +425,11 @@ impl RPCProcessor {
let pr_reader = dec_blob_reader let pr_reader = dec_blob_reader
.get_root::<veilid_capnp::private_route::Reader>() .get_root::<veilid_capnp::private_route::Reader>()
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
decode_private_route(&pr_reader, self.crypto.clone())? decode_private_route(&pr_reader)?
}; };
// Validate the private route
private_route.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
// Switching from full safety route to private route first hop // Switching from full safety route to private route first hop
network_result_try!( network_result_try!(
@ -440,9 +446,12 @@ impl RPCProcessor {
let rh_reader = dec_blob_reader let rh_reader = dec_blob_reader
.get_root::<veilid_capnp::route_hop::Reader>() .get_root::<veilid_capnp::route_hop::Reader>()
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
decode_route_hop(&rh_reader, self.crypto.clone())? decode_route_hop(&rh_reader)?
}; };
// Validate the route hop
route_hop.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
// Continue the full safety route with another hop // Continue the full safety route with another hop
network_result_try!( network_result_try!(
self.process_route_safety_route_hop( self.process_route_safety_route_hop(

View File

@ -3,9 +3,7 @@ mod record;
mod record_data; mod record_data;
mod record_store; mod record_store;
mod record_store_limits; mod record_store_limits;
mod signed_value_data; mod types;
mod signed_value_descriptor;
mod value_detail;
use keys::*; use keys::*;
use record::*; use record::*;
@ -13,9 +11,7 @@ use record_data::*;
use record_store::*; use record_store::*;
use record_store_limits::*; use record_store_limits::*;
pub use signed_value_data::*; pub use types::*;
pub use signed_value_descriptor::*;
pub use value_detail::*;
use super::*; use super::*;
use crate::rpc_processor::*; use crate::rpc_processor::*;
@ -174,14 +170,15 @@ impl StorageManager {
&self, &self,
vcrypto: CryptoSystemVersion, vcrypto: CryptoSystemVersion,
record: Record, record: Record,
) -> Result<(), VeilidAPIError> { ) -> Result<TypedKey, VeilidAPIError> {
// add value record to record store // add value record to record store
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
let Some(local_record_store) = inner.local_record_store.as_mut() else { let Some(local_record_store) = inner.local_record_store.as_mut() else {
apibail_generic!("not initialized"); apibail_generic!("not initialized");
}; };
let key = self.get_key(vcrypto.clone(), &record); let key = self.get_key(vcrypto.clone(), &record);
local_record_store.new_record(key, record).await local_record_store.new_record(key, record).await?;
Ok(key)
} }
pub async fn create_record( pub async fn create_record(
@ -202,22 +199,27 @@ impl StorageManager {
let owner = vcrypto.generate_keypair(); let owner = vcrypto.generate_keypair();
// Make a signed value descriptor for this dht value // Make a signed value descriptor for this dht value
let signed_value_descriptor = SignedValueDescriptor::new(owner.key, ) let signed_value_descriptor = SignedValueDescriptor::make_signature(
owner.key,
schema_data,
vcrypto.clone(),
owner.secret,
)?;
// Add new local value record // Add new local value record
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
let record = Record::new( let record = Record::new(
cur_ts, cur_ts,
owner.key, signed_value_descriptor,
Some(owner.secret), Some(owner.secret),
schema,
safety_selection, safety_selection,
); )?;
self.new_local_record(vcrypto.clone(), record) let dht_key = self
.new_local_record(vcrypto, record)
.await .await
.map_err(VeilidAPIError::internal)?; .map_err(VeilidAPIError::internal)?;
Ok(key) Ok(dht_key)
} }
pub async fn open_record( pub async fn open_record(

View File

@ -0,0 +1,9 @@
mod signed_value_data;
mod signed_value_descriptor;
mod value_detail;
use super::*;
pub use signed_value_data::*;
pub use signed_value_descriptor::*;
pub use value_detail::*;

View File

@ -24,31 +24,32 @@ pub struct SignedValueData {
signature: Signature, signature: Signature,
} }
impl SignedValueData { impl SignedValueData {
pub fn new( pub fn new(value_data: ValueData, signature: Signature) -> Self {
value_data: ValueData, Self {
owner: PublicKey,
subkey: ValueSubkey,
signature: Signature,
vcrypto: CryptoSystemVersion,
) -> Result<Self, VeilidAPIError> {
let node_info_bytes = Self::make_signature_bytes(&value_data, &owner, subkey)?;
// validate signature
vcrypto.verify(&value_data.writer(), &node_info_bytes, &signature)?;
Ok(Self {
value_data, value_data,
signature, signature,
}) }
}
pub fn validate(
&self,
owner: &PublicKey,
subkey: ValueSubkey,
vcrypto: CryptoSystemVersion,
) -> Result<(), VeilidAPIError> {
let node_info_bytes = Self::make_signature_bytes(&self.value_data, owner, subkey)?;
// validate signature
vcrypto.verify(&self.value_data.writer(), &node_info_bytes, &self.signature)
} }
pub fn make_signature( pub fn make_signature(
value_data: ValueData, value_data: ValueData,
owner: PublicKey, owner: &PublicKey,
subkey: ValueSubkey, subkey: ValueSubkey,
vcrypto: CryptoSystemVersion, vcrypto: CryptoSystemVersion,
writer_secret: SecretKey, writer_secret: SecretKey,
) -> Result<Self, VeilidAPIError> { ) -> Result<Self, VeilidAPIError> {
let node_info_bytes = Self::make_signature_bytes(&value_data, &owner, subkey)?; let node_info_bytes = Self::make_signature_bytes(&value_data, owner, subkey)?;
// create signature // create signature
let signature = vcrypto.sign(&value_data.writer(), &writer_secret, &node_info_bytes)?; let signature = vcrypto.sign(&value_data.writer(), &writer_secret, &node_info_bytes)?;

View File

@ -25,20 +25,17 @@ pub struct SignedValueDescriptor {
signature: Signature, signature: Signature,
} }
impl SignedValueDescriptor { impl SignedValueDescriptor {
pub fn new( pub fn new(owner: PublicKey, schema_data: Vec<u8>, signature: Signature) -> Self {
owner: PublicKey, Self {
schema_data: Vec<u8>,
signature: Signature,
vcrypto: CryptoSystemVersion,
) -> Result<Self, VeilidAPIError> {
// validate signature
vcrypto.verify(&owner, &schema_data, &signature)?;
Ok(Self {
owner, owner,
schema_data, schema_data,
signature, signature,
}) }
}
pub fn validate(&self, vcrypto: CryptoSystemVersion) -> Result<(), VeilidAPIError> {
// validate signature
vcrypto.verify(&self.owner, &self.schema_data, &self.signature)
} }
pub fn owner(&self) -> &PublicKey { pub fn owner(&self) -> &PublicKey {
@ -75,4 +72,12 @@ impl SignedValueDescriptor {
pub fn total_size(&self) -> usize { pub fn total_size(&self) -> usize {
mem::size_of::<Self>() + self.schema_data.len() mem::size_of::<Self>() + self.schema_data.len()
} }
pub fn cmp_no_sig(&self, other: &Self) -> cmp::Ordering {
let o = self.owner.cmp(&other.owner);
if o != cmp::Ordering::Equal {
return o;
}
self.schema_data.cmp(&other.schema_data)
}
} }

View File

@ -0,0 +1,77 @@
use super::*;
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
use serde::*;
/////////////////////////////////////////////////////////////////////////////////////////////////////
///
#[derive(
Clone,
Debug,
PartialOrd,
PartialEq,
Eq,
Ord,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct ValueDetail {
signed_value_data: SignedValueData,
descriptor: Option<SignedValueDescriptor>,
}
impl ValueDetail {
pub fn new(
signed_value_data: SignedValueData,
descriptor: Option<SignedValueDescriptor>,
) -> Self {
Self {
signed_value_data,
descriptor,
}
}
pub fn validate(
&self,
last_descriptor: Option<&SignedValueDescriptor>,
subkey: ValueSubkey,
vcrypto: CryptoSystemVersion,
) -> Result<(), VeilidAPIError> {
// Get descriptor to validate with
let descriptor = if let Some(descriptor) = &self.descriptor {
if let Some(last_descriptor) = last_descriptor {
if descriptor.cmp_no_sig(&last_descriptor) != cmp::Ordering::Equal {
return Err(VeilidAPIError::generic(
"value detail descriptor does not match last descriptor",
));
}
}
descriptor
} else {
let Some(descriptor) = last_descriptor else {
return Err(VeilidAPIError::generic(
"no last descriptor, requires a descriptor",
));
};
descriptor
};
// Ensure the descriptor itself validates
descriptor.validate(vcrypto.clone())?;
// And the signed value data
self.signed_value_data
.validate(descriptor.owner(), subkey, vcrypto)
}
pub fn signed_value_data(&self) -> &SignedValueData {
&self.signed_value_data
}
pub fn descriptor(&self) -> Option<&SignedValueDescriptor> {
self.descriptor.as_ref()
}
}

View File

@ -1,43 +0,0 @@
use super::*;
use rkyv::{Archive as RkyvArchive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
use serde::*;
/////////////////////////////////////////////////////////////////////////////////////////////////////
///
#[derive(
Clone,
Debug,
PartialOrd,
PartialEq,
Eq,
Ord,
Serialize,
Deserialize,
RkyvArchive,
RkyvSerialize,
RkyvDeserialize,
)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct ValueDetail {
signed_value_data: SignedValueData,
descriptor: Option<SignedValueDescriptor>,
}
impl ValueDetail {
pub fn new(
signed_value_data: SignedValueData,
descriptor: Option<SignedValueDescriptor>,
) -> Self {
Self {
signed_value_data,
descriptor,
}
}
pub fn signed_value_data(&self) -> &SignedValueData {
&self.signed_value_data
}
pub fn descriptor(&self) -> Option<&SignedValueDescriptor> {
self.descriptor.as_ref()
}
}