Skip to content

Commit

Permalink
[fix] #3899: Fix topology mismatch bug (#3903)
Browse files Browse the repository at this point in the history
Signed-off-by: Daniil Polyakov <[email protected]>
  • Loading branch information
Arjentix authored and 6r1d committed Oct 17, 2023
1 parent fedc55b commit 99b659e
Show file tree
Hide file tree
Showing 26 changed files with 746 additions and 438 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ iroha_macro = { workspace = true }
iroha_logger = { workspace = true }
iroha_futures = { workspace = true }
iroha_data_model = { workspace = true, features = ["http"] }
iroha_primitives = { workspace = true }
iroha_telemetry = { workspace = true, optional = true }
iroha_version = { workspace = true, features = ["http"] }
iroha_config = { workspace = true }
Expand Down
5 changes: 3 additions & 2 deletions cli/src/samples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use iroha_config::{
};
use iroha_crypto::{KeyPair, PublicKey};
use iroha_data_model::{peer::PeerId, prelude::*};
use iroha_primitives::unique_vec::UniqueVec;

/// Get sample trusted peers. The public key must be the same as `configuration.public_key`
///
Expand Down Expand Up @@ -52,7 +53,7 @@ pub fn get_trusted_peers(public_key: Option<&PublicKey>) -> HashSet<PeerId> {
///
/// # Panics
/// - when [`KeyPair`] generation fails (rare case).
pub fn get_config_proxy(peers: HashSet<PeerId>, key_pair: Option<KeyPair>) -> ConfigurationProxy {
pub fn get_config_proxy(peers: UniqueVec<PeerId>, key_pair: Option<KeyPair>) -> ConfigurationProxy {
let (public_key, private_key) = key_pair
.unwrap_or_else(|| KeyPair::generate().expect("Key pair generation failed"))
.into();
Expand Down Expand Up @@ -94,7 +95,7 @@ pub fn get_config_proxy(peers: HashSet<PeerId>, key_pair: Option<KeyPair>) -> Co
///
/// # Panics
/// - when [`KeyPair`] generation fails (rare case).
pub fn get_config(trusted_peers: HashSet<PeerId>, key_pair: Option<KeyPair>) -> Configuration {
pub fn get_config(trusted_peers: UniqueVec<PeerId>, key_pair: Option<KeyPair>) -> Configuration {
get_config_proxy(trusted_peers, key_pair)
.build()
.expect("Iroha config should build as all required fields were provided")
Expand Down
11 changes: 3 additions & 8 deletions client/benches/torii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use iroha_config::base::runtime_upgrades::Reload;
use iroha_crypto::KeyPair;
use iroha_data_model::prelude::*;
use iroha_genesis::{GenesisNetwork, RawGenesisBlockBuilder};
use iroha_primitives::unique_vec;
use iroha_version::Encode;
use test_network::{get_key_pair, Peer as TestPeer, PeerBuilder, TestRuntime};
use tokio::runtime::Runtime;
Expand All @@ -17,10 +18,7 @@ const MINIMUM_SUCCESS_REQUEST_RATIO: f32 = 0.9;

fn query_requests(criterion: &mut Criterion) {
let mut peer = <TestPeer>::new().expect("Failed to create peer");
let configuration = get_config(
std::iter::once(peer.id.clone()).collect(),
Some(get_key_pair()),
);
let configuration = get_config(unique_vec![peer.id.clone()], Some(get_key_pair()));

let rt = Runtime::test();
let genesis = GenesisNetwork::from_configuration(
Expand Down Expand Up @@ -117,10 +115,7 @@ fn instruction_submits(criterion: &mut Criterion) {
println!("instruction submits");
let rt = Runtime::test();
let mut peer = <TestPeer>::new().expect("Failed to create peer");
let configuration = get_config(
std::iter::once(peer.id.clone()).collect(),
Some(get_key_pair()),
);
let configuration = get_config(unique_vec![peer.id.clone()], Some(get_key_pair()));
let genesis = GenesisNetwork::from_configuration(
RawGenesisBlockBuilder::new()
.domain("wonderland".parse().expect("Valid"))
Expand Down
6 changes: 2 additions & 4 deletions client/examples/million_accounts_genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{thread, time::Duration};
use iroha::samples::{construct_validator, get_config};
use iroha_data_model::prelude::*;
use iroha_genesis::{GenesisNetwork, RawGenesisBlock, RawGenesisBlockBuilder};
use iroha_primitives::unique_vec;
use test_network::{
get_key_pair, wait_for_genesis_committed, Peer as TestPeer, PeerBuilder, TestRuntime,
};
Expand Down Expand Up @@ -37,10 +38,7 @@ fn generate_genesis(num_domains: u32) -> RawGenesisBlock {

fn main_genesis() {
let mut peer = <TestPeer>::new().expect("Failed to create peer");
let configuration = get_config(
std::iter::once(peer.id.clone()).collect(),
Some(get_key_pair()),
);
let configuration = get_config(unique_vec![peer.id.clone()], Some(get_key_pair()));
let rt = Runtime::test();
let genesis = GenesisNetwork::from_configuration(
generate_genesis(1_000_000_u32),
Expand Down
3 changes: 2 additions & 1 deletion client/tests/integration/restart_peer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{str::FromStr, sync::Arc};
use eyre::Result;
use iroha_client::client::{self, QueryResult};
use iroha_data_model::prelude::*;
use iroha_primitives::unique_vec;
use tempfile::TempDir;
use test_network::*;
use tokio::runtime::Runtime;
Expand All @@ -17,7 +18,7 @@ fn restarted_peer_should_have_the_same_asset_amount() -> Result<()> {

let mut configuration = Configuration::test();
let mut peer = <PeerBuilder>::new().with_port(10_000).build()?;
configuration.sumeragi.trusted_peers.peers = std::iter::once(peer.id.clone()).collect();
configuration.sumeragi.trusted_peers.peers = unique_vec![peer.id.clone()];

let account_id = AccountId::from_str("alice@wonderland").unwrap();
let asset_definition_id = AssetDefinitionId::from_str("xor#wonderland").unwrap();
Expand Down
65 changes: 10 additions & 55 deletions config/src/sumeragi.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//! `Sumeragi` configuration. Contains both block commit and Gossip-related configuration.
#![allow(clippy::std_instead_of_core, clippy::arithmetic_side_effects)]
use std::{collections::HashSet, fmt::Debug, fs::File, io::BufReader, path::Path};
use std::{fmt::Debug, fs::File, io::BufReader, path::Path};

use eyre::{Result, WrapErr};
use iroha_config_base::derive::{view, Documented, Proxy};
use iroha_crypto::prelude::*;
use iroha_data_model::prelude::*;
use iroha_primitives::{unique_vec, unique_vec::UniqueVec};
use serde::{Deserialize, Serialize};

use self::default::*;
Expand Down Expand Up @@ -92,14 +93,14 @@ impl ConfigurationProxy {
/// The [`peer_id`] field of [`Self`]
/// has not been initialized prior to calling this method.
pub fn insert_self_as_trusted_peers(&mut self) {
let mut peers = HashSet::new();
#[allow(clippy::expect_used)]
let peer_id = self
.peer_id
.clone()
.expect("Insertion of `self` as `trusted_peers` implies that `peer_id` field should be initialized");
peers.insert(peer_id);
self.trusted_peers = Some(TrustedPeers { peers });
self.trusted_peers = Some(TrustedPeers {
peers: unique_vec![peer_id],
});
}
}

Expand All @@ -122,52 +123,8 @@ impl Configuration {
pub struct TrustedPeers {
/// Optional list of predefined trusted peers. Must contain unique
/// entries. Custom deserializer raises error if duplicates found.
#[serde(deserialize_with = "deserialize_unique_trusted_peers")]
pub peers: HashSet<PeerId>,
}

/// Custom deserializer that ensures that `trusted_peers` only
/// contains unique `PeerId`'s.
///
/// # Errors
/// - Peer Ids not unique,
/// - Not a sequence (array)
fn deserialize_unique_trusted_peers<'de, D>(deserializer: D) -> Result<HashSet<PeerId>, D::Error>
where
D: serde::Deserializer<'de>,
{
/// Helper, for constructing a unique visitor that errors whenever
/// a duplicate entry is found.
struct UniqueVisitor(core::marker::PhantomData<fn() -> HashSet<PeerId>>);

impl<'de> serde::de::Visitor<'de> for UniqueVisitor {
type Value = HashSet<PeerId>;

fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("a set of unique `Peer::Id`s.")
}

fn visit_seq<S>(self, mut seq: S) -> Result<HashSet<PeerId>, S::Error>
where
S: serde::de::SeqAccess<'de>,
{
let mut result = HashSet::new();
while let Some(value) = seq.next_element()? {
if result.contains(&value) {
return Err(serde::de::Error::custom(format!(
"The peer id: {}'s public key appears twice.",
&value
)));
}
result.insert(value);
}

Ok(result)
}
}

let visitor = UniqueVisitor(core::marker::PhantomData);
deserializer.deserialize_seq(visitor)
#[serde(deserialize_with = "UniqueVec::display_deserialize_failing_on_duplicates")]
pub peers: UniqueVec<PeerId>,
}

impl TrustedPeers {
Expand All @@ -181,11 +138,9 @@ impl TrustedPeers {
let file = File::open(&path)
.wrap_err_with(|| format!("Failed to open trusted peers file {:?}", &path))?;
let reader = BufReader::new(file);
let trusted_peers: HashSet<PeerId> =
serde_json::from_reader(reader).wrap_err("Failed to deserialize json from reader")?;
Ok(TrustedPeers {
peers: trusted_peers,
})
serde_json::from_reader(reader)
.wrap_err("Failed to deserialize json from reader")
.map_err(Into::into)
}
}

Expand Down
Binary file modified configs/peer/validator.wasm
Binary file not shown.
7 changes: 4 additions & 3 deletions core/benches/blocks/common.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(missing_docs, clippy::restriction)]

use std::{collections::BTreeSet, str::FromStr as _};
use std::str::FromStr as _;

use eyre::Result;
use iroha_core::{
Expand All @@ -18,6 +18,7 @@ use iroha_data_model::{
prelude::*,
transaction::TransactionLimits,
};
use iroha_primitives::unique_vec::UniqueVec;
use serde_json::json;

/// Create block
Expand All @@ -33,7 +34,7 @@ pub fn create_block(
.unwrap();
let limits = wsv.transaction_validator().transaction_limits;

let topology = Topology::new(Vec::new());
let topology = Topology::new(UniqueVec::new());
let block = BlockBuilder::new(
vec![AcceptedTransaction::accept(transaction, &limits).unwrap()],
topology.clone(),
Expand Down Expand Up @@ -174,7 +175,7 @@ pub fn restore_every_nth(

pub fn build_wsv(account_id: &AccountId, key_pair: &KeyPair) -> WorldStateView {
let kura = iroha_core::kura::Kura::blank_kura_for_testing();
let mut wsv = WorldStateView::new(World::with([], BTreeSet::new()), kura);
let mut wsv = WorldStateView::new(World::with([], UniqueVec::new()), kura);
wsv.config.transaction_limits = TransactionLimits::new(u64::MAX, u64::MAX);
wsv.config.wasm_runtime_config.fuel_limit = u64::MAX;
wsv.config.wasm_runtime_config.max_memory = u32::MAX;
Expand Down
3 changes: 2 additions & 1 deletion core/benches/kura.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use iroha_core::{
};
use iroha_crypto::KeyPair;
use iroha_data_model::{prelude::*, transaction::TransactionLimits};
use iroha_primitives::unique_vec::UniqueVec;
use tokio::{fs, runtime::Runtime};

async fn measure_block_size_for_n_validators(n_validators: u32) {
Expand Down Expand Up @@ -42,7 +43,7 @@ async fn measure_block_size_for_n_validators(n_validators: u32) {
let _thread_handle = iroha_core::kura::Kura::start(kura.clone());

let mut wsv = WorldStateView::new(World::new(), kura);
let topology = Topology::new(Vec::new());
let topology = Topology::new(UniqueVec::new());
let mut block = BlockBuilder::new(vec![tx], topology, Vec::new())
.chain_first(&mut wsv)
.sign(KeyPair::generate().unwrap())
Expand Down
7 changes: 4 additions & 3 deletions core/benches/validation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(missing_docs, clippy::restriction)]

use std::{collections::BTreeSet, str::FromStr as _};
use std::str::FromStr as _;

use criterion::{criterion_group, criterion_main, Criterion};
use iroha_core::{
Expand All @@ -12,6 +12,7 @@ use iroha_core::{
wsv::World,
};
use iroha_data_model::{prelude::*, transaction::TransactionLimits};
use iroha_primitives::unique_vec::UniqueVec;

const START_DOMAIN: &str = "start";
const START_ACCOUNT: &str = "starter";
Expand Down Expand Up @@ -66,7 +67,7 @@ fn build_test_and_transient_wsv(keys: KeyPair) -> WorldStateView {
let mut domain = Domain::new(domain_id).build(&account_id);
let account = Account::new(account_id.clone(), [public_key]).build(&account_id);
assert!(domain.add_account(account).is_none());
World::with([domain], BTreeSet::new())
World::with([domain], UniqueVec::new())
},
kura,
);
Expand Down Expand Up @@ -146,7 +147,7 @@ fn sign_blocks(criterion: &mut Criterion) {
let key_pair = KeyPair::generate().expect("Failed to generate KeyPair.");
let kura = iroha_core::kura::Kura::blank_kura_for_testing();
let mut wsv = WorldStateView::new(World::new(), kura);
let topology = Topology::new(Vec::new());
let topology = Topology::new(UniqueVec::new());

let mut success_count = 0;
let mut failures_count = 0;
Expand Down
Loading

0 comments on commit 99b659e

Please sign in to comment.