mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 00:17:56 +00:00
Check for pruned block state (#648)
This commit is contained in:
committed by
Gav Wood
parent
73ad673404
commit
146ebceab4
@@ -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> {
|
||||
@@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 {
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)]
|
||||
@@ -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])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -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))? {
|
||||
@@ -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");
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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]
|
||||
@@ -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]
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user