Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Check for pruned block state #648

Merged
merged 1 commit into from
Sep 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
22 changes: 13 additions & 9 deletions substrate/client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,12 @@ impl<Block: BlockT> Backend<Block> {
}

#[cfg(test)]
fn new_test() -> Self {
fn new_test(keep_blocks: u32) -> Self {
use utils::NUM_COLUMNS;

let db = Arc::new(::kvdb_memorydb::create(NUM_COLUMNS));

Backend::from_kvdb(db as Arc<_>, PruningMode::keep_blocks(0), 0).expect("failed to create test-db")
Backend::from_kvdb(db as Arc<_>, PruningMode::keep_blocks(keep_blocks), 0).expect("failed to create test-db")
}

fn from_kvdb(db: Arc<KeyValueDB>, pruning: PruningMode, finalization_window: u64) -> Result<Self, client::error::Error> {
Expand Down Expand Up @@ -454,10 +454,14 @@ impl<Block> client::backend::Backend<Block, KeccakHasher, RlpCodec> for Backend<
_ => {}
}

self.blockchain.header(block).and_then(|maybe_hdr| maybe_hdr.map(|hdr| {
let root: H256 = H256::from_slice(hdr.state_root().as_ref());
DbState::with_storage(self.storage.clone(), root)
}).ok_or_else(|| client::error::ErrorKind::UnknownBlock(format!("{:?}", block)).into()))
match self.blockchain.header(block) {
Ok(Some(ref hdr)) if !self.storage.state_db.is_pruned(hdr.number().as_()) => {
let root = H256::from_slice(hdr.state_root().as_ref());
Ok(DbState::with_storage(self.storage.clone(), root))
},
Err(e) => Err(e),
_ => Err(client::error::ErrorKind::UnknownBlock(format!("{:?}", block)).into()),
}
}
}

Expand All @@ -477,7 +481,7 @@ mod tests {

#[test]
fn block_hash_inserted_correctly() {
let db = Backend::<Block>::new_test();
let db = Backend::<Block>::new_test(1);
for i in 0..10 {
assert!(db.blockchain().hash(i).unwrap().is_none());

Expand Down Expand Up @@ -516,7 +520,7 @@ mod tests {

#[test]
fn set_state_data() {
let db = Backend::<Block>::new_test();
let db = Backend::<Block>::new_test(2);
{
let mut op = db.begin_operation(BlockId::Hash(Default::default())).unwrap();
let mut header = Header {
Expand Down Expand Up @@ -595,7 +599,7 @@ mod tests {
#[test]
fn delete_only_when_negative_rc() {
let key;
let backend = Backend::<Block>::new_test();
let backend = Backend::<Block>::new_test(0);

let hash = {
let mut op = backend.begin_operation(BlockId::Hash(Default::default())).unwrap();
Expand Down
18 changes: 15 additions & 3 deletions substrate/state-db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ impl<BlockHash: Hash, Key: Hash> StateDbSync<BlockHash, Key> {
return self.unfinalized.last_finalized_block_number()
}

pub fn is_pruned(&self, number: u64) -> bool {
self.pruning.as_ref().map_or(false, |pruning| number < pruning.pending())
}

fn prune(&mut self, commit: &mut CommitSet<Key>) {
if let (&mut Some(ref mut pruning), &PruningMode::Constrained(ref constraints)) = (&mut self.pruning, &self.mode) {
loop {
Expand All @@ -241,7 +245,6 @@ impl<BlockHash: Hash, Key: Hash> StateDbSync<BlockHash, Key> {
if pruning.next_hash().map_or(false, |h| pinned.contains(&h)) {
break;
}

pruning.prune_one(commit);
}
}
Expand Down Expand Up @@ -328,6 +331,10 @@ impl<BlockHash: Hash, Key: Hash> StateDb<BlockHash, Key> {
return self.db.read().best_finalized()
}

/// Check if block is pruned away.
pub fn is_pruned(&self, number: u64) -> bool {
return self.db.read().is_pruned(number)
}
}

#[cfg(test)]
Expand Down Expand Up @@ -375,19 +382,24 @@ mod tests {

#[test]
fn prune_window_1() {
let (db, _) = make_test_db(PruningMode::Constrained(Constraints {
let (db, sdb) = make_test_db(PruningMode::Constrained(Constraints {
max_blocks: Some(1),
max_mem: None,
}));
assert!(sdb.is_pruned(0));
assert!(sdb.is_pruned(1));
assert!(!sdb.is_pruned(2));
assert!(db.data_eq(&make_db(&[21, 3, 922, 93, 94])));
}

#[test]
fn prune_window_2() {
let (db, _) = make_test_db(PruningMode::Constrained(Constraints {
let (db, sdb) = make_test_db(PruningMode::Constrained(Constraints {
max_blocks: Some(2),
max_mem: None,
}));
assert!(sdb.is_pruned(0));
assert!(!sdb.is_pruned(1));
assert!(db.data_eq(&make_db(&[1, 21, 3, 921, 922, 93, 94])));
}
}
16 changes: 10 additions & 6 deletions substrate/state-db/src/pruning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl<BlockHash: Hash, Key: Hash> RefWindow<BlockHash, Key> {
.map_err(|e| Error::Db(e))?;
let pending_number: u64 = match last_pruned {
Some(buffer) => u64::decode(&mut buffer.as_slice()).ok_or(Error::Decoding)? + 1,
None => 1,
None => 0,
};
let mut block = pending_number;
let mut pruning = RefWindow {
Expand All @@ -69,7 +69,7 @@ impl<BlockHash: Hash, Key: Hash> RefWindow<BlockHash, Key> {
pending_number: pending_number,
};
// read the journal
trace!(target: "state-db", "Reading pruning journal. Last pruned #{}", pending_number - 1);
trace!(target: "state-db", "Reading pruning journal. Pending #{}", pending_number);
loop {
let journal_key = to_journal_key(block);
match db.get_meta(&journal_key).map_err(|e| Error::Db(e))? {
Expand Down Expand Up @@ -119,6 +119,10 @@ impl<BlockHash: Hash, Key: Hash> RefWindow<BlockHash, Key> {
0
}

pub fn pending(&self) -> u64 {
self.pending_number
}

/// Prune next block. Expects at least one block in the window. Adds changes to `commit`.
pub fn prune_one(&mut self, commit: &mut CommitSet<Key>) {
let pruned = self.death_rows.pop_front().expect("prune_one is only called with a non-empty window");
Expand Down Expand Up @@ -168,7 +172,7 @@ mod tests {
fn created_from_empty_db() {
let db = make_db(&[]);
let pruning: RefWindow<H256, H256> = RefWindow::new(&db).unwrap();
assert_eq!(pruning.pending_number, 1);
assert_eq!(pruning.pending_number, 0);
assert!(pruning.death_rows.is_empty());
assert!(pruning.death_index.is_empty());
}
Expand Down Expand Up @@ -202,7 +206,7 @@ mod tests {
assert!(db.data_eq(&make_db(&[2, 4, 5])));
assert!(pruning.death_rows.is_empty());
assert!(pruning.death_index.is_empty());
assert_eq!(pruning.pending_number, 2);
assert_eq!(pruning.pending_number, 1);
}

#[test]
Expand All @@ -227,7 +231,7 @@ mod tests {
pruning.prune_one(&mut commit);
db.commit(&commit);
assert!(db.data_eq(&make_db(&[3, 4, 5])));
assert_eq!(pruning.pending_number, 3);
assert_eq!(pruning.pending_number, 2);
}

#[test]
Expand Down Expand Up @@ -258,6 +262,6 @@ mod tests {
pruning.prune_one(&mut commit);
db.commit(&commit);
assert!(db.data_eq(&make_db(&[1, 3])));
assert_eq!(pruning.pending_number, 4);
assert_eq!(pruning.pending_number, 3);
}
}