more route work

This commit is contained in:
John Smith
2022-10-30 23:23:12 -04:00
parent 50718b7074
commit 68d55a5e77
17 changed files with 312 additions and 211 deletions

View File

@@ -52,11 +52,11 @@ pub fn encode_route_hop(
let node_builder = builder.reborrow().init_node();
match &route_hop.node {
RouteNode::NodeId(ni) => {
let ni_builder = node_builder.init_node_id();
let mut ni_builder = node_builder.init_node_id();
encode_public_key(&ni.key, &mut ni_builder)?;
}
RouteNode::PeerInfo(pi) => {
let pi_builder = node_builder.init_peer_info();
let mut pi_builder = node_builder.init_peer_info();
encode_peer_info(&pi, &mut pi_builder)?;
}
}

View File

@@ -30,16 +30,18 @@ pub enum Destination {
impl Destination {
pub fn direct(target: NodeRef) -> Self {
let sequencing = target.sequencing();
Self::Direct {
target,
safety_selection: SafetySelection::Unsafe(target.sequencing()),
safety_selection: SafetySelection::Unsafe(sequencing),
}
}
pub fn relay(relay: NodeRef, target: DHTKey) -> Self {
let sequencing = relay.sequencing();
Self::Relay {
relay,
target,
safety_selection: SafetySelection::Unsafe(relay.sequencing()),
safety_selection: SafetySelection::Unsafe(sequencing),
}
}
pub fn private_route(private_route: PrivateRoute, safety_selection: SafetySelection) -> Self {

View File

@@ -425,22 +425,23 @@ impl RPCProcessor {
message_data: Vec<u8>,
) -> Result<NetworkResult<RenderedOperation>, RPCError> {
let routing_table = self.routing_table();
let rss = routing_table.route_spec_store();
let pr_hop_count = private_route.hop_count;
let pr_pubkey = private_route.public_key;
let compiled_route: CompiledRoute =
match self.routing_table().with_route_spec_store_mut(|rss, rti| {
// Compile the safety route with the private route
rss.compile_safety_route(rti, routing_table, safety_selection, private_route)
.map_err(RPCError::internal)
})? {
Some(cr) => cr,
None => {
return Ok(NetworkResult::no_connection_other(
"private route could not be compiled at this time",
))
}
};
// Compile the safety route with the private route
let compiled_route: CompiledRoute = match rss
.compile_safety_route(rti, routing_table, safety_selection, private_route)
.map_err(RPCError::internal)?
{
Some(cr) => cr,
None => {
return Ok(NetworkResult::no_connection_other(
"private route could not be compiled at this time",
))
}
};
// Encrypt routed operation
// Xmsg + ENC(Xmsg, DH(PKapr, SKbsr))
@@ -917,7 +918,7 @@ impl RPCProcessor {
opt_sender_nr,
}
}
RPCMessageHeaderDetail::PrivateRoute(detail) => {
RPCMessageHeaderDetail::PrivateRoute(_) => {
// Decode the RPC message
let operation = {
let reader = capnp::message::Reader::new(encoded_msg.data, Default::default());

View File

@@ -31,8 +31,14 @@ impl RPCProcessor {
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
pub(crate) async fn process_node_info_update(&self, msg: RPCMessage) -> Result<(), RPCError> {
let sender_node_id = msg.header.envelope.get_sender_id();
let routing_domain = msg.header.routing_domain;
let detail = match msg.header.detail {
RPCMessageHeaderDetail::Direct(detail) => detail,
RPCMessageHeaderDetail::PrivateRoute(_) => {
return Err(RPCError::protocol("node_info_update must be direct"));
}
};
let sender_node_id = detail.envelope.get_sender_id();
let routing_domain = detail.routing_domain;
// Get the statement
let node_info_update = match msg.operation.into_kind() {

View File

@@ -33,11 +33,23 @@ impl RPCProcessor {
// Handle it
let network_manager = self.network_manager();
network_result_value_or_log!(debug
network_manager
.handle_in_band_receipt(receipt, msg.header.peer_noderef)
.await => {}
);
match msg.header.detail {
RPCMessageHeaderDetail::Direct(detail) => {
network_result_value_or_log!(debug
network_manager
.handle_in_band_receipt(receipt, detail.peer_noderef)
.await => {}
);
}
RPCMessageHeaderDetail::PrivateRoute(detail) => {
network_result_value_or_log!(debug
network_manager
.handle_private_receipt(receipt)
.await => {}
);
}
}
Ok(())
}

View File

@@ -170,8 +170,13 @@ impl RPCProcessor {
// 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
let opt_pr_info = if private_route.public_key == self.routing_table.node_id() {
// the private route was a stub to our own node's secret
// return our secret key and an appropriate safety selection
// The private route was a stub
// Return our secret key and an appropriate safety selection
//
// Note: it is important that we never respond with a safety route to questions that come
// in without a private route. Giving away a safety route when the node id is known is
// a privacy violation!
// Get sequencing preference
let sequencing = if detail
.connection_descriptor
@@ -191,46 +196,45 @@ impl RPCProcessor {
let sender_id = detail.envelope.get_sender_id();
// Look up the private route and ensure it's one in our spec store
let opt_signatures_valid = self.routing_table.with_route_spec_store(|rss, rti| {
rss.with_route_spec_detail(&private_route.public_key, |rsd| {
// Ensure we have the right number of signatures
if routed_operation.signatures.len() != rsd.hops.len() - 1 {
// Wrong number of signatures
log_rpc!(debug "wrong number of signatures ({} should be {}) for routed operation on private route {}", routed_operation.signatures.len(), rsd.hops.len() - 1, private_route.public_key);
return None;
}
// Validate signatures to ensure the route was handled by the nodes and not messed with
for (hop_n, hop_public_key) in rsd.hops.iter().enumerate() {
// The last hop is not signed, as the whole packet is signed
if hop_n == routed_operation.signatures.len() {
// Verify the node we received the routed operation from is the last hop in our route
if *hop_public_key != sender_id {
log_rpc!(debug "received routed operation from the wrong hop ({} should be {}) on private route {}", hop_public_key.encode(), sender_id.encode(), private_route.public_key);
return None;
}
} else {
// Verify a signature for a hop node along the route
if let Err(e) = verify(
hop_public_key,
&routed_operation.data,
&routed_operation.signatures[hop_n],
) {
log_rpc!(debug "failed to verify signature for hop {} at {} on private route {}", hop_n, hop_public_key, private_route.public_key);
return None;
}
let rss= self.routing_table.route_spec_store();
let opt_signatures_valid = rss.with_route_spec_detail(&private_route.public_key, |rsd| {
// Ensure we have the right number of signatures
if routed_operation.signatures.len() != rsd.hops.len() - 1 {
// Wrong number of signatures
log_rpc!(debug "wrong number of signatures ({} should be {}) for routed operation on private route {}", routed_operation.signatures.len(), rsd.hops.len() - 1, private_route.public_key);
return None;
}
// Validate signatures to ensure the route was handled by the nodes and not messed with
for (hop_n, hop_public_key) in rsd.hops.iter().enumerate() {
// The last hop is not signed, as the whole packet is signed
if hop_n == routed_operation.signatures.len() {
// Verify the node we received the routed operation from is the last hop in our route
if *hop_public_key != sender_id {
log_rpc!(debug "received routed operation from the wrong hop ({} should be {}) on private route {}", hop_public_key.encode(), sender_id.encode(), private_route.public_key);
return None;
}
} else {
// Verify a signature for a hop node along the route
if let Err(e) = verify(
hop_public_key,
&routed_operation.data,
&routed_operation.signatures[hop_n],
) {
log_rpc!(debug "failed to verify signature for hop {} at {} on private route {}", hop_n, hop_public_key, private_route.public_key);
return None;
}
}
// We got the correct signatures, return a key ans
Some((
rsd.secret_key,
SafetySelection::Safe(SafetySpec {
preferred_route: Some(private_route.public_key),
hop_count: rsd.hops.len(),
stability: rsd.stability,
sequencing: rsd.sequencing,
})
))
})
}
// We got the correct signatures, return a key ans
Some((
rsd.secret_key,
SafetySelection::Safe(SafetySpec {
preferred_route: Some(private_route.public_key),
hop_count: rsd.hops.len(),
stability: rsd.stability,
sequencing: rsd.sequencing,
})
))
});
opt_signatures_valid.ok_or_else(|| {
RPCError::protocol("routed operation received on unallocated private route")

View File

@@ -32,7 +32,7 @@ impl RPCProcessor {
// Handle it
let network_manager = self.network_manager();
network_result_value_or_log!(debug network_manager
.handle_signal(msg.header.envelope.get_sender_id(), signal.signal_info)
.handle_signal(signal.signal_info)
.await
.map_err(RPCError::network)? => {
return Ok(());

View File

@@ -103,8 +103,15 @@ impl RPCProcessor {
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id, res), err)]
pub(crate) async fn process_status_q(&self, msg: RPCMessage) -> Result<(), RPCError> {
let connection_descriptor = msg.header.connection_descriptor;
let routing_domain = msg.header.routing_domain;
let detail = match &msg.header.detail {
RPCMessageHeaderDetail::Direct(detail) => detail,
RPCMessageHeaderDetail::PrivateRoute(_) => {
return Err(RPCError::protocol("status_q must be direct"));
}
};
let connection_descriptor = detail.connection_descriptor;
let routing_domain = detail.routing_domain;
// Get the question
let status_q = match msg.operation.kind() {

View File

@@ -34,7 +34,7 @@ impl RPCProcessor {
// Wait for receipt
match eventual_value.await.take_value().unwrap() {
ReceiptEvent::ReturnedInBand { inbound_noderef: _ } => {
ReceiptEvent::ReturnedPrivate | ReceiptEvent::ReturnedInBand { inbound_noderef: _ } => {
log_net!(debug "validate_dial_info receipt should be returned out-of-band".green());
Ok(false)
}
@@ -54,6 +54,13 @@ impl RPCProcessor {
#[instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), err)]
pub(crate) async fn process_validate_dial_info(&self, msg: RPCMessage) -> Result<(), RPCError> {
let detail = match msg.header.detail {
RPCMessageHeaderDetail::Direct(detail) => detail,
RPCMessageHeaderDetail::PrivateRoute(_) => {
return Err(RPCError::protocol("validate_dial_info must be direct"));
}
};
// Get the statement
let RPCOperationValidateDialInfo {
dial_info,
@@ -74,8 +81,8 @@ impl RPCProcessor {
// Use the address type though, to ensure we reach an ipv6 capable node if this is
// an ipv6 address
let routing_table = self.routing_table();
let sender_id = msg.header.envelope.get_sender_id();
let routing_domain = msg.header.routing_domain;
let sender_id = detail.envelope.get_sender_id();
let routing_domain = detail.routing_domain;
let node_count = {
let c = self.config.get();
c.network.dht.max_find_node_count as usize
@@ -141,8 +148,6 @@ impl RPCProcessor {
.await
.map_err(RPCError::network)?;
// tracing::Span::current().record("res", &tracing::field::display(res));
Ok(())
}
}