more route work
This commit is contained in:
@@ -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)?;
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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());
|
||||
|
@@ -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() {
|
||||
|
@@ -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(())
|
||||
}
|
||||
|
@@ -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")
|
||||
|
@@ -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(());
|
||||
|
@@ -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() {
|
||||
|
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user