mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 09:17:58 +00:00
PoV Reclaim (Clawback) Node Side (#1462)
This PR provides the infrastructure for the pov-reclaim mechanism discussed in #209. The goal is to provide the current proof size to the runtime so it can be used to reclaim storage weight. ## New Host Function - A new host function is provided [here](https://github.com/skunert/polkadot-sdk/blob/5b317fda3be205f4136f10d4490387ccd4f9765d/cumulus/primitives/pov-reclaim/src/lib.rs#L23). It returns the size of the current proof size to the runtime. If recording is not enabled, it returns 0. ## Implementation Overview - Implement option to enable proof recording during import in the client. This is currently enabled for `polkadot-parachain`, `parachain-template` and the cumulus test node. - Make the proof recorder ready for no-std. It was previously only enabled for std environments, but we need to record the proof size in `validate_block` too. - Provide a recorder implementation that only the records the size of incoming nodes and does not store the nodes itself. - Fix benchmarks that were broken by async backing changes - Provide new externalities extension that is registered by default if proof recording is enabled. - I think we should discuss the naming, pov-reclaim was more intuitive to me, but we could also go with clawback like in the issue. ## Impact of proof recording during import With proof recording: 6.3058 Kelem/s Without proof recording: 6.3427 Kelem/s The measured impact on the importing performance is quite low on my machine using the block import benchmark. With proof recording I am seeing a performance hit of 0.585%. --------- Co-authored-by: command-bot <> Co-authored-by: Davide Galassi <davxy@datawok.net> Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
@@ -30,6 +30,9 @@ mod storage_proof;
|
||||
mod trie_codec;
|
||||
mod trie_stream;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod proof_size_extension;
|
||||
|
||||
/// Our `NodeCodec`-specific error.
|
||||
pub use error::Error;
|
||||
/// Various re-exports from the `hash-db` crate.
|
||||
@@ -146,6 +149,29 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Type that is able to provide a [`trie_db::TrieRecorder`].
|
||||
///
|
||||
/// Types implementing this trait can be used to maintain recorded state
|
||||
/// across operations on different [`trie_db::TrieDB`] instances.
|
||||
pub trait TrieRecorderProvider<H: Hasher> {
|
||||
/// Recorder type that is going to be returned by implementors of this trait.
|
||||
type Recorder<'a>: trie_db::TrieRecorder<H::Out> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
/// Create a [`StorageProof`] derived from the internal state.
|
||||
fn drain_storage_proof(self) -> Option<StorageProof>;
|
||||
|
||||
/// Provide a recorder implementing [`trie_db::TrieRecorder`].
|
||||
fn as_trie_recorder(&self, storage_root: H::Out) -> Self::Recorder<'_>;
|
||||
}
|
||||
|
||||
/// Type that is able to provide a proof size estimation.
|
||||
pub trait ProofSizeProvider {
|
||||
/// Returns the storage proof size.
|
||||
fn estimate_encoded_size(&self) -> usize;
|
||||
}
|
||||
|
||||
/// TrieDB error over `TrieConfiguration` trait.
|
||||
pub type TrieError<L> = trie_db::TrieError<TrieHash<L>, CError<L>>;
|
||||
/// Reexport from `hash_db`, with genericity set for `Hasher` trait.
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Externalities extension that provides access to the current proof size
|
||||
//! of the underlying recorder.
|
||||
|
||||
use crate::ProofSizeProvider;
|
||||
|
||||
sp_externalities::decl_extension! {
|
||||
/// The proof size extension to fetch the current storage proof size
|
||||
/// in externalities.
|
||||
pub struct ProofSizeExt(Box<dyn ProofSizeProvider + 'static + Sync + Send>);
|
||||
}
|
||||
|
||||
impl ProofSizeExt {
|
||||
/// Creates a new instance of [`ProofSizeExt`].
|
||||
pub fn new<T: ProofSizeProvider + Sync + Send + 'static>(recorder: T) -> Self {
|
||||
ProofSizeExt(Box::new(recorder))
|
||||
}
|
||||
|
||||
/// Returns the storage proof size.
|
||||
pub fn storage_proof_size(&self) -> u64 {
|
||||
self.0.estimate_encoded_size() as _
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
use crate::{NodeCodec, StorageProof};
|
||||
use codec::Encode;
|
||||
use hash_db::Hasher;
|
||||
use parking_lot::Mutex;
|
||||
use parking_lot::{Mutex, MutexGuard};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
marker::PhantomData,
|
||||
@@ -80,7 +80,9 @@ impl<H> Default for RecorderInner<H> {
|
||||
|
||||
/// The trie recorder.
|
||||
///
|
||||
/// It can be used to record accesses to the trie and then to convert them into a [`StorageProof`].
|
||||
/// Owns the recorded data. Is used to transform data into a storage
|
||||
/// proof and to provide transaction support. The `as_trie_recorder` method provides a
|
||||
/// [`trie_db::TrieDB`] compatible recorder that implements the actual recording logic.
|
||||
pub struct Recorder<H: Hasher> {
|
||||
inner: Arc<Mutex<RecorderInner<H::Out>>>,
|
||||
/// The estimated encoded size of the storage proof this recorder will produce.
|
||||
@@ -112,11 +114,8 @@ impl<H: Hasher> Recorder<H> {
|
||||
///
|
||||
/// NOTE: This locks a mutex that stays locked until the return value is dropped.
|
||||
#[inline]
|
||||
pub fn as_trie_recorder(
|
||||
&self,
|
||||
storage_root: H::Out,
|
||||
) -> impl trie_db::TrieRecorder<H::Out> + '_ {
|
||||
TrieRecorder::<H, _> {
|
||||
pub fn as_trie_recorder(&self, storage_root: H::Out) -> TrieRecorder<'_, H> {
|
||||
TrieRecorder::<H> {
|
||||
inner: self.inner.lock(),
|
||||
storage_root,
|
||||
encoded_size_estimation: self.encoded_size_estimation.clone(),
|
||||
@@ -231,15 +230,33 @@ impl<H: Hasher> Recorder<H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Hasher> crate::ProofSizeProvider for Recorder<H> {
|
||||
fn estimate_encoded_size(&self) -> usize {
|
||||
Recorder::estimate_encoded_size(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`TrieRecorder`](trie_db::TrieRecorder) implementation.
|
||||
struct TrieRecorder<H: Hasher, I> {
|
||||
inner: I,
|
||||
pub struct TrieRecorder<'a, H: Hasher> {
|
||||
inner: MutexGuard<'a, RecorderInner<H::Out>>,
|
||||
storage_root: H::Out,
|
||||
encoded_size_estimation: Arc<AtomicUsize>,
|
||||
_phantom: PhantomData<H>,
|
||||
}
|
||||
|
||||
impl<H: Hasher, I: DerefMut<Target = RecorderInner<H::Out>>> TrieRecorder<H, I> {
|
||||
impl<H: Hasher> crate::TrieRecorderProvider<H> for Recorder<H> {
|
||||
type Recorder<'a> = TrieRecorder<'a, H> where H: 'a;
|
||||
|
||||
fn drain_storage_proof(self) -> Option<StorageProof> {
|
||||
Some(Recorder::drain_storage_proof(self))
|
||||
}
|
||||
|
||||
fn as_trie_recorder(&self, storage_root: H::Out) -> Self::Recorder<'_> {
|
||||
Recorder::as_trie_recorder(&self, storage_root)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, H: Hasher> TrieRecorder<'a, H> {
|
||||
/// Update the recorded keys entry for the given `full_key`.
|
||||
fn update_recorded_keys(&mut self, full_key: &[u8], access: RecordedForKey) {
|
||||
let inner = self.inner.deref_mut();
|
||||
@@ -283,9 +300,7 @@ impl<H: Hasher, I: DerefMut<Target = RecorderInner<H::Out>>> TrieRecorder<H, I>
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Hasher, I: DerefMut<Target = RecorderInner<H::Out>>> trie_db::TrieRecorder<H::Out>
|
||||
for TrieRecorder<H, I>
|
||||
{
|
||||
impl<'a, H: Hasher> trie_db::TrieRecorder<H::Out> for TrieRecorder<'a, H> {
|
||||
fn record(&mut self, access: TrieAccess<H::Out>) {
|
||||
let mut encoded_size_update = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user