Skip to content

Commit

Permalink
explorer: add more extensive sanity test
Browse files Browse the repository at this point in the history
mostly to account for the fact that at some point data won't be entirely
in memory, so we need to take epoch_stability_depth and utxo inputs into
account
  • Loading branch information
ecioppettini committed Apr 10, 2021
1 parent 9ec167a commit 33e3099
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 7 deletions.
131 changes: 129 additions & 2 deletions testing/jormungandr-integration-tests/src/jormungandr/explorer/mod.rs
@@ -1,11 +1,12 @@
use crate::common::{
jcli::JCli, jormungandr::ConfigurationBuilder, startup, transaction_utils::TransactionHash,
};
use chain_impl_mockchain::fragment::FragmentId;
use chain_impl_mockchain::key::Hash;
use chain_impl_mockchain::{block::ChainLength, fragment::Fragment};
use chain_impl_mockchain::{fragment::FragmentId, transaction::UtxoPointer};
use jormungandr_lib::interfaces::ActiveSlotCoefficient;
use jormungandr_testing_utils::stake_pool::StakePool;
use jormungandr_testing_utils::testing::node::Explorer;
use jormungandr_testing_utils::{stake_pool::StakePool, testing::node::time};
use jortestkit::process::Wait;
use std::str::FromStr;
use std::time::Duration;
Expand Down Expand Up @@ -93,6 +94,104 @@ pub fn explorer_sanity_test() {
epoch(&explorer);
}

#[test]
pub fn old_blocks_are_in_explorer() {
let jcli: JCli = Default::default();
let mut faucet = startup::create_new_account_address();
let receiver = startup::create_new_account_address();
let mut utxo_receiver = startup::create_new_utxo_address();

let epoch_stability_depth = 3;
let mut config = ConfigurationBuilder::new();
config
.with_epoch_stability_depth(epoch_stability_depth)
.with_explorer();

let (jormungandr, initial_stake_pools) =
startup::start_stake_pool(&[faucet.clone()], &[], &mut config).unwrap();

let transaction = faucet
.transaction_to(
&jormungandr.genesis_block_hash(),
&jormungandr.fees(),
utxo_receiver.address(),
1_000.into(),
)
.unwrap();

let output_value = match transaction {
Fragment::Transaction(ref tx) => {
let output = tx.as_slice().outputs().iter().next().unwrap();

output.value
}
_ => todo!(),
};

let encoded_transaction = transaction.encode();

let wait = Wait::new(Duration::from_secs(3), 20);
let fragment_id = jcli
.fragment_sender(&jormungandr)
.send(&encoded_transaction)
.assert_in_block_with_wait(&wait);

println!("explorer: utxo transaction {}", fragment_id);

let mut explorer = jormungandr.explorer();

let last_block = explorer.last_block().unwrap().data.unwrap().tip.block;
let current_tip_chain_length: u32 = last_block.chain_length.parse().unwrap();
let current_block_id = last_block.id;

time::wait_n_blocks(
ChainLength::from(current_tip_chain_length),
epoch_stability_depth + 5,
&mut explorer,
);

utxo_receiver.add_utxo(UtxoPointer {
transaction_id: transaction.hash(),
output_index: 0,
value: output_value,
});

let utxo_tx = utxo_receiver
.transaction_to(
&jormungandr.genesis_block_hash(),
&jormungandr.fees(),
utxo_receiver.address(),
1000.into(),
)
.unwrap()
.encode();

let _fragment_id = jcli
.fragment_sender(&jormungandr)
.send(&utxo_tx)
.assert_in_block_with_wait(&wait);

let block = explorer
.blocks_at_chain_length(current_tip_chain_length)
.unwrap();

let data = block.data.unwrap();
assert_eq!(data.blocks_by_chain_length.len(), 1, "block not found");

assert_eq!(
current_block_id, data.blocks_by_chain_length[0].id,
"unexpected block id was found"
);

println!("{}", jormungandr.logger.get_log_content());

transaction_by_id(&explorer, fragment_id.into());
blocks(&explorer, jormungandr.logger.get_created_blocks_hashes());
stake_pools(&explorer, &initial_stake_pools);
stake_pool(&explorer, &initial_stake_pools);
blocks_in_epoch(&explorer, jormungandr.logger.get_created_blocks_hashes());
}

fn transaction_by_id(explorer: &Explorer, fragment_id: FragmentId) {
let explorer_transaction = explorer
.transaction(fragment_id.into())
Expand Down Expand Up @@ -179,3 +278,31 @@ fn epoch(explorer: &Explorer) {

assert_eq!(epoch.data.unwrap().epoch.id, "1", "can't find epoch");
}

fn blocks_in_epoch(explorer: &Explorer, blocks_from_logs: Vec<Hash>) {
let epoch = explorer.epoch(0, 100).unwrap();
let explorer_blocks = epoch
.data
.unwrap()
.tip
.blocks_by_epoch
.unwrap()
.edges
.unwrap()
.iter()
.skip(1)
.map(|x| Hash::from_str(&x.as_ref().unwrap().node.id).unwrap())
.collect::<Vec<Hash>>();

let mut common_blocks = blocks_from_logs.clone();
common_blocks.retain(|x| !explorer_blocks.contains(x));

// we can have at least one non duplicated block
// due to explorer delay to logs content
assert!(
common_blocks.len() <= 1,
"blocks differents: Explorer {:?} vs Logs {:?}",
explorer_blocks,
blocks_from_logs
);
}
22 changes: 22 additions & 0 deletions testing/jormungandr-testing-utils/src/testing/node/time.rs
@@ -1,4 +1,5 @@
use crate::testing::node::explorer::Explorer;
use chain_impl_mockchain::block::ChainLength;
use jormungandr_lib::interfaces::BlockDate;

pub fn wait_for_epoch(epoch_id: u64, mut explorer: Explorer) {
Expand Down Expand Up @@ -39,3 +40,24 @@ pub fn wait_for_date(target_block_date: BlockDate, mut explorer: Explorer) {
std::thread::sleep(std::time::Duration::from_secs(1));
}
}

pub fn wait_n_blocks(start: ChainLength, n: u32, explorer: &Explorer) {
loop {
let current = explorer
.last_block()
.unwrap()
.data
.unwrap()
.tip
.block
.chain_length;

let current: u32 = current.parse().unwrap();

if u32::from(start) + n <= current {
return;
}

std::thread::sleep(std::time::Duration::from_secs(2));
}
}
21 changes: 18 additions & 3 deletions testing/jormungandr-testing-utils/src/wallet/mod.rs
Expand Up @@ -19,14 +19,14 @@ use chain_impl_mockchain::{
testing::data::{AddressData, AddressDataValue, Wallet as WalletLib},
transaction::{
InputOutputBuilder, Payload, PayloadSlice, TransactionBindingAuthDataPhantom,
TransactionSignDataHash, Witness,
TransactionSignDataHash, UtxoPointer, Witness,
},
value::Value as ValueLib,
vote::{Choice, CommitteeId},
};
use jormungandr_lib::{
crypto::{account::Identifier as AccountIdentifier, hash::Hash, key::Identifier},
interfaces::{Address, CommitteeIdDef, Initial, InitialUTxO, Value},
interfaces::{Address, CommitteeIdDef, Initial, InitialUTxO, UTxOInfo, Value},
};

use chain_addr::Discrimination;
Expand Down Expand Up @@ -233,7 +233,7 @@ impl Wallet {
pub fn add_input_with_value(&self, value: Value) -> Input {
match self {
Wallet::Account(account) => account.add_input_with_value(value),
Wallet::UTxO(_utxo) => unimplemented!(),
Wallet::UTxO(utxo) => utxo.add_input_with_value(value),
Wallet::Delegation(_delegation) => unimplemented!(),
}
}
Expand Down Expand Up @@ -430,6 +430,21 @@ impl Wallet {
self.address().1.public_key().unwrap().clone(),
))
}

pub fn add_utxo(&mut self, utxo_pointer: UtxoPointer) {
match self {
Wallet::UTxO(utxo) => {
let info = UTxOInfo::new(
utxo_pointer.transaction_id.into(),
utxo_pointer.output_index,
utxo.address(),
utxo_pointer.value.into(),
);
utxo.add_utxo(info);
}
_ => todo!("can not add utxo to non-utxo wallet"),
}
}
}

impl From<Wallet> for WalletLib {
Expand Down
26 changes: 24 additions & 2 deletions testing/jormungandr-testing-utils/src/wallet/utxo.rs
@@ -1,11 +1,11 @@
use chain_addr::Discrimination;
use chain_impl_mockchain::transaction::{TransactionSignDataHash, Witness};
use chain_impl_mockchain::transaction::{Input, TransactionSignDataHash, UtxoPointer, Witness};
use jormungandr_lib::{
crypto::{
hash::Hash,
key::{self, Identifier},
},
interfaces::{Address, UTxOInfo},
interfaces::{Address, UTxOInfo, Value},
};
use rand_chacha::ChaChaRng;
use rand_core::{CryptoRng, RngCore, SeedableRng};
Expand Down Expand Up @@ -94,4 +94,26 @@ impl Wallet {
self.last_signing_key().as_ref().sign(d)
})
}

pub fn add_input_with_value(&self, value: Value) -> Input {
if let Some((_, info)) = self
.utxos
.iter()
.find(|(_, info)| info.associated_fund() >= &value)
{
let utxo = UtxoPointer {
transaction_id: info.transaction_id().into_hash(),
output_index: info.index_in_transaction(),
value: value.into(),
};

Input::from_utxo(utxo)
} else {
todo!("no utxo found to cover for {}", value);
}
}

pub fn add_utxo(&mut self, utxo: UTxOInfo) {
self.utxos.push((0, utxo));
}
}

0 comments on commit 33e3099

Please sign in to comment.