checkpoint

This commit is contained in:
John Smith 2022-10-20 15:09:04 -04:00
parent 6d5df71ac1
commit fc6eb6e84a
3 changed files with 119 additions and 60 deletions

View File

@ -17,9 +17,9 @@ pub struct SafetySpec {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CompiledRoute { pub struct CompiledRoute {
/// The safety route attached to the private route /// The safety route attached to the private route
safety_route: SafetyRoute, pub safety_route: SafetyRoute,
/// The secret used to encrypt the message payload /// The secret used to encrypt the message payload
secret: DHTKeySecret, pub secret: DHTKeySecret,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -600,7 +600,7 @@ impl RouteSpecStore {
&mut self, &mut self,
rti: &RoutingTableInner, rti: &RoutingTableInner,
routing_table: RoutingTable, routing_table: RoutingTable,
safety_spec: SafetySpec, safety_spec: Option<SafetySpec>,
private_route: PrivateRoute, private_route: PrivateRoute,
) -> Result<Option<CompiledRoute>, RPCError> { ) -> Result<Option<CompiledRoute>, RPCError> {
let pr_hopcount = private_route.hop_count as usize; let pr_hopcount = private_route.hop_count as usize;
@ -608,7 +608,18 @@ impl RouteSpecStore {
return Err(RPCError::internal("private route hop count too long")); return Err(RPCError::internal("private route hop count too long"));
} }
// See if we are using a safety route, if not, short circuit this operation
if safety_spec.is_none() {
// Safety route stub with the node's public key as the safety route key since it's the 0th hop
return Ok(Some(CompiledRoute {
safety_route: SafetyRoute::new_stub(routing_table.node_id(), private_route),
secret: routing_table.node_id_secret(),
}));
}
let safety_spec = safety_spec.unwrap();
// See if the preferred route is here // See if the preferred route is here
let safety_route_public_key;
let opt_safety_rsd: Option<&mut RouteSpecDetail> = let opt_safety_rsd: Option<&mut RouteSpecDetail> =
if let Some(preferred_route) = safety_spec.preferred_route { if let Some(preferred_route) = safety_spec.preferred_route {
self.detail_mut(&preferred_route) self.detail_mut(&preferred_route)
@ -650,19 +661,21 @@ impl RouteSpecStore {
// xxx implement caching first! // xxx implement caching first!
// xxx implement, ensure we handle hops == 0 for our safetyspec
// Ensure the total hop count isn't too long for our config // Ensure the total hop count isn't too long for our config
let sr_hopcount = safety_spec.hop_count; let sr_hopcount = safety_spec.hop_count;
if sr_hopcount > self.max_route_hop_count { if sr_hopcount == 0 {
return Err(RPCError::internal("private route hop count too long")); return Err(RPCError::internal("safety route hop count is zero"));
} }
let total_hopcount = sr_hopcount + pr_hopcount; if sr_hopcount > self.max_route_hop_count {
return Err(RPCError::internal("safety route hop count too long"));
}
// See if we can optimize this compilation yet
// We don't want to include full nodeinfo if we don't have to
//let optimize = safety_rsd.
// Create hops // Create hops
let hops = if sr_hopcount == 0 { let hops = {
SafetyRouteHops::Private(private_route)
} else {
// start last blob-to-encrypt data off as private route // start last blob-to-encrypt data off as private route
let mut blob_data = { let mut blob_data = {
let mut pr_message = ::capnp::message::Builder::new_default(); let mut pr_message = ::capnp::message::Builder::new_default();
@ -681,16 +694,13 @@ impl RouteSpecStore {
// (outer hop is a RouteHopData, not a RouteHop). // (outer hop is a RouteHopData, not a RouteHop).
// Each loop mutates 'nonce', and 'blob_data' // Each loop mutates 'nonce', and 'blob_data'
let mut nonce = Crypto::get_random_nonce(); let mut nonce = Crypto::get_random_nonce();
let crypto = routing_table.network_manager().crypto();
for h in (1..sr_hopcount).rev() { for h in (1..sr_hopcount).rev() {
// Get blob to encrypt for next hop // Get blob to encrypt for next hop
blob_data = { blob_data = {
// Encrypt the previous blob ENC(nonce, DH(PKhop,SKsr)) // Encrypt the previous blob ENC(nonce, DH(PKhop,SKsr))
let dh_secret = self let dh_secret = crypto
.crypto .cached_dh(&safety_rsd.hops[h], &safety_rsd.secret_key)
.cached_dh(
&safety_route_spec.hops[h].dial_info.node_id.key,
&safety_route_spec.secret_key,
)
.map_err(RPCError::map_internal("dh failed"))?; .map_err(RPCError::map_internal("dh failed"))?;
let enc_msg_data = let enc_msg_data =
Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
@ -704,7 +714,7 @@ impl RouteSpecStore {
// Make route hop // Make route hop
let route_hop = RouteHop { let route_hop = RouteHop {
dial_info: safety_route_spec.hops[h].dial_info.clone(), node: safety_route_spec.hops[h].dial_info.clone(),
next_hop: Some(route_hop_data), next_hop: Some(route_hop_data),
}; };
@ -744,12 +754,15 @@ impl RouteSpecStore {
// Build safety route // Build safety route
let safety_route = SafetyRoute { let safety_route = SafetyRoute {
public_key: safety_route_spec.public_key, public_key: safety_rsd.
hop_count: safety_route_spec.hops.len() as u8, hop_count: safety_spec.hop_count as u8,
hops, hops,
}; };
Ok(safety_route) Ok(Some(CompiledRoute {
safety_route,
secret: todo!(),
}))
} }
/// Mark route as published /// Mark route as published

View File

@ -21,6 +21,7 @@ mod rpc_validate_dial_info;
mod rpc_value_changed; mod rpc_value_changed;
mod rpc_watch_value; mod rpc_watch_value;
pub use coders::*;
pub use destination::*; pub use destination::*;
pub use operation_waiter::*; pub use operation_waiter::*;
pub use rpc_error::*; pub use rpc_error::*;
@ -29,7 +30,6 @@ use super::*;
use crate::dht::*; use crate::dht::*;
use crate::xx::*; use crate::xx::*;
use capnp::message::ReaderSegments; use capnp::message::ReaderSegments;
use coders::*;
use futures_util::StreamExt; use futures_util::StreamExt;
use network_manager::*; use network_manager::*;
use receipt_manager::*; use receipt_manager::*;
@ -55,6 +55,8 @@ struct RPCMessageHeader {
connection_descriptor: ConnectionDescriptor, connection_descriptor: ConnectionDescriptor,
/// The routing domain the message was sent through /// The routing domain the message was sent through
routing_domain: RoutingDomain, routing_domain: RoutingDomain,
/// The private route the message was received through
private_route: Option<DHTKey>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -134,7 +136,7 @@ struct RenderedOperation {
message: Vec<u8>, // The rendered operation bytes message: Vec<u8>, // The rendered operation bytes
node_id: DHTKey, // Destination node id we're sending to node_id: DHTKey, // Destination node id we're sending to
node_ref: NodeRef, // Node to send envelope to (may not be destination node id in case of relay) node_ref: NodeRef, // Node to send envelope to (may not be destination node id in case of relay)
hop_count: usize, // Total safety + private route hop count hop_count: usize, // Total safety + private route hop count + 1 hop for the initial send
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -396,16 +398,25 @@ impl RPCProcessor {
} }
// Wrap an operation with a private route inside a safety route // Wrap an operation with a private route inside a safety route
pub(super) fn wrap_with_route(xxx continue here pub(super) fn wrap_with_route(
&self, &self,
safety_spec: SafetySpec, safety_spec: Option<SafetySpec>,
private_route: PrivateRoute, private_route: PrivateRoute,
message_data: Vec<u8>, message_data: Vec<u8>,
) -> Result<RenderedOperation, RPCError> { ) -> Result<NetworkResult<RenderedOperation>, RPCError> {
let compiled_route: CompiledRoute = self.routing_table().with_route_spec_store(|rss| { let routing_table = self.routing_table();
let compiled_route: CompiledRoute =
match self.routing_table().with_route_spec_store(|rss, rti| {
// Compile the safety route with the private route // Compile the safety route with the private route
rss.compile_safety_route(self.safety_spec, private_route) rss.compile_safety_route(rti, routing_table, safety_spec, private_route)
})?; })? {
Some(cr) => cr,
None => {
return Ok(NetworkResult::no_connection_other(
"private route could not be compiled at this time",
))
}
};
// Encrypt routed operation // Encrypt routed operation
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr)) // Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
@ -421,30 +432,42 @@ impl RPCProcessor {
let operation = RoutedOperation::new(nonce, enc_msg_data); let operation = RoutedOperation::new(nonce, enc_msg_data);
// Prepare route operation // Prepare route operation
let route = RPCOperationRoute { let route_operation = RPCOperationRoute {
safety_route, safety_route: compiled_route.safety_route,
operation, operation,
}; };
let operation = let operation = RPCOperation::new_statement(
RPCOperation::new_statement(RPCStatement::new(RPCStatementDetail::Route(route)), None); RPCStatement::new(RPCStatementDetail::Route(route_operation)),
None,
);
// Convert message to bytes and return it // Convert message to bytes and return it
let mut route_msg = ::capnp::message::Builder::new_default(); let mut route_msg = ::capnp::message::Builder::new_default();
let mut route_operation = route_msg.init_root::<veilid_capnp::operation::Builder>(); let mut route_operation = route_msg.init_root::<veilid_capnp::operation::Builder>();
operation.encode(&mut route_operation)?; operation.encode(&mut route_operation)?;
let out = builder_to_vec(route_msg)?; let out_message = builder_to_vec(route_msg)?;
// out_node_id = sr // Get the first hop this is going to
// .hops let out_node_id = compiled_route
// .first() .safety_route
// .ok_or_else(RPCError::else_internal("no hop in safety route"))? .hops
// .dial_info .first()
// .node_id .ok_or_else(RPCError::else_internal("no hop in safety route"))?
// .key; .dial_info
.node_id
.key;
//out_hop_count = 1 + sr.hops.len(); let out_hop_count =
(1 + compiled_route.safety_route.hop_count + private_route.hop_count) as usize;
Ok(out) let out = RenderedOperation {
message: out_message,
node_id: out_node_id,
node_ref: compiled_route.first_hop,
hop_count: out_hop_count,
};
Ok(NetworkResult::value(out))
} }
/// Produce a byte buffer that represents the wire encoding of the entire /// Produce a byte buffer that represents the wire encoding of the entire
@ -455,8 +478,8 @@ impl RPCProcessor {
&self, &self,
dest: Destination, dest: Destination,
operation: &RPCOperation, operation: &RPCOperation,
) -> Result<RenderedOperation, RPCError> { ) -> Result<NetworkResult<RenderedOperation>, RPCError> {
let out: RenderedOperation; let out: NetworkResult<RenderedOperation>;
// Encode message to a builder and make a message reader for it // Encode message to a builder and make a message reader for it
// Then produce the message as an unencrypted byte buffer // Then produce the message as an unencrypted byte buffer
@ -471,12 +494,12 @@ impl RPCProcessor {
match dest { match dest {
Destination::Direct { Destination::Direct {
target: ref node_ref, target: ref node_ref,
safety, safety_spec,
} }
| Destination::Relay { | Destination::Relay {
relay: ref node_ref, relay: ref node_ref,
target: _, target: _,
safety, safety_spec,
} => { } => {
// Send to a node without a private route // Send to a node without a private route
// -------------------------------------- // --------------------------------------
@ -485,7 +508,7 @@ impl RPCProcessor {
let (node_ref, node_id) = if let Destination::Relay { let (node_ref, node_id) = if let Destination::Relay {
relay: _, relay: _,
target: ref dht_key, target: ref dht_key,
safety: _, safety_spec: _,
} = dest } = dest
{ {
(node_ref.clone(), dht_key.clone()) (node_ref.clone(), dht_key.clone())
@ -495,36 +518,36 @@ impl RPCProcessor {
}; };
// Handle the existence of safety route // Handle the existence of safety route
match safety { match safety_spec {
false => { None => {
// If no safety route is being used, and we're not sending to a private // If no safety route is being used, and we're not sending to a private
// route, we can use a direct envelope instead of routing // route, we can use a direct envelope instead of routing
out = RenderedOperation { out = NetworkResult::value(RenderedOperation {
message, message,
node_id, node_id,
node_ref, node_ref,
hop_count: 1, hop_count: 1,
}; });
} }
true => { Some(safety_spec) => {
// No private route was specified for the request // No private route was specified for the request
// but we are using a safety route, so we must create an empty private route // but we are using a safety route, so we must create an empty private route
let private_route = PrivateRoute::new_stub(node_id); let private_route = PrivateRoute::new_stub(node_id);
// Wrap with safety route // Wrap with safety route
out = self.wrap_with_route(true, private_route, message)?; out = self.wrap_with_route(Some(safety_spec), private_route, message)?;
} }
}; };
} }
Destination::PrivateRoute { Destination::PrivateRoute {
private_route, private_route,
safety, safety_spec,
reliable, reliable,
} => { } => {
// Send to private route // Send to private route
// --------------------- // ---------------------
// Reply with 'route' operation // Reply with 'route' operation
out = self.wrap_with_route(safety, private_route, message)?; out = self.wrap_with_route(safety_spec, private_route, message)?;
} }
} }
@ -602,7 +625,7 @@ impl RPCProcessor {
node_id, node_id,
node_ref, node_ref,
hop_count, hop_count,
} = self.render_operation(dest, &operation)?; } = network_result_try!(self.render_operation(dest, &operation)?);
// Calculate answer timeout // Calculate answer timeout
// Timeout is number of hops times the timeout per hop // Timeout is number of hops times the timeout per hop
@ -665,7 +688,7 @@ impl RPCProcessor {
node_id, node_id,
node_ref, node_ref,
hop_count: _, hop_count: _,
} = self.render_operation(dest, &operation)?; } = network_result_try!(self.render_operation(dest, &operation)?);
// Send statement // Send statement
let bytes = message.len() as u64; let bytes = message.len() as u64;
@ -749,7 +772,7 @@ impl RPCProcessor {
node_id, node_id,
node_ref, node_ref,
hop_count: _, hop_count: _,
} = self.render_operation(dest, &operation)?; } = network_result_try!(self.render_operation(dest, &operation)?);
// Send the reply // Send the reply
let bytes = message.len() as u64; let bytes = message.len() as u64;

View File

@ -48,6 +48,19 @@ impl PrivateRoute {
first_hop: None, first_hop: None,
} }
} }
pub fn simplify(self) -> Self {
Self {
public_key: self.public_key,
hop_count: self.hop_count,
first_hop: self.first_hop.map(|h| RouteHop {
node: match h.node {
RouteNode::NodeId(ni) => RouteNode::NodeId(ni),
RouteNode::PeerInfo(pi) => RouteNode::NodeId(pi.node_id),
},
next_hop: h.next_hop,
}),
}
}
} }
impl fmt::Display for PrivateRoute { impl fmt::Display for PrivateRoute {
@ -79,6 +92,16 @@ pub struct SafetyRoute {
pub hops: SafetyRouteHops, pub hops: SafetyRouteHops,
} }
impl SafetyRoute {
pub fn new_stub(public_key: DHTKey, private_route: PrivateRoute) -> Self {
Self {
public_key,
hop_count: 0,
hops: SafetyRouteHops::Private(private_route),
}
}
}
impl fmt::Display for SafetyRoute { impl fmt::Display for SafetyRoute {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(