Skip to content

Commit

Permalink
Merge pull request #4 from mangata-finance/feature/enable_client_db_t…
Browse files Browse the repository at this point in the history
…ests

Feature/enable client db tests
  • Loading branch information
gleb-urvanov authored Sep 7, 2021
2 parents 5b0a05f + 27dfa3c commit a388297
Show file tree
Hide file tree
Showing 25 changed files with 243 additions and 198 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

51 changes: 37 additions & 14 deletions client/basic-authorship/src/basic_authorship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,12 +356,14 @@ mod tests {
use sp_inherents::{InherentData, ProvideInherentData};
use sp_runtime::traits::NumberFor;
use sp_transaction_pool::{ChainEvent, MaintainedTransactionPool, TransactionSource};
use sc_client_api::BlockImportOperation;

use substrate_test_runtime_client::{
prelude::*,
runtime::{Extrinsic, Transfer},
runtime::{Extrinsic, Transfer, Block},
TestClientBuilder, TestClientBuilderExt,
};
use sp_runtime::traits::Block as BlockT;

const SOURCE: TransactionSource = TransactionSource::External;

Expand Down Expand Up @@ -490,8 +492,12 @@ mod tests {
}

#[test]
// that test should be enabled when extended header will be implemented
// the main problem is when block is executed to verify storage changes
// it actully tries to execute extrinsics stored
fn proposed_storage_changes_should_match_execute_block_storage_changes() {
let (client, backend) = TestClientBuilder::new().build_with_backend();
let _ = backend.blockchain();
let client = Arc::new(client);
let spawner = sp_core::testing::TaskExecutor::new();
let txpool = BasicPool::new_full(Default::default(), None, spawner, client.clone());
Expand Down Expand Up @@ -528,8 +534,13 @@ mod tests {

assert_eq!(proposal.block.extrinsics().len(), 1);

// TODO perform full validation when all required information will be stored inside
// header
let api = client.runtime_api();
api.execute_block(&block_id, proposal.block).unwrap();
let mut header = proposal.block.header.clone();
let prev_header = backend.blockchain().header(BlockId::Hash(genesis_hash)).unwrap().unwrap();
header.set_extrinsics_root(*prev_header.extrinsics_root());
api.execute_block(&block_id, <Block as BlockT>::new(header, vec![])).unwrap();

let state = backend.state_at(block_id).unwrap();
let changes_trie_state =
Expand All @@ -546,16 +557,16 @@ mod tests {
}

#[test]
// TODO this tests fails due two reasons. It verifies extrinsics order compairing extrinsic
// root hash block-builder/src/lib.rs:272 and due to fact that extrinsic validation mechanism
// has been disabled BlockBuilder::push. Once shuffling will be done at runtime and validation
// will be reverted it can be enalbed again
#[ignore]
fn should_not_remove_invalid_transactions_when_skipping() {
// given
let mut client = Arc::new(substrate_test_runtime_client::new());
let spawner = sp_core::testing::TaskExecutor::new();
let txpool = BasicPool::new_full(Default::default(), None, spawner, client.clone());
let txpool = BasicPool::new_full(
Default::default(),
None,
spawner,
client.clone(),
);

futures::executor::block_on(
txpool.submit_at(&BlockId::number(0), SOURCE, vec![
Expand Down Expand Up @@ -597,10 +608,10 @@ mod tests {
proposer.propose(create_inherents(), Default::default(), deadline, RecordProof::No)
).map(|r| r.block).unwrap();

// then
// block should have some extrinsics although we have some more in the pool.
//assert_eq!(block.extrinsics().len(), expected_block_extrinsics);
assert_eq!(txpool.ready().count(), expected_pool_transactions);
// then
// block should have some extrinsics although we have some more in the pool.
assert_eq!(block.extrinsics().len(), expected_block_extrinsics);
assert_eq!(txpool.ready().count(), expected_pool_transactions);

block
};
Expand All @@ -615,18 +626,30 @@ mod tests {

// let's create one block and import it
let block = propose_block(&client, 0, 2, 7);
let block_hash = block.header().hash();
client.import(BlockOrigin::Own, block).unwrap();

// push one extra block - extrinsics in the pool makred as 'exhausted_resources'
// to succeed needs to be executed as first in the processed block. Due to
// modifications in block_builder all extrinsics from previous block are applied
// beofre trying to validate extrinsics from the tx pool. Once we include empty
// block in between 'exhausted_resources' extrinsic from the pool is exeucted as
// the first one and the origin test logic is maintained
let block = client.new_block_at(&BlockId::Hash(block_hash), Default::default(), false)
.unwrap()
.build(Default::default())
.unwrap();
client.import(BlockOrigin::Own, block.block).unwrap();

futures::executor::block_on(
txpool.maintain(chain_event(
client.header(&BlockId::Number(1))
.expect("header get error")
.expect("there should be header")
))
);

// now let's make sure that we can still make some progress
let block = propose_block(&client, 1, 2, 5);
let block = propose_block(&client, 2, 2, 5);
client.import(BlockOrigin::Own, block).unwrap();
}
}
61 changes: 22 additions & 39 deletions client/block-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use sp_runtime::{
generic::BlockId,
traits::{BlakeTwo256, Header as HeaderT, Hash, Block as BlockT, HashFor, DigestFor, NumberFor, One},
};
use sp_blockchain::{ApplyExtrinsicFailed, Error};
use sp_blockchain::Error;
use sp_core::ExecutionContext;
use sp_api::{
Core, ApiExt, ApiErrorFor, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof,
Expand Down Expand Up @@ -144,7 +144,6 @@ where

let block_id = BlockId::Hash(parent_hash);

info!("Api call to initialize the block");
api.initialize_block_with_context(
&block_id, ExecutionContext::BlockConstruction, &header,
)?;
Expand Down Expand Up @@ -236,9 +235,7 @@ where
mut self,
seed: SeedType,
) -> Result<BuiltBlock<Block, backend::StateBackendFor<B, Block>>, ApiErrorFor<A, Block>> {
let extrinsics = self.extrinsics.clone();
let parent_hash = self.parent_hash;

let block_id = &self.block_id;

match self
Expand All @@ -248,45 +245,31 @@ where
.unwrap()
{
Some(previous_block_extrinsics) => {
if previous_block_extrinsics.is_empty() {
info!("No extrinsics found for previous block");
extrinsics.into_iter().for_each(|xt| {
self.api.execute_in_transaction(|api| {
match api.apply_extrinsic_with_context(
block_id,
ExecutionContext::BlockConstruction,
xt.clone(),
) {
Ok(Ok(_)) => TransactionOutcome::Commit(()),
Ok(Err(_tx_validity)) => TransactionOutcome::Rollback(()),
Err(_e) => TransactionOutcome::Rollback(()),
}
})
});
} else {
info!("transaction count {}", previous_block_extrinsics.len());

let shuffled_extrinsics = extrinsic_shuffler::shuffle::<Block, A>(
log::debug!(target: "block_builder", "transaction count {}", previous_block_extrinsics.len());
let shuffled_extrinsics = if previous_block_extrinsics.len() <= 1 {
previous_block_extrinsics
}else{
extrinsic_shuffler::shuffle::<Block, A>(
&self.api,
&self.block_id,
previous_block_extrinsics,
seed,
);

for xt in shuffled_extrinsics.iter() {
log::debug!(target: "block_builder", "executing extrinsic :{:?}", BlakeTwo256::hash(&xt.encode()));
self.api.execute_in_transaction(|api| {
match api.apply_extrinsic_with_context(
block_id,
ExecutionContext::BlockConstruction,
xt.clone(),
) {
Ok(Ok(_)) => TransactionOutcome::Commit(()),
Ok(Err(_tx_validity)) => TransactionOutcome::Rollback(()),
Err(_e) => TransactionOutcome::Rollback(()),
}
})
}
)
};

for xt in shuffled_extrinsics.iter() {
log::debug!(target: "block_builder", "executing extrinsic :{:?}", BlakeTwo256::hash(&xt.encode()));
self.api.execute_in_transaction(|api| {
match api.apply_extrinsic_with_context(
block_id,
ExecutionContext::BlockConstruction,
xt.clone(),
) {
Ok(Ok(_)) => TransactionOutcome::Commit(()),
Ok(Err(_tx_validity)) => TransactionOutcome::Rollback(()),
Err(_e) => TransactionOutcome::Rollback(()),
}
})
}
}
None => {
Expand Down
7 changes: 3 additions & 4 deletions client/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,10 +688,9 @@ fn inject_inherents<'a>(
.sr25519_vrf_sign(<AuthorityId as AppKey>::ID, public, transcript_data)
.map_err(|_| sp_consensus::Error::StateUnavailable(String::from("signing seed failure")))?;

sp_ignore_tx::IgnoreTXInherentDataProvider({
let flag = slot_info.number == (epoch.start_slot + epoch.duration - 1);
flag
})
sp_ignore_tx::IgnoreTXInherentDataProvider(
slot_info.number == (epoch.start_slot + epoch.duration - 1)
)
.provide_inherent_data(&mut slot_info.inherent_data)
.map_err(|_| sp_consensus::Error::StateUnavailable(String::from("cannot inject RandomSeed inherent data")))?;

Expand Down
2 changes: 2 additions & 0 deletions client/consensus/manual-seal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../..

[dev-dependencies]
tokio = { version = "0.2", features = ["rt-core", "macros"] }
pallet-random-seed = { path='../../../frame/random-seed', version = "2.0.0" }
sp-ignore-tx = { path = "../../../primitives/ignore-tx", version = "2.0.0"}
sc-basic-authorship = { path = "../../basic-authorship", version = "0.8.0" }
substrate-test-runtime-client = { path = "../../../test-utils/runtime/client", version = "2.0.0" }
substrate-test-runtime-transaction-pool = { path = "../../../test-utils/runtime/transaction-pool", version = "2.0.0" }
Expand Down
26 changes: 16 additions & 10 deletions client/consensus/manual-seal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub use self::{
error::Error,
consensus::ConsensusDataProvider,
finalize_block::{finalize_block, FinalizeBlockParams},
seal_block::{SealBlockParams, seal_block, MAX_PROPOSAL_DURATION},
seal_block::{SealBlockParams, /*seal_block,*/ MAX_PROPOSAL_DURATION},
rpc::{EngineCommand, CreatedBlock},
};
use sp_api::{ProvideRuntimeApi, TransactionFor};
Expand Down Expand Up @@ -143,7 +143,8 @@ pub struct InstantSealParams<B: BlockT, BI, E, C: ProvideRuntimeApi<B>, A: txpoo
}

/// Creates the background authorship task for the manual seal engine.
pub async fn run_manual_seal<B, BI, CB, E, C, A, SC, CS>(
#[allow(dead_code)]
async fn run_manual_seal<B, BI, CB, E, C, A, SC, CS>(
ManualSealParams {
mut block_import,
mut env,
Expand Down Expand Up @@ -177,7 +178,7 @@ pub async fn run_manual_seal<B, BI, CB, E, C, A, SC, CS>(
parent_hash,
sender,
} => {
seal_block(
seal_block::seal_block(
SealBlockParams {
sender,
parent_hash,
Expand Down Expand Up @@ -211,7 +212,8 @@ pub async fn run_manual_seal<B, BI, CB, E, C, A, SC, CS>(
/// runs the background authorship task for the instant seal engine.
/// instant-seal creates a new block for every transaction imported into
/// the transaction pool.
pub async fn run_instant_seal<B, BI, CB, E, C, A, SC>(
#[allow(dead_code)]
async fn run_instant_seal<B, BI, CB, E, C, A, SC>(
InstantSealParams {
block_import,
env,
Expand Down Expand Up @@ -286,13 +288,19 @@ mod tests {

const SOURCE: TransactionSource = TransactionSource::External;

fn create_data_providres() -> InherentDataProviders {
let providers = InherentDataProviders::new();
providers.register_provider(pallet_random_seed::RandomSeedInherentDataProvider(Default::default())).unwrap();
providers.register_provider(sp_ignore_tx::IgnoreTXInherentDataProvider(false)).unwrap();
providers
}

#[tokio::test]
#[ignore]
async fn instant_seal() {
let builder = TestClientBuilder::new();
let (client, select_chain) = builder.build_with_longest_chain();
let client = Arc::new(client);
let inherent_data_providers = InherentDataProviders::new();
let inherent_data_providers = create_data_providres();
let spawner = sp_core::testing::TaskExecutor::new();
let pool = Arc::new(BasicPool::with_revalidation_type(
Options::default(), api(), None, RevalidationType::Full, spawner,
Expand Down Expand Up @@ -359,12 +367,11 @@ mod tests {
}

#[tokio::test]
#[ignore]
async fn manual_seal_and_finalization() {
let builder = TestClientBuilder::new();
let (client, select_chain) = builder.build_with_longest_chain();
let client = Arc::new(client);
let inherent_data_providers = InherentDataProviders::new();
let inherent_data_providers = create_data_providres();
let spawner = sp_core::testing::TaskExecutor::new();
let pool = Arc::new(BasicPool::with_revalidation_type(
Options::default(), api(), None, RevalidationType::Full, spawner,
Expand Down Expand Up @@ -434,12 +441,11 @@ mod tests {
}

#[tokio::test]
#[ignore]
async fn manual_seal_fork_blocks() {
let builder = TestClientBuilder::new();
let (client, select_chain) = builder.build_with_longest_chain();
let client = Arc::new(client);
let inherent_data_providers = InherentDataProviders::new();
let inherent_data_providers = create_data_providres();
let pool_api = api();
let spawner = sp_core::testing::TaskExecutor::new();
let pool = Arc::new(BasicPool::with_revalidation_type(
Expand Down
14 changes: 10 additions & 4 deletions client/consensus/manual-seal/src/seal_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub struct SealBlockParams<'a, B: BlockT, BI, SC, C: ProvideRuntimeApi<B>, E, P:
}

/// seals a new block with the given params
#[allow(dead_code)]
pub async fn seal_block<B, BI, SC, C, E, P>(
SealBlockParams {
create_empty,
Expand Down Expand Up @@ -113,7 +114,6 @@ pub async fn seal_block<B, BI, SC, C, E, P>(
let proposer = env.init(&parent)
.map_err(|err| Error::StringError(format!("{}", err))).await?;
let id = inherent_data_provider.create_inherent_data()?;
let inherents_len = id.len();

let digest = if let Some(digest_provider) = digest_provider {
digest_provider.create_digest(&parent, &id)?
Expand All @@ -124,9 +124,15 @@ pub async fn seal_block<B, BI, SC, C, E, P>(
let proposal = proposer.propose(id.clone(), digest, Duration::from_secs(MAX_PROPOSAL_DURATION), false.into())
.map_err(|err| Error::StringError(format!("{}", err))).await?;

if proposal.block.extrinsics().len() == inherents_len && !create_empty {
return Err(Error::EmptyTransactionPool)
}
// bellow assumption is not correct - not every inherent needs to produce extrinsic!
// and thats how we are using inherents - just to communicate some informations
// for example if its new epoch block
// that function does not seem to be used anywhere in mangata - so its no longer
// exported by manual-seal - just in case

// if proposal.block.extrinsics().len() == inherents_len && !create_empty {
// return Err(Error::EmptyTransactionPool)
// }

let (header, body) = proposal.block.deconstruct();
let mut params = BlockImportParams::new(BlockOrigin::Own, header.clone());
Expand Down
1 change: 0 additions & 1 deletion client/db/src/changes_tries_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,6 @@ mod tests {
}

#[test]
#[ignore]
fn changes_tries_are_pruned_on_finalization() {
let mut backend = Backend::<Block>::new_test(1000, 100);
backend.changes_tries_storage.min_blocks_to_keep = Some(8);
Expand Down
Loading

0 comments on commit a388297

Please sign in to comment.