checkpoint
This commit is contained in:
parent
c330faa4fa
commit
b3c55f4a6d
@ -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> {
|
||||||
|
@ -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)?
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user