checkpoint
This commit is contained in:
@@ -891,11 +891,20 @@ impl RoutingTable {
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
pub fn register_find_node_answer(&self, peers: Vec<PeerInfo>) -> Vec<NodeRef> {
|
||||
// register nodes we'd found
|
||||
pub fn register_find_node_answer(
|
||||
&self,
|
||||
crypto_kind: CryptoKind,
|
||||
peers: Vec<PeerInfo>,
|
||||
) -> Vec<NodeRef> {
|
||||
// Register nodes we'd found
|
||||
let mut out = Vec::<NodeRef>::with_capacity(peers.len());
|
||||
for p in peers {
|
||||
// register the node if it's new
|
||||
// Ensure we're getting back nodes we asked for
|
||||
if !p.node_ids.kinds().contains(&crypto_kind) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Register the node if it's new
|
||||
if let Some(nr) =
|
||||
self.register_node_with_peer_info(RoutingDomain::PublicInternet, p, false)
|
||||
{
|
||||
@@ -922,29 +931,41 @@ impl RoutingTable {
|
||||
|
||||
// register nodes we'd found
|
||||
Ok(NetworkResult::value(
|
||||
self.register_find_node_answer(res.answer),
|
||||
self.register_find_node_answer(node_id.kind, res.answer),
|
||||
))
|
||||
}
|
||||
|
||||
/// Ask a remote node to list the nodes it has around the current node
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
pub async fn find_self(&self, node_ref: NodeRef) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
let self_node_id = self.node_id();
|
||||
pub async fn find_self(
|
||||
&self,
|
||||
crypto_kind: CryptoKind,
|
||||
node_ref: NodeRef,
|
||||
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
let self_node_id = self.node_id(crypto_kind);
|
||||
self.find_node(node_ref, self_node_id).await
|
||||
}
|
||||
|
||||
/// Ask a remote node to list the nodes it has around itself
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
pub async fn find_target(&self, node_ref: NodeRef) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
let target_node_id = node_ref.node_id();
|
||||
pub async fn find_target(
|
||||
&self,
|
||||
crypto_kind: CryptoKind,
|
||||
node_ref: NodeRef,
|
||||
) -> EyreResult<NetworkResult<Vec<NodeRef>>> {
|
||||
let Some(target_node_id) = node_ref.node_ids().get(crypto_kind) else {
|
||||
bail!("no target node ids for this crypto kind");
|
||||
};
|
||||
self.find_node(node_ref, target_node_id).await
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
pub async fn reverse_find_node(&self, node_ref: NodeRef, wide: bool) {
|
||||
// Ask bootstrap node to 'find' our own node so we can get some more nodes near ourselves
|
||||
pub async fn reverse_find_node(&self, crypto_kind: CryptoKind, node_ref: NodeRef, wide: bool) {
|
||||
// Ask node to 'find node' on own node so we can get some more nodes near ourselves
|
||||
// and then contact those nodes to inform -them- that we exist
|
||||
|
||||
// Ask bootstrap server for nodes closest to our own node
|
||||
let closest_nodes = network_result_value_or_log!(match self.find_self(node_ref.clone()).await {
|
||||
// Ask node for nodes closest to our own node
|
||||
let closest_nodes = network_result_value_or_log!(match self.find_self(crypto_kind, node_ref.clone()).await {
|
||||
Err(e) => {
|
||||
log_rtab!(error
|
||||
"find_self failed for {:?}: {:?}",
|
||||
@@ -960,7 +981,7 @@ impl RoutingTable {
|
||||
// Ask each node near us to find us as well
|
||||
if wide {
|
||||
for closest_nr in closest_nodes {
|
||||
network_result_value_or_log!(match self.find_self(closest_nr.clone()).await {
|
||||
network_result_value_or_log!(match self.find_self(crypto_kind, closest_nr.clone()).await {
|
||||
Err(e) => {
|
||||
log_rtab!(error
|
||||
"find_self failed for {:?}: {:?}",
|
||||
|
@@ -168,7 +168,7 @@ pub struct RouteSpecDetail {
|
||||
/// Secret key
|
||||
#[with(Skip)]
|
||||
secret_key: SecretKey,
|
||||
/// Route hops
|
||||
/// Route hops (node id keys)
|
||||
hops: Vec<PublicKey>,
|
||||
/// Route noderefs
|
||||
#[with(Skip)]
|
||||
@@ -444,7 +444,7 @@ impl RouteSpecStore {
|
||||
let mut dead_keys = Vec::new();
|
||||
for (k, rsd) in &mut content.details {
|
||||
for h in &rsd.hops {
|
||||
let Some(nr) = routing_table.lookup_node_ref(*h) else {
|
||||
let Some(nr) = routing_table.lookup_node_ref(TypedKey::new(rsd.crypto_kind, *h)) else {
|
||||
dead_keys.push(*k);
|
||||
break;
|
||||
};
|
||||
@@ -582,13 +582,13 @@ impl RouteSpecStore {
|
||||
|
||||
fn detail<'a>(
|
||||
inner: &'a RouteSpecStoreInner,
|
||||
route_spec_key: &TypedKey,
|
||||
route_spec_key: &PublicKey,
|
||||
) -> Option<&'a RouteSpecDetail> {
|
||||
inner.content.details.get(route_spec_key)
|
||||
}
|
||||
fn detail_mut<'a>(
|
||||
inner: &'a mut RouteSpecStoreInner,
|
||||
route_spec_key: &TypedKey,
|
||||
route_spec_key: &PublicKey,
|
||||
) -> Option<&'a mut RouteSpecDetail> {
|
||||
inner.content.details.get_mut(route_spec_key)
|
||||
}
|
||||
@@ -1594,9 +1594,10 @@ impl RouteSpecStore {
|
||||
&self,
|
||||
inner: &mut RouteSpecStoreInner,
|
||||
rti: &RoutingTableInner,
|
||||
crypto_kind: CryptoKind,
|
||||
safety_spec: &SafetySpec,
|
||||
direction: DirectionSet,
|
||||
avoid_nodes: &[PublicKey],
|
||||
avoid_nodes: &[TypedKey],
|
||||
) -> EyreResult<Option<PublicKey>> {
|
||||
// Ensure the total hop count isn't too long for our config
|
||||
let max_route_hop_count = self.unlocked_inner.max_route_hop_count;
|
||||
@@ -1610,9 +1611,12 @@ impl RouteSpecStore {
|
||||
// See if the preferred route is here
|
||||
if let Some(preferred_route) = safety_spec.preferred_route {
|
||||
if let Some(preferred_rsd) = inner.content.details.get(&preferred_route) {
|
||||
// Only use the preferred route if it doesn't end with the avoid nodes
|
||||
if !avoid_node_ids.contains(preferred_rsd.hops.last().unwrap()) {
|
||||
return Ok(Some(preferred_route));
|
||||
// Only use the preferred route if it has the desire crypto kind
|
||||
if preferred_rsd.crypto_kind == crypto_kind {
|
||||
// Only use the preferred route if it doesn't end with the avoid nodes
|
||||
if !avoid_nodes.contains(&TypedKey::new(crypto_kind, preferred_rsd.hops.last().cloned().unwrap())) {
|
||||
return Ok(Some(preferred_route));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1657,7 +1661,7 @@ impl RouteSpecStore {
|
||||
&self,
|
||||
crypto_kind: CryptoKind,
|
||||
safety_spec: &SafetySpec,
|
||||
avoid_nodes: &[PublicKey],
|
||||
avoid_nodes: &[TypedKey],
|
||||
) -> EyreResult<Option<PublicKey>> {
|
||||
let inner = &mut *self.inner.lock();
|
||||
let routing_table = self.unlocked_inner.routing_table.clone();
|
||||
@@ -1666,6 +1670,7 @@ impl RouteSpecStore {
|
||||
Ok(self.get_route_for_safety_spec_inner(
|
||||
inner,
|
||||
rti,
|
||||
crypto_kind,
|
||||
safety_spec,
|
||||
Direction::Inbound.into(),
|
||||
avoid_nodes,
|
||||
@@ -1673,6 +1678,7 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
/// Assemble private route for publication
|
||||
/// Returns a PrivateRoute object for an allocated private route
|
||||
#[instrument(level = "trace", skip(self), err)]
|
||||
pub fn assemble_private_route(
|
||||
&self,
|
||||
@@ -1683,8 +1689,15 @@ impl RouteSpecStore {
|
||||
let routing_table = self.unlocked_inner.routing_table.clone();
|
||||
let rti = &*routing_table.inner.read();
|
||||
|
||||
// Get the route spec detail for the requested private route
|
||||
let rsd = Self::detail(inner, key).ok_or_else(|| eyre!("route does not exist"))?;
|
||||
|
||||
// Ensure we get the crypto for it
|
||||
let crypto = routing_table.network_manager().crypto();
|
||||
let Some(vcrypto) = crypto.get(rsd.crypto_kind) else {
|
||||
bail!("crypto not supported for route");
|
||||
};
|
||||
|
||||
// See if we can optimize this compilation yet
|
||||
// We don't want to include full nodeinfo if we don't have to
|
||||
let optimized = optimized
|
||||
@@ -1696,7 +1709,10 @@ impl RouteSpecStore {
|
||||
if !rti.has_valid_own_node_info(RoutingDomain::PublicInternet) {
|
||||
bail!("can't make private routes until our node info is valid");
|
||||
}
|
||||
RouteNode::NodeId(NodeId::new(routing_table.node_id()))
|
||||
let Some(node_id) = routing_table.node_ids().get(rsd.crypto_kind) else {
|
||||
bail!("missing node id for crypto kind");
|
||||
};
|
||||
RouteNode::NodeId(node_id.key)
|
||||
} else {
|
||||
let Some(pi) = rti.get_own_peer_info(RoutingDomain::PublicInternet) else {
|
||||
bail!("can't make private routes until our node info is valid");
|
||||
@@ -1706,12 +1722,11 @@ impl RouteSpecStore {
|
||||
next_hop: None,
|
||||
};
|
||||
|
||||
let crypto = routing_table.network_manager().crypto();
|
||||
// Loop for each hop
|
||||
let hop_count = rsd.hops.len();
|
||||
// iterate hops in private route order (reverse, but inside out)
|
||||
for h in 0..hop_count {
|
||||
let nonce = Crypto::get_random_nonce();
|
||||
let nonce = vcrypto.random_nonce();
|
||||
|
||||
let blob_data = {
|
||||
let mut rh_message = ::capnp::message::Builder::new_default();
|
||||
@@ -1721,10 +1736,10 @@ impl RouteSpecStore {
|
||||
};
|
||||
|
||||
// Encrypt the previous blob ENC(nonce, DH(PKhop,SKpr))
|
||||
let dh_secret = crypto
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&rsd.hops[h], &rsd.secret_key)
|
||||
.wrap_err("dh failed")?;
|
||||
let enc_msg_data = Crypto::encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
|
||||
let enc_msg_data = vcrypto.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)
|
||||
.wrap_err("encryption failed")?;
|
||||
let route_hop_data = RouteHopData {
|
||||
nonce,
|
||||
@@ -1734,14 +1749,14 @@ impl RouteSpecStore {
|
||||
route_hop = RouteHop {
|
||||
node: if optimized {
|
||||
// Optimized, no peer info, just the dht key
|
||||
RouteNode::NodeId(NodeId::new(rsd.hops[h]))
|
||||
RouteNode::NodeId(rsd.hops[h])
|
||||
} else {
|
||||
// Full peer info, required until we are sure the route has been fully established
|
||||
let node_id = rsd.hops[h];
|
||||
let node_id = TypedKey::new(rsd.crypto_kind, rsd.hops[h]);
|
||||
let pi = rti
|
||||
.with_node_entry(node_id, |entry| {
|
||||
entry.with(rti, |_rti, e| {
|
||||
e.make_peer_info(node_id, RoutingDomain::PublicInternet)
|
||||
e.make_peer_info(RoutingDomain::PublicInternet)
|
||||
})
|
||||
})
|
||||
.flatten();
|
||||
@@ -1755,7 +1770,7 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
let private_route = PrivateRoute {
|
||||
public_key: key.clone(),
|
||||
public_key: TypedKey::new(rsd.crypto_kind, key.clone()),
|
||||
// add hop for 'FirstHop'
|
||||
hop_count: (hop_count + 1).try_into().unwrap(),
|
||||
hops: PrivateRouteHops::FirstHop(route_hop),
|
||||
@@ -1765,27 +1780,35 @@ impl RouteSpecStore {
|
||||
|
||||
/// Import a remote private route for compilation
|
||||
#[instrument(level = "trace", skip(self, blob), ret, err)]
|
||||
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<PublicKey> {
|
||||
pub fn import_remote_private_route(&self, blob: Vec<u8>) -> EyreResult<TypedKeySet> {
|
||||
// decode the pr blob
|
||||
let private_route = RouteSpecStore::blob_to_private_route(blob)?;
|
||||
let private_routes = RouteSpecStore::blob_to_private_routes(blob)?;
|
||||
|
||||
// ensure private route has first hop
|
||||
if !matches!(private_route.hops, PrivateRouteHops::FirstHop(_)) {
|
||||
bail!("private route must have first hop");
|
||||
}
|
||||
|
||||
// ensure this isn't also an allocated route
|
||||
let mut out = TypedKeySet::new();
|
||||
let inner = &mut *self.inner.lock();
|
||||
if Self::detail(inner, &private_route.public_key).is_some() {
|
||||
bail!("should not import allocated route");
|
||||
|
||||
for private_route in private_routes {
|
||||
|
||||
// ensure private route has first hop
|
||||
if !matches!(private_route.hops, PrivateRouteHops::FirstHop(_)) {
|
||||
bail!("private route must have first hop");
|
||||
}
|
||||
|
||||
// ensure this isn't also an allocated route
|
||||
if Self::detail(inner, &private_route.public_key.key).is_some() {
|
||||
bail!("should not import allocated route");
|
||||
}
|
||||
|
||||
// store the private route in our cache
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
let key = Self::with_create_remote_private_route(inner, cur_ts, private_route, |r| {
|
||||
r.private_route.as_ref().unwrap().public_key.clone()
|
||||
});
|
||||
|
||||
out.add(key);
|
||||
}
|
||||
|
||||
// store the private route in our cache
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
let key = Self::with_create_remote_private_route(inner, cur_ts, private_route, |r| {
|
||||
r.private_route.as_ref().unwrap().public_key.clone()
|
||||
});
|
||||
Ok(key)
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Release a remote private route that is no longer in use
|
||||
@@ -1829,7 +1852,7 @@ impl RouteSpecStore {
|
||||
where
|
||||
F: FnOnce(&mut RemotePrivateRouteInfo) -> R,
|
||||
{
|
||||
let pr_pubkey = private_route.public_key;
|
||||
let pr_pubkey = private_route.public_key.key;
|
||||
|
||||
let rpr = inner
|
||||
.cache
|
||||
@@ -2045,33 +2068,64 @@ impl RouteSpecStore {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert private route to binary blob
|
||||
pub fn private_route_to_blob(private_route: &PrivateRoute) -> EyreResult<Vec<u8>> {
|
||||
/// Convert private route list to binary blob
|
||||
pub fn private_routes_to_blob(private_routes: &[PrivateRoute]) -> EyreResult<Vec<u8>> {
|
||||
let mut pr_message = ::capnp::message::Builder::new_default();
|
||||
let mut pr_builder = pr_message.init_root::<veilid_capnp::private_route::Builder>();
|
||||
encode_private_route(&private_route, &mut pr_builder)
|
||||
.wrap_err("failed to encode private route")?;
|
||||
|
||||
|
||||
let mut buffer = vec![];
|
||||
capnp::serialize_packed::write_message(&mut buffer, &pr_message)
|
||||
.map_err(RPCError::internal)
|
||||
.wrap_err("failed to convert builder to vec")?;
|
||||
|
||||
// Serialize count
|
||||
let pr_count = private_routes.len();
|
||||
if pr_count > MAX_CRYPTO_KINDS {
|
||||
bail!("too many crypto kinds to encode blob");
|
||||
}
|
||||
let pr_count = pr_count as u8;
|
||||
buffer.push(pr_count);
|
||||
|
||||
// Serialize stream of private routes
|
||||
for private_route in private_routes {
|
||||
encode_private_route(private_route, &mut pr_builder)
|
||||
.wrap_err("failed to encode private route")?;
|
||||
|
||||
capnp::serialize_packed::write_message(&mut buffer, &pr_message)
|
||||
.map_err(RPCError::internal)
|
||||
.wrap_err("failed to convert builder to vec")?;
|
||||
}
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
/// Convert binary blob to private route
|
||||
pub fn blob_to_private_route(blob: Vec<u8>) -> EyreResult<PrivateRoute> {
|
||||
let reader = capnp::serialize_packed::read_message(
|
||||
blob.as_slice(),
|
||||
capnp::message::ReaderOptions::new(),
|
||||
)
|
||||
.map_err(RPCError::internal)
|
||||
.wrap_err("failed to make message reader")?;
|
||||
pub fn blob_to_private_routes(blob: Vec<u8>) -> EyreResult<Vec<PrivateRoute>> {
|
||||
|
||||
let pr_reader = reader
|
||||
.get_root::<veilid_capnp::private_route::Reader>()
|
||||
// Deserialize count
|
||||
if blob.is_empty() {
|
||||
bail!("not deserializing empty private route blob");
|
||||
}
|
||||
|
||||
let pr_count = blob[0] as usize;
|
||||
if pr_count > MAX_CRYPTO_KINDS {
|
||||
bail!("too many crypto kinds to decode blob");
|
||||
}
|
||||
|
||||
// Deserialize stream of private routes
|
||||
let pr_slice = &blob[1..];
|
||||
let mut out = Vec::with_capacity(pr_count);
|
||||
for _ in 0..pr_count {
|
||||
let reader = capnp::serialize_packed::read_message(
|
||||
&mut pr_slice,
|
||||
capnp::message::ReaderOptions::new(),
|
||||
)
|
||||
.map_err(RPCError::internal)
|
||||
.wrap_err("failed to make reader for private_route")?;
|
||||
decode_private_route(&pr_reader).wrap_err("failed to decode private route")
|
||||
.wrap_err("failed to make message reader")?;
|
||||
|
||||
let pr_reader = reader
|
||||
.get_root::<veilid_capnp::private_route::Reader>()
|
||||
.map_err(RPCError::internal)
|
||||
.wrap_err("failed to make reader for private_route")?;
|
||||
let private_route = decode_private_route(&pr_reader).wrap_err("failed to decode private route")?;
|
||||
out.push(private_route);
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
@@ -413,6 +413,7 @@ impl RoutingTableInner {
|
||||
&self,
|
||||
routing_domain_set: RoutingDomainSet,
|
||||
min_state: BucketEntryState,
|
||||
crypto_kinds: &[CryptoKind], xxx finish this and peer minimum refresh and bootstrap tick, then both routines
|
||||
) -> usize {
|
||||
let mut count = 0usize;
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
@@ -451,7 +452,7 @@ impl RoutingTableInner {
|
||||
mut f: F,
|
||||
) -> Option<T> {
|
||||
for entry in self.all_entries {
|
||||
if entry.with(self, |_rti, e| e.state(cur_ts) >= min_state) {
|
||||
if entry.with_inner(|e| e.state(cur_ts) >= min_state) {
|
||||
if let Some(out) = f(self, entry) {
|
||||
return Some(out);
|
||||
}
|
||||
@@ -474,7 +475,7 @@ impl RoutingTableInner {
|
||||
// Collect all entries that are 'needs_ping' and have some node info making them reachable somehow
|
||||
let mut node_refs = Vec::<NodeRef>::with_capacity(self.bucket_entry_count());
|
||||
self.with_entries(cur_ts, BucketEntryState::Unreliable, |rti, entry| {
|
||||
if entry.with(rti, |rti, e| {
|
||||
if entry.with_inner(|e| {
|
||||
// If this isn't in the routing domain we are checking, don't include it
|
||||
if !e.exists_in_routing_domain(rti, routing_domain) {
|
||||
return false;
|
||||
@@ -757,7 +758,7 @@ impl RoutingTableInner {
|
||||
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
for entry in self.all_entries {
|
||||
match entry.with(self, |_rti, e| e.state(cur_ts)) {
|
||||
match entry.with_inner(|e| e.state(cur_ts)) {
|
||||
BucketEntryState::Reliable => {
|
||||
reliable_entry_count += 1;
|
||||
}
|
||||
@@ -807,7 +808,7 @@ impl RoutingTableInner {
|
||||
) -> Vec<NodeRef> {
|
||||
let public_node_filter = Box::new(|rti: &RoutingTableInner, v: Option<Arc<BucketEntry>>| {
|
||||
let entry = v.unwrap();
|
||||
entry.with(rti, |_rti, e| {
|
||||
entry.with_inner(|e| {
|
||||
// skip nodes on local network
|
||||
if e.node_info(RoutingDomain::LocalNetwork).is_some() {
|
||||
return false;
|
||||
@@ -838,7 +839,7 @@ impl RoutingTableInner {
|
||||
) -> bool {
|
||||
match entry {
|
||||
None => has_valid_own_node_info,
|
||||
Some(entry) => entry.with(self, |_rti, e| {
|
||||
Some(entry) => entry.with_inner(|e| {
|
||||
e.signed_node_info(routing_domain.into())
|
||||
.map(|sni| sni.has_any_signature())
|
||||
.unwrap_or(false)
|
||||
@@ -854,7 +855,7 @@ impl RoutingTableInner {
|
||||
) -> PeerInfo {
|
||||
match entry {
|
||||
None => own_peer_info.clone(),
|
||||
Some(entry) => entry.with(self, |_rti, e| e.make_peer_info(routing_domain).unwrap()),
|
||||
Some(entry) => entry.with_inner(|e| e.make_peer_info(routing_domain).unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -932,7 +933,7 @@ impl RoutingTableInner {
|
||||
move |rti: &RoutingTableInner, v: Option<Arc<BucketEntry>>| {
|
||||
if let Some(entry) = &v {
|
||||
// always filter out dead nodes
|
||||
if entry.with(rti, |_rti, e| e.state(cur_ts) == BucketEntryState::Dead) {
|
||||
if entry.with_inner(|e| e.state(cur_ts) == BucketEntryState::Dead) {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
@@ -970,8 +971,8 @@ impl RoutingTableInner {
|
||||
// reliable nodes come first
|
||||
let ae = a_entry.as_ref().unwrap();
|
||||
let be = b_entry.as_ref().unwrap();
|
||||
ae.with(rti, |rti, ae| {
|
||||
be.with(rti, |_rti, be| {
|
||||
ae.with_inner(|ae| {
|
||||
be.with_inner(|be| {
|
||||
let ra = ae.check_reliable(cur_ts);
|
||||
let rb = be.check_reliable(cur_ts);
|
||||
if ra != rb {
|
||||
@@ -1020,7 +1021,25 @@ impl RoutingTableInner {
|
||||
{
|
||||
let cur_ts = get_aligned_timestamp();
|
||||
|
||||
// closest sort
|
||||
// Get the crypto kind
|
||||
let crypto_kind = node_id.kind;
|
||||
let vcrypto = self.unlocked_inner.crypto().get(crypto_kind).unwrap();
|
||||
|
||||
// Filter to ensure entries support the crypto kind in use
|
||||
|
||||
let filter = Box::new(
|
||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||
if let Some(entry) = opt_entry {
|
||||
entry.with_inner(|e| e.crypto_kinds().contains(&crypto_kind))
|
||||
} else {
|
||||
VALID_CRYPTO_KINDS.contains(&crypto_kind)
|
||||
}
|
||||
},
|
||||
) as RoutingTableEntryFilter;
|
||||
filters.push_front(filter);
|
||||
|
||||
// Closest sort
|
||||
// Distance is done using the node id's distance metric which may vary based on crypto system
|
||||
let sort = |rti: &RoutingTableInner,
|
||||
a_entry: &Option<Arc<BucketEntry>>,
|
||||
b_entry: &Option<Arc<BucketEntry>>| {
|
||||
@@ -1038,10 +1057,10 @@ impl RoutingTableInner {
|
||||
// reliable nodes come first, pessimistically treating our own node as unreliable
|
||||
let ra = a_entry
|
||||
.as_ref()
|
||||
.map_or(false, |x| x.with(rti, |_rti, x| x.check_reliable(cur_ts)));
|
||||
.map_or(false, |x| x.with_inner(|x| x.check_reliable(cur_ts)));
|
||||
let rb = b_entry
|
||||
.as_ref()
|
||||
.map_or(false, |x| x.with(rti, |_rti, x| x.check_reliable(cur_ts)));
|
||||
.map_or(false, |x| x.with_inner(|x| x.check_reliable(cur_ts)));
|
||||
if ra != rb {
|
||||
if ra {
|
||||
return core::cmp::Ordering::Less;
|
||||
@@ -1050,9 +1069,24 @@ impl RoutingTableInner {
|
||||
}
|
||||
}
|
||||
|
||||
// get keys
|
||||
let a_key = if let Some(a_entry) = a_entry {
|
||||
a_entry.with_inner(|e| e.node_ids().get(crypto_kind).unwrap())
|
||||
} else {
|
||||
self.unlocked_inner.node_id(crypto_kind)
|
||||
};
|
||||
let b_key = if let Some(b_entry) = b_entry {
|
||||
b_entry.with_inner(|e| e.node_ids().get(crypto_kind).unwrap())
|
||||
} else {
|
||||
self.unlocked_inner.node_id(crypto_kind)
|
||||
};
|
||||
|
||||
// distance is the next metric, closer nodes first
|
||||
let da = distance(a_key, &node_id);
|
||||
let db = distance(b_key, &node_id);
|
||||
// since multiple cryptosystems are in use, the distance for a key is the shortest
|
||||
// distance to that key over all supported cryptosystems
|
||||
|
||||
let da = vcrypto.distance(&a_key.key, &node_id.key);
|
||||
let db = vcrypto.distance(&b_key.key, &node_id.key);
|
||||
da.cmp(&db)
|
||||
};
|
||||
|
||||
|
@@ -262,12 +262,15 @@ impl RoutingTable {
|
||||
self.register_node_with_peer_info(RoutingDomain::PublicInternet, pi, false)
|
||||
{
|
||||
// Add this our futures to process in parallel
|
||||
let routing_table = self.clone();
|
||||
unord.push(
|
||||
// lets ask bootstrap to find ourselves now
|
||||
async move { routing_table.reverse_find_node(nr, true).await }
|
||||
.instrument(Span::current()),
|
||||
);
|
||||
for crypto_kind in VALID_CRYPTO_KINDS {
|
||||
let routing_table = self.clone();
|
||||
let nr = nr.clone();
|
||||
unord.push(
|
||||
// lets ask bootstrap to find ourselves now
|
||||
async move { routing_table.reverse_find_node(crypto_kind, nr, true).await }
|
||||
.instrument(Span::current()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,27 +340,32 @@ impl RoutingTable {
|
||||
self.register_node_with_peer_info(RoutingDomain::PublicInternet, pi, true)
|
||||
{
|
||||
// Add this our futures to process in parallel
|
||||
let routing_table = self.clone();
|
||||
unord.push(
|
||||
async move {
|
||||
// Need VALID signed peer info, so ask bootstrap to find_node of itself
|
||||
// which will ensure it has the bootstrap's signed peer info as part of the response
|
||||
let _ = routing_table.find_target(nr.clone()).await;
|
||||
for crypto_kind in VALID_CRYPTO_KINDS {
|
||||
let nr = nr.clone();
|
||||
let routing_table = self.clone();
|
||||
unord.push(
|
||||
async move {
|
||||
// Need VALID signed peer info, so ask bootstrap to find_node of itself
|
||||
// which will ensure it has the bootstrap's signed peer info as part of the response
|
||||
let _ = routing_table.find_target(crypto_kind, nr.clone()).await;
|
||||
|
||||
// Ensure we got the signed peer info
|
||||
if !nr.signed_node_info_has_valid_signature(RoutingDomain::PublicInternet) {
|
||||
log_rtab!(warn
|
||||
"bootstrap at {:?} did not return valid signed node info",
|
||||
nr
|
||||
);
|
||||
// If this node info is invalid, it will time out after being unpingable
|
||||
} else {
|
||||
// otherwise this bootstrap is valid, lets ask it to find ourselves now
|
||||
routing_table.reverse_find_node(nr, true).await
|
||||
// Ensure we got the signed peer info
|
||||
if !nr
|
||||
.signed_node_info_has_valid_signature(RoutingDomain::PublicInternet)
|
||||
{
|
||||
log_rtab!(warn
|
||||
"bootstrap at {:?} did not return valid signed node info",
|
||||
nr
|
||||
);
|
||||
// If this node info is invalid, it will time out after being unpingable
|
||||
} else {
|
||||
// otherwise this bootstrap is valid, lets ask it to find ourselves now
|
||||
routing_table.reverse_find_node(crypto_kind, nr, true).await
|
||||
}
|
||||
}
|
||||
}
|
||||
.instrument(Span::current()),
|
||||
);
|
||||
.instrument(Span::current()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,22 +20,39 @@ impl RoutingTable {
|
||||
|
||||
// For the PublicInternet routing domain, get list of all peers we know about
|
||||
// even the unreliable ones, and ask them to find nodes close to our node too
|
||||
let routing_table = self.clone();
|
||||
let noderefs = routing_table.find_fastest_nodes(
|
||||
min_peer_count,
|
||||
VecDeque::new(),
|
||||
|_rti, entry: Option<Arc<BucketEntry>>| {
|
||||
NodeRef::new(routing_table.clone(), entry.unwrap().clone(), None)
|
||||
},
|
||||
);
|
||||
|
||||
let mut ord = FuturesOrdered::new();
|
||||
for nr in noderefs {
|
||||
|
||||
for crypto_kind in VALID_CRYPTO_KINDS {
|
||||
let routing_table = self.clone();
|
||||
ord.push_back(
|
||||
async move { routing_table.reverse_find_node(nr, false).await }
|
||||
.instrument(Span::current()),
|
||||
|
||||
let mut filters = VecDeque::new();
|
||||
let filter = Box::new(
|
||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||
if let Some(entry) = opt_entry {
|
||||
entry.with_inner(|e| e.crypto_kinds().contains(&crypto_kind))
|
||||
} else {
|
||||
VALID_CRYPTO_KINDS.contains(&crypto_kind)
|
||||
}
|
||||
},
|
||||
) as RoutingTableEntryFilter;
|
||||
filters.push_front(filter);
|
||||
|
||||
let noderefs = routing_table.find_fastest_nodes(
|
||||
min_peer_count,
|
||||
filters,
|
||||
|_rti, entry: Option<Arc<BucketEntry>>| {
|
||||
NodeRef::new(routing_table.clone(), entry.unwrap().clone(), None)
|
||||
},
|
||||
);
|
||||
|
||||
for nr in noderefs {
|
||||
let routing_table = self.clone();
|
||||
ord.push_back(
|
||||
async move { routing_table.reverse_find_node(nr, false).await }
|
||||
.instrument(Span::current()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// do peer minimum search in order from fastest to slowest
|
||||
|
Reference in New Issue
Block a user