checkpoint

This commit is contained in:
John Smith
2023-02-11 15:54:55 -05:00
parent 064e6c018c
commit 1ba0cdb9cf
42 changed files with 655 additions and 350 deletions

View File

@@ -134,7 +134,7 @@ struct PublicAddressCheckCacheKey(ProtocolType, AddressType);
// The mutable state of the network manager
struct NetworkManagerInner {
stats: NetworkManagerStats,
client_whitelist: LruCache<PublicKey, ClientWhitelistEntry>,
client_whitelist: LruCache<TypedKey, ClientWhitelistEntry>,
public_address_check_cache:
BTreeMap<PublicAddressCheckCacheKey, LruCache<IpAddr, SocketAddress>>,
public_address_inconsistencies_table:
@@ -396,7 +396,7 @@ impl NetworkManager {
debug!("finished network manager shutdown");
}
pub fn update_client_whitelist(&self, client: PublicKey) {
pub fn update_client_whitelist(&self, client: TypedKey) {
let mut inner = self.inner.lock();
match inner.client_whitelist.entry(client) {
hashlink::lru_cache::Entry::Occupied(mut entry) => {
@@ -411,7 +411,7 @@ impl NetworkManager {
}
#[instrument(level = "trace", skip(self), ret)]
pub fn check_client_whitelist(&self, client: PublicKey) -> bool {
pub fn check_client_whitelist(&self, client: TypedKey) -> bool {
let mut inner = self.inner.lock();
match inner.client_whitelist.entry(client) {
@@ -519,12 +519,15 @@ impl NetworkManager {
let routing_table = self.routing_table();
// Generate receipt and serialized form to return
xxx add 'preferred_kind' and propagate envelope changes so we can make recent_peers work with cryptokind
let nonce = Crypto::get_random_nonce();
let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?;
let vcrypto = self.crypto().best();
let nonce = vcrypto.random_nonce();
let node_id = routing_table.node_id(vcrypto.kind());
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
let receipt = Receipt::try_new(MAX_ENVELOPE_VERSION, node_id.kind, nonce, node_id.key, extra_data)?;
let out = receipt
.to_signed_data(&routing_table.node_id_secret())
.to_signed_data(self.crypto(), &node_id_secret)
.wrap_err("failed to generate signed receipt")?;
// Record the receipt for later
@@ -545,10 +548,15 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
let routing_table = self.routing_table();
// Generate receipt and serialized form to return
let nonce = Crypto::get_random_nonce();
let receipt = Receipt::try_new(0, nonce, routing_table.node_id(), extra_data)?;
let vcrypto = self.crypto().best();
let nonce = vcrypto.random_nonce();
let node_id = routing_table.node_id(vcrypto.kind());
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
let receipt = Receipt::try_new(MAX_ENVELOPE_VERSION, node_id.kind, nonce, node_id.key, extra_data)?;
let out = receipt
.to_signed_data(&routing_table.node_id_secret())
.to_signed_data(self.crypto(), &node_id_secret)
.wrap_err("failed to generate signed receipt")?;
// Record the receipt for later
@@ -568,7 +576,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
) -> NetworkResult<()> {
let receipt_manager = self.receipt_manager();
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
let receipt = match Receipt::from_signed_data(self.crypto(), receipt_data.as_ref()) {
Err(e) => {
return NetworkResult::invalid_message(e.to_string());
}
@@ -589,7 +597,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
) -> NetworkResult<()> {
let receipt_manager = self.receipt_manager();
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
let receipt = match Receipt::from_signed_data(self.crypto(), receipt_data.as_ref()) {
Err(e) => {
return NetworkResult::invalid_message(e.to_string());
}
@@ -609,7 +617,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
) -> NetworkResult<()> {
let receipt_manager = self.receipt_manager();
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
let receipt = match Receipt::from_signed_data(self.crypto(), receipt_data.as_ref()) {
Err(e) => {
return NetworkResult::invalid_message(e.to_string());
}
@@ -626,11 +634,11 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
pub async fn handle_private_receipt<R: AsRef<[u8]>>(
&self,
receipt_data: R,
private_route: PublicKey,
private_route: TypedKey,
) -> NetworkResult<()> {
let receipt_manager = self.receipt_manager();
let receipt = match Receipt::from_signed_data(receipt_data.as_ref()) {
let receipt = match Receipt::from_signed_data(self.crypto(), receipt_data.as_ref()) {
Err(e) => {
return NetworkResult::invalid_message(e.to_string());
}
@@ -653,8 +661,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
// Add the peer info to our routing table
let peer_nr = match routing_table.register_node_with_peer_info(
RoutingDomain::PublicInternet,
peer_info.node_id.key,
peer_info.signed_node_info,
peer_info,
false,
) {
None => {
@@ -677,8 +684,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
// Add the peer info to our routing table
let mut peer_nr = match routing_table.register_node_with_peer_info(
RoutingDomain::PublicInternet,
peer_info.node_id.key,
peer_info.signed_node_info,
peer_info,
false,
) {
None => {
@@ -733,21 +739,25 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
#[instrument(level = "trace", skip(self, body), err)]
fn build_envelope<B: AsRef<[u8]>>(
&self,
dest_node_id: PublicKey,
dest_node_id: TypedKey,
version: u8,
body: B,
) -> EyreResult<Vec<u8>> {
// DH to get encryption key
let routing_table = self.routing_table();
let node_id = routing_table.node_id();
let node_id_secret = routing_table.node_id_secret();
let Some(vcrypto) = self.crypto().get(dest_node_id.kind) else {
bail!("should not have a destination with incompatible crypto here");
};
let node_id = routing_table.node_id(vcrypto.kind());
let node_id_secret = routing_table.node_id_secret(vcrypto.kind());
// Get timestamp, nonce
let ts = get_aligned_timestamp();
let nonce = Crypto::get_random_nonce();
let nonce = vcrypto.random_nonce();
// Encode envelope
let envelope = Envelope::new(version, ts, nonce, node_id, dest_node_id);
let envelope = Envelope::new(version, node_id.kind, ts, nonce, node_id.key, dest_node_id.key);
envelope
.to_encrypted_data(self.crypto(), body.as_ref(), &node_id_secret)
.wrap_err("envelope failed to encode")
@@ -755,19 +765,22 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
/// Called by the RPC handler when we want to issue an RPC request or response
/// node_ref is the direct destination to which the envelope will be sent
/// If 'node_id' is specified, it can be different than node_ref.node_id()
/// If 'envelope_node_id' is specified, it can be different than the node_ref being sent to
/// which will cause the envelope to be relayed
#[instrument(level = "trace", skip(self, body), ret, err)]
pub async fn send_envelope<B: AsRef<[u8]>>(
&self,
node_ref: NodeRef,
envelope_node_id: Option<PublicKey>,
envelope_node_id: Option<TypedKey>,
body: B,
) -> EyreResult<NetworkResult<SendDataKind>> {
let via_node_id = node_ref.node_id();
let envelope_node_id = envelope_node_id.unwrap_or(via_node_id);
let via_node_ids = node_ref.node_ids();
let Some(best_via_node_id) = via_node_ids.best() else {
bail!("should have a best node id");
};
let envelope_node_id = envelope_node_id.unwrap_or(best_via_node_id);
if envelope_node_id != via_node_id {
if !via_node_ids.contains(&envelope_node_id) {
log_net!(
"sending envelope to {:?} via {:?}",
envelope_node_id,
@@ -776,11 +789,13 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
} else {
log_net!("sending envelope to {:?}", node_ref);
}
// Get node's min/max version and see if we can send to it
// Get node's min/max envelope version and see if we can send to it
// and if so, get the max version we can use
let version = if let Some(min_max_version) = node_ref.min_max_version() {
node_ref.envelope_support()
let envelope_version = if let Some(min_max_version) = {
#[allow(clippy::absurd_extreme_comparisons)]
if min_max_version.min > MAX_CRYPTO_VERSION || min_max_version.max < MIN_CRYPTO_VERSION
if min_max_version.min > MAX_ENVELOPE_VERSION || min_max_version.max < MIN_ENVELOPE_VERSION
{
bail!(
"can't talk to this node {} because version is unsupported: ({},{})",
@@ -1374,7 +1389,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
// If the recipient id is not our node id, then it needs relaying
let sender_id = TypedKey::new(envelope.get_crypto_kind(), envelope.get_sender_id());
let recipient_id = TypedKey::new(envelope.get_crypto_kind(), envelope.get_recipient_id());
if recipient_id != routing_table.node_id() {
if !routing_table.matches_own_node_id(&[recipient_id]) {
// See if the source node is allowed to resolve nodes
// This is a costly operation, so only outbound-relay permitted
// nodes are allowed to do this, for example PWA users
@@ -1419,7 +1434,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
}
// DH to get decryption key (cached)
let node_id_secret = routing_table.node_id_secret();
let node_id_secret = routing_table.node_id_secret(envelope.get_crypto_kind());
// Decrypt the envelope body
let body = match envelope
@@ -1445,7 +1460,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
}
Some(v) => v,
};
source_noderef.set_min_max_version(envelope.get_min_max_version());
source_noderef.add_envelope_version(envelope.get_version());
// xxx: deal with spoofing and flooding here?
@@ -1539,7 +1554,7 @@ xxx add 'preferred_kind' and propagate envelope changes so we can make recent_pe
if let Some(nr) = routing_table.lookup_node_ref(k) {
let peer_stats = nr.peer_stats();
let peer = PeerTableData {
node_ids: k,
node_ids: nr.node_ids(),
peer_address: v.last_connection.remote(),
peer_stats,
};

View File

@@ -112,7 +112,7 @@ impl DiscoveryContext {
&self,
protocol_type: ProtocolType,
address_type: AddressType,
ignore_node: Option<PublicKey>,
ignore_node_ids: Option<TypedKeySet>,
) -> Option<(SocketAddress, NodeRef)> {
let node_count = {
let config = self.routing_table.network_manager().config();
@@ -121,7 +121,7 @@ impl DiscoveryContext {
};
// Build an filter that matches our protocol and address type
// and excludes relays so we can get an accurate external address
// and excludes relayed nodes so we can get an accurate external address
let dial_info_filter = DialInfoFilter::all()
.with_protocol_type(protocol_type)
.with_address_type(address_type);
@@ -130,11 +130,11 @@ impl DiscoveryContext {
dial_info_filter.clone(),
);
let disallow_relays_filter = Box::new(
move |rti: &RoutingTableInner, _k: PublicKey, v: Option<Arc<BucketEntry>>| {
move |rti: &RoutingTableInner, v: Option<Arc<BucketEntry>>| {
let v = v.unwrap();
v.with(rti, |_rti, e| {
if let Some(n) = e.signed_node_info(RoutingDomain::PublicInternet) {
n.relay_id().is_none()
n.relay_ids().is_empty()
} else {
false
}
@@ -158,8 +158,8 @@ impl DiscoveryContext {
// For each peer, if it's not our ignore-node, ask them for our public address, filtering on desired dial info
for mut peer in peers {
if let Some(ignore_node) = ignore_node {
if peer.node_id() == ignore_node {
if let Some(ignore_node_ids) = &ignore_node_ids {
if peer.node_ids().contains_any(ignore_node_ids) {
continue;
}
}
@@ -478,12 +478,12 @@ impl DiscoveryContext {
// Get our external address from some fast node, that is not node 1, call it node 2
let (external_2_address, node_2) = match self
.discover_external_address(protocol_type, address_type, Some(node_1.node_id()))
.discover_external_address(protocol_type, address_type, Some(node_1.node_ids()))
.await
{
None => {
// If we can't get an external address, allow retry
log_net!(debug "failed to discover external address 2 for {:?}:{:?}, skipping node {:?}", protocol_type, address_type, node_1.node_id());
log_net!(debug "failed to discover external address 2 for {:?}:{:?}, skipping node {:?}", protocol_type, address_type, node_1);
return Ok(false);
}
Some(v) => v,