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

Add stale branches heads to finality notifications #10639

Merged
merged 16 commits into from
Jan 27, 2022
Merged

Conversation

davxy
Copy link
Member

@davxy davxy commented Jan 11, 2022

Closes #10605

Includes stale branches heads to finality notifications sent by the client.

Warning

Previous implementation was sending a notification for each block between the previous (explicitly) finalized block and
the new finalized one (with an hardcoded limit of 256). Thus finalization messages were sent also for implicitly finalized blocks.

Now finality notification is sent only for the new finalized head and it contains the hash of the new finalized head hash, new finalized head header, a list of all the implicitly finalized blocks and a list of stale branches heads (i.e. heads that are not part of the canonical chain anymore).

@github-actions github-actions bot added the A3-in_progress Pull request is in progress. No review needed at this stage. label Jan 11, 2022
@bkchr bkchr removed their assignment Jan 11, 2022
client/api/src/client.rs Outdated Show resolved Hide resolved
Warning. Previous implementation was sending a notification for
each block between the previous (explicitly) finalized block and
the new finalized one (with an hardcoded limit of 256).

Now finality notification is sent only for the new finalized head and it
contains the hash of the new finalized head, new finalized head header,
a list of all the implicitly finalized blocks and a list of stale
branches heads (i.e. the branches heads that are not part of the
canonical chain anymore).
@davxy davxy requested a review from bkchr January 12, 2022 14:04
@davxy davxy marked this pull request as ready for review January 12, 2022 14:15
@github-actions github-actions bot added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. labels Jan 12, 2022
@davxy davxy added A3-in_progress Pull request is in progress. No review needed at this stage. and removed A0-please_review Pull request needs code review. labels Jan 12, 2022
@davxy davxy marked this pull request as draft January 12, 2022 15:10
The list contains all the blocks between the previously finalized block
up to the parent of the currently finalized one, sorted by block number.

`Finalized` messages handler, part of the `MaintainedTransactionPool`
implementation for `BasicPool`, still propagate full set of finalized
blocks to the txpool by iterating over implicitly finalized blocks list.
@davxy davxy added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. labels Jan 15, 2022
@davxy davxy marked this pull request as ready for review January 15, 2022 12:03
@davxy
Copy link
Member Author

davxy commented Jan 17, 2022

@bkchr @andresilva

TL;DR

A fairly meticulous inspection of finality_notification_stream consumers;

In particular assumptions about sequential block finalization messages were checked and eventually fixed.

Looks like receiving the last finalized block message was sufficient for almost all consumers with the exception of txpool, where a fix is already contained in this PR.

A review from more experienced people for the single components is still required.

Follows a recap for Substrate, Cumulus and Polkadot with code references to simplify the inspection.

Substrate

Transaction Pool

  • Stream read by notification_future here
  • Validated transaction pool assumes to receive a notification message for each finalized block.
  • Message handler has been adjusted to send the full finalized list to pool.validated_pool().on_block_finalized()

See here

Beefy

  • Stream read by BeefyWorker here

  • Message is then processed here

  • Looks happy with final head notification.

Networking

  • Stream is read within build_network_future here
  • A wrapper to find the last finalized block was present here. This is not required anymore.
  • build_network_future forwards finality notification to network.on_block_finalized(hash, number) here
  • message arrives to ChainSync::on_block_finalized here.
  • message is forwarded to ExtraRequests::on_block_finalized in here

RPC

  • Stream read messages are forwarded to subscribers of subscribe_finalized_heads API here

  • WARNING: we are now sending notifications only for finalized heads but external applications may rely on previous behaviour?

Cumulus

PovRecovery

  • Stream is read within PovRecovery::run here

  • Calls handle_block_finalized(finalized_number) that is used to remove from self.pending_candidates blocks with number <= finalized_number here

  • Seems happy with final head notification

RelaychainClient

  • Stream is read within RelaychainClient for RCInterface :: finalized_heads implementation here

  • The stream result is then used in follow_finalized_head. here

    • for each new finalized head the parachain.finalize_block(finalized_hash) is called.
    • this is already correctly handled by Substrate Client implementation for Finalizer trait.
  • Seems happy with final head notification

Polkadot

Overseer

node/overseer/src/lib.rs

  • forward_events() forwards stream messages to the overseer wrapper using Handle::block_finalized here
  • Handle::block_finalized sends messages to Overseer task.
  • The event is catched within the Overseer::run and managed using Overseer::block_finalized here
    • This prunes leaves below the finalized head here

The loop was there to prevent sending to
`peer.network.on_block_finalized` the full list of finalized blocks.

Now only the finalized heads are received.
@davxy davxy added B3-apinoteworthy C1-low PR touches the given topic and has a low impact on builders. labels Jan 18, 2022
@bkchr
Copy link
Member

bkchr commented Jan 18, 2022

@davxy ty for the detailed report. Looks good as far as I can see :)

Copy link
Contributor

@andresilva andresilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work @davxy, LGTM overall. For the RPC I'm not sure whether we should change it to take the summary and emit a notification for each block. We need to add some tests for the creation of stale heads because I am not sure if all cases are covered or whether we might be missing some heads.

@jacogr When multiple blocks are finalized at once, would getting a single finality notification for the latest block, as opposed to now getting one for each finalized block, have any effect on polkadot.js/apps?

client/service/src/lib.rs Show resolved Hide resolved
client/service/src/client/client.rs Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@andresilva andresilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Nice work @davxy

client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/test/src/client/mod.rs Show resolved Hide resolved
Copy link
Member

@bkchr bkchr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks already very good, but needs some more adjustments.

client/service/src/client/client.rs Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/src/client/client.rs Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
@bkchr
Copy link
Member

bkchr commented Jan 26, 2022

Ahh and @davxy please don't use force pushes :)

client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
client/service/src/client/client.rs Show resolved Hide resolved
client/service/src/client/client.rs Outdated Show resolved Hide resolved
davxy and others added 2 commits January 27, 2022 16:21
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
@davxy davxy merged commit 3c1d5b9 into master Jan 27, 2022
@davxy davxy deleted the davxy-stale-heads-notify branch January 27, 2022 17:22
Wizdave97 pushed a commit to ComposableFi/substrate that referenced this pull request Feb 4, 2022
* Add stale branches heads to finality notifications

Warning. Previous implementation was sending a notification for
each block between the previous (explicitly) finalized block and
the new finalized one (with an hardcoded limit of 256).

Now finality notification is sent only for the new finalized head and it
contains the hash of the new finalized head, new finalized head header,
a list of all the implicitly finalized blocks and a list of stale
branches heads (i.e. the branches heads that are not part of the
canonical chain anymore).

* Add implicitly finalized blocks list to `ChainEvent::Finalized` message

The list contains all the blocks between the previously finalized block
up to the parent of the currently finalized one, sorted by block number.

`Finalized` messages handler, part of the `MaintainedTransactionPool`
implementation for `BasicPool`, still propagate full set of finalized
blocks to the txpool by iterating over implicitly finalized blocks list.

* Rust fmt

* Greedy evaluation of `stale_heads` during finalization

* Fix outdated assumption in a comment

* Removed a test optimization that is no more relevant

The loop was there to prevent sending to
`peer.network.on_block_finalized` the full list of finalized blocks.

Now only the finalized heads are received.

* Last finalized block lookup not required anymore

* Tests for block finality notifications payloads

* Document a bit tricky condition to avoid duplicate finalization notifications

* More idiomatic way to skip an iterator entry

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Cargo fmt iteration

* Typo fix

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Fix potential failure when a finalized orphan block is imported

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
grishasobol pushed a commit to gear-tech/substrate that referenced this pull request Mar 28, 2022
* Add stale branches heads to finality notifications

Warning. Previous implementation was sending a notification for
each block between the previous (explicitly) finalized block and
the new finalized one (with an hardcoded limit of 256).

Now finality notification is sent only for the new finalized head and it
contains the hash of the new finalized head, new finalized head header,
a list of all the implicitly finalized blocks and a list of stale
branches heads (i.e. the branches heads that are not part of the
canonical chain anymore).

* Add implicitly finalized blocks list to `ChainEvent::Finalized` message

The list contains all the blocks between the previously finalized block
up to the parent of the currently finalized one, sorted by block number.

`Finalized` messages handler, part of the `MaintainedTransactionPool`
implementation for `BasicPool`, still propagate full set of finalized
blocks to the txpool by iterating over implicitly finalized blocks list.

* Rust fmt

* Greedy evaluation of `stale_heads` during finalization

* Fix outdated assumption in a comment

* Removed a test optimization that is no more relevant

The loop was there to prevent sending to
`peer.network.on_block_finalized` the full list of finalized blocks.

Now only the finalized heads are received.

* Last finalized block lookup not required anymore

* Tests for block finality notifications payloads

* Document a bit tricky condition to avoid duplicate finalization notifications

* More idiomatic way to skip an iterator entry

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Cargo fmt iteration

* Typo fix

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Fix potential failure when a finalized orphan block is imported

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
ark0f pushed a commit to gear-tech/substrate that referenced this pull request Feb 27, 2023
* Add stale branches heads to finality notifications

Warning. Previous implementation was sending a notification for
each block between the previous (explicitly) finalized block and
the new finalized one (with an hardcoded limit of 256).

Now finality notification is sent only for the new finalized head and it
contains the hash of the new finalized head, new finalized head header,
a list of all the implicitly finalized blocks and a list of stale
branches heads (i.e. the branches heads that are not part of the
canonical chain anymore).

* Add implicitly finalized blocks list to `ChainEvent::Finalized` message

The list contains all the blocks between the previously finalized block
up to the parent of the currently finalized one, sorted by block number.

`Finalized` messages handler, part of the `MaintainedTransactionPool`
implementation for `BasicPool`, still propagate full set of finalized
blocks to the txpool by iterating over implicitly finalized blocks list.

* Rust fmt

* Greedy evaluation of `stale_heads` during finalization

* Fix outdated assumption in a comment

* Removed a test optimization that is no more relevant

The loop was there to prevent sending to
`peer.network.on_block_finalized` the full list of finalized blocks.

Now only the finalized heads are received.

* Last finalized block lookup not required anymore

* Tests for block finality notifications payloads

* Document a bit tricky condition to avoid duplicate finalization notifications

* More idiomatic way to skip an iterator entry

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Cargo fmt iteration

* Typo fix

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Fix potential failure when a finalized orphan block is imported

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
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. 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.

Extend finality notifications to include displaced leaves
3 participants