diff --git a/crates/iroha/tests/extra_functional/connected_peers.rs b/crates/iroha/tests/extra_functional/connected_peers.rs index 7dbab107963..31272cfd8b5 100644 --- a/crates/iroha/tests/extra_functional/connected_peers.rs +++ b/crates/iroha/tests/extra_functional/connected_peers.rs @@ -3,10 +3,7 @@ use std::iter::once; use assert_matches::assert_matches; use eyre::Result; use futures_util::{stream::FuturesUnordered, StreamExt}; -use iroha::data_model::{ - isi::{Register, Unregister}, - peer::Peer, -}; +use iroha::data_model::isi::{Register, Unregister}; use iroha_config_base::toml::WriteExt; use iroha_test_network::*; use rand::{prelude::IteratorRandom, seq::SliceRandom, thread_rng}; @@ -31,12 +28,12 @@ async fn register_new_peer() -> Result<()> { network .config() // only one random peer - .write(["sumeragi", "trusted_peers"], [network.peer().id()]), + .write(["sumeragi", "trusted_peers"], [network.peer().peer()]), None, ) .await; - let register = Register::peer(Peer::new(peer.id())); + let register = Register::peer(peer.peer_id()); let client = network.client(); spawn_blocking(move || client.submit_blocking(register)).await??; @@ -62,7 +59,7 @@ async fn connected_peers_with_f(faults: usize) -> Result<()> { // Unregister a peer: committed with f = `faults` then `status.peers` decrements let client = randomized_peers.choose(&mut thread_rng()).unwrap().client(); - let unregister_peer = Unregister::peer(removed_peer.id()); + let unregister_peer = Unregister::peer(removed_peer.peer_id()); spawn_blocking(move || client.submit_blocking(unregister_peer)).await??; timeout( network.sync_timeout(), @@ -81,7 +78,7 @@ async fn connected_peers_with_f(faults: usize) -> Result<()> { assert_eq!(status.peers, 0); // Re-register the peer: committed with f = `faults` - 1 then `status.peers` increments - let register_peer = Register::peer(Peer::new(removed_peer.id())); + let register_peer = Register::peer(removed_peer.peer_id()); let client = randomized_peers .iter() .choose(&mut thread_rng()) @@ -112,13 +109,13 @@ async fn assert_peers_status( status.peers, expected_peers, "unexpected peers for {}", - peer.id() + peer.peer_id() ); assert_eq!( status.blocks, expected_blocks, "expected blocks for {}", - peer.id() + peer.peer_id() ); }) .collect::>() diff --git a/crates/iroha/tests/extra_functional/offline_peers.rs b/crates/iroha/tests/extra_functional/offline_peers.rs index d61e5475b1f..13a79664441 100644 --- a/crates/iroha/tests/extra_functional/offline_peers.rs +++ b/crates/iroha/tests/extra_functional/offline_peers.rs @@ -2,12 +2,8 @@ use eyre::{OptionExt, Result}; use futures_util::stream::{FuturesUnordered, StreamExt}; use iroha::{ crypto::KeyPair, - data_model::{ - peer::{Peer as DataModelPeer, PeerId}, - prelude::*, - }, + data_model::{peer::PeerId, prelude::*}, }; -use iroha_primitives::addr::socket_addr; use iroha_test_network::*; use iroha_test_samples::ALICE_ID; use tokio::task::spawn_blocking; @@ -66,11 +62,10 @@ async fn register_offline_peer() -> Result<()> { let network = NetworkBuilder::new().with_peers(N_PEERS).start().await?; check_status(&network, N_PEERS as u64 - 1).await; - let address = socket_addr!(128.0.0.2:8085); let key_pair = KeyPair::random(); let public_key = key_pair.public_key().clone(); - let peer_id = PeerId::new(address, public_key); - let register_peer = Register::peer(DataModelPeer::new(peer_id)); + let peer_id = PeerId::new(public_key); + let register_peer = Register::peer(peer_id); // Wait for some time to allow peers to connect let client = network.client(); diff --git a/crates/iroha/tests/extra_functional/unregister_peer.rs b/crates/iroha/tests/extra_functional/unregister_peer.rs index c2c40f6d5bd..52151f8aa76 100644 --- a/crates/iroha/tests/extra_functional/unregister_peer.rs +++ b/crates/iroha/tests/extra_functional/unregister_peer.rs @@ -47,14 +47,14 @@ async fn network_stable_after_add_and_after_remove_peer() -> Result<()> { network.ensure_blocks(3).await?; // and a new peer is registered let new_peer = NetworkPeer::generate(); - let new_peer_id = new_peer.id(); + let new_peer_id = new_peer.peer_id(); let new_peer_client = new_peer.client(); network.add_peer(&new_peer); new_peer.start(network.config(), None).await; { let client = client.clone(); let id = new_peer_id.clone(); - spawn_blocking(move || client.submit_blocking(Register::peer(Peer::new(id)))).await??; + spawn_blocking(move || client.submit_blocking(Register::peer(id))).await??; } network.ensure_blocks(4).await?; // Then the new peer should already have the mint result. diff --git a/crates/iroha_cli/src/main.rs b/crates/iroha_cli/src/main.rs index e4fe13d190f..41c8d252843 100644 --- a/crates/iroha_cli/src/main.rs +++ b/crates/iroha_cli/src/main.rs @@ -11,7 +11,7 @@ use erased_serde::Serialize; use error_stack::{fmt::ColorMode, IntoReportCompat, ResultExt}; use eyre::{eyre, Error, Result, WrapErr}; use iroha::{client::Client, config::Config, data_model::prelude::*}; -use iroha_primitives::{addr::SocketAddr, json::Json}; +use iroha_primitives::json::Json; use thiserror::Error; /// Re-usable clap `--metadata ` (`-m`) argument. @@ -1033,9 +1033,6 @@ mod peer { /// Register subcommand of peer #[derive(clap::Args, Debug)] pub struct Register { - /// P2P address of the peer e.g. `127.0.0.1:1337` - #[arg(short, long)] - pub address: SocketAddr, /// Public key of the peer #[arg(short, long)] pub key: PublicKey, @@ -1045,13 +1042,8 @@ mod peer { impl RunArgs for Register { fn run(self, context: &mut dyn RunContext) -> Result<()> { - let Self { - address, - key, - metadata, - } = self; - let register_peer = - iroha::data_model::isi::Register::peer(Peer::new(PeerId::new(address, key))); + let Self { key, metadata } = self; + let register_peer = iroha::data_model::isi::Register::peer(key.into()); submit([register_peer], metadata.load()?, context).wrap_err("Failed to register peer") } } @@ -1059,9 +1051,6 @@ mod peer { /// Unregister subcommand of peer #[derive(clap::Args, Debug)] pub struct Unregister { - /// P2P address of the peer e.g. `127.0.0.1:1337` - #[arg(short, long)] - pub address: SocketAddr, /// Public key of the peer #[arg(short, long)] pub key: PublicKey, @@ -1071,13 +1060,8 @@ mod peer { impl RunArgs for Unregister { fn run(self, context: &mut dyn RunContext) -> Result<()> { - let Self { - address, - key, - metadata, - } = self; - let unregister_peer = - iroha::data_model::isi::Unregister::peer(PeerId::new(address, key)); + let Self { key, metadata } = self; + let unregister_peer = iroha::data_model::isi::Unregister::peer(key.into()); submit([unregister_peer], metadata.load()?, context) .wrap_err("Failed to unregister peer") } diff --git a/crates/iroha_config/iroha_test_config.toml b/crates/iroha_config/iroha_test_config.toml index ac65c79a9c3..0fb2e8ff6d3 100644 --- a/crates/iroha_config/iroha_test_config.toml +++ b/crates/iroha_config/iroha_test_config.toml @@ -4,6 +4,7 @@ private_key = "802620282ED9F3CF92811C3818DBC4AE594ED59DC1A2F78E4241E31924E101D6B [network] address = "127.0.0.1:1337" +public_address = "127.0.0.1:1337" [genesis] public_key = "ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4" diff --git a/crates/iroha_config/src/parameters/actual.rs b/crates/iroha_config/src/parameters/actual.rs index 89fafe21f23..015f9a4bf40 100644 --- a/crates/iroha_config/src/parameters/actual.rs +++ b/crates/iroha_config/src/parameters/actual.rs @@ -10,7 +10,10 @@ use std::{ use error_stack::{Result, ResultExt}; use iroha_config_base::{read::ConfigReader, toml::TomlSource, util::Bytes, WithOrigin}; use iroha_crypto::{KeyPair, PublicKey}; -use iroha_data_model::{peer::PeerId, ChainId}; +use iroha_data_model::{ + peer::{Peer, PeerId}, + ChainId, Identifiable, +}; use iroha_primitives::{addr::SocketAddr, unique_vec::UniqueVec}; use url::Url; pub use user::{DevTelemetry, Logger, Snapshot}; @@ -66,7 +69,7 @@ impl Root { pub struct Common { pub chain: ChainId, pub key_pair: KeyPair, - pub peer: PeerId, + pub peer: Peer, } /// Network options @@ -74,6 +77,7 @@ pub struct Common { #[derive(Debug, Clone)] pub struct Network { pub address: WithOrigin, + pub public_address: WithOrigin, pub idle_timeout: Duration, } @@ -125,15 +129,18 @@ pub struct Sumeragi { #[derive(Debug, Clone)] #[allow(missing_docs)] pub struct TrustedPeers { - pub myself: PeerId, - pub others: UniqueVec, + pub myself: Peer, + pub others: UniqueVec, } impl TrustedPeers { /// Returns a list of trusted peers which is guaranteed to have at /// least one element - the id of the peer itself. pub fn into_non_empty_vec(self) -> UniqueVec { - std::iter::once(self.myself).chain(self.others).collect() + std::iter::once(self.myself) + .chain(self.others) + .map(|peer| peer.id().clone()) + .collect() } /// Tells whether a trusted peers list has some other peers except for the peer itself @@ -197,8 +204,8 @@ mod tests { use super::*; - fn dummy_id(port: u16) -> PeerId { - PeerId::new( + fn dummy_peer(port: u16) -> Peer { + Peer::new( socket_addr!(127.0.0.1:port), KeyPair::random().into_parts().0, ) @@ -207,7 +214,7 @@ mod tests { #[test] fn no_trusted_peers() { let value = TrustedPeers { - myself: dummy_id(80), + myself: dummy_peer(80), others: unique_vec![], }; assert!(!value.contains_other_trusted_peers()); @@ -216,8 +223,8 @@ mod tests { #[test] fn one_trusted_peer() { let value = TrustedPeers { - myself: dummy_id(80), - others: unique_vec![dummy_id(81)], + myself: dummy_peer(80), + others: unique_vec![dummy_peer(81)], }; assert!(value.contains_other_trusted_peers()); } @@ -225,8 +232,8 @@ mod tests { #[test] fn many_trusted_peers() { let value = TrustedPeers { - myself: dummy_id(80), - others: unique_vec![dummy_id(1), dummy_id(2), dummy_id(3), dummy_id(4),], + myself: dummy_peer(80), + others: unique_vec![dummy_peer(1), dummy_peer(2), dummy_peer(3), dummy_peer(4),], }; assert!(value.contains_other_trusted_peers()); } diff --git a/crates/iroha_config/src/parameters/user.rs b/crates/iroha_config/src/parameters/user.rs index 550f702b971..6edfe2077f8 100644 --- a/crates/iroha_config/src/parameters/user.rs +++ b/crates/iroha_config/src/parameters/user.rs @@ -26,7 +26,7 @@ use iroha_config_base::{ ReadConfig, WithOrigin, }; use iroha_crypto::{PrivateKey, PublicKey}; -use iroha_data_model::{peer::PeerId, ChainId}; +use iroha_data_model::{peer::Peer, ChainId}; use iroha_primitives::{addr::SocketAddr, unique_vec::UniqueVec}; use serde::Deserialize; use url::Url; @@ -116,16 +116,16 @@ impl Root { let (torii, live_query_store) = self.torii.parse(); let telemetry = self.telemetry.map(actual::Telemetry::from); - let peer_id = key_pair.as_ref().map(|key_pair| { - PeerId::new( + let peer = key_pair.as_ref().map(|key_pair| { + Peer::new( network.address.value().clone(), key_pair.public_key().clone(), ) }); - let sumeragi = peer_id + let sumeragi = peer .as_ref() - .map(|id| self.sumeragi.parse_and_push_self(id.clone())); + .map(|peer| self.sumeragi.parse_and_push_self(peer.clone())); emitter.into_result()?; @@ -133,7 +133,7 @@ impl Root { let peer = actual::Common { chain: self.chain.0, key_pair, - peer: peer_id.unwrap(), + peer: peer.unwrap(), }; Ok(actual::Root { @@ -226,7 +226,7 @@ pub struct Sumeragi { } #[derive(Debug, Deserialize)] -pub struct TrustedPeers(UniqueVec); +pub struct TrustedPeers(UniqueVec); impl FromEnvStr for TrustedPeers { type Error = json5::Error; @@ -246,7 +246,7 @@ impl Default for TrustedPeers { } impl Sumeragi { - fn parse_and_push_self(self, self_id: PeerId) -> actual::Sumeragi { + fn parse_and_push_self(self, self_id: Peer) -> actual::Sumeragi { let Self { trusted_peers, debug: SumeragiDebug { force_soft_fork }, @@ -270,9 +270,13 @@ pub struct SumeragiDebug { #[derive(Debug, Clone, ReadConfig)] pub struct Network { - /// Peer-to-peer address + /// Peer-to-peer address (internal, will be used only to bind to it). #[config(env = "P2P_ADDRESS")] pub address: WithOrigin, + /// Peer-to-peer address (external, as seen by other peers). + /// Will be gossiped to connected peers so that they can gossip it to other peers. + #[config(env = "P2P_PUBLIC_ADDRESS")] + pub public_address: WithOrigin, #[config(default = "defaults::network::BLOCK_GOSSIP_SIZE")] pub block_gossip_size: NonZeroU32, #[config(default = "defaults::network::BLOCK_GOSSIP_PERIOD.into()")] @@ -296,6 +300,7 @@ impl Network { ) { let Self { address, + public_address, block_gossip_size, block_gossip_period_ms: block_gossip_period, transaction_gossip_size, @@ -306,6 +311,7 @@ impl Network { ( actual::Network { address, + public_address, idle_timeout: idle_timeout.get(), }, actual::BlockSync { diff --git a/crates/iroha_config/tests/fixtures.rs b/crates/iroha_config/tests/fixtures.rs index b772453c3b6..c6ea25042ca 100644 --- a/crates/iroha_config/tests/fixtures.rs +++ b/crates/iroha_config/tests/fixtures.rs @@ -11,6 +11,7 @@ use error_stack::ResultExt; use expect_test::expect; use iroha_config::parameters::{actual::Root as Config, user::Root as UserConfig}; use iroha_config_base::{env::MockEnv, read::ConfigReader}; +use iroha_data_model::Identifiable; use thiserror::Error; fn fixtures_dir() -> PathBuf { @@ -80,13 +81,9 @@ fn minimal_config_snapshot() { ), private_key: "[REDACTED PrivateKey]", }, - peer: PeerId { + peer: Peer { address: 127.0.0.1:1337, - public_key: PublicKey( - ed25519( - "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB", - ), - ), + id: ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB, }, }, network: Network { @@ -97,6 +94,13 @@ fn minimal_config_snapshot() { path: "tests/fixtures/base.toml", }, }, + public_address: WithOrigin { + value: 127.0.0.1:1337, + origin: File { + id: ParameterId(network.public_address), + path: "tests/fixtures/base.toml", + }, + }, idle_timeout: 60s, }, genesis: Genesis { @@ -133,23 +137,15 @@ fn minimal_config_snapshot() { sumeragi: Sumeragi { trusted_peers: WithOrigin { value: TrustedPeers { - myself: PeerId { + myself: Peer { address: 127.0.0.1:1337, - public_key: PublicKey( - ed25519( - "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB", - ), - ), + id: ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB, }, others: UniqueVec( [ - PeerId { + Peer { address: 127.0.0.1:1338, - public_key: PublicKey( - ed25519( - "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB", - ), - ), + id: ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB, }, ], ), @@ -219,7 +215,7 @@ fn self_is_presented_in_trusted_peers() { .value() .clone() .into_non_empty_vec() - .contains(&config.common.peer)); + .contains(&config.common.peer.id())); } #[test] diff --git a/crates/iroha_config/tests/fixtures/bad.torii_addr_eq_p2p_addr.toml b/crates/iroha_config/tests/fixtures/bad.torii_addr_eq_p2p_addr.toml index 79f9c324cee..480b0667195 100644 --- a/crates/iroha_config/tests/fixtures/bad.torii_addr_eq_p2p_addr.toml +++ b/crates/iroha_config/tests/fixtures/bad.torii_addr_eq_p2p_addr.toml @@ -2,6 +2,7 @@ extends = ["base.toml", "base_trusted_peers.toml"] [network] address = "127.0.0.1:8080" +public_address = "127.0.0.1:8080" [torii] address = "127.0.0.1:8080" diff --git a/crates/iroha_config/tests/fixtures/base.toml b/crates/iroha_config/tests/fixtures/base.toml index c0d1355a1f6..48400e0a113 100644 --- a/crates/iroha_config/tests/fixtures/base.toml +++ b/crates/iroha_config/tests/fixtures/base.toml @@ -4,6 +4,7 @@ private_key = "8026208F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB89 [network] address = "127.0.0.1:1337" +public_address = "127.0.0.1:1337" [genesis] public_key = "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" diff --git a/crates/iroha_config/tests/fixtures/full.env b/crates/iroha_config/tests/fixtures/full.env index d7b916be708..3d09c06d861 100644 --- a/crates/iroha_config/tests/fixtures/full.env +++ b/crates/iroha_config/tests/fixtures/full.env @@ -2,6 +2,7 @@ CHAIN=0-0 PUBLIC_KEY=ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB PRIVATE_KEY=8026208F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB894F84F P2P_ADDRESS=127.0.0.1:5432 +P2P_PUBLIC_ADDRESS=iroha1:5432 GENESIS_PUBLIC_KEY=ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB GENESIS=./genesis.signed.scale API_ADDRESS=127.0.0.1:8080 diff --git a/crates/iroha_config/tests/fixtures/full.toml b/crates/iroha_config/tests/fixtures/full.toml index 298d5582a86..c65fcf9d382 100644 --- a/crates/iroha_config/tests/fixtures/full.toml +++ b/crates/iroha_config/tests/fixtures/full.toml @@ -10,6 +10,7 @@ file = "genesis.signed.scale" [network] address = "localhost:3840" +public_address = "localhost:3840" block_gossip_period_ms = 10_000 block_gossip_size = 4 transaction_gossip_period_ms = 1_000 diff --git a/crates/iroha_config/tests/fixtures/minimal_file_and_env.toml b/crates/iroha_config/tests/fixtures/minimal_file_and_env.toml index 10e7d77dac3..f4b8d4b32f5 100644 --- a/crates/iroha_config/tests/fixtures/minimal_file_and_env.toml +++ b/crates/iroha_config/tests/fixtures/minimal_file_and_env.toml @@ -6,6 +6,7 @@ private_key = "8026208F4C15E5D664DA3F13778801D23D4E89B76E94C1B94B389544168B6CB89 [network] address = "127.0.0.1:1337" +public_address = "127.0.0.1:1337" [genesis] public_key = "ed01208BA62848CF767D72E7F7F4B9D2D7BA07FEE33760F79ABE5597A51520E292A0CB" diff --git a/crates/iroha_core/benches/blocks/apply_blocks.rs b/crates/iroha_core/benches/blocks/apply_blocks.rs index 7db0939c1a4..63dcfb19839 100644 --- a/crates/iroha_core/benches/blocks/apply_blocks.rs +++ b/crates/iroha_core/benches/blocks/apply_blocks.rs @@ -29,7 +29,7 @@ impl StateApplyBlocks { let (domain_ids, account_ids, asset_definition_ids) = generate_ids(domains, accounts_per_domain, assets_per_domain); let (peer_public_key, peer_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); + let peer_id = PeerId::new(peer_public_key); let topology = Topology::new(vec![peer_id]); let (alice_id, alice_keypair) = gen_account_in("wonderland"); let state = build_state(rt, &alice_id); diff --git a/crates/iroha_core/benches/blocks/validate_blocks.rs b/crates/iroha_core/benches/blocks/validate_blocks.rs index b5a831bb1d0..1eed207cb26 100644 --- a/crates/iroha_core/benches/blocks/validate_blocks.rs +++ b/crates/iroha_core/benches/blocks/validate_blocks.rs @@ -30,7 +30,7 @@ impl StateValidateBlocks { let (domain_ids, account_ids, asset_definition_ids) = generate_ids(domains, accounts_per_domain, assets_per_domain); let (peer_public_key, peer_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); + let peer_id = PeerId::new(peer_public_key); let topology = Topology::new(vec![peer_id]); let (alice_id, alice_keypair) = gen_account_in("wonderland"); let state = build_state(rt, &alice_id); diff --git a/crates/iroha_core/benches/kura.rs b/crates/iroha_core/benches/kura.rs index 9ff2fb8eb4c..df53c0782ad 100644 --- a/crates/iroha_core/benches/kura.rs +++ b/crates/iroha_core/benches/kura.rs @@ -49,10 +49,7 @@ async fn measure_block_size_for_n_executors(n_executors: u32) { let tx = AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits) .expect("Failed to accept Transaction."); let peer_key_pair = KeyPair::random(); - let peer_id = PeerId::new( - "127.0.0.1:8080".parse().unwrap(), - peer_key_pair.public_key().clone(), - ); + let peer_id = PeerId::new(peer_key_pair.public_key().clone()); let topology = Topology::new(vec![peer_id]); let mut block = { let unverified_block = BlockBuilder::new(vec![tx]) diff --git a/crates/iroha_core/src/block.rs b/crates/iroha_core/src/block.rs index 7c34ee37023..3de376e6385 100644 --- a/crates/iroha_core/src/block.rs +++ b/crates/iroha_core/src/block.rs @@ -870,16 +870,14 @@ mod valid { use iroha_crypto::SignatureOf; use super::*; - use crate::sumeragi::network_topology::test_peers; + use crate::sumeragi::network_topology::test_topology_with_keys; #[test] fn signature_verification_ok() { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(7) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0, 1, 2, 3, 4, 5, 6: key_pairs_iter]; - let topology = Topology::new(peers); + let topology = test_topology_with_keys(&key_pairs); let mut block = ValidBlock::new_dummy(key_pairs[0].private_key()); let payload = block.0.payload().clone(); @@ -910,9 +908,7 @@ mod valid { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(1) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0,: key_pairs_iter]; - let topology = Topology::new(peers); + let topology = test_topology_with_keys(&key_pairs); let block = ValidBlock::new_dummy(key_pairs[0].private_key()); @@ -925,9 +921,7 @@ mod valid { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(7) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0, 1, 2, 3, 4, 5, 6: key_pairs_iter]; - let topology = Topology::new(peers); + let topology = test_topology_with_keys(&key_pairs); let mut block = ValidBlock::new_dummy(key_pairs[0].private_key()); block.sign(&key_pairs[4], &topology); @@ -948,9 +942,7 @@ mod valid { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(7) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0, 1, 2, 3, 4, 5, 6: key_pairs_iter]; - let topology = Topology::new(peers); + let topology = test_topology_with_keys(&key_pairs); let mut block = ValidBlock::new_dummy(key_pairs[0].private_key()); let payload = block.0.payload().clone(); @@ -1154,16 +1146,13 @@ mod tests { use super::*; use crate::{ kura::Kura, query::store::LiveQueryStore, smartcontracts::isi::Registrable as _, - state::State, + state::State, sumeragi::network_topology::test_topology, }; #[test] pub fn committed_and_valid_block_hashes_are_equal() { let peer_key_pair = KeyPair::random(); - let peer_id = PeerId::new( - "127.0.0.1:8080".parse().unwrap(), - peer_key_pair.public_key().clone(), - ); + let peer_id = PeerId::new(peer_key_pair.public_key().clone()); let topology = Topology::new(vec![peer_id]); let valid_block = ValidBlock::new_dummy(peer_key_pair.private_key()); let committed_block = valid_block @@ -1390,9 +1379,7 @@ mod tests { // Create genesis block let transactions = vec![tx]; - let (peer_public_key, _) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); - let topology = Topology::new(vec![peer_id]); + let topology = test_topology(1); let unverified_block = BlockBuilder::new(transactions) .chain(0, state.view().latest_block().as_deref()) .sign(genesis_correct_key.private_key()) diff --git a/crates/iroha_core/src/block_sync.rs b/crates/iroha_core/src/block_sync.rs index 128e0fc2323..4da00f391be 100644 --- a/crates/iroha_core/src/block_sync.rs +++ b/crates/iroha_core/src/block_sync.rs @@ -49,7 +49,7 @@ impl BlockSynchronizerHandle { pub struct BlockSynchronizer { sumeragi: SumeragiHandle, kura: Arc, - peer_id: PeerId, + peer: Peer, gossip_period: Duration, gossip_size: NonZeroU32, network: IrohaNetwork, @@ -114,11 +114,11 @@ impl BlockSynchronizer { /// Get a random online peer. #[allow(clippy::disallowed_types)] - fn random_peer(peers: &std::collections::HashSet) -> Option { + fn random_peer(peers: &std::collections::HashSet) -> Option { use rand::{seq::IteratorRandom, SeedableRng}; let rng = &mut rand::rngs::StdRng::from_entropy(); - peers.iter().choose(rng).map(|id| Peer::new(id.clone())) + peers.iter().choose(rng).cloned() } /// Sends request for latest blocks to a chosen peer @@ -128,7 +128,7 @@ impl BlockSynchronizer { (state_view.prev_block_hash(), state_view.latest_block_hash()) }; message::Message::GetBlocksAfter(message::GetBlocksAfter::new( - self.peer_id.clone(), + self.peer.id.clone(), prev_hash, latest_hash, self.seen_blocks @@ -145,12 +145,12 @@ impl BlockSynchronizer { config: &Config, sumeragi: SumeragiHandle, kura: Arc, - peer_id: PeerId, + peer: Peer, network: IrohaNetwork, state: Arc, ) -> Self { Self { - peer_id, + peer, sumeragi, kura, gossip_period: config.gossip_period, @@ -245,7 +245,7 @@ pub mod message { let start_height = if let Some(hash) = *prev_hash { let Some(height) = block_sync.kura.get_block_height_by_hash(hash) else { error!( - peer=%block_sync.peer_id, + peer=%block_sync.peer, block=%hash, "Block hash not found" ); @@ -273,7 +273,7 @@ pub mod message { if !blocks.is_empty() { trace!(hash=?prev_hash, "Sharing blocks after hash"); - Message::ShareBlocks(ShareBlocks::new(blocks, block_sync.peer_id.clone())) + Message::ShareBlocks(ShareBlocks::new(blocks, block_sync.peer.id.clone())) .send_to(&block_sync.network, peer_id.clone()) .await; } @@ -413,11 +413,10 @@ pub mod message { #[test] fn candidate_empty() { let (leader_public_key, _) = KeyPair::random().into_parts(); - let leader_peer_id = - PeerId::new("127.0.0.1:1234".parse().unwrap(), leader_public_key); + let leader_peer = PeerId::new(leader_public_key); let candidate = ShareBlocksCandidate { blocks: Vec::new(), - peer: leader_peer_id, + peer: leader_peer, }; assert!(matches!(candidate.validate(), Err(ShareBlocksError::Empty))) } @@ -425,8 +424,7 @@ pub mod message { #[test] fn candidate_height_missed() { let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let leader_peer_id = - PeerId::new("127.0.0.1:1234".parse().unwrap(), leader_public_key); + let leader_peer_id = PeerId::new(leader_public_key); let block0: SignedBlock = ValidBlock::new_dummy(&leader_private_key).into(); let block1 = ValidBlock::new_dummy_and_modify_header(&leader_private_key, |header| { @@ -446,8 +444,7 @@ pub mod message { #[test] fn candidate_prev_block_hash_mismatch() { let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let leader_peer_id = - PeerId::new("127.0.0.1:1234".parse().unwrap(), leader_public_key); + let leader_peer_id = PeerId::new(leader_public_key); let block0: SignedBlock = ValidBlock::new_dummy(&leader_private_key).into(); let block1 = ValidBlock::new_dummy_and_modify_header(&leader_private_key, |header| { @@ -469,8 +466,7 @@ pub mod message { #[test] fn candidate_ok() { let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let leader_peer_id = - PeerId::new("127.0.0.1:1234".parse().unwrap(), leader_public_key); + let leader_peer_id = PeerId::new(leader_public_key); let block0: SignedBlock = ValidBlock::new_dummy(&leader_private_key).into(); let block1 = ValidBlock::new_dummy_and_modify_header(&leader_private_key, |header| { diff --git a/crates/iroha_core/src/kura.rs b/crates/iroha_core/src/kura.rs index e18725ddc37..1725ca46b93 100644 --- a/crates/iroha_core/src/kura.rs +++ b/crates/iroha_core/src/kura.rs @@ -1068,7 +1068,7 @@ mod tests { let mut blocks = Vec::new(); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); diff --git a/crates/iroha_core/src/lib.rs b/crates/iroha_core/src/lib.rs index 63456ff5c2f..29ba08689ff 100644 --- a/crates/iroha_core/src/lib.rs +++ b/crates/iroha_core/src/lib.rs @@ -7,6 +7,7 @@ pub mod gossiper; pub mod kiso; pub mod kura; pub mod metrics; +pub mod peers_gossiper; pub mod query; pub mod queue; pub mod smartcontracts; @@ -25,6 +26,7 @@ use tokio::sync::broadcast; use crate::{ block_sync::message::Message as BlockSyncMessage, + peers_gossiper::PeersGossip, prelude::*, sumeragi::message::{BlockMessage, ControlFlowMessage}, }; @@ -52,6 +54,8 @@ pub enum NetworkMessage { BlockSync(Box), /// Transaction gossiper message TransactionGossiper(Box), + /// Peers addresses gossiper message + PeersGossiper(Box), /// Health check message Health, } diff --git a/crates/iroha_core/src/peers_gossiper.rs b/crates/iroha_core/src/peers_gossiper.rs new file mode 100644 index 00000000000..0752cd37c27 --- /dev/null +++ b/crates/iroha_core/src/peers_gossiper.rs @@ -0,0 +1,220 @@ +//! Peers gossiper is actor which is responsible for gossiping addresses of peers. +//! +//! E.g. peer A changes address, connects to peer B, +//! and then peer B will broadcast address of peer A to other peers. + +use std::{ + collections::{BTreeMap, BTreeSet}, + time::Duration, +}; + +use iroha_config::parameters::actual::TrustedPeers; +use iroha_data_model::peer::{Peer, PeerId}; +use iroha_futures::supervisor::{Child, OnShutdown, ShutdownSignal}; +use iroha_p2p::{Broadcast, UpdatePeers, UpdateTopology}; +use iroha_primitives::{addr::SocketAddr, unique_vec::UniqueVec}; +use iroha_version::{Decode, Encode}; +use parity_scale_codec::{Error, Input}; +use tokio::sync::mpsc; + +use crate::{IrohaNetwork, NetworkMessage}; + +/// [`Gossiper`] actor handle. +#[derive(Clone)] +pub struct PeersGossiperHandle { + message_sender: mpsc::Sender<(PeersGossip, Peer)>, + update_topology_sender: mpsc::UnboundedSender, +} + +impl PeersGossiperHandle { + /// Send [`PeersGossip`] to actor + pub async fn gossip(&self, gossip: PeersGossip, peer: Peer) { + self.message_sender + .send((gossip, peer)) + .await + .expect("Gossiper must handle messages until there is at least one handle to it") + } + + /// Send [`UpdateTopology`] message on network actor. + pub fn update_topology(&self, topology: UpdateTopology) { + self.update_topology_sender + .send(topology) + .expect("Gossiper must accept messages until there is at least one handle to it") + } +} + +/// Actor which gossips peers addresses. +pub struct PeersGossiper { + /// Peers provided at startup + initial_peers: BTreeMap, + /// Peers received via gossiping from other peers + /// First-level key corresponds to `SocketAddr` + /// Second-level key - peer from which such `SocketAddr` was received + gossip_peers: BTreeMap>, + current_topology: BTreeSet, + network: IrohaNetwork, +} + +/// Terminology: +/// * Topology - public keys of current network derived from blockchain (Register/Unregister Peer Isi) +/// * Peers addresses - currently known addresses for peers in topology. Might be unknown for some peer. +/// +/// There are three sources of peers addresses: +/// 1. Provided at iroha startup (`TRUSTED_PEERS` env var) +/// 2. Currently connected online peers. +/// Some peer might change address and connect to our peer, +/// such connection will be accepted if peer public key is in topology. +/// 3. Received via gossiping from other peers. +impl PeersGossiper { + /// Start actor. + pub fn start( + trusted_peers: TrustedPeers, + network: IrohaNetwork, + shutdown_signal: ShutdownSignal, + ) -> (PeersGossiperHandle, Child) { + let initial_peers = trusted_peers + .others + .into_iter() + .map(|peer| (peer.id, peer.address)) + .collect(); + let gossiper = Self { + initial_peers, + gossip_peers: BTreeMap::new(), + current_topology: BTreeSet::new(), + network, + }; + gossiper.network_update_peers_addresses(); + + let (message_sender, message_receiver) = mpsc::channel(1); + let (update_topology_sender, update_topology_receiver) = mpsc::unbounded_channel(); + ( + PeersGossiperHandle { + message_sender, + update_topology_sender, + }, + Child::new( + tokio::task::spawn(gossiper.run( + message_receiver, + update_topology_receiver, + shutdown_signal, + )), + OnShutdown::Abort, + ), + ) + } + + async fn run( + mut self, + mut message_receiver: mpsc::Receiver<(PeersGossip, Peer)>, + mut update_topology_receiver: mpsc::UnboundedReceiver, + shutdown_signal: ShutdownSignal, + ) { + let mut gossip_period = tokio::time::interval(Duration::from_secs(60)); + loop { + tokio::select! { + Some(update_topology) = update_topology_receiver.recv() => { + self.set_current_topology(update_topology); + } + _ = gossip_period.tick() => { + self.gossip_peers() + } + () = self.network.wait_online_peers_update(|_| ()) => { + self.gossip_peers(); + } + Some((peers_gossip, peer)) = message_receiver.recv() => { + self.handle_peers_gossip(peers_gossip, &peer); + } + () = shutdown_signal.receive() => { + iroha_logger::debug!("Shutting down peers gossiper"); + break; + }, + } + tokio::task::yield_now().await; + } + } + + fn set_current_topology(&mut self, UpdateTopology(topology): UpdateTopology) { + self.gossip_peers.retain(|peer, map| { + if !topology.contains(peer) { + return false; + } + + map.retain(|peer, _| topology.contains(peer)); + !map.is_empty() + }); + + self.current_topology = topology.into_iter().collect(); + } + + fn gossip_peers(&self) { + let online_peers = self.network.online_peers(Clone::clone); + let online_peers = UniqueVec::from_iter(online_peers); + let data = NetworkMessage::PeersGossiper(Box::new(PeersGossip(online_peers))); + self.network.broadcast(Broadcast { data }); + } + + fn handle_peers_gossip(&mut self, PeersGossip(peers): PeersGossip, from_peer: &Peer) { + if !self.current_topology.contains(&from_peer.id) { + return; + } + for peer in peers { + if self.current_topology.contains(&peer.id) { + let map = self.gossip_peers.entry(peer.id).or_default(); + map.insert(from_peer.id.clone(), peer.address); + } + } + self.network_update_peers_addresses(); + } + + fn network_update_peers_addresses(&self) { + let online_peers = self.network.online_peers(Clone::clone); + let online_peers_ids = online_peers + .into_iter() + .map(|peer| peer.id) + .collect::>(); + + let mut peers = Vec::new(); + for (id, address) in &self.initial_peers { + if !online_peers_ids.contains(id) { + peers.push((id.clone(), address.clone())); + } + } + for (id, addresses) in &self.gossip_peers { + if !online_peers_ids.contains(id) { + peers.push((id.clone(), choose_address_majority_rule(addresses))); + } + } + + let update = UpdatePeers(peers); + self.network.update_peers_addresses(update); + } +} + +fn choose_address_majority_rule(addresses: &BTreeMap) -> SocketAddr { + let mut count_map = BTreeMap::new(); + for address in addresses.values() { + *count_map.entry(address).or_insert(0) += 1; + } + count_map + .into_iter() + .max_by_key(|(_, count)| *count) + .map(|(address, _)| address) + .expect("There must be no empty inner map in addresses") + .clone() +} + +/// Message for gossiping peers addresses. +#[derive(Encode, Debug, Clone)] +pub struct PeersGossip(UniqueVec); + +impl Decode for PeersGossip { + fn decode(input: &mut I) -> Result { + let peers = Vec::::decode(input)?; + let peers_len = peers.len(); + let peers = UniqueVec::from_iter(peers); + if peers.len() != peers_len { + Err("Duplicated peers in the gossip message")?; + } + Ok(Self(peers)) + } +} diff --git a/crates/iroha_core/src/smartcontracts/isi/query.rs b/crates/iroha_core/src/smartcontracts/isi/query.rs index b5d2d759825..8eb0263ef43 100644 --- a/crates/iroha_core/src/smartcontracts/isi/query.rs +++ b/crates/iroha_core/src/smartcontracts/isi/query.rs @@ -74,7 +74,7 @@ impl SortableQueryOutput for CommittedTransaction { } } -impl SortableQueryOutput for Peer { +impl SortableQueryOutput for PeerId { fn get_metadata_sorting_key(&self, _key: &Name) -> Option { None } @@ -430,7 +430,7 @@ mod tests { transactions.append(&mut vec![invalid_tx; invalid_tx_per_block]); let (peer_public_key, peer_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); + let peer_id = PeerId::new(peer_public_key); let topology = Topology::new(vec![peer_id]); let unverified_first_block = BlockBuilder::new(transactions.clone()) .chain(0, state.view().latest_block().as_deref()) @@ -607,7 +607,7 @@ mod tests { let va_tx = AcceptedTransaction::accept(tx, &chain_id, max_clock_drift, tx_limits)?; let (peer_public_key, _) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), peer_public_key); + let peer_id = PeerId::new(peer_public_key); let topology = Topology::new(vec![peer_id]); let unverified_block = BlockBuilder::new(vec![va_tx.clone()]) .chain(0, state.view().latest_block().as_deref()) diff --git a/crates/iroha_core/src/smartcontracts/isi/world.rs b/crates/iroha_core/src/smartcontracts/isi/world.rs index 8993e7e7de7..69f6a216c5a 100644 --- a/crates/iroha_core/src/smartcontracts/isi/world.rs +++ b/crates/iroha_core/src/smartcontracts/isi/world.rs @@ -36,7 +36,7 @@ pub mod isi { _authority: &AccountId, state_transaction: &mut StateTransaction<'_, '_>, ) -> Result<(), Error> { - let peer_id = self.object.id; + let peer_id = self.object; let world = &mut state_transaction.world; if let PushResult::Duplicate(duplicate) = world.trusted_peers_ids.push(peer_id.clone()) @@ -451,7 +451,6 @@ pub mod query { use eyre::Result; use iroha_data_model::{ parameter::Parameters, - peer::Peer, prelude::*, query::{ error::QueryExecutionFail as Error, @@ -515,7 +514,6 @@ pub mod query { .world() .peers() .cloned() - .map(Peer::new) .filter(move |peer| filter.applies(peer))) } } diff --git a/crates/iroha_core/src/snapshot.rs b/crates/iroha_core/src/snapshot.rs index d2f85dc65b5..0bbb06dbf19 100644 --- a/crates/iroha_core/src/snapshot.rs +++ b/crates/iroha_core/src/snapshot.rs @@ -341,10 +341,7 @@ mod tests { let state = state_factory(); let peer_key_pair = KeyPair::random(); - let peer_id = PeerId::new( - "127.0.0.1:8080".parse().unwrap(), - peer_key_pair.public_key().clone(), - ); + let peer_id = PeerId::new(peer_key_pair.public_key().clone()); let topology = Topology::new(vec![peer_id]); let valid_block = ValidBlock::new_dummy(peer_key_pair.private_key()); let committed_block = valid_block @@ -400,10 +397,7 @@ mod tests { let state = state_factory(); let peer_key_pair = KeyPair::random(); - let peer_id = PeerId::new( - "127.0.0.1:8080".parse().unwrap(), - peer_key_pair.public_key().clone(), - ); + let peer_id = PeerId::new(peer_key_pair.public_key().clone()); let topology = Topology::new(vec![peer_id]); let valid_block = ValidBlock::new_dummy(peer_key_pair.private_key()); let committed_block = valid_block diff --git a/crates/iroha_core/src/state.rs b/crates/iroha_core/src/state.rs index fc282755508..d77a6c41dc7 100644 --- a/crates/iroha_core/src/state.rs +++ b/crates/iroha_core/src/state.rs @@ -2083,7 +2083,7 @@ mod tests { /// Used to inject faulty payload for testing fn new_dummy_block_with_payload(f: impl FnOnce(&mut BlockHeader)) -> CommittedBlock { let (leader_public_key, leader_private_key) = iroha_crypto::KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); ValidBlock::new_dummy_and_modify_header(&leader_private_key, f) diff --git a/crates/iroha_core/src/sumeragi/main_loop.rs b/crates/iroha_core/src/sumeragi/main_loop.rs index e63479c1e20..efdfd30db89 100644 --- a/crates/iroha_core/src/sumeragi/main_loop.rs +++ b/crates/iroha_core/src/sumeragi/main_loop.rs @@ -8,7 +8,10 @@ use iroha_p2p::UpdateTopology; use tracing::{span, Level}; use super::{view_change::ProofBuilder, *}; -use crate::{block::*, queue::TransactionGuard, sumeragi::tracing::instrument}; +use crate::{ + block::*, peers_gossiper::PeersGossiperHandle, queue::TransactionGuard, + sumeragi::tracing::instrument, +}; /// `Sumeragi` is the implementation of the consensus. pub struct Sumeragi { @@ -19,13 +22,15 @@ pub struct Sumeragi { /// Address of queue pub queue: Arc, /// The peer id of myself. - pub peer_id: PeerId, + pub peer: Peer, /// An actor that sends events pub events_sender: EventsSender, /// Kura instance used for IO pub kura: Arc, /// [`iroha_p2p::Network`] actor address pub network: IrohaNetwork, + /// Peers gossiper + pub peers_gossiper: PeersGossiperHandle, /// Receiver channel, for control flow messages. pub control_message_receiver: mpsc::Receiver, /// Receiver channel. @@ -57,14 +62,14 @@ impl Debug for Sumeragi { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("Sumeragi") .field("public_key", &self.key_pair.public_key()) - .field("peer_id", &self.peer_id) + .field("peer_id", &self.peer) .finish() } } impl Sumeragi { fn role(&self) -> Role { - self.topology.role(&self.peer_id) + self.topology.role(&self.peer.id) } /// Send a sumeragi packet over the network to the specified `peer`. @@ -72,7 +77,7 @@ impl Sumeragi { /// Fails if network sending fails #[instrument(skip(self, packet))] fn post_packet_to(&self, packet: BlockMessage, peer: &PeerId) { - if peer == &self.peer_id { + if peer == &self.peer.id { return; } @@ -112,8 +117,9 @@ impl Sumeragi { /// Connect or disconnect peers according to the current network topology. fn connect_peers(&self, topology: &Topology) { - let peers = topology.iter().cloned().collect(); - self.network.update_topology(UpdateTopology(peers)); + let update = UpdateTopology(topology.iter().cloned().collect()); + self.network.update_topology(update.clone()); + self.peers_gossiper.update_topology(update); } fn send_event(&self, event: impl Into) { @@ -206,7 +212,7 @@ impl Sumeragi { shutdown_signal: &ShutdownSignal, ) -> Result<(), EarlyReturn> { info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Listening for genesis..." ); @@ -247,7 +253,7 @@ impl Sumeragi { Ok(block) => block, Err(error) => { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, ?error, "Received invalid genesis block" ); @@ -258,7 +264,7 @@ impl Sumeragi { if block.as_ref().errors().next().is_some() { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Genesis contains invalid transactions" ); @@ -352,7 +358,7 @@ impl Sumeragi { // Commit new block making it's effect visible for the rest of application state_block.commit(); info!( - peer_id=%self.peer_id, + peer_id=%self.peer, %prev_role, next_role=%self.role(), block_hash=%block_hash, @@ -361,7 +367,7 @@ impl Sumeragi { ); #[cfg(debug_assertions)] iroha_logger::info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), topology=?self.topology, "Topology after commit" @@ -402,7 +408,7 @@ impl Sumeragi { .map(|(block, state_block)| VotingBlock::new(block, state_block)) .map_err(|(block, error)| { warn!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), ?error, @@ -437,7 +443,7 @@ impl Sumeragi { match (message, self.role()) { (BlockMessage::BlockSyncUpdate(BlockSyncUpdate { block }), _) => { info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), "Block sync update received" @@ -463,7 +469,7 @@ impl Sumeragi { .expect("INTERNAL BUG: No latest block"); warn!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), peer_latest_block_hash=?state_block.latest_block_hash(), peer_latest_block_view_change_index=%latest_block.header().view_change_index, @@ -476,7 +482,7 @@ impl Sumeragi { } Err((block, BlockSyncError::BlockNotValid(error))) => { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), ?error, @@ -485,7 +491,7 @@ impl Sumeragi { } Err((block, BlockSyncError::SoftForkBlockNotValid(error))) => { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), ?error, @@ -500,7 +506,7 @@ impl Sumeragi { }, )) => { debug!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), peer_latest_block_hash=?state.view().latest_block_hash(), peer_latest_block_view_change_index=?peer_view_change_index, @@ -517,7 +523,7 @@ impl Sumeragi { }, )) => { warn!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), %block_height, @@ -529,7 +535,7 @@ impl Sumeragi { } (BlockMessage::BlockCreated(BlockCreated { block }), Role::ValidatingPeer) => { info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), "Block received" @@ -549,7 +555,7 @@ impl Sumeragi { self.broadcast_packet_to(msg, [topology.proxy_tail()]); info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%valid_block.block.as_ref().hash(), "Voted for the block" @@ -559,7 +565,7 @@ impl Sumeragi { } (BlockMessage::BlockCreated(BlockCreated { block }), Role::ObservingPeer) => { info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), "Block received" @@ -580,7 +586,7 @@ impl Sumeragi { self.broadcast_packet_to(msg, [topology.proxy_tail()]); info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%valid_block.block.as_ref().hash(), "Voted for the block" @@ -592,7 +598,7 @@ impl Sumeragi { } (BlockMessage::BlockCreated(BlockCreated { block }), Role::ProxyTail) => { info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%block.hash(), "Block received" @@ -615,7 +621,7 @@ impl Sumeragi { } (BlockMessage::BlockSigned(BlockSigned { hash, signature }), Role::ProxyTail) => { info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%hash, "Received block signatures" @@ -626,7 +632,7 @@ impl Sumeragi { s } else { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), ?signatory_idx, topology_size=%self.topology.as_ref().len(), @@ -638,22 +644,22 @@ impl Sumeragi { match self.topology.role(signatory) { Role::Leader => error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Signatory is leader" ), Role::Undefined => error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Unknown signatory" ), Role::ObservingPeer if view_change_index == 0 => error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Signatory is observing peer" ), Role::ProxyTail => error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Signatory is proxy tail" ), @@ -663,7 +669,7 @@ impl Sumeragi { if hash != actual_hash { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), expected_hash=?hash, ?actual_hash, @@ -674,7 +680,7 @@ impl Sumeragi { voted_block.block.add_signature(signature, &self.topology) { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), ?err, "Signature not valid" @@ -689,7 +695,7 @@ impl Sumeragi { // the block (sent by the leader). Collect the signatures and wait for the block to be received if !voting_signatures.insert(signature) { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Duplicate signature" ); @@ -699,7 +705,7 @@ impl Sumeragi { } } else { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Signatory index exceeds usize::MAX" ); @@ -712,7 +718,7 @@ impl Sumeragi { Role::Leader | Role::ValidatingPeer | Role::ObservingPeer, ) => { info!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), block=%hash, "Received block committed", @@ -739,7 +745,7 @@ impl Sumeragi { } Err((mut block, error)) => { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), ?error, "Block failed to be committed" @@ -756,7 +762,7 @@ impl Sumeragi { } Err(error) => { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), ?error, "Received incorrect signatures" @@ -767,7 +773,7 @@ impl Sumeragi { } } else { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), expected_hash=?hash, ?actual_hash, @@ -776,7 +782,7 @@ impl Sumeragi { } } else { error!( - peer_id=%self.peer_id, + peer_id=%self.peer, role=%self.role(), "Peer missing voting block" ); @@ -785,7 +791,7 @@ impl Sumeragi { (msg, _) => { trace!( role=%self.role(), - peer_id=%self.peer_id, + peer_id=%self.peer, ?msg, "message not handled" ); @@ -881,7 +887,7 @@ impl Sumeragi { .sign(self.key_pair.private_key()) .unpack(|e| self.send_event(e)); info!( - peer_id=%self.peer_id, + peer_id=%self.peer, block_hash=%unverified_block.header().hash(), txns=%unverified_block.transactions().len(), view_change_index=%self.topology.view_change_index(), @@ -1012,7 +1018,7 @@ pub(crate) fn run( span.exit(); info!( - peer_id=%sumeragi.peer_id, + peer_id=%sumeragi.peer, role=%sumeragi.role(), "Sumeragi initialized", ); @@ -1074,7 +1080,7 @@ pub(crate) fn run( ); reset_state( - &sumeragi.peer_id, + &sumeragi.peer.id, state .world .view() @@ -1143,7 +1149,7 @@ pub(crate) fn run( // NOTE: Suspecting the tail node because it hasn't committed the block yet warn!( - peer_id=%sumeragi.peer_id, + peer_id=%sumeragi.peer, role=%sumeragi.role(), block=%block.as_ref().hash(), "Block not committed in due time, requesting view change..." @@ -1153,7 +1159,7 @@ pub(crate) fn run( // If the current node has a transaction, leader should have as well warn!( - peer_id=%sumeragi.peer_id, + peer_id=%sumeragi.peer, role=%sumeragi.role(), "No block produced in due time, requesting view change..." ); @@ -1204,7 +1210,7 @@ pub(crate) fn run( } reset_state( - &sumeragi.peer_id, + &sumeragi.peer.id, state .world .view() @@ -1478,7 +1484,6 @@ mod tests { topology .iter() .cloned() - .map(Peer::new) .map(Register::peer) .map(InstructionBox::from), ) @@ -1541,7 +1546,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, _, block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); @@ -1561,7 +1566,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, kura, unverified_block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); @@ -1598,7 +1603,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, _, block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); @@ -1633,7 +1638,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, _, block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); @@ -1652,7 +1657,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, kura, unverified_block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); @@ -1689,7 +1694,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, kura, block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); @@ -1742,7 +1747,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, _, block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); @@ -1779,7 +1784,7 @@ mod tests { let chain_id = ChainId::from("00000000-0000-0000-0000-000000000000"); let (leader_public_key, leader_private_key) = KeyPair::random().into_parts(); - let peer_id = PeerId::new("127.0.0.1:8080".parse().unwrap(), leader_public_key); + let peer_id = PeerId::new(leader_public_key); let topology = Topology::new(vec![peer_id]); let (state, _, unverified_block, genesis_public_key) = create_data_for_test(&chain_id, &topology, &leader_private_key); diff --git a/crates/iroha_core/src/sumeragi/mod.rs b/crates/iroha_core/src/sumeragi/mod.rs index eafe0eacf9a..c256b4eddc3 100644 --- a/crates/iroha_core/src/sumeragi/mod.rs +++ b/crates/iroha_core/src/sumeragi/mod.rs @@ -28,12 +28,15 @@ pub mod network_topology; pub mod view_change; use self::{message::*, view_change::ProofChain}; -use crate::{kura::Kura, prelude::*, queue::Queue, EventsSender, IrohaNetwork, NetworkMessage}; +use crate::{ + kura::Kura, peers_gossiper::PeersGossiperHandle, prelude::*, queue::Queue, EventsSender, + IrohaNetwork, NetworkMessage, +}; /// Handle to `Sumeragi` actor #[derive(Clone)] pub struct SumeragiHandle { - peer_id: PeerId, + peer: Peer, /// Counter for amount of dropped messages by sumeragi #[cfg(feature = "telemetry")] dropped_messages_metric: iroha_telemetry::metrics::DroppedMessagesCounter, @@ -51,7 +54,7 @@ impl SumeragiHandle { self.dropped_messages_metric.inc(); error!( - peer_id=%self.peer_id, + peer_id=%self.peer, ?error, "This peer is faulty. \ Incoming control messages have to be dropped due to low processing speed." @@ -78,7 +81,7 @@ impl SumeragiHandle { self.dropped_messages_metric.inc(); error!( - peer_id=%self.peer_id, + peer_id=%self.peer, ?error, "This peer is faulty. \ Incoming messages have to be dropped due to low processing speed." @@ -144,6 +147,7 @@ impl SumeragiStartArgs { queue, kura, network, + peers_gossiper, genesis_network, block_count: BlockCount(block_count), #[cfg(feature = "telemetry")] @@ -208,15 +212,16 @@ impl SumeragiStartArgs { #[cfg(not(debug_assertions))] let debug_force_soft_fork = false; - let peer_id = common_config.peer; + let peer = common_config.peer; let sumeragi = main_loop::Sumeragi { chain_id: common_config.chain, key_pair: common_config.key_pair, - peer_id: peer_id.clone(), + peer: peer.clone(), queue: Arc::clone(&queue), events_sender, kura: Arc::clone(&kura), network: network.clone(), + peers_gossiper, control_message_receiver, message_receiver, debug_force_soft_fork, @@ -240,7 +245,7 @@ impl SumeragiStartArgs { ( SumeragiHandle { - peer_id, + peer, #[cfg(feature = "telemetry")] dropped_messages_metric: dropped_messages, control_message_sender, @@ -297,6 +302,7 @@ pub struct SumeragiStartArgs { pub queue: Arc, pub kura: Arc, pub network: IrohaNetwork, + pub peers_gossiper: PeersGossiperHandle, pub genesis_network: GenesisWithPubKey, pub block_count: BlockCount, #[cfg(feature = "telemetry")] diff --git a/crates/iroha_core/src/sumeragi/network_topology.rs b/crates/iroha_core/src/sumeragi/network_topology.rs index 7d5dc3bf552..cea5eab73e6 100644 --- a/crates/iroha_core/src/sumeragi/network_topology.rs +++ b/crates/iroha_core/src/sumeragi/network_topology.rs @@ -2,6 +2,8 @@ use derive_more::Display; use indexmap::IndexSet; +#[cfg(test)] +use iroha_crypto::KeyPair; use iroha_crypto::PublicKey; use iroha_data_model::{block::BlockSignature, prelude::PeerId}; @@ -258,23 +260,26 @@ pub enum Role { } #[cfg(test)] -macro_rules! test_peers { - ($($id:literal),+$(,)?) => {{ - let mut iter = ::core::iter::repeat_with( - || iroha_crypto::KeyPair::random() - ); +fn test_peers(n_peers: usize) -> Vec { + (0..n_peers) + .map(|_| PeerId::new(KeyPair::random().into_parts().0)) + .collect() +} - test_peers![$($id),*: iter] - }}; - ($($id:literal),+$(,)?: $key_pair_iter:expr) => { - ::iroha_primitives::unique_vec![ - $(PeerId::new((([0, 0, 0, 0], $id).into()), $key_pair_iter.next().expect("Not enough key pairs").public_key().clone())),+ - ] - }; +#[cfg(test)] +pub fn test_topology(n_peers: usize) -> Topology { + let keys = (0..n_peers).map(|_| KeyPair::random()).collect::>(); + test_topology_with_keys(&keys) } #[cfg(test)] -pub(crate) use test_peers; +#[allow(single_use_lifetimes)] // false-positive +pub fn test_topology_with_keys<'a>(keys: impl IntoIterator) -> Topology { + let peers = keys + .into_iter() + .map(|key| PeerId::new(key.public_key().clone())); + Topology::new(peers) +} #[cfg(test)] mod tests { @@ -284,37 +289,42 @@ mod tests { use super::*; use crate::block::ValidBlock; - fn topology() -> Topology { - let peers = test_peers![0, 1, 2, 3, 4, 5, 6]; - Topology::new(peers) - } - - fn extract_ports(topology: &Topology) -> Vec { - topology.0.iter().map(|peer| peer.address.port()).collect() + fn extract_order(topology: &Topology, initial_topology: &Topology) -> Vec { + topology + .0 + .iter() + .map(|peer| { + initial_topology + .0 + .iter() + .position(|p| p.public_key == peer.public_key) + .unwrap() + }) + .collect() } #[test] fn rotate_set_a() { - let mut topology = topology(); + let mut topology = test_topology(7); + let initial_topology = topology.clone(); topology.rotate_set_a(); - assert_eq!(extract_ports(&topology), vec![1, 2, 3, 4, 0, 5, 6]) + assert_eq!( + extract_order(&topology, &initial_topology), + vec![1, 2, 3, 4, 0, 5, 6] + ) } #[test] fn update_peer_list() { - let mut topology = topology(); + let mut topology = test_topology(7); + let peer0 = topology.0[0].clone(); + let peer2 = topology.0[2].clone(); + let peer5 = topology.0[5].clone(); + let peer7 = test_peers(1).remove(0); // New peers will be 0, 2, 5, 7 - let new_peers = { - let mut peers = unique_vec![ - topology.0[5].clone(), - topology.0[0].clone(), - topology.0[2].clone(), - ]; - peers.extend(test_peers![7]); - peers - }; + let new_peers = unique_vec![peer5.clone(), peer0.clone(), peer2.clone(), peer7.clone()]; topology.update_peer_list(new_peers); - assert_eq!(extract_ports(&topology), vec![0, 2, 5, 7]) + assert_eq!(topology.0, vec![peer0, peer2, peer5, peer7]) } #[test] @@ -322,9 +332,7 @@ mod tests { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(7) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0, 1, 2, 3, 4, 5, 6: key_pairs_iter]; - let topology = Topology::new(peers); + let topology = test_topology_with_keys(&key_pairs); let dummy_block = ValidBlock::new_dummy(key_pairs[0].private_key()); let dummy_signature = &dummy_block.as_ref().signatures().next().unwrap().1; @@ -362,9 +370,8 @@ mod tests { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(7) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0: key_pairs_iter]; - let topology = Topology::new(peers); + let key_pairs_iter = key_pairs.iter().take(1); + let topology = test_topology_with_keys(key_pairs_iter); let dummy_block = ValidBlock::new_dummy(key_pairs[0].private_key()); let dummy_signature = &dummy_block.as_ref().signatures().next().unwrap().1; @@ -396,9 +403,8 @@ mod tests { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(7) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0, 1: key_pairs_iter]; - let topology = Topology::new(peers); + let key_pairs_iter = key_pairs.iter().take(2); + let topology = test_topology_with_keys(key_pairs_iter); let dummy_block = ValidBlock::new_dummy(key_pairs[0].private_key()); let dummy_signature = &dummy_block.as_ref().signatures().next().unwrap().1; @@ -432,9 +438,8 @@ mod tests { let key_pairs = core::iter::repeat_with(KeyPair::random) .take(7) .collect::>(); - let mut key_pairs_iter = key_pairs.iter(); - let peers = test_peers![0, 1, 2: key_pairs_iter]; - let topology = Topology::new(peers); + let key_pairs_iter = key_pairs.iter().take(3); + let topology = test_topology_with_keys(key_pairs_iter); let dummy_block = ValidBlock::new_dummy(key_pairs[0].private_key()); let dummy_signature = &dummy_block.as_ref().signatures().next().unwrap().1; @@ -467,7 +472,7 @@ mod tests { #[test] fn proxy_tail() { - let peers = test_peers![0, 1, 2, 3, 4, 5, 6]; + let peers = test_peers(7); let topology = Topology::new(peers.clone()); assert_eq!( @@ -487,8 +492,7 @@ mod tests { #[test] fn proxy_tail_1() { - let peers = test_peers![0]; - let topology = Topology::new(peers); + let topology = test_topology(1); assert_eq!( topology @@ -501,7 +505,7 @@ mod tests { #[test] fn proxy_tail_2() { - let peers = test_peers![0, 1]; + let peers = test_peers(2); let topology = Topology::new(peers.clone()); assert_eq!( @@ -515,7 +519,7 @@ mod tests { #[test] fn proxy_tail_3() { - let peers = test_peers![0, 1, 2]; + let peers = test_peers(3); let topology = Topology::new(peers.clone()); assert_eq!( @@ -529,7 +533,7 @@ mod tests { #[test] fn leader() { - let peers = test_peers![0, 1, 2, 3, 4, 5, 6]; + let peers = test_peers(7); let topology = Topology::new(peers.clone()); assert_eq!( @@ -543,7 +547,7 @@ mod tests { #[test] fn leader_1() { - let peers = test_peers![0]; + let peers = test_peers(1); let topology = Topology::new(peers.clone()); assert_eq!( @@ -557,7 +561,7 @@ mod tests { #[test] fn leader_2() { - let peers = test_peers![0, 1]; + let peers = test_peers(2); let topology = Topology::new(peers.clone()); assert_eq!( @@ -571,7 +575,7 @@ mod tests { #[test] fn leader_3() { - let peers = test_peers![0, 1, 3]; + let peers = test_peers(3); let topology = Topology::new(peers.clone()); assert_eq!( @@ -585,7 +589,7 @@ mod tests { #[test] fn validating_peers() { - let peers = test_peers![0, 1, 2, 3, 4, 5, 6]; + let peers = test_peers(7); let topology = Topology::new(peers.clone()); assert_eq!( @@ -599,7 +603,7 @@ mod tests { #[test] fn validating_peers_1() { - let peers = test_peers![0]; + let peers = test_peers(1); let topology = Topology::new(peers); assert_eq!( @@ -613,7 +617,7 @@ mod tests { #[test] fn validating_peers_2() { - let peers = test_peers![0, 1]; + let peers = test_peers(2); let topology = Topology::new(peers); let empty_peer_slice: &[PeerId] = &[]; @@ -628,7 +632,7 @@ mod tests { #[test] fn validating_peers_3() { - let peers = test_peers![0, 1, 2]; + let peers = test_peers(3); let topology = Topology::new(peers.clone()); assert_eq!( @@ -642,7 +646,7 @@ mod tests { #[test] fn observing_peers() { - let peers = test_peers![0, 1, 2, 3, 4, 5, 6]; + let peers = test_peers(7); let topology = Topology::new(peers.clone()); assert_eq!( @@ -656,7 +660,7 @@ mod tests { #[test] fn observing_peers_1() { - let peers = test_peers![0]; + let peers = test_peers(1); let topology = Topology::new(peers); assert_eq!( @@ -670,7 +674,7 @@ mod tests { #[test] fn observing_peers_2() { - let peers = test_peers![0, 1]; + let peers = test_peers(2); let topology = Topology::new(peers); let empty_peer_slice: &[PeerId] = &[]; @@ -685,7 +689,7 @@ mod tests { #[test] fn observing_peers_3() { - let peers = test_peers![0, 1, 2]; + let peers = test_peers(3); let topology = Topology::new(peers); let empty_peer_slice: &[PeerId] = &[]; @@ -700,7 +704,7 @@ mod tests { #[test] fn validating_peers_empty() { - let peers = test_peers![0, 1]; + let peers = test_peers(2); let topology = Topology::new(peers); assert_eq!( @@ -714,7 +718,7 @@ mod tests { #[test] fn observing_peers_empty() { - let peers = test_peers![0, 1, 2]; + let peers = test_peers(3); let topology = Topology::new(peers); assert_eq!( diff --git a/crates/iroha_core/src/sumeragi/view_change.rs b/crates/iroha_core/src/sumeragi/view_change.rs index 902988504ec..ce7c7f932e2 100644 --- a/crates/iroha_core/src/sumeragi/view_change.rs +++ b/crates/iroha_core/src/sumeragi/view_change.rs @@ -252,9 +252,9 @@ mod candidate { #[cfg(test)] mod tests { use iroha_crypto::{Hash, HashOf, KeyPair}; - use iroha_data_model::peer::PeerId; use super::*; + use crate::sumeragi::network_topology::test_topology_with_keys; fn key_pairs() -> [KeyPair; N] { [(); N].map(|()| KeyPair::random()) @@ -262,11 +262,7 @@ mod tests { fn prepare_data() -> ([KeyPair; N], Topology, HashOf) { let key_pairs = key_pairs::(); - let peer_ids = key_pairs.clone().map(|key_pair| { - let (public_key, _) = key_pair.into_parts(); - PeerId::new(([127, 0, 0, 1], 8080).into(), public_key) - }); - let topology = Topology::new(peer_ids); + let topology = test_topology_with_keys(&key_pairs); let latest_block = HashOf::from_untyped_unchecked(Hash::prehashed([0; 32])); (key_pairs, topology, latest_block) diff --git a/crates/iroha_data_model/src/isi.rs b/crates/iroha_data_model/src/isi.rs index 5f0e6b5ae1f..75b3b341c32 100644 --- a/crates/iroha_data_model/src/isi.rs +++ b/crates/iroha_data_model/src/isi.rs @@ -444,7 +444,7 @@ mod transparent { impl Register { /// Constructs a new [`Register`] for a [`Peer`]. - pub fn peer(new_peer: Peer) -> Self { + pub fn peer(new_peer: PeerId) -> Self { Self { object: new_peer } } } diff --git a/crates/iroha_data_model/src/peer.rs b/crates/iroha_data_model/src/peer.rs index b11c3d469fc..ef398bf0ecb 100644 --- a/crates/iroha_data_model/src/peer.rs +++ b/crates/iroha_data_model/src/peer.rs @@ -2,13 +2,9 @@ #[cfg(not(feature = "std"))] use alloc::{format, string::String, vec::Vec}; -use core::{ - borrow::Borrow, - cmp::Ordering, - hash::{Hash, Hasher}, -}; +use core::hash::Hash; -use derive_more::Display; +use derive_more::{Constructor, DebugCustom, Display}; use iroha_data_model_derive::model; use iroha_primitives::addr::SocketAddr; @@ -30,87 +26,78 @@ mod model { /// Equality is tested by `public_key` field only. /// Each peer should have a unique public key. #[derive( - Debug, Display, Clone, Eq, Decode, Encode, Deserialize, Serialize, IntoSchema, Getters, + DebugCustom, + Display, + Clone, + Constructor, + Ord, + PartialOrd, + Eq, + PartialEq, + Hash, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + Getters, )] - #[display(fmt = "{public_key}@@{address}")] + #[display(fmt = "{public_key}")] + #[debug(fmt = "{public_key}")] #[getset(get = "pub")] - #[ffi_type] + #[serde(transparent)] + #[repr(transparent)] + // TODO: Make it transparent in FFI? + #[ffi_type(opaque)] pub struct PeerId { - /// Address of the [`Peer`]'s entrypoint. - pub address: SocketAddr, /// Public Key of the [`Peer`]. pub public_key: PublicKey, } /// Representation of other Iroha Peer instances running in separate processes. #[derive( - Debug, Display, Clone, IdEqOrdHash, Decode, Encode, Deserialize, Serialize, IntoSchema, + Debug, + Display, + Clone, + IdEqOrdHash, + Decode, + Encode, + Deserialize, + Serialize, + IntoSchema, + Getters, )] - #[display(fmt = "@@{}", "id.address")] - #[serde(transparent)] - #[repr(transparent)] - // TODO: Make it transparent in FFI? - #[ffi_type(opaque)] + #[display(fmt = "{id}@@{address}")] + #[ffi_type] pub struct Peer { + /// Address of the [`Peer`]'s entrypoint. + #[getset(get = "pub")] + pub address: SocketAddr, + #[serde(rename = "public_key")] /// Peer Identification. pub id: PeerId, } } -impl PeerId { - /// Construct [`PeerId`] given `public_key` and `address`. - #[inline] - pub fn new(address: SocketAddr, public_key: PublicKey) -> Self { - Self { - address, - public_key, - } +impl From for PeerId { + fn from(public_key: PublicKey) -> Self { + Self { public_key } } } impl Peer { - /// Construct `Peer` given `id`. + /// Construct `Peer` given `id` and `address`. #[inline] - pub const fn new(id: PeerId) -> ::With { - Self { id } - } -} - -impl PartialEq for PeerId { - fn eq(&self, other: &Self) -> bool { - // Comparison is done by public key only. - // It is a system invariant that each peer has a unique public key. - // Also it helps to handle peer id comparison without domain name resolution. - self.public_key == other.public_key - } -} - -impl PartialOrd for PeerId { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for PeerId { - fn cmp(&self, other: &Self) -> Ordering { - self.public_key.cmp(&other.public_key) - } -} - -impl Hash for PeerId { - fn hash(&self, state: &mut H) { - self.public_key.hash(state); - } -} - -impl Borrow for PeerId { - fn borrow(&self) -> &PublicKey { - &self.public_key + pub fn new(address: SocketAddr, id: impl Into) -> Self { + Self { + address, + id: id.into(), + } } } impl Registered for Peer { - type With = Self; + type With = PeerId; } /// The prelude re-exports most commonly used traits, structs and macros from this crate. diff --git a/crates/iroha_data_model/src/query/mod.rs b/crates/iroha_data_model/src/query/mod.rs index 96b1ad13c19..64c7bc257ea 100644 --- a/crates/iroha_data_model/src/query/mod.rs +++ b/crates/iroha_data_model/src/query/mod.rs @@ -27,7 +27,7 @@ use crate::{ block::{BlockHeader, SignedBlock}, domain::Domain, parameter::{Parameter, Parameters}, - peer::Peer, + peer::PeerId, permission::Permission, role::{Role, RoleId}, seal::Sealed, @@ -119,7 +119,7 @@ mod model { Parameter(Vec), Permission(Vec), Transaction(Vec), - Peer(Vec), + Peer(Vec), RoleId(Vec), TriggerId(Vec), Trigger(Vec), @@ -562,7 +562,7 @@ impl_iter_queries! { FindAssets => crate::asset::Asset, FindAssetsDefinitions => crate::asset::AssetDefinition, FindDomains => crate::domain::Domain, - FindPeers => crate::peer::Peer, + FindPeers => crate::peer::PeerId, FindActiveTriggerIds => crate::trigger::TriggerId, FindTriggers => crate::trigger::Trigger, FindTransactions => CommittedTransaction, diff --git a/crates/iroha_data_model/src/query/predicate/predicate_atoms/peer.rs b/crates/iroha_data_model/src/query/predicate/predicate_atoms/peer.rs index e4c3700edc2..a3512c8ee4d 100644 --- a/crates/iroha_data_model/src/query/predicate/predicate_atoms/peer.rs +++ b/crates/iroha_data_model/src/query/predicate/predicate_atoms/peer.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use super::impl_predicate_box; use crate::{ - peer::Peer, + peer::PeerId, query::predicate::{ predicate_ast_extensions::AstPredicateExt as _, predicate_combinators::{AndAstPredicate, NotAstPredicate, OrAstPredicate}, @@ -24,10 +24,10 @@ pub enum PeerPredicateBox { // nothing here yet } -impl_predicate_box!(Peer: PeerPredicateBox); +impl_predicate_box!(PeerId: PeerPredicateBox); -impl EvaluatePredicate for PeerPredicateBox { - fn applies(&self, _input: &Peer) -> bool { +impl EvaluatePredicate for PeerPredicateBox { + fn applies(&self, _input: &PeerId) -> bool { match *self {} } } diff --git a/crates/iroha_data_model_derive/src/id.rs b/crates/iroha_data_model_derive/src/id.rs index d35e6c42afe..963811de7f6 100644 --- a/crates/iroha_data_model_derive/src/id.rs +++ b/crates/iroha_data_model_derive/src/id.rs @@ -110,6 +110,12 @@ pub fn impl_id_eq_ord_hash(emitter: &mut Emitter, input: &syn::DeriveInput) -> T ::id(self).hash(state) } } + + impl #impl_generics core::borrow::Borrow<::Id> for #name #ty_generics #where_clause where Self: Identifiable { + fn borrow(&self) -> &::Id { + ::id(self) + } + } } } diff --git a/crates/iroha_genesis/src/lib.rs b/crates/iroha_genesis/src/lib.rs index c868995e40e..7d11ccd9f63 100644 --- a/crates/iroha_genesis/src/lib.rs +++ b/crates/iroha_genesis/src/lib.rs @@ -10,8 +10,8 @@ use std::{ use derive_more::Constructor; use eyre::{eyre, Result, WrapErr}; -use iroha_crypto::{KeyPair, PublicKey}; -use iroha_data_model::{block::SignedBlock, parameter::Parameter, peer::Peer, prelude::*}; +use iroha_crypto::KeyPair; +use iroha_data_model::{block::SignedBlock, parameter::Parameter, prelude::*}; use iroha_executor_data_model::permission::trigger::{ CanRegisterAnyTrigger, CanUnregisterAnyTrigger, }; @@ -199,7 +199,6 @@ impl RawGenesisTransaction { let instructions = self .topology .into_iter() - .map(Peer::new) .map(Register::peer) .map(InstructionBox::from) .collect(); diff --git a/crates/iroha_p2p/src/network.rs b/crates/iroha_p2p/src/network.rs index 548e9d225d9..27163113146 100644 --- a/crates/iroha_p2p/src/network.rs +++ b/crates/iroha_p2p/src/network.rs @@ -8,26 +8,28 @@ use std::{ use futures::{stream::FuturesUnordered, StreamExt}; use iroha_config::parameters::actual::Network as Config; -use iroha_crypto::{KeyPair, PublicKey}; -use iroha_data_model::prelude::PeerId; +use iroha_crypto::KeyPair; +use iroha_data_model::{ + prelude::{Peer, PeerId}, + Identifiable, +}; use iroha_futures::supervisor::{Child, OnShutdown, ShutdownSignal}; use iroha_logger::prelude::*; use iroha_primitives::addr::SocketAddr; -use parity_scale_codec::Encode as _; use tokio::{ net::{TcpListener, TcpStream}, sync::{mpsc, watch}, }; use crate::{ - blake2b_hash, boilerplate::*, peer::{ handles::{connected_from, connecting, PeerHandle}, message::*, Connection, ConnectionId, }, - unbounded_with_len, Broadcast, Error, NetworkMessage, OnlinePeers, Post, UpdateTopology, + unbounded_with_len, Broadcast, Error, NetworkMessage, OnlinePeers, Post, UpdatePeers, + UpdateTopology, }; /// [`NetworkBase`] actor handle. @@ -38,11 +40,13 @@ use crate::{ #[debug(fmt = "core::any::type_name::()")] pub struct NetworkBaseHandle { /// Sender to subscribe for messages received form other peers in the network - subscribe_to_peers_messages_sender: mpsc::UnboundedSender>, + subscribe_to_peers_messages_sender: mpsc::UnboundedSender>>, /// Receiver of `OnlinePeer` message online_peers_receiver: watch::Receiver, /// [`UpdateTopology`] message sender update_topology_sender: mpsc::UnboundedSender, + /// [`UpdatePeers`] message sender + update_peers_sender: mpsc::UnboundedSender, /// Sender of [`NetworkMessage`] message network_message_sender: unbounded_with_len::Sender>, /// Key exchange used by network @@ -57,6 +61,7 @@ impl Clone for NetworkBaseHandle { subscribe_to_peers_messages_sender: self.subscribe_to_peers_messages_sender.clone(), online_peers_receiver: self.online_peers_receiver.clone(), update_topology_sender: self.update_topology_sender.clone(), + update_peers_sender: self.update_peers_sender.clone(), network_message_sender: self.network_message_sender.clone(), _key_exchange: core::marker::PhantomData::, _encryptor: core::marker::PhantomData::, @@ -74,6 +79,7 @@ impl NetworkBaseHandle { key_pair: KeyPair, Config { address: listen_addr, + public_address, idle_timeout, }: Config, shutdown_signal: ShutdownSignal, @@ -85,12 +91,14 @@ impl NetworkBaseHandle { let (subscribe_to_peers_messages_sender, subscribe_to_peers_messages_receiver) = mpsc::unbounded_channel(); let (update_topology_sender, update_topology_receiver) = mpsc::unbounded_channel(); + let (update_peers_sender, update_peers_receiver) = mpsc::unbounded_channel(); let (network_message_sender, network_message_receiver) = unbounded_with_len::unbounded_channel(); let (peer_message_sender, peer_message_receiver) = mpsc::channel(1); let (service_message_sender, service_message_receiver) = mpsc::channel(1); let network = NetworkBase { listen_addr: listen_addr.into_value(), + public_address: public_address.into_value(), listener, peers: HashMap::new(), connecting_peers: HashMap::new(), @@ -99,13 +107,15 @@ impl NetworkBaseHandle { subscribe_to_peers_messages_receiver, online_peers_sender, update_topology_receiver, + update_peers_receiver, network_message_receiver, peer_message_receiver, peer_message_sender, service_message_receiver, service_message_sender, current_conn_id: 0, - current_topology: HashMap::new(), + current_topology: HashSet::new(), + current_peers_addresses: Vec::new(), idle_timeout, _key_exchange: core::marker::PhantomData::, _encryptor: core::marker::PhantomData::, @@ -119,6 +129,7 @@ impl NetworkBaseHandle { subscribe_to_peers_messages_sender, online_peers_receiver, update_topology_sender, + update_peers_sender, network_message_sender, _key_exchange: core::marker::PhantomData, _encryptor: core::marker::PhantomData, @@ -128,7 +139,7 @@ impl NetworkBaseHandle { } /// Subscribe to messages received from other peers in the network - pub fn subscribe_to_peers_messages(&self, sender: mpsc::Sender) { + pub fn subscribe_to_peers_messages(&self, sender: mpsc::Sender>) { self.subscribe_to_peers_messages_sender .send(sender) .expect("NetworkBase must accept messages until there is at least one handle to it") @@ -157,6 +168,13 @@ impl NetworkBaseHandle { .expect("NetworkBase must accept messages until there is at least one handle to it") } + /// Send [`UpdatePeers`] message on network actor. + pub fn update_peers_addresses(&self, peers: UpdatePeers) { + self.update_peers_sender + .send(peers) + .expect("NetworkBase must accept messages until there is at least one handle to it") + } + /// Receive latest update of [`OnlinePeers`] pub fn online_peers

(&self, f: impl FnOnce(&OnlinePeers) -> P) -> P { f(&self.online_peers_receiver.borrow()) @@ -179,22 +197,26 @@ impl NetworkBaseHandle { struct NetworkBase { /// Listening address for incoming connections. Must parse into [`std::net::SocketAddr`] listen_addr: SocketAddr, + /// External address of the peer (as seen by other peers) + public_address: SocketAddr, /// Current [`Peer`]s in [`Peer::Ready`] state. - peers: HashMap>, + peers: HashMap>, /// [`Peer`]s in process of being connected. - connecting_peers: HashMap, + connecting_peers: HashMap, /// [`TcpListener`] that is accepting [`Peer`]s' connections listener: TcpListener, /// Our app-level key pair key_pair: KeyPair, /// Recipients of messages received from other peers in the network. - subscribers_to_peers_messages: Vec>, + subscribers_to_peers_messages: Vec>>, /// Receiver to subscribe for messages received from other peers in the network. - subscribe_to_peers_messages_receiver: mpsc::UnboundedReceiver>, + subscribe_to_peers_messages_receiver: mpsc::UnboundedReceiver>>, /// Sender of `OnlinePeer` message online_peers_sender: watch::Sender, /// [`UpdateTopology`] message receiver update_topology_receiver: mpsc::UnboundedReceiver, + /// [`UpdatePeers`] message receiver + update_peers_receiver: mpsc::UnboundedReceiver, /// Receiver of [`Post`] message network_message_receiver: unbounded_with_len::Receiver>, /// Channel to gather messages from all peers @@ -208,8 +230,13 @@ struct NetworkBase { /// Current available connection id current_conn_id: ConnectionId, /// Current topology - /// Bool determines who is responsible for initiating connection - current_topology: HashMap, + current_topology: HashSet, + /// Can have two addresses for same `PeerId`. + /// * One initially provided via config + /// * Second received from other peers via gossiping + /// + /// Will try to establish connection via both addresses. + current_peers_addresses: Vec<(PeerId, SocketAddr)>, /// Duration after which terminate connection with idle peer idle_timeout: Duration, /// Key exchange used by network @@ -236,6 +263,9 @@ impl NetworkBase { Some(update_topology) = self.update_topology_receiver.recv() => { self.set_current_topology(update_topology); } + Some(update_peers) = self.update_peers_receiver.recv() => { + self.set_current_peers_addresses(update_peers); + } // Frequency of update is relatively low, so it won't block other tasks from execution _ = update_topology_interval.tick() => { self.update_topology() @@ -273,7 +303,7 @@ impl NetworkBase { Ok((stream, addr)) => { iroha_logger::debug!(from_addr = %addr, "Accepted connection"); // Handle creation of new peer - self.accept_new_peer(stream, &addr.into()); + self.accept_new_peer(stream); }, Err(error) => { iroha_logger::warn!(%error, "Error accepting connection"); @@ -297,11 +327,11 @@ impl NetworkBase { } } - fn accept_new_peer(&mut self, stream: TcpStream, addr: &SocketAddr) { + fn accept_new_peer(&mut self, stream: TcpStream) { let conn_id = self.get_conn_id(); let service_message_sender = self.service_message_sender.clone(); connected_from::( - addr.clone(), + self.public_address.clone(), self.key_pair.clone(), Connection::new(conn_id, stream), service_message_sender, @@ -311,43 +341,41 @@ impl NetworkBase { fn set_current_topology(&mut self, UpdateTopology(topology): UpdateTopology) { iroha_logger::debug!(?topology, "Network receive new topology"); - let self_public_key_hash = blake2b_hash(self.key_pair.public_key().encode()); let topology = topology .into_iter() .filter(|peer_id| peer_id.public_key() != self.key_pair.public_key()) - .map(|peer_id| { - // Determine who is responsible for connecting - let peer_public_key_hash = blake2b_hash(peer_id.public_key().encode()); - let is_active = self_public_key_hash >= peer_public_key_hash; - (peer_id, is_active) - }) .collect(); self.current_topology = topology; self.update_topology() } + fn set_current_peers_addresses(&mut self, UpdatePeers(peers): UpdatePeers) { + debug!(?peers, "Network receive new peers addresses"); + self.current_peers_addresses = peers; + self.update_topology() + } + fn update_topology(&mut self) { let to_connect = self - .current_topology + .current_peers_addresses .iter() // Peer is not connected but should - .filter_map(|(peer, is_active)| { - (!self.peers.contains_key(peer.public_key()) + .filter(|(id, address)| { + self.current_topology.contains(id) + && !self.peers.contains_key(id) && !self .connecting_peers .values() - .any(|public_key| peer.public_key() == public_key) - && *is_active) - .then_some(peer) + .any(|peer| (peer.id(), peer.address()) == (id, address)) }) - .cloned() + .map(|(id, address)| Peer::new(address.clone(), id.clone())) .collect::>(); let to_disconnect = self .peers .keys() // Peer is connected but shouldn't - .filter(|public_key| !self.current_topology.contains_key(*public_key)) + .filter(|&peer_id| !self.current_topology.contains(peer_id)) .cloned() .collect::>(); @@ -360,19 +388,19 @@ impl NetworkBase { } } - fn connect_peer(&mut self, peer: &PeerId) { + fn connect_peer(&mut self, peer: &Peer) { iroha_logger::trace!( listen_addr = %self.listen_addr, peer.id.address = %peer.address(), "Creating new peer actor", ); let conn_id = self.get_conn_id(); - self.connecting_peers - .insert(conn_id, peer.public_key().clone()); + self.connecting_peers.insert(conn_id, peer.clone()); let service_message_sender = self.service_message_sender.clone(); connecting::( // NOTE: we intentionally use peer's address and our public key, it's used during handshake peer.address().clone(), + self.public_address.clone(), self.key_pair.clone(), conn_id, service_message_sender, @@ -380,22 +408,21 @@ impl NetworkBase { ); } - fn disconnect_peer(&mut self, public_key: &PublicKey) { - let peer = match self.peers.remove(public_key) { + fn disconnect_peer(&mut self, peer_id: &PeerId) { + let peer = match self.peers.remove(peer_id) { Some(peer) => peer, - _ => return iroha_logger::warn!(?public_key, "Not found peer to disconnect"), + _ => return iroha_logger::warn!(?peer_id, "Not found peer to disconnect"), }; iroha_logger::debug!(listen_addr = %self.listen_addr, %peer.conn_id, "Disconnecting peer"); - let peer_id = PeerId::new(peer.p2p_addr, public_key.clone()); - Self::remove_online_peer(&self.online_peers_sender, &peer_id); + Self::remove_online_peer(&self.online_peers_sender, peer_id); } - #[log(skip_all, fields(peer=%peer_id, conn_id=connection_id, disambiguator=disambiguator))] + #[log(skip_all, fields(peer=%peer, conn_id=connection_id, disambiguator=disambiguator))] fn peer_connected( &mut self, Connected { - peer_id, + peer, connection_id, ready_peer_handle, peer_message_sender, @@ -404,13 +431,13 @@ impl NetworkBase { ) { self.connecting_peers.remove(&connection_id); - if !self.current_topology.contains_key(&peer_id) { - iroha_logger::warn!(%peer_id, topology=?self.current_topology, "Peer not present in topology is trying to connect"); + if !self.current_topology.contains(peer.id()) { + iroha_logger::warn!(peer=%peer.id(), topology=?self.current_topology, "Peer not present in topology is trying to connect"); return; } // Insert peer if peer not in peers yet or replace peer if it's disambiguator value is smaller than new one (simultaneous connections resolution rule) - match self.peers.get(peer_id.public_key()) { + match self.peers.get(peer.id()) { Some(peer) if peer.disambiguator > disambiguator => { iroha_logger::debug!( "Peer is disconnected due to simultaneous connection resolution policy" @@ -428,22 +455,22 @@ impl NetworkBase { let ref_peer = RefPeer { handle: ready_peer_handle, conn_id: connection_id, - p2p_addr: peer_id.address().clone(), + p2p_addr: peer.address().clone(), disambiguator, }; let _ = peer_message_sender.send(self.peer_message_sender.clone()); - self.peers.insert(peer_id.public_key().clone(), ref_peer); - Self::add_online_peer(&self.online_peers_sender, peer_id); + self.peers.insert(peer.id().clone(), ref_peer); + Self::add_online_peer(&self.online_peers_sender, peer); } - fn peer_terminated(&mut self, Terminated { peer_id, conn_id }: Terminated) { + fn peer_terminated(&mut self, Terminated { peer, conn_id }: Terminated) { self.connecting_peers.remove(&conn_id); - if let Some(peer_id) = peer_id { - if let Some(peer) = self.peers.get(peer_id.public_key()) { - if peer.conn_id == conn_id { - iroha_logger::debug!(conn_id, peer=%peer_id, "Peer terminated"); - self.peers.remove(peer_id.public_key()); - Self::remove_online_peer(&self.online_peers_sender, &peer_id); + if let Some(peer) = peer { + if let Some(ref_peer) = self.peers.get(peer.id()) { + if ref_peer.conn_id == conn_id { + iroha_logger::debug!(conn_id, peer=%peer, "Peer terminated"); + self.peers.remove(peer.id()); + Self::remove_online_peer(&self.online_peers_sender, peer.id()); } } } @@ -451,11 +478,11 @@ impl NetworkBase { fn post(&mut self, Post { data, peer_id }: Post) { iroha_logger::trace!(peer=%peer_id, "Post message"); - match self.peers.get(peer_id.public_key()) { - Some(peer) => { - if peer.handle.post(data).is_err() { + match self.peers.get(&peer_id) { + Some(ref_peer) => { + if ref_peer.handle.post(data).is_err() { iroha_logger::error!(peer=%peer_id, "Failed to send message to peer"); - self.peers.remove(peer_id.public_key()); + self.peers.remove(&peer_id); Self::remove_online_peer(&self.online_peers_sender, &peer_id); } } @@ -476,9 +503,9 @@ impl NetworkBase { } = self; peers.retain(|public_key, ref_peer| { if ref_peer.handle.post(data.clone()).is_err() { - let peer_id = PeerId::new(ref_peer.p2p_addr.clone(), public_key.clone()); - iroha_logger::error!(peer=%peer_id, "Failed to send message to peer"); - Self::remove_online_peer(online_peers_sender, &peer_id); + let peer = Peer::new(ref_peer.p2p_addr.clone(), public_key.clone()); + iroha_logger::error!(peer=%peer, "Failed to send message to peer"); + Self::remove_online_peer(online_peers_sender, peer.id()); false } else { true @@ -486,9 +513,9 @@ impl NetworkBase { }); } - async fn peer_message(&mut self, PeerMessage(peer_id, msg): PeerMessage) { + async fn peer_message(&mut self, msg: PeerMessage) { // TODO: consider broadcast channel instead - iroha_logger::trace!(peer=%peer_id, "Received peer message"); + iroha_logger::trace!(peer=%msg.0, "Received peer message"); if self.subscribers_to_peers_messages.is_empty() { iroha_logger::warn!("No subscribers to send message to"); return; @@ -509,7 +536,7 @@ impl NetworkBase { .await; } - fn subscribe_to_peers_messages(&mut self, subscriber: mpsc::Sender) { + fn subscribe_to_peers_messages(&mut self, subscriber: mpsc::Sender>) { self.subscribers_to_peers_messages.push(subscriber); iroha_logger::trace!( subscribers = self.subscribers_to_peers_messages.len(), @@ -517,8 +544,8 @@ impl NetworkBase { ); } - fn add_online_peer(online_peers_sender: &watch::Sender, peer_id: PeerId) { - online_peers_sender.send_if_modified(|online_peers| online_peers.insert(peer_id)); + fn add_online_peer(online_peers_sender: &watch::Sender, peer: Peer) { + online_peers_sender.send_if_modified(|online_peers| online_peers.insert(peer)); } fn remove_online_peer(online_peers_sender: &watch::Sender, peer_id: &PeerId) { @@ -535,14 +562,20 @@ impl NetworkBase { pub mod message { //! Module for network messages + use iroha_data_model::peer::Peer; + use super::*; /// Current online network peers - pub type OnlinePeers = HashSet; + pub type OnlinePeers = HashSet; /// The message that is sent to [`NetworkBase`] to update p2p topology of the network. #[derive(Clone, Debug)] - pub struct UpdateTopology(pub OnlinePeers); + pub struct UpdateTopology(pub HashSet); + + /// The message that is sent to [`NetworkBase`] to update peers addresses of the network. + #[derive(Clone, Debug)] + pub struct UpdatePeers(pub Vec<(PeerId, SocketAddr)>); /// The message to be sent to the other [`Peer`]. #[derive(Clone, Debug)] diff --git a/crates/iroha_p2p/src/peer.rs b/crates/iroha_p2p/src/peer.rs index b95dfd8f61a..6e6b787bdd9 100644 --- a/crates/iroha_p2p/src/peer.rs +++ b/crates/iroha_p2p/src/peer.rs @@ -1,7 +1,6 @@ //! Tokio actor Peer use bytes::{Buf, BufMut, BytesMut}; -use iroha_data_model::prelude::PeerId; use message::*; use parity_scale_codec::{DecodeAll, Encode}; use tokio::{ @@ -35,6 +34,7 @@ pub mod handles { /// Start Peer in [`state::Connecting`] state pub fn connecting( peer_addr: SocketAddr, + our_public_address: SocketAddr, key_pair: KeyPair, connection_id: ConnectionId, service_message_sender: mpsc::Sender>, @@ -42,6 +42,7 @@ pub mod handles { ) { let peer = state::Connecting { peer_addr, + our_public_address, key_pair, connection_id, }; @@ -55,14 +56,14 @@ pub mod handles { /// Start Peer in [`state::ConnectedFrom`] state pub fn connected_from( - peer_addr: SocketAddr, + our_public_address: SocketAddr, key_pair: KeyPair, connection: Connection, service_message_sender: mpsc::Sender>, idle_timeout: Duration, ) { let peer = state::ConnectedFrom { - peer_addr, + our_public_address, key_pair, connection, }; @@ -125,7 +126,7 @@ mod run { // Insure proper termination from every execution path. async { // Try to do handshake process - let peer = match tokio::time::timeout(idle_timeout, peer.handshake()).await { + let ready_peer = match tokio::time::timeout(idle_timeout, peer.handshake()).await { Ok(Ok(ready)) => ready, Ok(Err(error)) => { iroha_logger::warn!(?error, "Failure during handshake."); @@ -138,7 +139,7 @@ mod run { }; let Ready { - peer_id: new_peer_id, + peer: new_peer_id, connection: Connection { read, @@ -146,7 +147,7 @@ mod run { id: connection_id, }, cryptographer, - } = peer; + } = ready_peer; let peer_id = peer_id.insert(new_peer_id); let disambiguator = cryptographer.disambiguator; @@ -160,7 +161,7 @@ mod run { if service_message_sender .send(ServiceMessage::Connected(Connected { connection_id, - peer_id: peer_id.clone(), + peer: peer_id.clone(), ready_peer_handle, peer_message_sender, disambiguator, @@ -280,7 +281,10 @@ mod run { iroha_logger::debug!("Peer is terminated."); let _ = service_message_sender - .send(ServiceMessage::Terminated(Terminated { peer_id, conn_id })) + .send(ServiceMessage::Terminated(Terminated { + peer: peer_id, + conn_id, + })) .await; } @@ -452,6 +456,7 @@ mod state { //! Module for peer stages. use iroha_crypto::{KeyGenOption, KeyPair, PublicKey, Signature}; + use iroha_data_model::peer::Peer; use iroha_primitives::addr::SocketAddr; use super::{cryptographer::Cryptographer, *}; @@ -460,6 +465,7 @@ mod state { /// outgoing peer. pub(super) struct Connecting { pub peer_addr: SocketAddr, + pub our_public_address: SocketAddr, pub key_pair: KeyPair, pub connection_id: ConnectionId, } @@ -468,6 +474,7 @@ mod state { pub(super) async fn connect_to( Self { peer_addr, + our_public_address, key_pair, connection_id, }: Self, @@ -475,7 +482,7 @@ mod state { let stream = TcpStream::connect(peer_addr.to_string()).await?; let connection = Connection::new(connection_id, stream); Ok(ConnectedTo { - peer_addr, + our_public_address, key_pair, connection, }) @@ -484,7 +491,7 @@ mod state { /// Peer that is being connected to. pub(super) struct ConnectedTo { - peer_addr: SocketAddr, + our_public_address: SocketAddr, key_pair: KeyPair, connection: Connection, } @@ -493,7 +500,7 @@ mod state { #[allow(clippy::similar_names)] pub(super) async fn send_client_hello( Self { - peer_addr, + our_public_address, key_pair, mut connection, }: Self, @@ -515,7 +522,7 @@ mod state { let shared_key = key_exchange.compute_shared_secret(&kx_local_sk, &kx_remote_pk); let cryptographer = Cryptographer::new(&shared_key); Ok(SendKey { - peer_addr, + our_public_address, key_pair, kx_local_pk, kx_remote_pk, @@ -527,7 +534,7 @@ mod state { /// Peer that is being connected from pub(super) struct ConnectedFrom { - pub peer_addr: SocketAddr, + pub our_public_address: SocketAddr, pub key_pair: KeyPair, pub connection: Connection, } @@ -536,7 +543,7 @@ mod state { #[allow(clippy::similar_names)] pub(super) async fn read_client_hello( Self { - peer_addr, + our_public_address, key_pair, mut connection, .. @@ -557,7 +564,7 @@ mod state { let shared_key = key_exchange.compute_shared_secret(&kx_local_sk, &kx_remote_pk); let cryptographer = Cryptographer::new(&shared_key); Ok(SendKey { - peer_addr, + our_public_address, key_pair, kx_local_pk, kx_remote_pk, @@ -569,7 +576,7 @@ mod state { /// Peer that needs to send key. pub(super) struct SendKey { - peer_addr: SocketAddr, + our_public_address: SocketAddr, key_pair: KeyPair, kx_local_pk: K::PublicKey, kx_remote_pk: K::PublicKey, @@ -580,7 +587,7 @@ mod state { impl SendKey { pub(super) async fn send_our_public_key( Self { - peer_addr, + our_public_address, key_pair, kx_local_pk, kx_remote_pk, @@ -592,7 +599,7 @@ mod state { let payload = create_payload::(&kx_local_pk, &kx_remote_pk); let signature = Signature::new(key_pair.private_key(), &payload); - let data = (key_pair.public_key(), signature).encode(); + let data = (key_pair.public_key(), signature, our_public_address).encode(); let data = &cryptographer.encrypt(data.as_slice())?; @@ -603,7 +610,6 @@ mod state { write_half.write_all(&buf).await?; Ok(GetKey { - peer_addr, connection, kx_local_pk, kx_remote_pk, @@ -614,7 +620,6 @@ mod state { /// Peer that needs to get key. pub struct GetKey { - peer_addr: SocketAddr, connection: Connection, kx_local_pk: K::PublicKey, kx_remote_pk: K::PublicKey, @@ -625,7 +630,6 @@ mod state { /// Read the peer's public key pub(super) async fn read_their_public_key( Self { - peer_addr, mut connection, kx_local_pk, kx_remote_pk, @@ -640,17 +644,20 @@ mod state { let data = cryptographer.decrypt(data.as_slice())?; - let (remote_pub_key, signature): (PublicKey, Signature) = - DecodeAll::decode_all(&mut data.as_slice())?; + let (remote_pub_key, signature, remote_public_address): ( + PublicKey, + Signature, + SocketAddr, + ) = DecodeAll::decode_all(&mut data.as_slice())?; // Swap order of keys since we are verifying for other peer order remote/local keys is reversed let payload = create_payload::(&kx_remote_pk, &kx_local_pk); signature.verify(&remote_pub_key, &payload)?; - let peer_id = PeerId::new(peer_addr, remote_pub_key); + let peer = Peer::new(remote_public_address, remote_pub_key); Ok(Ready { - peer_id, + peer, connection, cryptographer, }) @@ -660,7 +667,7 @@ mod state { /// Peer that is ready for communication after finishing the /// handshake process. pub(super) struct Ready { - pub peer_id: PeerId, + pub peer: Peer, pub connection: Connection, pub cryptographer: Cryptographer, } @@ -752,12 +759,14 @@ mod handshake { pub mod message { //! Module for peer messages + use iroha_data_model::peer::Peer; + use super::*; /// Connection and Handshake was successful pub struct Connected { - /// Peer Id - pub peer_id: PeerId, + /// Peer + pub peer: Peer, /// Connection Id pub connection_id: ConnectionId, /// Handle for peer to send messages and terminate command @@ -769,12 +778,13 @@ pub mod message { } /// Messages received from Peer - pub struct PeerMessage(pub PeerId, pub T); + #[derive(Clone)] + pub struct PeerMessage(pub Peer, pub T); /// Peer faced error or `Terminate` message, send to indicate that it is terminated pub struct Terminated { - /// Peer Id - pub peer_id: Option, + /// Peer + pub peer: Option, /// Connection Id pub conn_id: ConnectionId, } diff --git a/crates/iroha_p2p/tests/integration/p2p.rs b/crates/iroha_p2p/tests/integration/p2p.rs index c5911f92f27..fbb3019fbcc 100644 --- a/crates/iroha_p2p/tests/integration/p2p.rs +++ b/crates/iroha_p2p/tests/integration/p2p.rs @@ -11,10 +11,10 @@ use futures::{prelude::*, stream::FuturesUnordered, task::AtomicWaker}; use iroha_config::parameters::actual::Network as Config; use iroha_config_base::WithOrigin; use iroha_crypto::KeyPair; -use iroha_data_model::prelude::PeerId; +use iroha_data_model::{prelude::Peer, Identifiable}; use iroha_futures::supervisor::ShutdownSignal; use iroha_logger::{prelude::*, test_logger}; -use iroha_p2p::{network::message::*, NetworkHandle}; +use iroha_p2p::{network::message::*, peer::message::PeerMessage, NetworkHandle}; use iroha_primitives::addr::socket_addr; use parity_scale_codec::{Decode, Encode}; use tokio::{ @@ -44,6 +44,7 @@ async fn network_create() { let idle_timeout = Duration::from_secs(60); let config = Config { address: WithOrigin::inline(address.clone()), + public_address: WithOrigin::inline(address.clone()), idle_timeout, }; let (network, _) = NetworkHandle::start(key_pair, config, ShutdownSignal::new()) @@ -52,15 +53,14 @@ async fn network_create() { tokio::time::sleep(delay).await; info!("Connecting to peer..."); - let peer1 = PeerId::new(address.clone(), public_key.clone()); - let topology = HashSet::from([peer1.clone()]); - network.update_topology(UpdateTopology(topology)); + let peer1 = Peer::new(address.clone(), public_key.clone()); + update_topology_and_peers_addresses(&network, &[peer1.clone()]); tokio::time::sleep(delay).await; info!("Posting message..."); network.post(Post { data: TestMessage("Some data to send to peer".to_owned()), - peer_id: peer1, + peer_id: peer1.id().clone(), }); tokio::time::sleep(delay).await; @@ -120,18 +120,18 @@ impl Future for WaitForN { #[derive(Debug)] pub struct TestActor { messages: WaitForN, - receiver: mpsc::Receiver, + receiver: mpsc::Receiver>, } impl TestActor { - fn start(messages: WaitForN) -> mpsc::Sender { + fn start(messages: WaitForN) -> mpsc::Sender> { let (sender, receiver) = mpsc::channel(10); let mut test_actor = Self { messages, receiver }; tokio::task::spawn(async move { loop { tokio::select! { - Some(msg) = test_actor.receiver.recv() => { - info!(?msg, "Actor received message"); + Some(PeerMessage(peer, msg)) = test_actor.receiver.recv() => { + info!(?msg, "Actor received message from {peer}"); test_actor.messages.inc(); }, else => break, @@ -157,6 +157,7 @@ async fn two_networks() { let address1 = socket_addr!(127.0.0.1:12_005); let config1 = Config { address: WithOrigin::inline(address1.clone()), + public_address: WithOrigin::inline(address1.clone()), idle_timeout, }; let (mut network1, _) = NetworkHandle::start(key_pair1, config1, ShutdownSignal::new()) @@ -167,6 +168,7 @@ async fn two_networks() { let address2 = socket_addr!(127.0.0.1:12_010); let config2 = Config { address: WithOrigin::inline(address2.clone()), + public_address: WithOrigin::inline(address2.clone()), idle_timeout, }; let (network2, _) = NetworkHandle::start(key_pair2, config2, ShutdownSignal::new()) @@ -178,13 +180,11 @@ async fn two_networks() { network2.subscribe_to_peers_messages(actor2); info!("Connecting peers..."); - let peer1 = PeerId::new(address1.clone(), public_key1); - let peer2 = PeerId::new(address2.clone(), public_key2); - let topology1 = HashSet::from([peer2.clone()]); - let topology2 = HashSet::from([peer1.clone()]); + let peer1 = Peer::new(address1.clone(), public_key1); + let peer2 = Peer::new(address2.clone(), public_key2); // Connect peers with each other - network1.update_topology(UpdateTopology(topology1.clone())); - network2.update_topology(UpdateTopology(topology2)); + update_topology_and_peers_addresses(&network1, &[peer2.clone()]); + update_topology_and_peers_addresses(&network2, &[peer1.clone()]); tokio::time::timeout(Duration::from_millis(2000), async { let mut connections = network1.wait_online_peers_update(HashSet::len).await; @@ -198,7 +198,7 @@ async fn two_networks() { info!("Posting message..."); network1.post(Post { data: TestMessage("Some data to send to peer".to_owned()), - peer_id: peer2, + peer_id: peer2.id().clone(), }); tokio::time::timeout(delay, &mut messages2) @@ -215,13 +215,6 @@ async fn two_networks() { let connected_peers2 = network2.online_peers(HashSet::len); assert_eq!(connected_peers2, 1); - - // Connecting to the same peer from network1 - network1.update_topology(UpdateTopology(topology1)); - tokio::time::sleep(delay).await; - - let connected_peers = network1.online_peers(HashSet::len); - assert_eq!(connected_peers, 1); } #[tokio::test(flavor = "multi_thread", worker_threads = 8)] @@ -235,7 +228,7 @@ async fn multiple_networks() { let address = socket_addr!(127.0.0.1: 12_015 + ( i * 5)); let key_pair = KeyPair::random(); let public_key = key_pair.public_key().clone(); - peers.push(PeerId::new(address, public_key)); + peers.push(Peer::new(address, public_key)); key_pairs.push(key_pair); } @@ -274,7 +267,7 @@ async fn multiple_networks() { for id in &peer_ids { let post = Post { data: TestMessage(String::from("Some data to send to peer")), - peer_id: id.clone(), + peer_id: id.id().clone(), }; network.post(post); } @@ -294,13 +287,13 @@ async fn multiple_networks() { } async fn start_network( - peer: PeerId, + peer: Peer, key_pair: KeyPair, - peers: Vec, + peers: Vec, messages: WaitForN, barrier: Arc, shutdown_signal: ShutdownSignal, -) -> (PeerId, NetworkHandle) { +) -> (Peer, NetworkHandle) { info!(peer_addr = %peer.address(), "Starting network"); // This actor will get the messages from other peers and increment the counter @@ -309,7 +302,8 @@ async fn start_network( let address = peer.address().clone(); let idle_timeout = Duration::from_secs(60); let config = Config { - address: WithOrigin::inline(address), + address: WithOrigin::inline(address.clone()), + public_address: WithOrigin::inline(address.clone()), idle_timeout, }; let (mut network, _) = NetworkHandle::start(key_pair, config, shutdown_signal) @@ -318,12 +312,9 @@ async fn start_network( network.subscribe_to_peers_messages(actor); let _ = barrier.wait().await; - let topology = peers - .into_iter() - .filter(|p| p != &peer) - .collect::>(); - let conn_count = topology.len(); - network.update_topology(UpdateTopology(topology)); + let peers = peers.into_iter().filter(|p| p != &peer).collect::>(); + let conn_count = peers.len(); + update_topology_and_peers_addresses(&network, &peers); let _ = barrier.wait().await; tokio::time::timeout(Duration::from_millis(10_000), async { @@ -336,11 +327,29 @@ async fn start_network( .await .expect("Failed to get all connections"); + // This is needed to ensure that all peers are connected to each other. + // The problem is that both peers establish connection (in each pair of peers), + // and one of connections is dropped based on disambiguator rule. + // So the check above (`conn_count != connections`) doesn't work, + // since peer can establish connection but then it will be dropped. + tokio::time::sleep(Duration::from_secs(10)).await; + info!(peer_addr = %peer.address(), %conn_count, "Got all connections!"); (peer, network) } +fn update_topology_and_peers_addresses(network: &NetworkHandle, peers: &[Peer]) { + let topology = peers.iter().map(|peer| peer.id().clone()).collect(); + network.update_topology(UpdateTopology(topology)); + + let addresses = peers + .iter() + .map(|peer| (peer.id().clone(), peer.address().clone())) + .collect(); + network.update_peers_addresses(UpdatePeers(addresses)); +} + #[test] fn test_encryption() { use iroha_crypto::encryption::{ChaCha20Poly1305, SymmetricEncryptor}; diff --git a/crates/iroha_schema_gen/src/lib.rs b/crates/iroha_schema_gen/src/lib.rs index 1e958e6db73..7fd0f8887a6 100644 --- a/crates/iroha_schema_gen/src/lib.rs +++ b/crates/iroha_schema_gen/src/lib.rs @@ -269,8 +269,6 @@ types!( InstructionType, InvalidParameterError, IpfsPath, - Ipv4Addr, - Ipv6Addr, Json, Level, Log, @@ -326,7 +324,6 @@ types!( Parameter, ParameterChanged, Parameters, - Peer, PeerEvent, PeerEventFilter, PeerEventSet, @@ -414,10 +411,6 @@ types!( SingularQueryOutputBox, SmartContractParameter, SmartContractParameters, - SocketAddr, - SocketAddrHost, - SocketAddrV4, - SocketAddrV6, Sorting, String, StringPredicateBox, @@ -490,7 +483,6 @@ types!( Vec, Vec, Vec, - Vec, Vec, Vec, Vec, @@ -503,9 +495,7 @@ types!( WasmExecutionFail, WasmSmartContract, - [u16; 8], [u8; 32], - [u8; 4], u16, u32, u64, @@ -562,12 +552,7 @@ pub mod complete_data_model { }; pub use iroha_genesis::{GenesisWasmAction, GenesisWasmTrigger, WasmPath}; pub use iroha_multisig_data_model::{MultisigAccountArgs, MultisigTransactionArgs}; - pub use iroha_primitives::{ - addr::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrHost, SocketAddrV4, SocketAddrV6}, - const_vec::ConstVec, - conststr::ConstString, - json::Json, - }; + pub use iroha_primitives::{const_vec::ConstVec, conststr::ConstString, json::Json}; pub use iroha_schema::Compact; } diff --git a/crates/iroha_swarm/src/lib.rs b/crates/iroha_swarm/src/lib.rs index 1c7053a9862..6c252ada9ca 100644 --- a/crates/iroha_swarm/src/lib.rs +++ b/crates/iroha_swarm/src/lib.rs @@ -41,7 +41,7 @@ struct PeerSettings { chain: iroha_data_model::ChainId, genesis_key_pair: peer::ExposedKeyPair, network: std::collections::BTreeMap, - topology: std::collections::BTreeSet, + topology: std::collections::BTreeSet, } impl PeerSettings { @@ -186,12 +186,13 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA PRIVATE_KEY: 802620F173D8C4913E2244715B9BF810AC0A4DBE1C9E08F595C8D9510E3E335EF964BB + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E GENESIS_PRIVATE_KEY: 802620FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0 GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' + TOPOLOGY: '["ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"]' ports: - 1337:1337 - 8080:8080 @@ -242,12 +243,13 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA PRIVATE_KEY: 802620F173D8C4913E2244715B9BF810AC0A4DBE1C9E08F595C8D9510E3E335EF964BB + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E GENESIS_PRIVATE_KEY: 802620FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0 GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' + TOPOLOGY: '["ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"]' ports: - 1337:1337 - 8080:8080 @@ -297,13 +299,14 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA PRIVATE_KEY: 802620F173D8C4913E2244715B9BF810AC0A4DBE1C9E08F595C8D9510E3E335EF964BB + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' GENESIS_PRIVATE_KEY: 802620FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0 GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' + TOPOLOGY: '["ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26","ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2","ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA","ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"]' ports: - 1337:1337 - 8080:8080 @@ -339,6 +342,7 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2 PRIVATE_KEY: 802620FD8E2F03755AA130464ABF57A75E207BE870636B57F614D7A7B94E42318F9CA9 + P2P_PUBLIC_ADDRESS: irohad1:1338 P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E @@ -359,6 +363,7 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300 PRIVATE_KEY: 8026203A18FAC2654F1C8A331A84F4B142396EEC900022B38842D88D55E0DE144C8DF2 + P2P_PUBLIC_ADDRESS: irohad2:1339 P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E @@ -379,6 +384,7 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26 PRIVATE_KEY: 8026209464445DBA9030D6AC4F83161D3219144F886068027F6708AF9686F85DF6C4F0 + P2P_PUBLIC_ADDRESS: irohad3:1340 P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E @@ -409,12 +415,13 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA PRIVATE_KEY: 802620F173D8C4913E2244715B9BF810AC0A4DBE1C9E08F595C8D9510E3E335EF964BB + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E GENESIS_PRIVATE_KEY: 802620FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0 GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' + TOPOLOGY: '["ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"]' ports: - 1337:1337 - 8080:8080 @@ -467,13 +474,14 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA PRIVATE_KEY: 802620F173D8C4913E2244715B9BF810AC0A4DBE1C9E08F595C8D9510E3E335EF964BB + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' GENESIS_PRIVATE_KEY: 802620FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0 GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' + TOPOLOGY: '["ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26","ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2","ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA","ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"]' ports: - 1337:1337 - 8080:8080 @@ -513,6 +521,7 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2 PRIVATE_KEY: 802620FD8E2F03755AA130464ABF57A75E207BE870636B57F614D7A7B94E42318F9CA9 + P2P_PUBLIC_ADDRESS: irohad1:1338 P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E @@ -537,6 +546,7 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300 PRIVATE_KEY: 8026203A18FAC2654F1C8A331A84F4B142396EEC900022B38842D88D55E0DE144C8DF2 + P2P_PUBLIC_ADDRESS: irohad2:1339 P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E @@ -561,6 +571,7 @@ mod tests { CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26 PRIVATE_KEY: 8026209464445DBA9030D6AC4F83161D3219144F886068027F6708AF9686F85DF6C4F0 + P2P_PUBLIC_ADDRESS: irohad3:1340 P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E diff --git a/crates/iroha_swarm/src/peer.rs b/crates/iroha_swarm/src/peer.rs index a9a397047aa..e050591b507 100644 --- a/crates/iroha_swarm/src/peer.rs +++ b/crates/iroha_swarm/src/peer.rs @@ -38,12 +38,12 @@ pub fn chain() -> iroha_data_model::ChainId { iroha_data_model::ChainId::from(crate::CHAIN_ID) } -pub fn peer_id( +pub fn peer( name: &str, port: u16, public_key: iroha_crypto::PublicKey, -) -> iroha_data_model::peer::PeerId { - iroha_data_model::peer::PeerId::new( +) -> iroha_data_model::peer::Peer { + iroha_data_model::peer::Peer::new( iroha_primitives::addr::SocketAddrHost { host: name.to_owned().into(), port, @@ -56,10 +56,10 @@ pub fn peer_id( #[allow(single_use_lifetimes)] pub fn topology<'a>( peers: impl Iterator, -) -> std::collections::BTreeSet { +) -> std::collections::BTreeSet { peers .map(|(service_name, [port_p2p, _], (public_key, _))| { - peer_id(service_name, *port_p2p, public_key.clone()) + peer(service_name, *port_p2p, public_key.clone()) }) .collect() } diff --git a/crates/iroha_swarm/src/schema.rs b/crates/iroha_swarm/src/schema.rs index 1384f285d27..a0aa9620fe2 100644 --- a/crates/iroha_swarm/src/schema.rs +++ b/crates/iroha_swarm/src/schema.rs @@ -1,5 +1,7 @@ //! Docker Compose schema. +use iroha_data_model::Identifiable; + use crate::{path, peer, ImageSettings, PeerSettings}; mod serde_impls; @@ -140,12 +142,13 @@ struct PeerEnv<'a> { chain: &'a iroha_data_model::ChainId, public_key: &'a iroha_crypto::PublicKey, private_key: &'a iroha_crypto::ExposedPrivateKey, + p2p_public_address: iroha_primitives::addr::SocketAddr, p2p_address: iroha_primitives::addr::SocketAddr, api_address: iroha_primitives::addr::SocketAddr, genesis_public_key: &'a iroha_crypto::PublicKey, #[serde(skip_serializing_if = "std::collections::BTreeSet::is_empty")] #[serde_as(as = "serde_with::json::JsonString")] - trusted_peers: std::collections::BTreeSet<&'a iroha_data_model::peer::PeerId>, + trusted_peers: std::collections::BTreeSet<&'a iroha_data_model::peer::Peer>, } impl<'a> PeerEnv<'a> { @@ -154,18 +157,25 @@ impl<'a> PeerEnv<'a> { [port_p2p, port_api]: [u16; 2], chain: &'a iroha_data_model::ChainId, genesis_public_key: &'a iroha_crypto::PublicKey, - topology: &'a std::collections::BTreeSet, + topology: &'a std::collections::BTreeSet, ) -> Self { + let p2p_public_address = topology + .iter() + .find(|&peer| peer.id().public_key() == public_key) + .unwrap() + .address + .clone(); Self { chain, public_key, private_key, + p2p_public_address, p2p_address: iroha_primitives::addr::socket_addr!(0.0.0.0:port_p2p), api_address: iroha_primitives::addr::socket_addr!(0.0.0.0:port_api), genesis_public_key, trusted_peers: topology .iter() - .filter(|&peer| peer.public_key() != public_key) + .filter(|&peer| peer.id().public_key() != public_key) .collect(), } } @@ -189,13 +199,16 @@ impl<'a> GenesisEnv<'a> { ports: [u16; 2], chain: &'a iroha_data_model::ChainId, (genesis_public_key, genesis_private_key): peer::ExposedKeyRefPair<'a>, - topology: &'a std::collections::BTreeSet, + topology: &'a std::collections::BTreeSet, ) -> Self { Self { base: PeerEnv::new(key_pair, ports, chain, genesis_public_key, topology), genesis_private_key, genesis: CONTAINER_SIGNED_GENESIS, - topology: topology.iter().collect(), + topology: topology + .iter() + .map(iroha_data_model::prelude::Peer::id) + .collect(), } } } @@ -403,7 +416,7 @@ impl<'a> BuildOrPull<'a> { chain: &'a iroha_data_model::ChainId, (genesis_public_key, genesis_private_key): &'a peer::ExposedKeyPair, network: &'a std::collections::BTreeMap, - topology: &'a std::collections::BTreeSet, + topology: &'a std::collections::BTreeSet, ) -> Self { Self::Pull { irohad0: Self::irohad0( @@ -434,7 +447,7 @@ impl<'a> BuildOrPull<'a> { chain: &'a iroha_data_model::ChainId, (genesis_public_key, genesis_private_key): &'a peer::ExposedKeyPair, network: &'a std::collections::BTreeMap, - topology: &'a std::collections::BTreeSet, + topology: &'a std::collections::BTreeSet, ) -> Self { Self::Build { irohad0: Self::irohad0( @@ -465,7 +478,7 @@ impl<'a> BuildOrPull<'a> { chain: &'a iroha_data_model::ChainId, (genesis_public_key, genesis_private_key): peer::ExposedKeyRefPair<'a>, network: &'a std::collections::BTreeMap, - topology: &'a std::collections::BTreeSet, + topology: &'a std::collections::BTreeSet, ) -> Irohad0<'a, Image> { let (_, ports, key_pair) = network.get(&0).expect("irohad0 must be present"); Irohad0::new( @@ -490,7 +503,7 @@ impl<'a> BuildOrPull<'a> { chain: &'a iroha_data_model::ChainId, genesis_public_key: &'a iroha_crypto::PublicKey, network: &'a std::collections::BTreeMap, - topology: &'a std::collections::BTreeSet, + topology: &'a std::collections::BTreeSet, ) -> std::collections::BTreeMap> { network .iter() @@ -617,7 +630,7 @@ mod tests { let genesis_key_pair = peer::generate_key_pair(None, &[]); let ports = [BASE_PORT_P2P, BASE_PORT_API]; let chain = peer::chain(); - let topology = [peer::peer_id("dummy", BASE_PORT_API, key_pair.0.clone())].into(); + let topology = [peer::peer("dummy", BASE_PORT_API, key_pair.0.clone())].into(); let env = PeerEnv::new(&key_pair, ports, &chain, &genesis_key_pair.0, &topology); let mock_env = iroha_config::base::env::MockEnv::from(env); let _ = iroha_config::base::read::ConfigReader::new() @@ -633,7 +646,7 @@ mod tests { let (genesis_public_key, genesis_private_key) = &peer::generate_key_pair(None, &[]); let ports = [BASE_PORT_P2P, BASE_PORT_API]; let chain = peer::chain(); - let topology = [peer::peer_id("dummy", BASE_PORT_API, key_pair.0.clone())].into(); + let topology = [peer::peer("dummy", BASE_PORT_API, key_pair.0.clone())].into(); let env = GenesisEnv::new( &key_pair, ports, diff --git a/crates/iroha_test_network/src/lib.rs b/crates/iroha_test_network/src/lib.rs index a03e70561b9..187ca60eb0c 100644 --- a/crates/iroha_test_network/src/lib.rs +++ b/crates/iroha_test_network/src/lib.rs @@ -206,7 +206,7 @@ impl Network { self } - fn topology(&self) -> UniqueVec { + fn topology(&self) -> UniqueVec { self.peers.iter().map(|x| x.id.clone()).collect() } @@ -316,7 +316,7 @@ impl NetworkBuilder { pub fn build(self) -> Network { let peers: Vec<_> = (0..self.n_peers).map(|_| NetworkPeer::generate()).collect(); - let topology: UniqueVec<_> = peers.iter().map(|peer| peer.id.clone()).collect(); + let topology: UniqueVec<_> = peers.iter().map(|peer| peer.peer_id()).collect(); let block_sync_gossip_period = DEFAULT_BLOCK_SYNC; @@ -457,7 +457,7 @@ pub enum PeerLifecycleEvent { /// When dropped, aborts the child process (if it is running). #[derive(Clone, Debug)] pub struct NetworkPeer { - id: PeerId, + id: Peer, key_pair: KeyPair, dir: Arc, run: Arc>>, @@ -476,7 +476,7 @@ impl NetworkPeer { let key_pair = KeyPair::random(); let port_p2p = AllocatedPort::new(); let port_api = AllocatedPort::new(); - let id = PeerId::new( + let id = Peer::new( socket_addr!(127.0.0.1:*port_p2p), key_pair.public_key().clone(), ); @@ -549,6 +549,10 @@ impl NetworkPeer { ["network", "address"], format!("127.0.0.1:{}", self.port_p2p), ) + .write( + ["network", "public_address"], + format!("127.0.0.1:{}", self.port_p2p), + ) .write(["torii", "address"], format!("127.0.0.1:{}", self.port_api)) .write(["logger", "format"], "json"); @@ -772,11 +776,16 @@ impl NetworkPeer { } } - /// Generated [`PeerId`] - pub fn id(&self) -> PeerId { + /// Generated [`Peer`] + pub fn peer(&self) -> Peer { self.id.clone() } + /// Generated [`PeerId`] + pub fn peer_id(&self) -> PeerId { + self.id.id.clone() + } + /// Check whether the peer is running pub fn is_running(&self) -> bool { self.is_running.load(Ordering::Relaxed) @@ -828,12 +837,6 @@ impl PartialEq for NetworkPeer { } } -impl From for Box { - fn from(val: NetworkPeer) -> Self { - Box::new(Peer::new(val.id.clone())) - } -} - /// Prints collected STDERR on drop. /// /// Used to avoid loss of useful data in case of task abortion before it is printed directly. diff --git a/crates/irohad/src/main.rs b/crates/irohad/src/main.rs index f3c7235f723..493fd79b93a 100644 --- a/crates/irohad/src/main.rs +++ b/crates/irohad/src/main.rs @@ -19,6 +19,7 @@ use iroha_core::{ gossiper::{TransactionGossiper, TransactionGossiperHandle}, kiso::KisoHandle, kura::Kura, + peers_gossiper::{PeersGossiper, PeersGossiperHandle}, query::store::LiveQueryStore, queue::Queue, smartcontracts::isi::Registrable as _, @@ -132,6 +133,7 @@ struct NetworkRelay { sumeragi: SumeragiHandle, block_sync: BlockSynchronizerHandle, tx_gossiper: TransactionGossiperHandle, + peers_gossiper: PeersGossiperHandle, network: IrohaNetwork, } @@ -140,12 +142,12 @@ impl NetworkRelay { let (sender, mut receiver) = mpsc::channel(1); self.network.subscribe_to_peers_messages(sender); while let Some(msg) = receiver.recv().await { - self.handle_message(msg).await; + self.handle_message(msg.0, msg.1).await; } iroha_logger::debug!("Exiting the network relay"); } - async fn handle_message(&mut self, msg: iroha_core::NetworkMessage) { + async fn handle_message(&mut self, peer: Peer, msg: iroha_core::NetworkMessage) { use iroha_core::NetworkMessage::*; match msg { @@ -157,6 +159,7 @@ impl NetworkRelay { } BlockSync(data) => self.block_sync.message(*data).await, TransactionGossiper(data) => self.tx_gossiper.gossip(*data).await, + PeersGossiper(data) => self.peers_gossiper.gossip(*data, peer).await, Health => {} } } @@ -256,6 +259,13 @@ impl Iroha { queue.clone(), ); + let (peers_gossiper, child) = PeersGossiper::start( + config.sumeragi.trusted_peers.value().clone(), + network.clone(), + supervisor.shutdown_signal(), + ); + supervisor.monitor(child); + let (sumeragi, child) = SumeragiStartArgs { sumeragi_config: config.sumeragi.clone(), common_config: config.common.clone(), @@ -264,6 +274,7 @@ impl Iroha { queue: queue.clone(), kura: kura.clone(), network: network.clone(), + peers_gossiper: peers_gossiper.clone(), genesis_network: GenesisWithPubKey { genesis, public_key: config.genesis.public_key.clone(), @@ -304,6 +315,7 @@ impl Iroha { sumeragi, block_sync, tx_gossiper, + peers_gossiper, network, } .run(), @@ -726,6 +738,7 @@ mod tests { .write("public_key", pubkey) .write("private_key", ExposedPrivateKey(privkey)) .write(["network", "address"], socket_addr!(127.0.0.1:1337)) + .write(["network", "public_address"], socket_addr!(127.0.0.1:1337)) .write(["torii", "address"], socket_addr!(127.0.0.1:8080)) .write(["genesis", "public_key"], genesis_public_key); table diff --git a/defaults/docker-compose.local.yml b/defaults/docker-compose.local.yml index 2667e84ff20..43ec3d21de4 100644 --- a/defaults/docker-compose.local.yml +++ b/defaults/docker-compose.local.yml @@ -11,13 +11,14 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D PRIVATE_KEY: 802620A4DFC16789FBF9A588525E4AC7F791AC51B12AEE8919EACC03EB2FC31D32C692 + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' GENESIS_PRIVATE_KEY: 80262082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TOPOLOGY: '["ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10","ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D","ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D","ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"]' ports: - 1337:1337 - 8080:8080 @@ -59,6 +60,7 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D PRIVATE_KEY: 8026203ECA64ADC23DC106C9D703233375EA6AC345AD7299FF3AD45F355DE6CD1B5510 + P2P_PUBLIC_ADDRESS: irohad1:1338 P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -85,6 +87,7 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10 PRIVATE_KEY: 8026207B1C78F733EDAFD6AF9BAC3A0D6C5A494557DD031609A4FDD9796EEF471D928C + P2P_PUBLIC_ADDRESS: irohad2:1339 P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -111,6 +114,7 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE PRIVATE_KEY: 8026206C7FF4CA09D395C7B7332C654099406E929C6238942E3CE85155CC1A5E2CF519 + P2P_PUBLIC_ADDRESS: irohad3:1340 P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 diff --git a/defaults/docker-compose.single.yml b/defaults/docker-compose.single.yml index 1f200380e46..b654bfb7668 100644 --- a/defaults/docker-compose.single.yml +++ b/defaults/docker-compose.single.yml @@ -11,12 +11,13 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D PRIVATE_KEY: 802620A4DFC16789FBF9A588525E4AC7F791AC51B12AEE8919EACC03EB2FC31D32C692 + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 GENESIS_PRIVATE_KEY: 80262082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"}]' + TOPOLOGY: '["ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"]' ports: - 1337:1337 - 8080:8080 diff --git a/defaults/docker-compose.yml b/defaults/docker-compose.yml index 026a7013e29..675e9b943ee 100644 --- a/defaults/docker-compose.yml +++ b/defaults/docker-compose.yml @@ -9,13 +9,14 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D PRIVATE_KEY: 802620A4DFC16789FBF9A588525E4AC7F791AC51B12AEE8919EACC03EB2FC31D32C692 + P2P_PUBLIC_ADDRESS: irohad0:1337 P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' GENESIS_PRIVATE_KEY: 80262082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD GENESIS: /tmp/genesis.signed.scale - TOPOLOGY: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TOPOLOGY: '["ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10","ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D","ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D","ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"]' ports: - 1337:1337 - 8080:8080 @@ -54,6 +55,7 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D PRIVATE_KEY: 8026203ECA64ADC23DC106C9D703233375EA6AC345AD7299FF3AD45F355DE6CD1B5510 + P2P_PUBLIC_ADDRESS: irohad1:1338 P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -77,6 +79,7 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10 PRIVATE_KEY: 8026207B1C78F733EDAFD6AF9BAC3A0D6C5A494557DD031609A4FDD9796EEF471D928C + P2P_PUBLIC_ADDRESS: irohad2:1339 P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 @@ -100,6 +103,7 @@ services: CHAIN: 00000000-0000-0000-0000-000000000000 PUBLIC_KEY: ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE PRIVATE_KEY: 8026206C7FF4CA09D395C7B7332C654099406E929C6238942E3CE85155CC1A5E2CF519 + P2P_PUBLIC_ADDRESS: irohad3:1340 P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index fe659e5eecf..375ab8fcc43 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -228,24 +228,12 @@ } ] }, - "Array": { - "Array": { - "type": "u16", - "len": 8 - } - }, "Array": { "Array": { "type": "u8", "len": 32 } }, - "Array": { - "Array": { - "type": "u8", - "len": 4 - } - }, "Asset": { "Struct": [ { @@ -2378,8 +2366,6 @@ ] }, "IpfsPath": "String", - "Ipv4Addr": "Array", - "Ipv6Addr": "Array", "Json": "String", "Level": { "Enum": [ @@ -2888,14 +2874,6 @@ } ] }, - "Peer": { - "Struct": [ - { - "name": "id", - "type": "PeerId" - } - ] - }, "PeerEvent": { "Enum": [ { @@ -2939,10 +2917,6 @@ }, "PeerId": { "Struct": [ - { - "name": "address", - "type": "SocketAddr" - }, { "name": "public_key", "type": "PublicKey" @@ -3194,7 +3168,7 @@ { "tag": "Peer", "discriminant": 8, - "type": "Vec" + "type": "Vec" }, { "tag": "RoleId", @@ -3545,7 +3519,7 @@ "Struct": [ { "name": "object", - "type": "Peer" + "type": "PeerId" } ] }, @@ -4219,61 +4193,6 @@ } ] }, - "SocketAddr": { - "Enum": [ - { - "tag": "Ipv4", - "discriminant": 0, - "type": "SocketAddrV4" - }, - { - "tag": "Ipv6", - "discriminant": 1, - "type": "SocketAddrV6" - }, - { - "tag": "Host", - "discriminant": 2, - "type": "SocketAddrHost" - } - ] - }, - "SocketAddrHost": { - "Struct": [ - { - "name": "host", - "type": "String" - }, - { - "name": "port", - "type": "u16" - } - ] - }, - "SocketAddrV4": { - "Struct": [ - { - "name": "ip", - "type": "Ipv4Addr" - }, - { - "name": "port", - "type": "u16" - } - ] - }, - "SocketAddrV6": { - "Struct": [ - { - "name": "ip", - "type": "Ipv6Addr" - }, - { - "name": "port", - "type": "u16" - } - ] - }, "SortedMap": { "Map": { "key": "AccountId", @@ -5039,9 +4958,6 @@ "Vec": { "Vec": "Parameter" }, - "Vec": { - "Vec": "Peer" - }, "Vec": { "Vec": "PeerId" }, diff --git a/scripts/test_env.py b/scripts/test_env.py index ed9cfb351a0..eba7d41410d 100755 --- a/scripts/test_env.py +++ b/scripts/test_env.py @@ -37,6 +37,7 @@ def __init__(self, args: argparse.Namespace): logging.info("Generating shared configuration...") trusted_peers = [{"address": f"{peer.host_ip}:{peer.p2p_port}", "public_key": peer.public_key} for peer in self.peers] + topology = [peer.public_key for peer in self.peers] genesis_path = pathlib.Path(args.out_dir) / "genesis.json" genesis_key_pair = kagami_generate_key_pair(args.out_dir, seed="Irohagenesis") genesis_public_key = genesis_key_pair["public_key"] @@ -58,7 +59,7 @@ def __init__(self, args: argparse.Namespace): tomli_w.dump(shared_config, f) copy_or_prompt_build_bin("irohad", args.root_dir, peers_dir) - copy_genesis_json_and_change_topology(args, genesis_path, trusted_peers) + copy_genesis_json_and_change_topology(args, genesis_path, topology) sign_genesis_with_kagami(args, genesis_path, genesis_public_key, genesis_private_key) @@ -116,7 +117,8 @@ def __init__(self, args: argparse.Namespace, nth: int): "public_key": self.public_key, "private_key": self.private_key, "network": { - "address": f"{self.host_ip}:{self.p2p_port}" + "address": f"{self.host_ip}:{self.p2p_port}", + "public_address": f"{self.host_ip}:{self.p2p_port}" }, "torii": { "address": f"{self.host_ip}:{self.api_port}"