Skip to content

Commit d627cf7

Browse files
committed
feat: draft unstable network tests (doesn't work yet)
Signed-off-by: 0x009922 <[email protected]>
1 parent 64ff720 commit d627cf7

File tree

1 file changed

+157
-1
lines changed

1 file changed

+157
-1
lines changed

crates/iroha/tests/faulty_peers.rs

+157-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ use std::time::Duration;
33
use eyre::Result;
44
use futures_util::{stream::FuturesUnordered, StreamExt};
55
use iroha_config_base::toml::WriteExt;
6+
use iroha_data_model::{
7+
asset::AssetDefinition, isi::Register, parameter::BlockParameter, prelude::*,
8+
};
69
use iroha_test_network::{
710
genesis_factory, once_blocks_sync, Network, NetworkBuilder, PeerLifecycleEvent,
811
};
12+
use iroha_test_samples::ALICE_ID;
13+
use nonzero_ext::nonzero;
14+
use rand::{prelude::SliceRandom, thread_rng};
915
use relay::P2pRelay;
10-
use tokio::{self, time::timeout};
16+
use tokio::{self, task::spawn_blocking, time::timeout};
1117

1218
mod relay {
1319
use std::{
@@ -361,3 +367,153 @@ async fn suspending_works() -> Result<()> {
361367

362368
Ok(())
363369
}
370+
371+
// ======= ACTUAL TESTS BEGIN HERE =======
372+
373+
struct UnstableNetwork {
374+
n_peers: usize,
375+
n_faulty_peers: usize,
376+
n_transactions: usize,
377+
force_soft_fork: bool,
378+
}
379+
380+
impl UnstableNetwork {
381+
async fn run(self) -> Result<()> {
382+
assert!(self.n_peers > self.n_faulty_peers);
383+
384+
let account_id = ALICE_ID.clone();
385+
let asset_definition_id: AssetDefinitionId = "camomile#wonderland".parse().expect("Valid");
386+
387+
let network = NetworkBuilder::new()
388+
.with_peers(self.n_peers)
389+
.with_config(|cfg| {
390+
if self.force_soft_fork {
391+
cfg.write(["sumeragi", "debug_force_soft_fork"], true);
392+
}
393+
})
394+
.with_genesis_instruction(SetParameter(Parameter::Block(
395+
BlockParameter::MaxTransactions(nonzero!(1u64)),
396+
)))
397+
.build();
398+
let mut relay = start_network_with_relay(&network).await?;
399+
400+
relay.start();
401+
{
402+
let client = network.client();
403+
let isi =
404+
Register::asset_definition(AssetDefinition::numeric(asset_definition_id.clone()));
405+
spawn_blocking(move || client.submit_blocking(isi)).await??;
406+
}
407+
let init_blocks = 2;
408+
network.ensure_blocks(init_blocks).await?;
409+
410+
for i in 0..self.n_transactions {
411+
// Make random peers faulty.
412+
let faulty: Vec<_> = network
413+
.peers()
414+
.choose_multiple(&mut thread_rng(), self.n_faulty_peers)
415+
.map(|peer| peer.id())
416+
.collect();
417+
for peer in &faulty {
418+
relay.suspend(peer).activate();
419+
}
420+
421+
// When minted
422+
let quantity = Numeric::ONE;
423+
let mint_asset = Mint::asset_numeric(
424+
quantity,
425+
AssetId::new(asset_definition_id.clone(), account_id.clone()),
426+
);
427+
let client = network
428+
.peers()
429+
.iter()
430+
.find(|x| faulty.contains(&x.id()))
431+
.expect("there should be some working peers")
432+
.client();
433+
spawn_blocking(move || client.submit_blocking(mint_asset)).await??;
434+
435+
// Then all non-faulty peers get the new block
436+
timeout(
437+
network.sync_timeout(),
438+
once_blocks_sync(
439+
network.peers().iter().filter(|x| !faulty.contains(&x.id())),
440+
init_blocks + (i as u64),
441+
),
442+
)
443+
.await?;
444+
445+
// Return all peers to normal function.
446+
for peer in &faulty {
447+
relay.suspend(peer).deactivate();
448+
}
449+
}
450+
451+
// When network is sync at last
452+
network
453+
.ensure_blocks(init_blocks + self.n_transactions as u64)
454+
.await?;
455+
456+
// Then there are N assets minted
457+
let client = network.client();
458+
let asset = spawn_blocking(move || {
459+
client
460+
.query(FindAssets)
461+
.filter_with(|asset| asset.id.definition_id.eq(asset_definition_id))
462+
.execute_all()
463+
})
464+
.await??
465+
.into_iter()
466+
.next()
467+
.expect("there should be 1 result");
468+
assert_eq!(
469+
asset.value,
470+
AssetValue::Numeric(Numeric::new(self.n_transactions as u128 + 1, 0))
471+
);
472+
473+
Ok(())
474+
}
475+
}
476+
477+
#[tokio::test]
478+
async fn unstable_network_5_peers_1_fault() -> Result<()> {
479+
UnstableNetwork {
480+
n_peers: 5,
481+
n_faulty_peers: 1,
482+
n_transactions: 20,
483+
force_soft_fork: false,
484+
}
485+
.run()
486+
.await
487+
}
488+
489+
// #[tokio::test]
490+
// async fn soft_fork() {
491+
// let n_peers = 4;
492+
// let n_transactions = 20;
493+
// unstable_network(n_peers, 0, n_transactions, true, 10_830);
494+
// }
495+
496+
#[tokio::test]
497+
async fn unstable_network_8_peers_1_fault() -> Result<()> {
498+
UnstableNetwork {
499+
n_peers: 8,
500+
n_faulty_peers: 1,
501+
n_transactions: 20,
502+
force_soft_fork: false,
503+
}
504+
.run()
505+
.await
506+
}
507+
508+
#[tokio::test]
509+
// #[ignore = "This test does not guarantee to have positive outcome given a fixed time."]
510+
async fn unstable_network_9_peers_2_faults() -> Result<()> {
511+
UnstableNetwork {
512+
n_peers: 9,
513+
n_faulty_peers: 2,
514+
n_transactions: 5,
515+
force_soft_fork: false,
516+
}
517+
.run()
518+
.await
519+
}

0 commit comments

Comments
 (0)