consensus_config/
test_committee.rs1use std::net::{TcpListener, TcpStream};
5
6use fastcrypto::traits::{KeyPair as _, ToFromBytes as _};
7use mysten_network::Multiaddr;
8use rand::{SeedableRng as _, rngs::StdRng};
9
10use crate::{Authority, AuthorityName, Committee, Epoch, NetworkKeyPair, ProtocolKeyPair, Stake};
11
12pub fn local_committee_and_keys(
14 epoch: Epoch,
15 authorities_stake: Vec<Stake>,
16) -> (Committee, Vec<(NetworkKeyPair, ProtocolKeyPair)>) {
17 local_committee_and_keys_with_test_options(epoch, authorities_stake, true)
18}
19
20pub fn local_committee_and_keys_with_test_options(
21 epoch: Epoch,
22 authorities_stake: Vec<Stake>,
23 unused_port: bool,
24) -> (Committee, Vec<(NetworkKeyPair, ProtocolKeyPair)>) {
25 let mut authorities = vec![];
26 let mut key_pairs = vec![];
27 let mut rng = StdRng::from_seed([0; 32]);
28 for (i, stake) in authorities_stake.into_iter().enumerate() {
29 let authority_keypair = fastcrypto::bls12381::min_sig::BLS12381KeyPair::generate(&mut rng);
30 let protocol_keypair = ProtocolKeyPair::generate(&mut rng);
31 let network_keypair = NetworkKeyPair::generate(&mut rng);
32 authorities.push(Authority {
33 stake,
34 address: if unused_port {
35 get_available_local_address()
36 } else {
37 "/ip4/127.0.0.1/udp/8081".parse().unwrap()
38 },
39 hostname: format!("test_host_{i}").to_string(),
40 authority_name: AuthorityName::from_bytes(authority_keypair.public().as_bytes()),
41 protocol_key: protocol_keypair.public(),
42 network_key: network_keypair.public(),
43 });
44 key_pairs.push((network_keypair, protocol_keypair));
45 }
46
47 let committee = Committee::new(epoch, authorities);
48 (committee, key_pairs)
49}
50
51fn get_available_local_address() -> Multiaddr {
53 let host = "127.0.0.1";
54 let port = get_available_port(host);
55 format!("/ip4/{}/udp/{}", host, port).parse().unwrap()
56}
57
58fn get_available_port(host: &str) -> u16 {
62 const MAX_PORT_RETRIES: u32 = 1000;
63
64 for _ in 0..MAX_PORT_RETRIES {
65 if let Ok(port) = get_ephemeral_port(host) {
66 return port;
67 }
68 }
69
70 panic!("Error: could not find an available port");
71}
72
73fn get_ephemeral_port(host: &str) -> std::io::Result<u16> {
74 let listener = TcpListener::bind((host, 0))?;
76 let addr = listener.local_addr()?;
77
78 let _sender = TcpStream::connect(addr)?;
82 let _incoming = listener.accept()?;
83
84 Ok(addr.port())
85}