Skip to content
Snippets Groups Projects
Commit ac3c88fd authored by Kian Paimani's avatar Kian Paimani Committed by GitHub
Browse files

Inject hashed prefix for remote-ext (#8960)


* Inject for remote-ext

* Update utils/frame/remote-externalities/src/lib.rs

Co-authored-by: default avatarZeke Mostov <32168567+emostov@users.noreply.github.com>

* Update utils/frame/remote-externalities/src/lib.rs

Co-authored-by: default avatarZeke Mostov <32168567+emostov@users.noreply.github.com>

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: default avatarZeke Mostov <32168567+emostov@users.noreply.github.com>
parent ba52404a
No related merge requests found
......@@ -447,7 +447,7 @@ pub trait AppCrypto<Public, Signature> {
// TODO [#5663] Could this be just `T::Signature as traits::Verify>::Signer`?
// Seems that this may cause issues with bounds resolution.
pub trait SigningTypes: crate::Config {
/// A public key that is capable of identifing `AccountId`s.
/// A public key that is capable of identifying `AccountId`s.
///
/// Usually that's either a raw crypto public key (e.g. `sr25519::Public`) or
/// an aggregate type for multiple crypto public keys, like `MulitSigner`.
......
......@@ -19,87 +19,6 @@
//!
//! An equivalent of `sp_io::TestExternalities` that can load its state from a remote substrate
//! based chain, or a local state snapshot file.
//!
//! #### Runtime to Test Against
//!
//! While not absolutely necessary, you most likely need a `Runtime` equivalent in your test setup
//! through which you can infer storage types. There are two options here:
//!
//! 1. Build a mock runtime, similar how to you would build one in a pallet test (see example
//! below). The very important point here is that this mock needs to hold real values for types
//! that matter for you, based on the chain of interest. Some typical ones are:
//!
//! - `sp_runtime::AccountId32` as `AccountId`.
//! - `u32` as `BlockNumber`.
//! - `u128` as Balance.
//!
//! Once you have your `Runtime`, you can use it for storage type resolution and do things like
//! `<my_pallet::Pallet<Runtime>>::storage_getter()` or `<my_pallet::StorageItem<Runtime>>::get()`.
//!
//! 2. Or, you can use a real runtime.
//!
//! ### Example
//!
//! With a test runtime
//!
//! ```ignore
//! use remote_externalities::Builder;
//!
//! #[derive(Clone, Eq, PartialEq, Debug, Default)]
//! pub struct TestRuntime;
//!
//! use frame_system as system;
//! impl_outer_origin! {
//! pub enum Origin for TestRuntime {}
//! }
//!
//! impl frame_system::Config for TestRuntime {
//! ..
//! // we only care about these two for now. The rest can be mock. The block number type of
//! // kusama is u32.
//! type BlockNumber = u32;
//! type Header = Header;
//! ..
//! }
//!
//! #[test]
//! fn test_runtime_works() {
//! let hash: Hash =
//! hex!["f9a4ce984129569f63edc01b1c13374779f9384f1befd39931ffdcc83acf63a7"].into();
//! let parent: Hash =
//! hex!["540922e96a8fcaf945ed23c6f09c3e189bd88504ec945cc2171deaebeaf2f37e"].into();
//! Builder::new()
//! .at(hash)
//! .module("System")
//! .build()
//! .execute_with(|| {
//! assert_eq!(
//! // note: the hash corresponds to 3098546. We can check only the parent.
//! // https://polkascan.io/kusama/block/3098546
//! <frame_system::Pallet<Runtime>>::block_hash(3098545u32),
//! parent,
//! )
//! });
//! }
//! ```
//!
//! Or with the real kusama runtime.
//!
//! ```ignore
//! use remote_externalities::Builder;
//! use kusama_runtime::Runtime;
//!
//! #[test]
//! fn test_runtime_works() {
//! let hash: Hash =
//! hex!["f9a4ce984129569f63edc01b1c13374779f9384f1befd39931ffdcc83acf63a7"].into();
//! Builder::new()
//! .at(hash)
//! .module("Staking")
//! .build()
//! .execute_with(|| assert_eq!(<pallet_staking::Module<Runtime>>::validator_count(), 400));
//! }
//! ```
use std::{
fs,
......@@ -235,8 +154,10 @@ impl Default for SnapshotConfig {
/// Builder for remote-externalities.
pub struct Builder<B: BlockT> {
/// Pallets to inject their prefix into the externalities.
/// Custom key-pairs to be injected into the externalities.
inject: Vec<KeyPair>,
/// Storage entry key prefixes to be injected into the externalities. The *hashed* prefix must be given.
hashed_prefixes: Vec<Vec<u8>>,
/// connectivity mode, online or offline.
mode: Mode<B>,
}
......@@ -245,7 +166,7 @@ pub struct Builder<B: BlockT> {
// that.
impl<B: BlockT> Default for Builder<B> {
fn default() -> Self {
Self { inject: Default::default(), mode: Default::default() }
Self { inject: Default::default(), mode: Default::default(), hashed_prefixes: Default::default() }
}
}
......@@ -394,7 +315,7 @@ impl<B: BlockT> Builder<B> {
/// initialize `Self` from state snapshot. Panics if the file does not exist.
fn load_state_snapshot(&self, path: &Path) -> Result<Vec<KeyPair>, &'static str> {
info!(target: LOG_TARGET, "scraping keypairs from state snapshot {:?}", path,);
info!(target: LOG_TARGET, "scraping key-pairs from state snapshot {:?}", path,);
let bytes = fs::read(path).map_err(|_| "fs::read failed.")?;
Decode::decode(&mut &*bytes).map_err(|_| "decode failed")
}
......@@ -407,9 +328,9 @@ impl<B: BlockT> Builder<B> {
.at
.expect("online config must be initialized by this point; qed.")
.clone();
info!(target: LOG_TARGET, "scraping keypairs from remote @ {:?}", at);
info!(target: LOG_TARGET, "scraping key-pairs from remote @ {:?}", at);
let keys_and_values = if config.modules.len() > 0 {
let mut keys_and_values = if config.modules.len() > 0 {
let mut filtered_kv = vec![];
for f in config.modules.iter() {
let hashed_prefix = StorageKey(twox_128(f.as_bytes()).to_vec());
......@@ -429,6 +350,12 @@ impl<B: BlockT> Builder<B> {
self.rpc_get_pairs_paged(StorageKey(vec![]), at).await?
};
for prefix in &self.hashed_prefixes {
info!(target: LOG_TARGET, "adding data for hashed prefix: {:?}", HexDisplay::from(prefix));
let additional_key_values = self.rpc_get_pairs_paged(StorageKey(prefix.to_vec()), at).await?;
keys_and_values.extend(additional_key_values);
}
Ok(keys_and_values)
}
......@@ -491,6 +418,12 @@ impl<B: BlockT> Builder<B> {
self
}
/// Inject a hashed prefix. This is treated as-is, and should be pre-hashed.
pub fn inject_hashed_prefix(mut self, hashed: &[u8]) -> Self {
self.hashed_prefixes.push(hashed.to_vec());
self
}
/// Configure a state snapshot to be used.
pub fn mode(mut self, mode: Mode<B>) -> Self {
self.mode = mode;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment