checkpoint

This commit is contained in:
John Smith 2023-02-26 21:27:16 -05:00
parent c330faa4fa
commit b3c55f4a6d
3 changed files with 66 additions and 38 deletions

View File

@ -90,6 +90,14 @@ impl RouteSetSpecDetail {
Sequencing::EnsureOrdered => self.can_do_sequenced, Sequencing::EnsureOrdered => self.can_do_sequenced,
} }
} }
pub fn contains_nodes(&self, nodes: &[TypedKey]) -> bool {
for h in self.hop_node_refs {
if h.node_ids().contains_any(nodes) {
return true;
}
}
false
}
/// Generate a key for the cache that can be used to uniquely identify this route's contents /// Generate a key for the cache that can be used to uniquely identify this route's contents
pub fn make_cache_key(&self) -> Vec<u8> { pub fn make_cache_key(&self) -> Vec<u8> {

View File

@ -537,7 +537,7 @@ impl RouteSpecStore {
last_hop_id: PublicKey, last_hop_id: PublicKey,
callback: F, callback: F,
) -> Option<R> ) -> Option<R>
where F: FnOnce(&RouteSpecDetail) -> R, where F: FnOnce(&RouteSetSpecDetail, &RouteSpecDetail) -> R,
R: fmt::Debug, R: fmt::Debug,
{ {
let inner = &*self.inner.lock(); let inner = &*self.inner.lock();
@ -585,7 +585,7 @@ impl RouteSpecStore {
} }
} }
// We got the correct signatures, return a key and response safety spec // We got the correct signatures, return a key and response safety spec
Some(callback(rsd)) Some(callback(rssd, rsd))
} }
#[instrument(level = "trace", skip(self), ret, err)] #[instrument(level = "trace", skip(self), ret, err)]
@ -593,15 +593,22 @@ impl RouteSpecStore {
// Make loopback route to test with // Make loopback route to test with
let dest = { let dest = {
// Match the private route's hop length for safety route length // Get the best private route for this id
let hop_count = { let (key, hop_count) = {
let inner = &mut *self.inner.lock(); let inner = &mut *self.inner.lock();
let Some(rssd) = inner.content.get_detail(&private_route_id) else { let Some(rssd) = inner.content.get_detail(&private_route_id) else {
bail!("route id not allocated"); bail!("route id not allocated");
}; };
rssd.hop_count() let Some(key) = rssd.get_best_route_set_key() else {
bail!("no best key to test allocated route");
};
// Match the private route's hop length for safety route length
let hop_count = rssd.hop_count();
(key, hop_count)
}; };
// Get the private route to send to
let private_route = self.assemble_private_route(&key, None)?;
// Always test routes with safety routes that are more likely to succeed // Always test routes with safety routes that are more likely to succeed
let stability = Stability::Reliable; let stability = Stability::Reliable;
// Routes can test with whatever sequencing they were allocated with // Routes can test with whatever sequencing they were allocated with
@ -639,6 +646,12 @@ impl RouteSpecStore {
// Make private route test // Make private route test
let dest = { let dest = {
// Get the route to test
let Some(private_route) = self.best_remote_private_route(&private_route_id) else {
bail!("no best key to test remote route");
};
// Get a safety route that is good enough // Get a safety route that is good enough
let safety_spec = SafetySpec { let safety_spec = SafetySpec {
preferred_route: None, preferred_route: None,
@ -722,7 +735,7 @@ impl RouteSpecStore {
stability: Stability, stability: Stability,
sequencing: Sequencing, sequencing: Sequencing,
directions: DirectionSet, directions: DirectionSet,
avoid_node_ids: &[PublicKey], avoid_nodes: &[TypedKey],
) -> Option<PublicKey> { ) -> Option<PublicKey> {
let cur_ts = get_aligned_timestamp(); let cur_ts = get_aligned_timestamp();
@ -740,7 +753,7 @@ impl RouteSpecStore {
{ {
let mut avoid = false; let mut avoid = false;
for h in &detail.1.hops { for h in &detail.1.hops {
if avoid_node_ids.contains(h) { if avoid_nodes.contains(h) {
avoid = true; avoid = true;
break; break;
} }
@ -1054,7 +1067,7 @@ impl RouteSpecStore {
Ok(Some(compiled_route)) Ok(Some(compiled_route))
} }
/// Get a route that matches a particular safety spec /// Get an allocated route that matches a particular safety spec
#[instrument(level = "trace", skip(self, inner, rti), ret, err)] #[instrument(level = "trace", skip(self, inner, rti), ret, err)]
fn get_route_for_safety_spec_inner( fn get_route_for_safety_spec_inner(
&self, &self,
@ -1076,12 +1089,12 @@ impl RouteSpecStore {
// See if the preferred route is here // See if the preferred route is here
if let Some(preferred_route) = safety_spec.preferred_route { if let Some(preferred_route) = safety_spec.preferred_route {
if let Some(preferred_rsd) = inner.content.details.get(&preferred_route) { if let Some(preferred_rssd) = inner.content.get_detail(&preferred_route) {
// Only use the preferred route if it has the desire crypto kind // Only use the preferred route if it has the desire crypto kind
if preferred_rsd.crypto_kind == crypto_kind { if let Some(preferred_key) = preferred_rssd.get_route_set_keys().get(crypto_kind) {
// Only use the preferred route if it doesn't end with the avoid nodes // Only use the preferred route if it doesn't contain the avoid nodes
if !avoid_nodes.contains(&TypedKey::new(crypto_kind, preferred_rsd.hops.last().cloned().unwrap())) { if !preferred_rssd.contains_nodes(avoid_nodes) {
return Ok(Some(preferred_route)); return Ok(Some(preferred_key.key));
} }
} }
} }
@ -1095,7 +1108,7 @@ impl RouteSpecStore {
safety_spec.stability, safety_spec.stability,
safety_spec.sequencing, safety_spec.sequencing,
direction, direction,
avoid_node_ids, avoid_nodes,
) { ) {
// Found a route to use // Found a route to use
sr_pubkey sr_pubkey
@ -1105,11 +1118,12 @@ impl RouteSpecStore {
.allocate_route_inner( .allocate_route_inner(
inner, inner,
rti, rti,
crypto_kind, ???
safety_spec.stability, safety_spec.stability,
safety_spec.sequencing, safety_spec.sequencing,
safety_spec.hop_count, safety_spec.hop_count,
direction, direction,
avoid_node_ids, avoid_nodes,
) )
.map_err(RPCError::internal)? .map_err(RPCError::internal)?
{ {

View File

@ -194,7 +194,7 @@ impl RPCProcessor {
sender_id, sender_id,
|rsd| { |rsd| {
( (
rsd.get_secret_key(), rsd.secret_key,
SafetySpec { SafetySpec {
preferred_route: Some(pr_pubkey), preferred_route: Some(pr_pubkey),
hop_count: rsd.hop_count(), hop_count: rsd.hop_count(),
@ -243,7 +243,7 @@ impl RPCProcessor {
// If the private route public key is our node id, then this was sent via safety route to our node directly // If the private route public key is our node id, then this was sent via safety route to our node directly
// so there will be no signatures to validate // so there will be no signatures to validate
if pr_pubkey == self.routing_table.node_id() { if self.routing_table.node_ids().contains(&pr_pubkey) {
// The private route was a stub // The private route was a stub
self.process_safety_routed_operation(detail, routed_operation, remote_sr_pubkey) self.process_safety_routed_operation(detail, routed_operation, remote_sr_pubkey)
} else { } else {
@ -314,13 +314,20 @@ impl RPCProcessor {
/// Decrypt route hop data and sign routed operation /// Decrypt route hop data and sign routed operation
pub(crate) fn decrypt_private_route_hop_data(&self, route_hop_data: &RouteHopData, pr_pubkey: &TypedKey, route_operation: &mut RoutedOperation) -> Result<NetworkResult<RouteHop>, RPCError> pub(crate) fn decrypt_private_route_hop_data(&self, route_hop_data: &RouteHopData, pr_pubkey: &TypedKey, route_operation: &mut RoutedOperation) -> Result<NetworkResult<RouteHop>, RPCError>
{ {
// Get crypto kind
let crypto_kind = pr_pubkey.kind;
let Some(vcrypto) = self.crypto.get(crypto_kind) else {
return Ok(NetworkResult::invalid_message(
"private route hop data crypto is not supported",
));
};
// Decrypt the blob with DEC(nonce, DH(the PR's public key, this hop's secret) // Decrypt the blob with DEC(nonce, DH(the PR's public key, this hop's secret)
let node_id_secret = self.routing_table.node_id_secret(); let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
let dh_secret = self let dh_secret = vcrypto
.crypto .cached_dh(&pr_pubkey.key, &node_id_secret)
.cached_dh(&pr_pubkey, &node_id_secret)
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
let dec_blob_data = match Crypto::decrypt_aead( let dec_blob_data = match vcrypto.decrypt_aead(
&route_hop_data.blob, &route_hop_data.blob,
&route_hop_data.nonce, &route_hop_data.nonce,
&dh_secret, &dh_secret,
@ -338,15 +345,15 @@ 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)? decode_route_hop(&rh_reader, self.crypto.clone())?
}; };
// 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
if route_hop.next_hop.is_some() { if route_hop.next_hop.is_some() {
let node_id = self.routing_table.node_id(); let node_id = self.routing_table.node_id(crypto_kind);
let node_id_secret = self.routing_table.node_id_secret(); let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
let sig = sign(&node_id, &node_id_secret, &route_operation.data) let sig = vcrypto.sign(&node_id.key, &node_id_secret, &route_operation.data)
.map_err(RPCError::internal)?; .map_err(RPCError::internal)?;
route_operation.signatures.push(sig); route_operation.signatures.push(sig);
} }
@ -378,25 +385,24 @@ impl RPCProcessor {
_ => panic!("not a statement"), _ => panic!("not a statement"),
}; };
// Process routed operation version // Get crypto kind
// xxx switch this to a Crypto trait factory method per issue#140 let crypto_kind = route.safety_route.crypto_kind();
if route.operation.version != MAX_CRYPTO_VERSION { let Some(vcrypto) = self.crypto.get(crypto_kind) else {
return Ok(NetworkResult::invalid_message( return Ok(NetworkResult::invalid_message(
"routes operation crypto is not valid version", "routed operation crypto is not supported",
)); ));
} };
// See what kind of safety route we have going on here // See what kind of safety route we have going on here
match route.safety_route.hops { match route.safety_route.hops {
// There is a safety route hop // There is a safety route hop
SafetyRouteHops::Data(ref route_hop_data) => { SafetyRouteHops::Data(ref route_hop_data) => {
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret) // Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
let node_id_secret = self.routing_table.node_id_secret(); let node_id_secret = self.routing_table.node_id_secret(crypto_kind);
let dh_secret = self let dh_secret = vcrypto
.crypto .cached_dh(&route.safety_route.public_key.key, &node_id_secret)
.cached_dh(&route.safety_route.public_key, &node_id_secret)
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
let mut dec_blob_data = Crypto::decrypt_aead(&route_hop_data.blob, &route_hop_data.nonce, &dh_secret, None) let mut dec_blob_data = vcrypto.decrypt_aead(&route_hop_data.blob, &route_hop_data.nonce, &dh_secret, None)
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
// See if this is last hop in safety route, if so, we're decoding a PrivateRoute not a RouteHop // See if this is last hop in safety route, if so, we're decoding a PrivateRoute not a RouteHop
@ -413,7 +419,7 @@ 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)? decode_private_route(&pr_reader, self.crypto.clone())?
}; };
// Switching from full safety route to private route first hop // Switching from full safety route to private route first hop
@ -429,7 +435,7 @@ 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)? decode_route_hop(&rh_reader, self.crypto.clone())?
}; };
// Continue the full safety route with another hop // Continue the full safety route with another hop