mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 12:11:09 +00:00
Mmr persist state (#12822)
client/mmr: persisting gadget state across runs Fixes #12780 * client/mmr: on init do canonicalization catch-up * client/mmr: add more tests * client/mmr: persist gadget progress in aux db * client/mmr: add more tests * client/mmr: replace async_std with tokio * remove leftover comment * address review comments Signed-off-by: acatangiu <adrian@parity.io>
This commit is contained in:
@@ -16,12 +16,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{
|
||||
future::Future,
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::MmrGadget;
|
||||
use parking_lot::Mutex;
|
||||
use sc_block_builder::BlockBuilderProvider;
|
||||
use sc_client_api::{
|
||||
Backend as BackendT, BlockchainEvents, FinalityNotifications, ImportNotifications,
|
||||
@@ -41,33 +37,34 @@ use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, Header as HeaderT},
|
||||
};
|
||||
use std::{future::Future, sync::Arc, time::Duration};
|
||||
use substrate_test_runtime_client::{
|
||||
runtime::{Block, BlockNumber, Hash, Header},
|
||||
Backend, BlockBuilderExt, Client, ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt,
|
||||
TestClientBuilder, TestClientBuilderExt,
|
||||
};
|
||||
|
||||
use crate::MmrGadget;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
type MmrHash = H256;
|
||||
|
||||
struct MockRuntimeApiData {
|
||||
num_blocks: BlockNumber,
|
||||
pub(crate) struct MockRuntimeApiData {
|
||||
pub(crate) num_blocks: BlockNumber,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MockRuntimeApi {
|
||||
data: Arc<Mutex<MockRuntimeApiData>>,
|
||||
pub(crate) struct MockRuntimeApi {
|
||||
pub(crate) data: Arc<Mutex<MockRuntimeApiData>>,
|
||||
}
|
||||
|
||||
impl MockRuntimeApi {
|
||||
pub const INDEXING_PREFIX: &'static [u8] = b"mmr_test";
|
||||
pub(crate) const INDEXING_PREFIX: &'static [u8] = b"mmr_test";
|
||||
}
|
||||
|
||||
pub struct MmrBlock {
|
||||
block: Block,
|
||||
leaf_idx: Option<LeafIndex>,
|
||||
leaf_data: Vec<u8>,
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct MmrBlock {
|
||||
pub(crate) block: Block,
|
||||
pub(crate) leaf_idx: Option<LeafIndex>,
|
||||
pub(crate) leaf_data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
@@ -90,7 +87,7 @@ impl MmrBlock {
|
||||
OffchainKeyType::Temp => NodesUtils::node_temp_offchain_key::<Header>(
|
||||
MockRuntimeApi::INDEXING_PREFIX,
|
||||
node,
|
||||
*self.block.header.parent_hash(),
|
||||
self.parent_hash(),
|
||||
),
|
||||
OffchainKeyType::Canon =>
|
||||
NodesUtils::node_canon_offchain_key(MockRuntimeApi::INDEXING_PREFIX, node),
|
||||
@@ -98,14 +95,14 @@ impl MmrBlock {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MockClient {
|
||||
client: Mutex<Client<Backend>>,
|
||||
backend: Arc<Backend>,
|
||||
runtime_api_params: Arc<Mutex<MockRuntimeApiData>>,
|
||||
pub(crate) struct MockClient {
|
||||
pub(crate) client: Mutex<Client<Backend>>,
|
||||
pub(crate) backend: Arc<Backend>,
|
||||
pub(crate) runtime_api_params: Arc<Mutex<MockRuntimeApiData>>,
|
||||
}
|
||||
|
||||
impl MockClient {
|
||||
fn new() -> Self {
|
||||
pub(crate) fn new() -> Self {
|
||||
let client_builder = TestClientBuilder::new().enable_offchain_indexing_api();
|
||||
let (client, backend) = client_builder.build_with_backend();
|
||||
MockClient {
|
||||
@@ -115,7 +112,7 @@ impl MockClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn offchain_db(&self) -> OffchainDb<<Backend as BackendT<Block>>::OffchainStorage> {
|
||||
pub(crate) fn offchain_db(&self) -> OffchainDb<<Backend as BackendT<Block>>::OffchainStorage> {
|
||||
OffchainDb::new(self.backend.offchain_storage().unwrap())
|
||||
}
|
||||
|
||||
@@ -125,7 +122,7 @@ impl MockClient {
|
||||
name: &[u8],
|
||||
maybe_leaf_idx: Option<LeafIndex>,
|
||||
) -> MmrBlock {
|
||||
let mut client = self.client.lock().unwrap();
|
||||
let mut client = self.client.lock();
|
||||
|
||||
let mut block_builder = client.new_block_at(at, Default::default(), false).unwrap();
|
||||
// Make sure the block has a different hash than its siblings
|
||||
@@ -157,9 +154,9 @@ impl MockClient {
|
||||
}
|
||||
|
||||
pub fn finalize_block(&self, hash: Hash, maybe_num_mmr_blocks: Option<BlockNumber>) {
|
||||
let client = self.client.lock().unwrap();
|
||||
let client = self.client.lock();
|
||||
if let Some(num_mmr_blocks) = maybe_num_mmr_blocks {
|
||||
self.runtime_api_params.lock().unwrap().num_blocks = num_mmr_blocks;
|
||||
self.runtime_api_params.lock().num_blocks = num_mmr_blocks;
|
||||
}
|
||||
|
||||
client.finalize_block(hash, None).unwrap();
|
||||
@@ -216,7 +213,7 @@ impl HeaderMetadata<Block> for MockClient {
|
||||
type Error = <Client<Backend> as HeaderMetadata<Block>>::Error;
|
||||
|
||||
fn header_metadata(&self, hash: Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
|
||||
self.client.lock().unwrap().header_metadata(hash)
|
||||
self.client.lock().header_metadata(hash)
|
||||
}
|
||||
|
||||
fn insert_header_metadata(&self, _hash: Hash, _header_metadata: CachedHeaderMetadata<Block>) {
|
||||
@@ -230,23 +227,23 @@ impl HeaderMetadata<Block> for MockClient {
|
||||
|
||||
impl HeaderBackend<Block> for MockClient {
|
||||
fn header(&self, id: BlockId<Block>) -> sc_client_api::blockchain::Result<Option<Header>> {
|
||||
self.client.lock().unwrap().header(&id)
|
||||
self.client.lock().header(&id)
|
||||
}
|
||||
|
||||
fn info(&self) -> Info<Block> {
|
||||
self.client.lock().unwrap().info()
|
||||
self.client.lock().info()
|
||||
}
|
||||
|
||||
fn status(&self, id: BlockId<Block>) -> sc_client_api::blockchain::Result<BlockStatus> {
|
||||
self.client.lock().unwrap().status(id)
|
||||
self.client.lock().status(id)
|
||||
}
|
||||
|
||||
fn number(&self, hash: Hash) -> sc_client_api::blockchain::Result<Option<BlockNumber>> {
|
||||
self.client.lock().unwrap().number(hash)
|
||||
self.client.lock().number(hash)
|
||||
}
|
||||
|
||||
fn hash(&self, number: BlockNumber) -> sc_client_api::blockchain::Result<Option<Hash>> {
|
||||
self.client.lock().unwrap().hash(number)
|
||||
self.client.lock().hash(number)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +253,7 @@ impl BlockchainEvents<Block> for MockClient {
|
||||
}
|
||||
|
||||
fn finality_notification_stream(&self) -> FinalityNotifications<Block> {
|
||||
self.client.lock().unwrap().finality_notification_stream()
|
||||
self.client.lock().finality_notification_stream()
|
||||
}
|
||||
|
||||
fn storage_changes_notification_stream(
|
||||
@@ -283,7 +280,7 @@ sp_api::mock_impl_runtime_apis! {
|
||||
}
|
||||
|
||||
fn mmr_leaf_count(&self) -> Result<LeafIndex, mmr::Error> {
|
||||
Ok(self.data.lock().unwrap().num_blocks)
|
||||
Ok(self.data.lock().num_blocks)
|
||||
}
|
||||
|
||||
fn generate_proof(
|
||||
@@ -310,13 +307,38 @@ sp_api::mock_impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_test_with_mmr_gadget<F, Fut>(f: F)
|
||||
pub(crate) fn run_test_with_mmr_gadget<F, Fut>(post_gadget: F)
|
||||
where
|
||||
F: FnOnce(Arc<MockClient>) -> Fut + 'static,
|
||||
Fut: Future<Output = ()>,
|
||||
{
|
||||
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||||
run_test_with_mmr_gadget_pre_post(|_| async {}, post_gadget);
|
||||
}
|
||||
|
||||
pub(crate) fn run_test_with_mmr_gadget_pre_post<F, G, RetF, RetG>(pre_gadget: F, post_gadget: G)
|
||||
where
|
||||
F: FnOnce(Arc<MockClient>) -> RetF + 'static,
|
||||
G: FnOnce(Arc<MockClient>) -> RetG + 'static,
|
||||
RetF: Future<Output = ()>,
|
||||
RetG: Future<Output = ()>,
|
||||
{
|
||||
let client = Arc::new(MockClient::new());
|
||||
run_test_with_mmr_gadget_pre_post_using_client(client, pre_gadget, post_gadget)
|
||||
}
|
||||
|
||||
pub(crate) fn run_test_with_mmr_gadget_pre_post_using_client<F, G, RetF, RetG>(
|
||||
client: Arc<MockClient>,
|
||||
pre_gadget: F,
|
||||
post_gadget: G,
|
||||
) where
|
||||
F: FnOnce(Arc<MockClient>) -> RetF + 'static,
|
||||
G: FnOnce(Arc<MockClient>) -> RetG + 'static,
|
||||
RetF: Future<Output = ()>,
|
||||
RetG: Future<Output = ()>,
|
||||
{
|
||||
let client_clone = client.clone();
|
||||
let runtime = Runtime::new().unwrap();
|
||||
runtime.block_on(async move { pre_gadget(client_clone).await });
|
||||
|
||||
let client_clone = client.clone();
|
||||
runtime.spawn(async move {
|
||||
@@ -327,6 +349,6 @@ where
|
||||
runtime.block_on(async move {
|
||||
tokio::time::sleep(Duration::from_millis(200)).await;
|
||||
|
||||
f(client).await
|
||||
post_gadget(client).await
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user