From 83e014c214f440517f20e27593567c46ccebbaf5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Sun, 30 Jun 2019 18:54:51 +0300 Subject: [PATCH] change meaning of none in blockchain cache (#2973) --- .../core/client/db/src/cache/list_cache.rs | 407 ++++++++---------- .../core/client/db/src/cache/list_entry.rs | 78 ++-- substrate/core/client/db/src/cache/mod.rs | 2 +- 3 files changed, 224 insertions(+), 263 deletions(-) diff --git a/substrate/core/client/db/src/cache/list_cache.rs b/substrate/core/client/db/src/cache/list_cache.rs index 4f343e93fd..727375244d 100644 --- a/substrate/core/client/db/src/cache/list_cache.rs +++ b/substrate/core/client/db/src/cache/list_cache.rs @@ -163,13 +163,15 @@ impl> ListCache }; match head { - Some(head) => head.search_best_before(&self.storage, at.number, true) - .map(|e| e.and_then(|e| e.0.value)), + Some(head) => head.search_best_before(&self.storage, at.number) + .map(|e| e.map(|e| e.0.value)), None => Ok(None), } } /// When new block is inserted into database. + /// + /// None passed as value means that the value has not changed since previous block. pub fn on_block_insert>( &self, tx: &mut Tx, @@ -191,6 +193,11 @@ impl> ListCache if !is_final { let mut fork_and_action = None; + // when value hasn't changed and block isn't final, there's nothing we need to do + if value.is_none() { + return Ok(None); + } + // first: try to find fork that is known to has the best block we're appending to for (index, fork) in self.unfinalized.iter().enumerate() { if fork.try_append(&parent) { @@ -231,7 +238,7 @@ impl> ListCache // it is possible that we're inserting extra (but still required) fork here let new_storage_entry = StorageEntry { prev_valid_from: Some(prev_valid_from), - value, + value: value.expect("chcecked abpve that !value.is_none(); qed"), }; tx.insert_storage_entry(&block, &new_storage_entry); @@ -250,7 +257,10 @@ impl> ListCache let new_storage_entry = match self.best_finalized_entry.as_ref() { Some(best_finalized_entry) => best_finalized_entry.try_update(value), - None if value.is_some() => Some(StorageEntry { prev_valid_from: None, value }), + None if value.is_some() => Some(StorageEntry { + prev_valid_from: None, + value: value.expect("value.is_some(); qed"), + }), None => None, }; @@ -378,8 +388,12 @@ impl> ListCache }); // destroy 'fork' ending with previous entry - Fork { best_block: None, head: Entry { valid_from: first_entry_to_truncate, value: None } } - .destroy(&self.storage, tx, None) + destroy_fork( + first_entry_to_truncate, + &self.storage, + tx, + None, + ) }; if let Err(error) = do_pruning() { @@ -491,25 +505,40 @@ impl Fork { tx: &mut Tx, best_finalized_block: Option>, ) -> ClientResult<()> { - let mut current = self.head.valid_from.clone(); - loop { - // optionally: deletion stops when we found entry at finalized block - if let Some(best_finalized_block) = best_finalized_block { - if chain::is_finalized_block(storage, ¤t, best_finalized_block)? { - return Ok(()); - } + destroy_fork( + self.head.valid_from.clone(), + storage, + tx, + best_finalized_block, + ) + } +} + +/// Destroy fork by deleting all unfinalized entries. +pub fn destroy_fork, Tx: StorageTransaction>( + head_valid_from: ComplexBlockId, + storage: &S, + tx: &mut Tx, + best_finalized_block: Option>, +) -> ClientResult<()> { + let mut current = head_valid_from; + loop { + // optionally: deletion stops when we found entry at finalized block + if let Some(best_finalized_block) = best_finalized_block { + if chain::is_finalized_block(storage, ¤t, best_finalized_block)? { + return Ok(()); } - - // read pointer to previous entry - let entry = storage.require_entry(¤t)?; - tx.remove_storage_entry(¤t); - - // deletion stops when there are no more entries in the list - current = match entry.prev_valid_from { - Some(prev_valid_from) => prev_valid_from, - None => return Ok(()), - }; } + + // read pointer to previous entry + let entry = storage.require_entry(¤t)?; + tx.remove_storage_entry(¤t); + + // deletion stops when there are no more entries in the list + current = match entry.prev_valid_from { + Some(prev_valid_from) => prev_valid_from, + None => return Ok(()), + }; } } @@ -639,24 +668,14 @@ pub mod tests { // ----------> [100] assert_eq!(ListCache::<_, u64, _>::new(DummyStorage::new(), 1024, test_id(100)) .value_at_block(&test_id(50)).unwrap(), None); - // when block is earlier than best finalized block AND it is finalized AND value is empty - // [30] ---- 50 ---> [100] - assert_eq!(ListCache::new( - DummyStorage::new() - .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, H256::from_low_u64_be(50)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: None }), - 1024, test_id(100) - ).value_at_block(&test_id(50)).unwrap(), None); // when block is earlier than best finalized block AND it is finalized AND value is some // [30] ---- 50 ---> [100] assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) .with_id(50, H256::from_low_u64_be(50)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: Some(30) }), + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }) + .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), 1024, test_id(100) ).value_at_block(&test_id(50)).unwrap(), Some(30)); // when block is the best finalized block AND value is some @@ -665,8 +684,8 @@ pub mod tests { DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) .with_id(100, H256::from_low_u64_be(100)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: Some(30) }), + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }) + .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), 1024, test_id(100) ).value_at_block(&test_id(100)).unwrap(), Some(100)); // when block is parallel to the best finalized block @@ -676,45 +695,21 @@ pub mod tests { DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) .with_id(50, H256::from_low_u64_be(50)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: Some(30) }), + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }) + .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), 1024, test_id(100) ).value_at_block(&ComplexBlockId::new(H256::from_low_u64_be(2), 100)).unwrap(), None); - // when block is later than last finalized block AND there are no forks AND finalized value is None - // ---> [100] --- 200 - assert_eq!(ListCache::<_, u64, _>::new( - DummyStorage::new() - .with_meta(Some(test_id(100)), Vec::new()) - .with_id(50, H256::from_low_u64_be(50)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: None }), - 1024, test_id(100) - ).value_at_block(&test_id(200)).unwrap(), None); // when block is later than last finalized block AND there are no forks AND finalized value is Some // ---> [100] --- 200 assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(test_id(100)), Vec::new()) .with_id(50, H256::from_low_u64_be(50)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(100) }), + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }), 1024, test_id(100) ).value_at_block(&test_id(200)).unwrap(), Some(100)); - // when block is later than last finalized block AND there are no matching forks - // AND block is connected to finalized block AND finalized value is None - // --- 3 - // ---> [2] /---------> [4] - assert_eq!(ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: None }) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(fork_header(0, 2, 3)), - 1024, test_id(2) - ).value_at_block(&fork_id(0, 2, 3)).unwrap(), None); // when block is later than last finalized block AND there are no matching forks // AND block is connected to finalized block AND finalized value is Some // --- 3 @@ -722,8 +717,8 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 }) .with_header(test_header(2)) .with_header(test_header(3)) .with_header(test_header(4)) @@ -737,8 +732,8 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 }) .with_header(test_header(1)) .with_header(test_header(2)) .with_header(test_header(3)) @@ -754,52 +749,12 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 }) .with_header(test_header(4)) .with_header(test_header(5)), 1024, test_id(2) ).value_at_block(&correct_id(5)).unwrap(), Some(4)); - // when block is later than last finalized block AND it appends to unfinalized fork from the end - // AND unfinalized value is None - // ---> [2] ---> [4] ---> 5 - assert_eq!(ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: None }) - .with_header(test_header(4)) - .with_header(test_header(5)), - 1024, test_id(2) - ).value_at_block(&correct_id(5)).unwrap(), None); - // when block is later than last finalized block AND it fits to the middle of unfinalized fork - // AND unfinalized value is Some - // ---> [2] ---> [4] ---> 5 ---> [6] - assert_eq!(ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(6)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) - .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(4)), value: None }) - .with_header(test_header(4)) - .with_header(test_header(5)) - .with_header(test_header(6)), - 1024, test_id(2) - ).value_at_block(&correct_id(5)).unwrap(), Some(4)); - // when block is later than last finalized block AND it fits to the middle of unfinalized fork - // AND unfinalized value is None - // ---> [2] ---> [4] ---> 5 ---> [6] - assert_eq!(ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(6)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: None }) - .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(4)), value: Some(4) }) - .with_header(test_header(4)) - .with_header(test_header(5)) - .with_header(test_header(6)), - 1024, test_id(2) - ).value_at_block(&correct_id(5)).unwrap(), None); // when block is later than last finalized block AND it does not fits unfinalized fork // AND it is connected to the finalized block AND finalized value is Some // ---> [2] ----------> [4] @@ -807,29 +762,14 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) + .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) .with_header(test_header(2)) .with_header(test_header(3)) .with_header(test_header(4)) .with_header(fork_header(0, 2, 3)), 1024, test_id(2) ).value_at_block(&fork_id(0, 2, 3)).unwrap(), Some(2)); - // when block is later than last finalized block AND it does not fits unfinalized fork - // AND it is connected to the finalized block AND finalized value is Some - // ---> [2] ----------> [4] - // \--- 3 - assert_eq!(ListCache::new( - DummyStorage::new() - .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: None }) - .with_header(test_header(2)) - .with_header(test_header(3)) - .with_header(test_header(4)) - .with_header(fork_header(0, 2, 3)), - 1024, test_id(2) - ).value_at_block(&fork_id(0, 2, 3)).unwrap(), None); } #[test] @@ -861,7 +801,7 @@ pub mod tests { let mut cache = ListCache::new( DummyStorage::new() .with_meta(None, vec![test_id(4)]) - .with_entry(test_id(4), StorageEntry { prev_valid_from: None, value: Some(4) }), + .with_entry(test_id(4), StorageEntry { prev_valid_from: None, value: 4 }), 1024, test_id(2) ); cache.unfinalized[0].best_block = Some(test_id(4)); @@ -875,7 +815,7 @@ pub mod tests { // AND new value is the same as in the fork' best block let mut tx = DummyTransaction::new(); assert_eq!(cache.on_block_insert(&mut tx, test_id(4), test_id(5), Some(5), nfin).unwrap(), - Some(CommitOperation::AppendNewEntry(0, Entry { valid_from: test_id(5), value: Some(5) }))); + Some(CommitOperation::AppendNewEntry(0, Entry { valid_from: test_id(5), value: 5 }))); assert_eq!(*tx.inserted_entries(), vec![test_id(5).hash].into_iter().collect()); assert!(tx.removed_entries().is_empty()); assert_eq!(*tx.updated_meta(), Some(Metadata { finalized: None, unfinalized: vec![test_id(5)] })); @@ -885,7 +825,7 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(None, vec![correct_id(4)]) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: None, value: Some(4) }) + .with_entry(correct_id(4), StorageEntry { prev_valid_from: None, value: 4 }) .with_header(test_header(4)), 1024, test_id(2) ); @@ -899,7 +839,7 @@ pub mod tests { // AND new value is the same as in the fork' best block let mut tx = DummyTransaction::new(); assert_eq!(cache.on_block_insert(&mut tx, correct_id(4), correct_id(5), Some(5), nfin).unwrap(), - Some(CommitOperation::AppendNewEntry(0, Entry { valid_from: correct_id(5), value: Some(5) }))); + Some(CommitOperation::AppendNewEntry(0, Entry { valid_from: correct_id(5), value: 5 }))); assert_eq!(*tx.inserted_entries(), vec![correct_id(5).hash].into_iter().collect()); assert!(tx.removed_entries().is_empty()); assert_eq!(*tx.updated_meta(), Some(Metadata { finalized: None, unfinalized: vec![correct_id(5)] })); @@ -908,8 +848,8 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(4)]) - .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(4) }) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) + .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 4 }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) .with_header(test_header(2)) .with_header(test_header(3)) .with_header(test_header(4)), @@ -917,7 +857,7 @@ pub mod tests { ); let mut tx = DummyTransaction::new(); assert_eq!(cache.on_block_insert(&mut tx, correct_id(3), fork_id(0, 3, 4), Some(14), nfin).unwrap(), - Some(CommitOperation::AddNewFork(Entry { valid_from: fork_id(0, 3, 4), value: Some(14) }))); + Some(CommitOperation::AddNewFork(Entry { valid_from: fork_id(0, 3, 4), value: 14 }))); assert_eq!(*tx.inserted_entries(), vec![fork_id(0, 3, 4).hash].into_iter().collect()); assert!(tx.removed_entries().is_empty()); assert_eq!(*tx.updated_meta(), Some(Metadata { finalized: Some(correct_id(2)), unfinalized: vec![correct_id(4), fork_id(0, 3, 4)] })); @@ -927,7 +867,7 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }), 1024, correct_id(2) ); let mut tx = DummyTransaction::new(); @@ -940,12 +880,12 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }), 1024, correct_id(2) ); let mut tx = DummyTransaction::new(); assert_eq!(cache.on_block_insert(&mut tx, correct_id(2), correct_id(3), Some(3), nfin).unwrap(), - Some(CommitOperation::AddNewFork(Entry { valid_from: correct_id(3), value: Some(3) }))); + Some(CommitOperation::AddNewFork(Entry { valid_from: correct_id(3), value: 3 }))); assert_eq!(*tx.inserted_entries(), vec![correct_id(3).hash].into_iter().collect()); assert!(tx.removed_entries().is_empty()); assert_eq!(*tx.updated_meta(), Some(Metadata { finalized: Some(correct_id(2)), unfinalized: vec![correct_id(3)] })); @@ -953,8 +893,14 @@ pub mod tests { // when inserting finalized entry AND there are no previous finalized entries let cache = ListCache::new(DummyStorage::new(), 1024, correct_id(2)); let mut tx = DummyTransaction::new(); - assert_eq!(cache.on_block_insert(&mut tx, correct_id(2), correct_id(3), Some(3), fin).unwrap(), - Some(CommitOperation::BlockFinalized(correct_id(3), Some(Entry { valid_from: correct_id(3), value: Some(3) }), Default::default()))); + assert_eq!( + cache.on_block_insert(&mut tx, correct_id(2), correct_id(3), Some(3), fin).unwrap(), + Some(CommitOperation::BlockFinalized( + correct_id(3), + Some(Entry { valid_from: correct_id(3), value: 3 }), + Default::default(), + )), + ); assert_eq!(*tx.inserted_entries(), vec![correct_id(3).hash].into_iter().collect()); assert!(tx.removed_entries().is_empty()); assert_eq!(*tx.updated_meta(), Some(Metadata { finalized: Some(correct_id(3)), unfinalized: vec![] })); @@ -962,7 +908,7 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }), 1024, correct_id(2) ); let mut tx = DummyTransaction::new(); @@ -973,8 +919,14 @@ pub mod tests { assert!(tx.updated_meta().is_none()); // when inserting finalized entry AND value differs from previous finalized let mut tx = DummyTransaction::new(); - assert_eq!(cache.on_block_insert(&mut tx, correct_id(2), correct_id(3), Some(3), fin).unwrap(), - Some(CommitOperation::BlockFinalized(correct_id(3), Some(Entry { valid_from: correct_id(3), value: Some(3) }), Default::default()))); + assert_eq!( + cache.on_block_insert(&mut tx, correct_id(2), correct_id(3), Some(3), fin).unwrap(), + Some(CommitOperation::BlockFinalized( + correct_id(3), + Some(Entry { valid_from: correct_id(3), value: 3 }), + Default::default(), + )), + ); assert_eq!(*tx.inserted_entries(), vec![correct_id(3).hash].into_iter().collect()); assert!(tx.removed_entries().is_empty()); assert_eq!(*tx.updated_meta(), Some(Metadata { finalized: Some(correct_id(3)), unfinalized: vec![] })); @@ -983,8 +935,8 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![fork_id(0, 1, 3)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: None, value: Some(13) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: None, value: 13 }), 1024, correct_id(2) ); let mut tx = DummyTransaction::new(); @@ -998,8 +950,8 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(5)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(5) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }), 1024, correct_id(2) ); let mut tx = DummyTransaction::new(); @@ -1012,13 +964,19 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(5)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(5) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }), 1024, correct_id(4) ); let mut tx = DummyTransaction::new(); - assert_eq!(cache.on_block_finalize(&mut tx, correct_id(4), correct_id(5)).unwrap(), - Some(CommitOperation::BlockFinalized(correct_id(5), Some(Entry { valid_from: correct_id(5), value: Some(5) }), vec![0].into_iter().collect()))); + assert_eq!( + cache.on_block_finalize(&mut tx, correct_id(4), correct_id(5)).unwrap(), + Some(CommitOperation::BlockFinalized( + correct_id(5), + Some(Entry { valid_from: correct_id(5), value: 5 }), + vec![0].into_iter().collect(), + )), + ); assert!(tx.inserted_entries().is_empty()); assert!(tx.removed_entries().is_empty()); assert_eq!(*tx.updated_meta(), Some(Metadata { finalized: Some(correct_id(5)), unfinalized: vec![] })); @@ -1026,8 +984,8 @@ pub mod tests { let cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![fork_id(0, 1, 3)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: None, value: Some(13) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: None, value: 13 }), 1024, correct_id(2) ); let mut tx = DummyTransaction::new(); @@ -1040,9 +998,9 @@ pub mod tests { let mut cache = ListCache::new( DummyStorage::new() .with_meta(Some(correct_id(2)), vec![correct_id(5), correct_id(6)]) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: Some(2) }) - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(5) }) - .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(5)), value: Some(6) }), + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }) + .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(5)), value: 6 }), 1024, correct_id(2) ); @@ -1050,17 +1008,21 @@ pub mod tests { cache.on_transaction_commit(CommitOperation::AppendNewBlock(0, correct_id(6))); assert_eq!(cache.unfinalized[0].best_block, Some(correct_id(6))); // when new entry is appended to unfinalized fork - cache.on_transaction_commit(CommitOperation::AppendNewEntry(0, Entry { valid_from: correct_id(7), value: Some(7) })); + cache.on_transaction_commit(CommitOperation::AppendNewEntry(0, Entry { valid_from: correct_id(7), value: 7 })); assert_eq!(cache.unfinalized[0].best_block, Some(correct_id(7))); - assert_eq!(cache.unfinalized[0].head, Entry { valid_from: correct_id(7), value: Some(7) }); + assert_eq!(cache.unfinalized[0].head, Entry { valid_from: correct_id(7), value: 7 }); // when new fork is added - cache.on_transaction_commit(CommitOperation::AddNewFork(Entry { valid_from: correct_id(10), value: Some(10) })); + cache.on_transaction_commit(CommitOperation::AddNewFork(Entry { valid_from: correct_id(10), value: 10 })); assert_eq!(cache.unfinalized[2].best_block, Some(correct_id(10))); - assert_eq!(cache.unfinalized[2].head, Entry { valid_from: correct_id(10), value: Some(10) }); + assert_eq!(cache.unfinalized[2].head, Entry { valid_from: correct_id(10), value: 10 }); // when block is finalized + entry is finalized + unfinalized forks are deleted - cache.on_transaction_commit(CommitOperation::BlockFinalized(correct_id(20), Some(Entry { valid_from: correct_id(20), value: Some(20) }), vec![0, 1, 2].into_iter().collect())); + cache.on_transaction_commit(CommitOperation::BlockFinalized( + correct_id(20), + Some(Entry { valid_from: correct_id(20), value: 20 }), + vec![0, 1, 2].into_iter().collect(), + )); assert_eq!(cache.best_finalized_block, correct_id(20)); - assert_eq!(cache.best_finalized_entry, Some(Entry { valid_from: correct_id(20), value: Some(20) })); + assert_eq!(cache.best_finalized_entry, Some(Entry { valid_from: correct_id(20), value: 20 })); assert!(cache.unfinalized.is_empty()); } @@ -1071,9 +1033,9 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(None, vec![fork_id(0, 1, 3), correct_id(5)]) - .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: Some(correct_id(1)), value: Some(13) }) - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(5) }) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: None }) + .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: Some(correct_id(1)), value: 13 }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: None, value: 2 }) .with_header(test_header(2)) .with_header(test_header(3)) .with_header(test_header(4)) @@ -1085,9 +1047,9 @@ pub mod tests { assert_eq!(ListCache::new( DummyStorage::new() .with_meta(None, vec![correct_id(5), fork_id(0, 1, 3)]) - .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: Some(correct_id(1)), value: Some(13) }) - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(5) }) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: Some(correct_id(1)), value: Some(2) }) + .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: Some(correct_id(1)), value: 13 }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: Some(correct_id(1)), value: 2 }) .with_header(test_header(2)) .with_header(test_header(3)) .with_header(test_header(4)) @@ -1103,9 +1065,9 @@ pub mod tests { assert!(ListCache::new( DummyStorage::new() .with_meta(None, vec![correct_id(5), fork_id(0, 1, 3)]) - .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: Some(correct_id(1)), value: Some(13) }) - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: Some(5) }) - .with_entry(correct_id(2), StorageEntry { prev_valid_from: Some(correct_id(1)), value: Some(2) }) + .with_entry(fork_id(0, 1, 3), StorageEntry { prev_valid_from: Some(correct_id(1)), value: 13 }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(2)), value: 5 }) + .with_entry(correct_id(2), StorageEntry { prev_valid_from: Some(correct_id(1)), value: 2 }) .with_header(test_header(2)) .with_header(test_header(3)) .with_header(test_header(4)) @@ -1123,59 +1085,59 @@ pub mod tests { fn fork_matches_works() { // when block is not within list range let storage = DummyStorage::new() - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: Some(50) }); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }) + .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }); + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } .matches(&storage, &test_id(20)).unwrap(), false); // when block is not connected to the begin block let storage = DummyStorage::new() - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: Some(100) }) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: Some(200) }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }) + .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) .with_header(test_header(5)) .with_header(test_header(4)) .with_header(test_header(3)) .with_header(fork_header(0, 2, 4)) .with_header(fork_header(0, 2, 3)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: 100 } } .matches(&storage, &fork_id(0, 2, 4)).unwrap(), false); // when block is not connected to the end block let storage = DummyStorage::new() - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: Some(100) }) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: Some(200) }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }) + .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) .with_header(test_header(5)) .with_header(test_header(4)) .with_header(test_header(3)) .with_header(fork_header(0, 3, 4)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: 100 } } .matches(&storage, &fork_id(0, 3, 4)).unwrap(), false); // when block is connected to the begin block AND end is open let storage = DummyStorage::new() - .with_entry(correct_id(5), StorageEntry { prev_valid_from: None, value: Some(100) }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: None, value: 100 }) .with_header(test_header(5)) .with_header(test_header(6)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: 100 } } .matches(&storage, &correct_id(6)).unwrap(), true); // when block is connected to the begin block AND to the end block let storage = DummyStorage::new() - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: Some(100) }) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: Some(200) }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }) + .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) .with_header(test_header(5)) .with_header(test_header(4)) .with_header(test_header(3)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: 100 } } .matches(&storage, &correct_id(4)).unwrap(), true); } #[test] fn fork_try_append_works() { // when best block is unknown - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } .try_append(&test_id(100)), false); // when best block is known but different - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } .try_append(&test_id(101)), false); // when best block is known and the same - assert_eq!(Fork::<_, u64> { best_block: Some(test_id(100)), head: Entry { valid_from: test_id(100), value: None } } + assert_eq!(Fork::<_, u64> { best_block: Some(test_id(100)), head: Entry { valid_from: test_id(100), value: 0 } } .try_append(&test_id(100)), true); } @@ -1183,49 +1145,52 @@ pub mod tests { fn fork_try_append_or_fork_works() { // when there's no entry before parent let storage = DummyStorage::new() - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: Some(50) }); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }) + .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }); + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } .try_append_or_fork(&storage, &test_id(30), None).unwrap(), None); // when parent does not belong to the fork let storage = DummyStorage::new() - .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: Some(100) }) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: Some(200) }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }) + .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) .with_header(test_header(5)) .with_header(test_header(4)) .with_header(test_header(3)) .with_header(fork_header(0, 2, 4)) .with_header(fork_header(0, 2, 3)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: 100 } } .try_append_or_fork(&storage, &fork_id(0, 2, 4), None).unwrap(), None); // when the entry before parent is the head entry let storage = DummyStorage::new() - .with_entry(ComplexBlockId::new(test_header(5).hash(), 5), StorageEntry { prev_valid_from: Some(correct_id(3)), value: Some(100) }) + .with_entry( + ComplexBlockId::new(test_header(5).hash(), 5), + StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }, + ) .with_header(test_header(6)) .with_header(test_header(5)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(5), value: 100 } } .try_append_or_fork(&storage, &correct_id(6), None).unwrap(), Some(ForkAppendResult::Append)); // when the parent located after last finalized entry let storage = DummyStorage::new() - .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(3)), value: Some(100) }) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: Some(200) }) + .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }) + .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) .with_header(test_header(6)) .with_header(test_header(5)) .with_header(test_header(4)) .with_header(test_header(3)) .with_header(fork_header(0, 4, 5)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(6), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(6), value: 100 } } .try_append_or_fork(&storage, &fork_id(0, 4, 5), None).unwrap(), Some(ForkAppendResult::Fork(ComplexBlockId::new(test_header(3).hash(), 3)))); // when the parent located before last finalized entry let storage = DummyStorage::new() - .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(3)), value: Some(100) }) - .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: Some(200) }) + .with_entry(correct_id(6), StorageEntry { prev_valid_from: Some(correct_id(3)), value: 100 }) + .with_entry(correct_id(3), StorageEntry { prev_valid_from: None, value: 200 }) .with_header(test_header(6)) .with_header(test_header(5)) .with_header(test_header(4)) .with_header(test_header(3)) .with_header(fork_header(0, 4, 5)); - assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(6), value: Some(100) } } + assert_eq!(Fork::<_, u64> { best_block: None, head: Entry { valid_from: correct_id(6), value: 100 } } .try_append_or_fork(&storage, &fork_id(0, 4, 5), Some(3)).unwrap(), None); } @@ -1234,30 +1199,30 @@ pub mod tests { // when we reached finalized entry without iterations let storage = DummyStorage::new().with_id(100, H256::from_low_u64_be(100)); let mut tx = DummyTransaction::new(); - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } + Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } .destroy(&storage, &mut tx, Some(200)).unwrap(); assert!(tx.removed_entries().is_empty()); // when we reach finalized entry with iterations let storage = DummyStorage::new() .with_id(10, H256::from_low_u64_be(10)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) - .with_entry(test_id(50), StorageEntry { prev_valid_from: Some(test_id(20)), value: Some(50) }) - .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(10)), value: Some(20) }) - .with_entry(test_id(10), StorageEntry { prev_valid_from: Some(test_id(5)), value: Some(10) }) - .with_entry(test_id(5), StorageEntry { prev_valid_from: Some(test_id(3)), value: Some(5) }) - .with_entry(test_id(3), StorageEntry { prev_valid_from: None, value: None }); + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }) + .with_entry(test_id(50), StorageEntry { prev_valid_from: Some(test_id(20)), value: 50 }) + .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(10)), value: 20 }) + .with_entry(test_id(10), StorageEntry { prev_valid_from: Some(test_id(5)), value: 10 }) + .with_entry(test_id(5), StorageEntry { prev_valid_from: Some(test_id(3)), value: 5 }) + .with_entry(test_id(3), StorageEntry { prev_valid_from: None, value: 0 }); let mut tx = DummyTransaction::new(); - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } + Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } .destroy(&storage, &mut tx, Some(200)).unwrap(); assert_eq!(*tx.removed_entries(), vec![test_id(100).hash, test_id(50).hash, test_id(20).hash].into_iter().collect()); // when we reach beginning of fork before finalized block let storage = DummyStorage::new() .with_id(10, H256::from_low_u64_be(10)) - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: Some(50) }); + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }) + .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }); let mut tx = DummyTransaction::new(); - Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: None } } + Fork::<_, u64> { best_block: None, head: Entry { valid_from: test_id(100), value: 0 } } .destroy(&storage, &mut tx, Some(200)).unwrap(); assert_eq!(*tx.removed_entries(), vec![test_id(100).hash, test_id(50).hash].into_iter().collect()); @@ -1355,14 +1320,14 @@ pub mod tests { #[test] fn read_forks_works() { let storage = DummyStorage::new() - .with_entry(test_id(10), StorageEntry { prev_valid_from: Some(test_id(1)), value: Some(11) }) - .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(2)), value: None }) - .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: Some(33) }); + .with_entry(test_id(10), StorageEntry { prev_valid_from: Some(test_id(1)), value: 11 }) + .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(2)), value: 0 }) + .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 33 }); let expected = ( - Some(Entry { valid_from: test_id(10), value: Some(11) }), + Some(Entry { valid_from: test_id(10), value: 11 }), vec![ - Fork { best_block: None, head: Entry { valid_from: test_id(20), value: None } }, - Fork { best_block: None, head: Entry { valid_from: test_id(30), value: Some(33) } }, + Fork { best_block: None, head: Entry { valid_from: test_id(20), value: 0 } }, + Fork { best_block: None, head: Entry { valid_from: test_id(30), value: 33 } }, ], ); @@ -1378,9 +1343,9 @@ pub mod tests { .with_id(10, H256::from_low_u64_be(10)) .with_id(20, H256::from_low_u64_be(20)) .with_id(30, H256::from_low_u64_be(30)) - .with_entry(test_id(10), StorageEntry { prev_valid_from: None, value: Some(10) }) - .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(10)), value: Some(20) }) - .with_entry(test_id(30), StorageEntry { prev_valid_from: Some(test_id(20)), value: Some(30) }), + .with_entry(test_id(10), StorageEntry { prev_valid_from: None, value: 10 }) + .with_entry(test_id(20), StorageEntry { prev_valid_from: Some(test_id(10)), value: 20 }) + .with_entry(test_id(30), StorageEntry { prev_valid_from: Some(test_id(20)), value: 30 }), 10, test_id(9)); let mut tx = DummyTransaction::new(); diff --git a/substrate/core/client/db/src/cache/list_entry.rs b/substrate/core/client/db/src/cache/list_entry.rs index 237ae9a268..3305b909d2 100644 --- a/substrate/core/client/db/src/cache/list_entry.rs +++ b/substrate/core/client/db/src/cache/list_entry.rs @@ -27,10 +27,10 @@ use crate::cache::list_storage::{Storage}; #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] pub struct Entry { - /// first block, when this value became actual + /// first block, when this value became actual. pub valid_from: ComplexBlockId, - /// None means that we do not know the value starting from `valid_from` block - pub value: Option, + /// Value stored at this entry. + pub value: T, } /// Internal representation of the single list-based cache entry. The entry points to the @@ -38,21 +38,24 @@ pub struct Entry { #[derive(Debug, Encode, Decode)] #[cfg_attr(test, derive(Clone, PartialEq))] pub struct StorageEntry { - /// None if valid from the beginning + /// None if valid from the beginning. pub prev_valid_from: Option>, - /// None means that we do not know the value starting from `valid_from` block - pub value: Option, + /// Value stored at this entry. + pub value: T, } impl Entry { /// Returns Some if the entry should be updated with the new value. pub fn try_update(&self, value: Option) -> Option> { - match self.value == value { - true => None, - false => Some(StorageEntry { - prev_valid_from: Some(self.valid_from.clone()), - value, - }), + match value { + Some(value) => match self.value == value { + true => None, + false => Some(StorageEntry { + prev_valid_from: Some(self.valid_from.clone()), + value, + }), + }, + None => None, } } @@ -62,7 +65,7 @@ impl Entry { storage: &S, block: NumberFor, ) -> ClientResult, Option>)>> { - Ok(self.search_best_before(storage, block, false)? + Ok(self.search_best_before(storage, block)? .map(|(entry, next)| (entry.valid_from, next))) } @@ -75,13 +78,12 @@ impl Entry { &self, storage: &S, block: NumberFor, - require_value: bool, ) -> ClientResult, Option>)>> { // we're looking for the best value let mut next = None; let mut current = self.valid_from.clone(); if block >= self.valid_from.number { - let value = if require_value { self.value.clone() } else { None }; + let value = self.value.clone(); return Ok(Some((Entry { valid_from: current, value }, next))); } @@ -119,47 +121,41 @@ mod tests { #[test] fn entry_try_update_works() { - // when trying to update with the same None value - assert_eq!(Entry::<_, u64> { valid_from: test_id(1), value: None }.try_update(None), None); + // when trying to update with None value + assert_eq!(Entry::<_, u64> { valid_from: test_id(1), value: 42 }.try_update(None), None); // when trying to update with the same Some value - assert_eq!(Entry { valid_from: test_id(1), value: Some(1) }.try_update(Some(1)), None); - // when trying to update with different None value - assert_eq!(Entry { valid_from: test_id(1), value: Some(1) }.try_update(None), - Some(StorageEntry { prev_valid_from: Some(test_id(1)), value: None })); + assert_eq!(Entry { valid_from: test_id(1), value: 1 }.try_update(Some(1)), None); // when trying to update with different Some value - assert_eq!(Entry { valid_from: test_id(1), value: Some(1) }.try_update(Some(2)), - Some(StorageEntry { prev_valid_from: Some(test_id(1)), value: Some(2) })); + assert_eq!(Entry { valid_from: test_id(1), value: 1 }.try_update(Some(2)), + Some(StorageEntry { prev_valid_from: Some(test_id(1)), value: 2 })); } #[test] fn entry_search_best_before_fails() { // when storage returns error - assert!(Entry::<_, u64> { valid_from: test_id(100), value: None }.search_best_before(&FaultyStorage, 50, false).is_err()); + assert!(Entry::<_, u64> { valid_from: test_id(100), value: 42 } + .search_best_before(&FaultyStorage, 50).is_err()); } #[test] fn entry_search_best_before_works() { - // when block is better than our best block AND value is not required - assert_eq!(Entry::<_, u64> { valid_from: test_id(100), value: Some(100) } - .search_best_before(&DummyStorage::new(), 150, false).unwrap(), - Some((Entry::<_, u64> { valid_from: test_id(100), value: None }, None))); - // when block is better than our best block AND value is required - assert_eq!(Entry::<_, u64> { valid_from: test_id(100), value: Some(100) } - .search_best_before(&DummyStorage::new(), 150, true).unwrap(), - Some((Entry::<_, u64> { valid_from: test_id(100), value: Some(100) }, None))); + // when block is better than our best block + assert_eq!(Entry::<_, u64> { valid_from: test_id(100), value: 100 } + .search_best_before(&DummyStorage::new(), 150).unwrap(), + Some((Entry::<_, u64> { valid_from: test_id(100), value: 100 }, None))); // when block is found between two entries - assert_eq!(Entry::<_, u64> { valid_from: test_id(100), value: Some(100) } + assert_eq!(Entry::<_, u64> { valid_from: test_id(100), value: 100 } .search_best_before(&DummyStorage::new() - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) - .with_entry(test_id(50), StorageEntry { prev_valid_from: Some(test_id(30)), value: Some(50) }), - 75, false).unwrap(), - Some((Entry::<_, u64> { valid_from: test_id(50), value: Some(50) }, Some(test_id(100))))); + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }) + .with_entry(test_id(50), StorageEntry { prev_valid_from: Some(test_id(30)), value: 50 }), + 75).unwrap(), + Some((Entry::<_, u64> { valid_from: test_id(50), value: 50 }, Some(test_id(100))))); // when block is not found - assert_eq!(Entry::<_, u64> { valid_from: test_id(100), value: Some(100) } + assert_eq!(Entry::<_, u64> { valid_from: test_id(100), value: 100 } .search_best_before(&DummyStorage::new() - .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: Some(100) }) - .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: Some(50) }), - 30, true).unwrap(), + .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(50)), value: 100 }) + .with_entry(test_id(50), StorageEntry { prev_valid_from: None, value: 50 }), + 30).unwrap(), None); } } diff --git a/substrate/core/client/db/src/cache/mod.rs b/substrate/core/client/db/src/cache/mod.rs index 64d3c4a25e..1c112c9036 100644 --- a/substrate/core/client/db/src/cache/mod.rs +++ b/substrate/core/client/db/src/cache/mod.rs @@ -221,7 +221,7 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { ), parent.clone(), block.clone(), - value.or(cache.value_at_block(&parent)?), + value, entry_type, )?; if let Some(op) = op {