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

Conversation

@davxy
Copy link
Member

@davxy davxy commented Aug 10, 2022

This PR introduces a new remove method for the leaves set maintained by the backend.

The remove, import, and finalization methods return types were named/renamed

  • RemoveOutcome
  • ImportDisplaced -> ImportOutcome
  • FinalizationDisplaced -> FinalizationOutcome

This naming/renaming has been done to better reflect what the operations are actually doing.
That is, for example:

  • an import always adds a new leaf, but not always removes its parent from the leaves set (the parent may not be a leaf already)
  • a remove not always removes a leaf and not always adds its parent to the set (it should be the last child to add the parent as a leaf).

The naming also better fits in the undo operations that were improved and better tested.


The new remove method has been immediately used to fix the remove_leaf_block backend method.
Before it was using revert and that has not the effect we actually need here.

The fix introduced the new 'removal' method for the backend leaves set
and the improvement of the undo features.
@davxy davxy requested review from arkpar, bkchr and cheme August 10, 2022 17:47
@github-actions github-actions bot added the A0-please_review Pull request needs code review. label Aug 10, 2022
@davxy davxy requested a review from a team August 10, 2022 17:47
@davxy davxy self-assigned this Aug 10, 2022
@davxy davxy added B0-silent Changes should not be mentioned in any release notes C1-low PR touches the given topic and has a low impact on builders. labels Aug 10, 2022
@davxy davxy requested a review from a team August 13, 2022 06:48
@davxy
Copy link
Member Author

davxy commented Aug 16, 2022

@skunert applied your suggestion. Thank you.

@bkchr fixed another little bug in the remove_leaf_block.
On block removal the persisted children list was not updated.

This is the new fix

substrate/client/db/src/lib.rs

Lines 2230 to 2253 in 39a9f30

let children: Vec<_> = self
.blockchain()
.children(hdr.parent)?
.into_iter()
.filter(|child_hash| child_hash != hash)
.collect();
let parent_leaf = if children.is_empty() {
children::remove_children(
&mut transaction,
columns::META,
meta_keys::CHILDREN_PREFIX,
hdr.parent,
);
Some(hdr.parent)
} else {
children::write_children(
&mut transaction,
columns::META,
meta_keys::CHILDREN_PREFIX,
hdr.parent,
children,
);
None
};

@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
The job name - cargo-check-benches
The job logs - https://gitlab.parity.io/parity/mirrors/substrate/-/jobs/1749976

@skunert
Copy link
Contributor

skunert commented Aug 16, 2022

I think this check is still broken, we now always insert the parent 🤔.
https://github.com/paritytech/substrate/pull/12005/files#diff-d631f4b5aa83ad9f2088c7d13236ad51b6a4ffdb870927f071532d9904bc2c5fR142

#[test]
fn removal_breaks() {
	let mut set = LeafSet::new();
	set.import(10_1u32, 10u32, 0u32);

	set.import(11_2, 11, 10_1);
	set.import(12_2, 12, 11_2);
	set.import(12_3, 12, 11_2);

	let outcome = set.remove(12_3, 12, Some(11_2)).unwrap();
	assert_eq!(outcome.removed.hash, 12_3);
	assert_eq!(outcome.inserted, None);
}

Here 12_3 is removed but sibling 12_2 still exists, so the parent 11_2 should not be inserted into the leave set. I think we need to check if any children of the parent node are still present.

@davxy
Copy link
Member Author

davxy commented Aug 16, 2022

I think this check is still broken, we now always insert the parent thinking. https://github.com/paritytech/substrate/pull/12005/files#diff-d631f4b5aa83ad9f2088c7d13236ad51b6a4ffdb870927f071532d9904bc2c5fR142

@skunert that test is expected to fail. See this (new) comment here:

/// Update the leaf list on removal.
///
/// Note that the leaves set structure doesn't have the information to decide if the
/// leaf we're removing is the last children of the parent. Follows that this method requires
/// the caller to check this condition and optionally pass the `parent_hash` if `hash` is
/// its last child.
///
/// Returns `None` if no modifications are applied.

Within the LeavesSet structure we don't have any information to infer if the removed leaf is the last child of a parent.
(at the moment is a fairly primitive low level "dumb" structure)
The caller should pass this information.

In your test case the caller should call:

    let outcome = set.remove(12_3, 12, None).unwrap();

Fortunately this function usage is not so widespread... remove has been just introduced by this PR. I'm the first user :-D

let remove_outcome = leaves.remove(*hash, hdr.number, parent_leaf);

@skunert
Copy link
Contributor

skunert commented Aug 16, 2022

Ah sorry, totally missed this, makes sense now 👍.

@davxy davxy merged commit 2cb89be into master Aug 17, 2022
@davxy davxy deleted the davxy/fix-block-remove branch August 17, 2022 15:36
ark0f pushed a commit to gear-tech/substrate that referenced this pull request Feb 27, 2023
* Fix leaf block removal in the backend

The fix introduced the new 'removal' method for the backend leaves set
and the improvement of the undo features.

* Update docs

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <[email protected]>

* Fix docs typo

* On block block removal the new children list should be persisted.

* Align leaves set removal tests to the new interface

Co-authored-by: Bastian Köcher <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

A0-please_review Pull request needs code review. B0-silent Changes should not be mentioned in any release notes C1-low PR touches the given topic and has a low impact on builders.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants