Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Added a test
  • Loading branch information
arkpar committed Nov 12, 2019
commit 002fe6ac1a5c55df11c5c601eff5354a0e1c356d
101 changes: 100 additions & 1 deletion core/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ pub(crate) mod tests {
use super::*;
use primitives::blake2_256;
use sr_primitives::DigestItem;
use consensus::{BlockOrigin, SelectChain};
use consensus::{BlockOrigin, SelectChain, BlockImport};
use test_client::{
prelude::*,
client_db::{Backend, DatabaseSettings, DatabaseSettingsSrc, PruningMode},
Expand Down Expand Up @@ -2893,4 +2893,103 @@ pub(crate) mod tests {
expected_err.to_string(),
);
}

#[test]
fn returns_status_for_pruned_blocks() {
let _ = env_logger::try_init();
let tmp = tempfile::tempdir().unwrap();

// set to prune after 1 block
// states
let backend = Arc::new(Backend::new(
DatabaseSettings {
state_cache_size: 1 << 20,
state_cache_child_ratio: None,
pruning: PruningMode::keep_blocks(1),
source: DatabaseSettingsSrc::Path {
path: tmp.path().into(),
cache_size: None,
}
},
u64::max_value(),
).unwrap());

let mut client = TestClientBuilder::with_backend(backend).build();

let a1 = client.new_block_at(&BlockId::Number(0), Default::default())
.unwrap().bake().unwrap();

let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap();

// b1 is created, but not imported
b1.push_transfer(Transfer {
from: AccountKeyring::Alice.into(),
to: AccountKeyring::Ferdie.into(),
amount: 1,
nonce: 0,
}).unwrap();
let b1 = b1.bake().unwrap();

let check_block_a1 = BlockCheckParams {
hash: a1.hash().clone(),
number: 0,
parent_hash: a1.header().parent_hash().clone(),
allow_missing_state: false
};

assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::imported(false));
assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::Unknown);

client.import_as_final(BlockOrigin::Own, a1.clone()).unwrap();

assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain);
assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainWithState);

let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default())
.unwrap().bake().unwrap();
client.import_as_final(BlockOrigin::Own, a2.clone()).unwrap();

let check_block_a2 = BlockCheckParams {
hash: a2.hash().clone(),
number: 1,
parent_hash: a1.header().parent_hash().clone(),
allow_missing_state: false
};

assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain);
assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned);
assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain);
assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainWithState);

let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default())
.unwrap().bake().unwrap();

client.import_as_final(BlockOrigin::Own, a3.clone()).unwrap();
let check_block_a3 = BlockCheckParams {
hash: a3.hash().clone(),
number: 2,
parent_hash: a2.header().parent_hash().clone(),
allow_missing_state: false
};

// a1 and a2 are both pruned at this point
assert_eq!(client.check_block(check_block_a1.clone()).unwrap(), ImportResult::AlreadyInChain);
assert_eq!(client.block_status(&BlockId::hash(check_block_a1.hash)).unwrap(), BlockStatus::InChainPruned);
assert_eq!(client.check_block(check_block_a2.clone()).unwrap(), ImportResult::AlreadyInChain);
assert_eq!(client.block_status(&BlockId::hash(check_block_a2.hash)).unwrap(), BlockStatus::InChainPruned);
assert_eq!(client.check_block(check_block_a3.clone()).unwrap(), ImportResult::AlreadyInChain);
assert_eq!(client.block_status(&BlockId::hash(check_block_a3.hash)).unwrap(), BlockStatus::InChainWithState);

let mut check_block_b1 = BlockCheckParams {
hash: b1.hash().clone(),
number: 0,
parent_hash: b1.header().parent_hash().clone(),
allow_missing_state: false
};
assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::MissingState);
check_block_b1.allow_missing_state = true;
assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::imported(false));
check_block_b1.parent_hash = H256::random();
assert_eq!(client.check_block(check_block_b1.clone()).unwrap(), ImportResult::UnknownParent);
}
}
1 change: 1 addition & 0 deletions core/consensus/common/src/block_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub enum ForkChoiceStrategy {
}

/// Data required to check validity of a Block.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct BlockCheckParams<Block: BlockT> {
/// Hash of the block that we verify.
pub hash: Block::Hash,
Expand Down
23 changes: 23 additions & 0 deletions core/test-client/src/client_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ pub trait ClientExt<Block: BlockT>: Sized {
fn import_as_best(&self, origin: BlockOrigin, block: Block)
-> Result<(), ConsensusError>;

/// Import a block and finalize it.
fn import_as_final(&self, origin: BlockOrigin, block: Block)
-> Result<(), ConsensusError>;

/// Import block with justification, finalizes block.
fn import_justified(
&self,
Expand Down Expand Up @@ -102,6 +106,25 @@ impl<B, E, RA, Block> ClientExt<Block> for Client<B, E, Block, RA>
BlockImport::import_block(&mut (&*self), import, HashMap::new()).map(|_| ())
}

fn import_as_final(&self, origin: BlockOrigin, block: Block)
-> Result<(), ConsensusError>
{
let (header, extrinsics) = block.deconstruct();
let import = BlockImportParams {
origin,
header,
justification: None,
post_digests: vec![],
body: Some(extrinsics),
finalized: true,
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::Custom(true),
allow_missing_state: false,
};

BlockImport::import_block(&mut (&*self), import, HashMap::new()).map(|_| ())
}

fn import_justified(
&self,
origin: BlockOrigin,
Expand Down