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

Commit

Permalink
Merge branch 'master' into anton/upgrade-libp2p-to-0.50.0
Browse files Browse the repository at this point in the history
  • Loading branch information
melekes committed Jan 4, 2023
2 parents ff5b576 + 6e52d60 commit 854c749
Show file tree
Hide file tree
Showing 7 changed files with 340 additions and 156 deletions.
1 change: 0 additions & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1181,7 +1181,6 @@ impl pallet_tips::Config for Runtime {
parameter_types! {
pub const DepositPerItem: Balance = deposit(1, 0);
pub const DepositPerByte: Balance = deposit(0, 1);
pub const MaxValueSize: u32 = 16 * 1024;
pub const DeletionQueueDepth: u32 = 128;
// The lazy deletion runs inside on_initialize.
pub DeletionWeightLimit: Weight = RuntimeBlockWeights::get()
Expand Down
270 changes: 186 additions & 84 deletions client/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use sc_client_api::{
utils::is_descendent_of,
IoInfo, MemoryInfo, MemorySize, UsageInfo,
};
use sc_state_db::{IsPruned, StateDb};
use sc_state_db::{IsPruned, LastCanonicalized, StateDb};
use sp_arithmetic::traits::Saturating;
use sp_blockchain::{
well_known_cache_keys, Backend as _, CachedHeaderMetadata, Error as ClientError, HeaderBackend,
Expand Down Expand Up @@ -1315,19 +1315,25 @@ impl<Block: BlockT> Backend<Block> {
&self,
transaction: &mut Transaction<DbHash>,
) -> ClientResult<()> {
let best_canonical = || self.storage.state_db.best_canonical().unwrap_or(0);
let best_canonical = match self.storage.state_db.last_canonicalized() {
LastCanonicalized::None => 0,
LastCanonicalized::Block(b) => b,
// Nothing needs to be done when canonicalization is not happening.
LastCanonicalized::NotCanonicalizing => return Ok(()),
};

let info = self.blockchain.info();
let best_number: u64 = self.blockchain.info().best_number.saturated_into();

while best_number.saturating_sub(best_canonical()) > self.canonicalization_delay {
let to_canonicalize = best_canonical() + 1;

for to_canonicalize in
best_canonical + 1..=best_number.saturating_sub(self.canonicalization_delay)
{
let hash_to_canonicalize = sc_client_api::blockchain::HeaderBackend::hash(
&self.blockchain,
to_canonicalize.saturated_into(),
)?
.ok_or_else(|| {
let best_hash = info.best_hash;
let best_hash = info.best_hash;

sp_blockchain::Error::Backend(format!(
"Can't canonicalize missing block number #{to_canonicalize} when for best block {best_hash:?} (#{best_number})",
Expand Down Expand Up @@ -1697,13 +1703,13 @@ impl<Block: BlockT> Backend<Block> {
}
transaction.set_from_vec(columns::META, meta_keys::FINALIZED_BLOCK, lookup_key);

if sc_client_api::Backend::have_state_at(self, f_hash, f_num) &&
self.storage
.state_db
.best_canonical()
.map(|c| f_num.saturated_into::<u64>() > c)
.unwrap_or(true)
{
let requires_canonicalization = match self.storage.state_db.last_canonicalized() {
LastCanonicalized::None => true,
LastCanonicalized::Block(b) => f_num.saturated_into::<u64>() > b,
LastCanonicalized::NotCanonicalizing => false,
};

if requires_canonicalization && sc_client_api::Backend::have_state_at(self, f_hash, f_num) {
let commit = self.storage.state_db.canonicalize_block(&f_hash).map_err(
sp_blockchain::Error::from_state_db::<
sc_state_db::Error<sp_database::error::DatabaseError>,
Expand Down Expand Up @@ -3824,102 +3830,198 @@ pub(crate) mod tests {

#[test]
fn force_delayed_canonicalize_waiting_for_blocks_to_be_finalized() {
let backend = Backend::<Block>::new_test(10, 1);
let pruning_modes = [BlocksPruning::Some(10), BlocksPruning::KeepAll];

let genesis =
insert_block(&backend, 0, Default::default(), None, Default::default(), vec![], None)
for pruning_mode in pruning_modes {
eprintln!("Running with pruning mode: {:?}", pruning_mode);

let backend = Backend::<Block>::new_test_with_tx_storage(pruning_mode, 1);

let genesis = insert_block(
&backend,
0,
Default::default(),
None,
Default::default(),
vec![],
None,
)
.unwrap();

let block1 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, genesis).unwrap();
let mut header = Header {
number: 1,
parent_hash: genesis,
state_root: Default::default(),
digest: Default::default(),
extrinsics_root: Default::default(),
};

let storage = vec![(vec![1, 3, 5], None), (vec![5, 5, 5], Some(vec![4, 5, 6]))];

let (root, overlay) = op.old_state.storage_root(
storage.iter().map(|(k, v)| (k.as_slice(), v.as_ref().map(|v| &v[..]))),
StateVersion::V1,
);
op.update_db_storage(overlay).unwrap();
header.state_root = root.into();

op.update_storage(storage, Vec::new()).unwrap();

op.set_block_data(
header.clone(),
Some(Vec::new()),
None,
None,
NewBlockState::Normal,
)
.unwrap();

let block1 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, genesis).unwrap();
let header = Header {
number: 1,
parent_hash: genesis,
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
digest: Default::default(),
extrinsics_root: Default::default(),
backend.commit_operation(op).unwrap();

header.hash()
};

op.set_block_data(header.clone(), Some(Vec::new()), None, None, NewBlockState::Normal)
.unwrap();
if matches!(pruning_mode, BlocksPruning::Some(_)) {
assert_eq!(
LastCanonicalized::Block(0),
backend.storage.state_db.last_canonicalized()
);
}

backend.commit_operation(op).unwrap();
// This should not trigger any forced canonicalization as we didn't have imported any
// best block by now.
let block2 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, block1).unwrap();
let mut header = Header {
number: 2,
parent_hash: block1,
state_root: Default::default(),
digest: Default::default(),
extrinsics_root: Default::default(),
};

header.hash()
};
let storage = vec![(vec![5, 5, 5], Some(vec![4, 5, 6, 2]))];

assert_eq!(0, backend.storage.state_db.best_canonical().unwrap());
let (root, overlay) = op.old_state.storage_root(
storage.iter().map(|(k, v)| (k.as_slice(), v.as_ref().map(|v| &v[..]))),
StateVersion::V1,
);
op.update_db_storage(overlay).unwrap();
header.state_root = root.into();

// This should not trigger any forced canonicalization as we didn't have imported any best
// block by now.
let block2 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, block1).unwrap();
let header = Header {
number: 2,
parent_hash: block1,
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
digest: Default::default(),
extrinsics_root: Default::default(),
};
op.update_storage(storage, Vec::new()).unwrap();

op.set_block_data(header.clone(), Some(Vec::new()), None, None, NewBlockState::Normal)
op.set_block_data(
header.clone(),
Some(Vec::new()),
None,
None,
NewBlockState::Normal,
)
.unwrap();

backend.commit_operation(op).unwrap();
backend.commit_operation(op).unwrap();

header.hash()
};
header.hash()
};

assert_eq!(0, backend.storage.state_db.best_canonical().unwrap());
if matches!(pruning_mode, BlocksPruning::Some(_)) {
assert_eq!(
LastCanonicalized::Block(0),
backend.storage.state_db.last_canonicalized()
);
}

// This should also not trigger it yet, because we import a best block, but the best block
// from the POV of the db is still at `0`.
let block3 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, block2).unwrap();
let header = Header {
number: 3,
parent_hash: block2,
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
digest: Default::default(),
extrinsics_root: Default::default(),
};
// This should also not trigger it yet, because we import a best block, but the best
// block from the POV of the db is still at `0`.
let block3 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, block2).unwrap();
let mut header = Header {
number: 3,
parent_hash: block2,
state_root: Default::default(),
digest: Default::default(),
extrinsics_root: Default::default(),
};

op.set_block_data(header.clone(), Some(Vec::new()), None, None, NewBlockState::Best)
.unwrap();
let storage = vec![(vec![5, 5, 5], Some(vec![4, 5, 6, 3]))];

backend.commit_operation(op).unwrap();
let (root, overlay) = op.old_state.storage_root(
storage.iter().map(|(k, v)| (k.as_slice(), v.as_ref().map(|v| &v[..]))),
StateVersion::V1,
);
op.update_db_storage(overlay).unwrap();
header.state_root = root.into();

header.hash()
};
op.update_storage(storage, Vec::new()).unwrap();

// Now it should kick in.
let block4 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, block3).unwrap();
let header = Header {
number: 4,
parent_hash: block3,
state_root: BlakeTwo256::trie_root(Vec::new(), StateVersion::V1),
digest: Default::default(),
extrinsics_root: Default::default(),
op.set_block_data(
header.clone(),
Some(Vec::new()),
None,
None,
NewBlockState::Best,
)
.unwrap();

backend.commit_operation(op).unwrap();

header.hash()
};

op.set_block_data(header.clone(), Some(Vec::new()), None, None, NewBlockState::Best)
// Now it should kick in.
let block4 = {
let mut op = backend.begin_operation().unwrap();
backend.begin_state_operation(&mut op, block3).unwrap();
let mut header = Header {
number: 4,
parent_hash: block3,
state_root: Default::default(),
digest: Default::default(),
extrinsics_root: Default::default(),
};

let storage = vec![(vec![5, 5, 5], Some(vec![4, 5, 6, 4]))];

let (root, overlay) = op.old_state.storage_root(
storage.iter().map(|(k, v)| (k.as_slice(), v.as_ref().map(|v| &v[..]))),
StateVersion::V1,
);
op.update_db_storage(overlay).unwrap();
header.state_root = root.into();

op.update_storage(storage, Vec::new()).unwrap();

op.set_block_data(
header.clone(),
Some(Vec::new()),
None,
None,
NewBlockState::Best,
)
.unwrap();

backend.commit_operation(op).unwrap();
backend.commit_operation(op).unwrap();

header.hash()
};
header.hash()
};

assert_eq!(2, backend.storage.state_db.best_canonical().unwrap());
if matches!(pruning_mode, BlocksPruning::Some(_)) {
assert_eq!(
LastCanonicalized::Block(2),
backend.storage.state_db.last_canonicalized()
);
}

assert_eq!(block1, backend.blockchain().hash(1).unwrap().unwrap());
assert_eq!(block2, backend.blockchain().hash(2).unwrap().unwrap());
assert_eq!(block3, backend.blockchain().hash(3).unwrap().unwrap());
assert_eq!(block4, backend.blockchain().hash(4).unwrap().unwrap());
assert_eq!(block1, backend.blockchain().hash(1).unwrap().unwrap());
assert_eq!(block2, backend.blockchain().hash(2).unwrap().unwrap());
assert_eq!(block3, backend.blockchain().hash(3).unwrap().unwrap());
assert_eq!(block4, backend.blockchain().hash(4).unwrap().unwrap());
}
}
}
Loading

0 comments on commit 854c749

Please sign in to comment.