//! Fixed test vectors for the address book. use std::time::Instant; use chrono::Utc; use tracing::Span; use zebra_chain::{ parameters::Network::*, serialization::{DateTime32, Duration32}, }; use crate::{ constants::{DEFAULT_MAX_CONNS_PER_IP, MAX_ADDRS_IN_ADDRESS_BOOK}, meta_addr::MetaAddr, protocol::external::types::PeerServices, AddressBook, }; /// Make sure an empty address book is actually empty. #[test] fn address_book_empty() { let address_book = AddressBook::new( "0.0.0.0:0".parse().unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, Span::current(), ); assert_eq!( address_book .reconnection_peers(Instant::now(), Utc::now()) .next(), None ); assert_eq!(address_book.len(), 0); } /// Make sure peers are attempted in priority order. #[test] fn address_book_peer_order() { let addr1 = "127.0.0.1:1".parse().unwrap(); let addr2 = "127.0.0.2:2".parse().unwrap(); let mut meta_addr1 = MetaAddr::new_gossiped_meta_addr(addr1, PeerServices::NODE_NETWORK, DateTime32::MIN); let mut meta_addr2 = MetaAddr::new_gossiped_meta_addr( addr2, PeerServices::NODE_NETWORK, DateTime32::MIN.saturating_add(Duration32::from_seconds(1)), ); // Regardless of the order of insertion, the most recent address should be chosen first let addrs = vec![meta_addr1, meta_addr2]; let address_book = AddressBook::new_with_addrs( "0.0.0.0:0".parse().unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, MAX_ADDRS_IN_ADDRESS_BOOK, Span::current(), addrs, ); assert_eq!( address_book .reconnection_peers(Instant::now(), Utc::now()) .next(), Some(meta_addr2), ); // Reverse the order, check that we get the same result let addrs = vec![meta_addr2, meta_addr1]; let address_book = AddressBook::new_with_addrs( "0.0.0.0:0".parse().unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, MAX_ADDRS_IN_ADDRESS_BOOK, Span::current(), addrs, ); assert_eq!( address_book .reconnection_peers(Instant::now(), Utc::now()) .next(), Some(meta_addr2), ); // Now check that the order depends on the time, not the address meta_addr1.addr = addr2; meta_addr2.addr = addr1; let addrs = vec![meta_addr1, meta_addr2]; let address_book = AddressBook::new_with_addrs( "0.0.0.0:0".parse().unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, MAX_ADDRS_IN_ADDRESS_BOOK, Span::current(), addrs, ); assert_eq!( address_book .reconnection_peers(Instant::now(), Utc::now()) .next(), Some(meta_addr2), ); // Reverse the order, check that we get the same result let addrs = vec![meta_addr2, meta_addr1]; let address_book = AddressBook::new_with_addrs( "0.0.0.0:0".parse().unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, MAX_ADDRS_IN_ADDRESS_BOOK, Span::current(), addrs, ); assert_eq!( address_book .reconnection_peers(Instant::now(), Utc::now()) .next(), Some(meta_addr2), ); } /// Check that `reconnection_peers` skips addresses with IPs for which /// Zebra already has recently updated outbound peers. #[test] fn reconnection_peers_skips_recently_updated_ip() { // tests that reconnection_peers() skips addresses where there's a connection at that IP with a recent: // - `last_response` test_reconnection_peers_skips_recently_updated_ip(true, MetaAddr::new_responded); // tests that reconnection_peers() *does not* skip addresses where there's a connection at that IP with a recent: // - `last_attempt` test_reconnection_peers_skips_recently_updated_ip(false, MetaAddr::new_reconnect); // - `last_failure` test_reconnection_peers_skips_recently_updated_ip(false, |addr| { MetaAddr::new_errored(addr, PeerServices::NODE_NETWORK) }); } fn test_reconnection_peers_skips_recently_updated_ip< M: Fn(crate::PeerSocketAddr) -> crate::meta_addr::MetaAddrChange, >( should_skip_ip: bool, make_meta_addr_change: M, ) { let addr1 = "127.0.0.1:1".parse().unwrap(); let addr2 = "127.0.0.1:2".parse().unwrap(); let meta_addr1 = make_meta_addr_change(addr1).into_new_meta_addr( Instant::now(), Utc::now().try_into().expect("will succeed until 2038"), ); let meta_addr2 = MetaAddr::new_gossiped_meta_addr( addr2, PeerServices::NODE_NETWORK, DateTime32::MIN.saturating_add(Duration32::from_seconds(1)), ); // The second address should be skipped because the first address has a // recent `last_response` time and the two addresses have the same IP. let addrs = vec![meta_addr1, meta_addr2]; let address_book = AddressBook::new_with_addrs( "0.0.0.0:0".parse().unwrap(), &Mainnet, DEFAULT_MAX_CONNS_PER_IP, MAX_ADDRS_IN_ADDRESS_BOOK, Span::current(), addrs, ); let next_reconnection_peer = address_book .reconnection_peers(Instant::now(), Utc::now()) .next(); if should_skip_ip { assert_eq!(next_reconnection_peer, None,); } else { assert_ne!(next_reconnection_peer, None,); } }