rpc/chainHead: Fix pruned blocks events from forks (#13379)

* rpc/chainhead: Test unpin for noncanonical prunned blocks

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/tests: Ensure fork is not reported by the Finalized event

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chainhead: Detect pruned forks to ignore from events

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/tests: Check unpin can be called on pruned hashes

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Fix clippy

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Handle race with memory blocks and notifications

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Add data config for the `follow` future

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Address feedback

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Move best block cache on the data config

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Send new events from the finalized stream

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chian_head: Report all pruned blocks

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Move `chainHead_follow` logic on dedicated file

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Delegate follow logic to `chain_head_follow`

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Remove subscriptions on drop

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/tests: Ignore pruned blocks for a longer fork

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/tests: Check all pruned blocks are reported, not just stale heads

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/tests: Remove println debug and fix indentation

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Remove unnecessary trait bounds

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Add debug log for pruned forks

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Revert "rpc/chain_head: Add debug log for pruned forks"

This reverts commit 425d6e7a8b60421bcece12add1941fe58524cf52.

* Adjust blockID for testing

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Update client/rpc-spec-v2/src/chain_head/chain_head_follow.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* rpc/chain_head: Rename `ChainHeadFollow` to `ChainHeadFollower`

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Remove subscriptions manually

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Improve log messages by adding subID and errors

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Ensure `follow` stops sending events on first error

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Use default constructor

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Add `StartupPoint` structure

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Rename `in_memory_blocks`

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Fix comment typo

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Keep unique blocks and remove itertools

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Make sure `bestBlocks` events are generated in order

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Maintain order of reported blocks

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Parent of finalized block could be unpinned

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* rpc/chain_head: Fix warning

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Co-authored-by: Davide Galassi <davxy@datawok.net>
This commit is contained in:
Alexandru Vasile
2023-03-07 11:56:14 +02:00
committed by GitHub
parent 8b94c57ece
commit 48baaa53ad
5 changed files with 989 additions and 381 deletions
@@ -19,7 +19,8 @@
//! Subscription management for tracking subscription IDs to pinned blocks.
use futures::channel::oneshot;
use parking_lot::{RwLock, RwLockWriteGuard};
use parking_lot::RwLock;
use sp_blockchain::Error;
use sp_runtime::traits::Block as BlockT;
use std::{
collections::{hash_map::Entry, HashMap, HashSet},
@@ -33,10 +34,22 @@ pub enum SubscriptionManagementError {
/// the subscription has exceeded the maximum number
/// of blocks pinned.
ExceededLimits,
/// Error originated from the blockchain (client or backend).
Blockchain(Error),
/// The database does not contain a block number.
BlockNumberAbsent,
/// The database does not contain a block hash.
BlockHashAbsent,
/// Custom error.
Custom(String),
}
impl From<Error> for SubscriptionManagementError {
fn from(err: Error) -> Self {
SubscriptionManagementError::Blockchain(err)
}
}
/// Inner subscription data structure.
struct SubscriptionInner<Block: BlockT> {
/// The `runtime_updates` parameter flag of the subscription.
@@ -53,10 +66,6 @@ struct SubscriptionInner<Block: BlockT> {
#[derive(Clone)]
pub struct SubscriptionHandle<Block: BlockT> {
inner: Arc<RwLock<SubscriptionInner<Block>>>,
/// The best reported block by this subscription.
/// Have this as a separate variable to easily share
/// the write guard with the RPC layer.
best_block: Arc<RwLock<Option<Block::Hash>>>,
}
impl<Block: BlockT> SubscriptionHandle<Block> {
@@ -69,7 +78,6 @@ impl<Block: BlockT> SubscriptionHandle<Block> {
blocks: HashSet::new(),
max_pinned_blocks,
})),
best_block: Arc::new(RwLock::new(None)),
}
}
@@ -125,11 +133,6 @@ impl<Block: BlockT> SubscriptionHandle<Block> {
let inner = self.inner.read();
inner.runtime_updates
}
/// Get the write guard of the best reported block.
pub fn best_block_write(&self) -> RwLockWriteGuard<'_, Option<Block::Hash>> {
self.best_block.write()
}
}
/// Manage block pinning / unpinning for subscription IDs.