Migrate remaining old decl_* macros to the new pallet attribute macros (#12271)

* Migrate remaining old decl_* macros to the new pallet attribute macros

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Apply review suggestions

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Apply review suggestions

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* use pallet::storage

* Fix dev rpc test

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Fix service tests

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

Signed-off-by: koushiro <koushiro.cqx@gmail.com>
This commit is contained in:
Qinxuan Chen
2022-09-22 16:53:51 +08:00
committed by GitHub
parent 8a43b42ab1
commit a395fec070
10 changed files with 206 additions and 107 deletions
+2
View File
@@ -10522,6 +10522,8 @@ dependencies = [
"sc-rpc-api",
"scale-info",
"serde",
"sp-core",
"sp-runtime",
"sp-storage",
"tokio",
]
+2 -2
View File
@@ -43,8 +43,8 @@ async fn block_stats_work() {
.await
.unwrap(),
Some(BlockStats {
witness_len: 597,
witness_compact_len: 500,
witness_len: 630,
witness_compact_len: 534,
block_len: 99,
num_extrinsics: 0,
}),
@@ -1663,7 +1663,7 @@ fn storage_keys_iter_works() {
let res: Vec<_> = client
.storage_keys_iter(&BlockId::Number(0), Some(&prefix), None)
.unwrap()
.take(8)
.take(9)
.map(|x| array_bytes::bytes2hex("", &x.0))
.collect();
assert_eq!(
@@ -1675,6 +1675,7 @@ fn storage_keys_iter_works() {
"1a560ecfd2a62c2b8521ef149d0804eb621050e3988ed97dca55f0d7c3e6aa34",
"1d66850d32002979d67dd29dc583af5b2ae2a1f71c1f35ad90fff122be7a3824",
"237498b98d8803334286e9f0483ef513098dd3c1c22ca21c4dc155b4ef6cc204",
"26aa394eea5630e07c48ae0c9558cef75e0621c4869aa60c02be9adcc98a0d1d",
"29b9db10ec5bf7907d8f74b5e60aa8140c4fbdd8127a1ee5600cb98e5ec01729",
"3a636f6465",
]
@@ -1699,7 +1700,7 @@ fn storage_keys_iter_works() {
"5c2d5fda66373dabf970e4fb13d277ce91c5233473321129d32b5a8085fa8133",
"6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081",
"66484000ed3f75c95fc7b03f39c20ca1e1011e5999278247d3b2f5e3c3273808",
"79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d",
"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
]
);
@@ -1708,7 +1709,7 @@ fn storage_keys_iter_works() {
&BlockId::Number(0),
Some(&prefix),
Some(&StorageKey(array_bytes::hex2bytes_unchecked(
"79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d",
"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
))),
)
.unwrap()
@@ -1718,11 +1719,11 @@ fn storage_keys_iter_works() {
assert_eq!(
res,
[
"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
"811ecfaadcf5f2ee1d67393247e2f71a1662d433e8ce7ff89fb0d4aa9561820b",
"a93d74caa7ec34ea1b04ce1e5c090245f867d333f0f88278a451e45299654dc5",
"a9ee1403384afbfc13f13be91ff70bfac057436212e53b9733914382ac942892",
"cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f",
"e3b47b6c84c0493481f97c5197d2554f",
]
);
}
+4 -4
View File
@@ -36,7 +36,7 @@ mod pallet_test {
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
pub struct Pallet<T>(PhantomData<T>);
#[pallet::config]
pub trait Config: frame_system::Config {
@@ -46,21 +46,21 @@ mod pallet_test {
}
#[pallet::storage]
#[pallet::getter(fn heartbeat_after)]
#[pallet::getter(fn value)]
pub(crate) type Value<T: Config> = StorageValue<_, u32, OptionQuery>;
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(0)]
pub fn set_value(origin: OriginFor<T>, n: u32) -> DispatchResult {
let _sender = frame_system::ensure_signed(origin)?;
let _sender = ensure_signed(origin)?;
Value::<T>::put(n);
Ok(())
}
#[pallet::weight(0)]
pub fn dummy(origin: OriginFor<T>, _n: u32) -> DispatchResult {
let _sender = frame_system::ensure_none(origin)?;
let _sender = ensure_none(origin)?;
Ok(())
}
@@ -28,48 +28,52 @@ use sp_runtime::{
};
use sp_std::prelude::*;
#[frame_support::pallet]
mod pallet_test {
use frame_support::pallet_prelude::Get;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
frame_support::decl_storage! {
trait Store for Module<T: Config<I>, I: Instance = DefaultInstance> as Test where
<T as OtherConfig>::OtherEvent: Into<<T as Config<I>>::RuntimeEvent>
{
pub Value get(fn value): Option<u32>;
}
}
frame_support::decl_module! {
pub struct Module<T: Config<I>, I: Instance = DefaultInstance> for enum Call where
origin: T::RuntimeOrigin, <T as OtherConfig>::OtherEvent: Into<<T as Config<I>>::RuntimeEvent>
{
#[weight = 0]
fn set_value(origin, n: u32) -> frame_support::dispatch::DispatchResult {
let _sender = frame_system::ensure_signed(origin)?;
Value::<I>::put(n);
Ok(())
}
#[weight = 0]
fn dummy(origin, _n: u32) -> frame_support::dispatch::DispatchResult {
let _sender = frame_system::ensure_none(origin)?;
Ok(())
}
}
}
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
pub trait OtherConfig {
type OtherEvent;
}
pub trait Config<I: Instance = DefaultInstance>: frame_system::Config + OtherConfig
where
Self::OtherEvent: Into<<Self as Config<I>>::RuntimeEvent>,
{
type RuntimeEvent;
#[pallet::config]
pub trait Config<I: 'static = ()>: frame_system::Config + OtherConfig {
type RuntimeEvent: From<Event<Self, I>>
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;
type LowerBound: Get<u32>;
type UpperBound: Get<u32>;
}
#[pallet::storage]
#[pallet::getter(fn value)]
pub(crate) type Value<T: Config<I>, I: 'static = ()> = StorageValue<_, u32, OptionQuery>;
#[pallet::event]
pub enum Event<T: Config<I>, I: 'static = ()> {}
#[pallet::call]
impl<T: Config<I>, I: 'static> Pallet<T, I>
where
<T as OtherConfig>::OtherEvent: Into<<T as Config<I>>::RuntimeEvent>,
{
#[pallet::weight(0)]
pub fn set_value(origin: OriginFor<T>, n: u32) -> DispatchResult {
let _sender = ensure_signed(origin)?;
Value::<T, I>::put(n);
Ok(())
}
#[pallet::weight(0)]
pub fn dummy(origin: OriginFor<T>, _n: u32) -> DispatchResult {
let _sender = ensure_none(origin)?;
Ok(())
}
}
}
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
@@ -82,7 +86,7 @@ frame_support::construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
TestPallet: pallet_test::{Pallet, Call, Storage},
TestPallet: pallet_test::{Pallet, Call, Storage, Event<T>},
}
);
@@ -90,18 +94,18 @@ impl frame_system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type RuntimeCall = RuntimeCall;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = ();
type DbWeight = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
@@ -110,7 +114,7 @@ impl frame_system::Config for Test {
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
type MaxConsumers = ConstU32<16>;
}
impl pallet_test::Config for Test {
@@ -130,15 +134,14 @@ fn new_test_ext() -> sp_io::TestExternalities {
mod benchmarks {
use super::pallet_test::{self, Value};
use crate::account;
use frame_support::{ensure, StorageValue};
use frame_support::ensure;
use frame_system::RawOrigin;
use sp_std::prelude::*;
// Additional used internally by the benchmark macro.
use super::pallet_test::{Call, Config, Pallet};
use frame_support::traits::Instance;
crate::benchmarks_instance! {
crate::benchmarks_instance_pallet! {
where_clause {
where
<T as pallet_test::OtherConfig>::OtherEvent: Clone
@@ -151,7 +154,7 @@ mod benchmarks {
let caller = account::<T::AccountId>("caller", 0, 0);
}: _ (RawOrigin::Signed(caller), b.into())
verify {
assert_eq!(Value::<pallet_test::DefaultInstance>::get(), Some(b));
assert_eq!(Value::<T, I>::get(), Some(b));
}
other_name {
@@ -17,8 +17,9 @@
//! Tool for creating the genesis block.
use super::{system, wasm_binary_unwrap, AccountId, AuthorityId};
use super::{system, wasm_binary_unwrap, AccountId, AuthorityId, Runtime};
use codec::{Encode, Joiner, KeyedVec};
use frame_support::traits::GenesisBuild;
use sc_service::client::genesis;
use sp_core::{
map,
@@ -80,10 +81,11 @@ impl GenesisConfig {
// Assimilate the system genesis config.
let mut storage =
Storage { top: map, children_default: self.extra_storage.children_default.clone() };
let config = system::GenesisConfig { authorities: self.authorities.clone() };
config
.assimilate_storage(&mut storage)
.expect("Adding `system::GensisConfig` to the genesis");
<system::GenesisConfig as GenesisBuild<Runtime>>::assimilate_storage(
&system::GenesisConfig { authorities: self.authorities.clone() },
&mut storage,
)
.expect("Adding `system::GensisConfig` to the genesis");
storage
}
+2
View File
@@ -610,6 +610,8 @@ impl frame_system::Config for Runtime {
type MaxConsumers = ConstU32<16>;
}
impl system::Config for Runtime {}
impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
+65 -32
View File
@@ -19,11 +19,11 @@
//! and depositing logs.
use crate::{
AccountId, AuthorityId, Block, BlockNumber, Digest, Extrinsic, Header, Transfer, H256 as Hash,
AccountId, AuthorityId, Block, BlockNumber, Digest, Extrinsic, Header, Runtime, Transfer,
H256 as Hash,
};
use codec::{Decode, Encode, KeyedVec};
use frame_support::{decl_module, decl_storage, storage};
use frame_system::Config;
use frame_support::storage;
use sp_core::storage::well_known_keys;
use sp_io::{hashing::blake2_256, storage::root as storage_root, trie};
use sp_runtime::{
@@ -39,19 +39,51 @@ use sp_std::prelude::*;
const NONCE_OF: &[u8] = b"nonce:";
const BALANCE_OF: &[u8] = b"balance:";
decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin {}
}
pub use self::pallet::*;
decl_storage! {
trait Store for Module<T: Config> as TestRuntime {
ExtrinsicData: map hasher(blake2_128_concat) u32 => Vec<u8>;
// The current block number being processed. Set by `execute_block`.
Number get(fn number): Option<BlockNumber>;
ParentHash get(fn parent_hash): Hash;
NewAuthorities get(fn new_authorities): Option<Vec<AuthorityId>>;
StorageDigest get(fn storage_digest): Option<Digest>;
Authorities get(fn authorities) config(): Vec<AuthorityId>;
#[frame_support::pallet]
mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::without_storage_info]
pub struct Pallet<T>(PhantomData<T>);
#[pallet::config]
pub trait Config: frame_system::Config {}
#[pallet::storage]
pub type ExtrinsicData<T> = StorageMap<_, Blake2_128Concat, u32, Vec<u8>, ValueQuery>;
// The current block number being processed. Set by `execute_block`.
#[pallet::storage]
pub type Number<T> = StorageValue<_, BlockNumber, OptionQuery>;
#[pallet::storage]
pub type ParentHash<T> = StorageValue<_, Hash, ValueQuery>;
#[pallet::storage]
pub type NewAuthorities<T> = StorageValue<_, Vec<AuthorityId>, OptionQuery>;
#[pallet::storage]
pub type StorageDigest<T> = StorageValue<_, Digest, OptionQuery>;
#[pallet::storage]
pub type Authorities<T> = StorageValue<_, Vec<AuthorityId>, ValueQuery>;
#[pallet::genesis_config]
#[cfg_attr(feature = "std", derive(Default))]
pub struct GenesisConfig {
pub authorities: Vec<AuthorityId>,
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
<Authorities<T>>::put(self.authorities.clone());
}
}
}
@@ -69,9 +101,9 @@ pub fn nonce_of(who: AccountId) -> u64 {
pub fn initialize_block(header: &Header) {
// populate environment.
<Number>::put(&header.number);
<ParentHash>::put(&header.parent_hash);
<StorageDigest>::put(header.digest());
<Number<Runtime>>::put(&header.number);
<ParentHash<Runtime>>::put(&header.parent_hash);
<StorageDigest<Runtime>>::put(header.digest());
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32);
// try to read something that depends on current header digest
@@ -82,15 +114,15 @@ pub fn initialize_block(header: &Header) {
}
pub fn authorities() -> Vec<AuthorityId> {
Authorities::get()
<Authorities<Runtime>>::get()
}
pub fn get_block_number() -> Option<BlockNumber> {
Number::get()
<Number<Runtime>>::get()
}
pub fn take_block_number() -> Option<BlockNumber> {
Number::take()
<Number<Runtime>>::take()
}
#[derive(Copy, Clone)]
@@ -124,8 +156,8 @@ fn execute_block_with_state_root_handler(block: &mut Block, mode: Mode) -> Heade
header.state_root = new_header.state_root;
} else {
info_expect_equal_hash(&new_header.state_root, &header.state_root);
assert!(
new_header.state_root == header.state_root,
assert_eq!(
new_header.state_root, header.state_root,
"Storage root must match that calculated.",
);
}
@@ -134,8 +166,8 @@ fn execute_block_with_state_root_handler(block: &mut Block, mode: Mode) -> Heade
header.extrinsics_root = new_header.extrinsics_root;
} else {
info_expect_equal_hash(&new_header.extrinsics_root, &header.extrinsics_root);
assert!(
new_header.extrinsics_root == header.extrinsics_root,
assert_eq!(
new_header.extrinsics_root, header.extrinsics_root,
"Transaction trie root must be valid.",
);
}
@@ -187,7 +219,7 @@ pub fn execute_transaction(utx: Extrinsic) -> ApplyExtrinsicResult {
let extrinsic_index: u32 =
storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap_or_default();
let result = execute_transaction_backend(&utx, extrinsic_index);
ExtrinsicData::insert(extrinsic_index, utx.encode());
<ExtrinsicData<Runtime>>::insert(extrinsic_index, utx.encode());
storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(extrinsic_index + 1));
result
}
@@ -196,13 +228,14 @@ pub fn execute_transaction(utx: Extrinsic) -> ApplyExtrinsicResult {
pub fn finalize_block() -> Header {
use sp_core::storage::StateVersion;
let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap();
let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect();
let txs: Vec<_> = (0..extrinsic_index).map(<ExtrinsicData<Runtime>>::take).collect();
let extrinsics_root = trie::blake2_256_ordered_root(txs, StateVersion::V0);
let number = <Number>::take().expect("Number is set by `initialize_block`");
let parent_hash = <ParentHash>::take();
let mut digest = <StorageDigest>::take().expect("StorageDigest is set by `initialize_block`");
let number = <Number<Runtime>>::take().expect("Number is set by `initialize_block`");
let parent_hash = <ParentHash<Runtime>>::take();
let mut digest =
<StorageDigest<Runtime>>::take().expect("StorageDigest is set by `initialize_block`");
let o_new_authorities = <NewAuthorities>::take();
let o_new_authorities = <NewAuthorities<Runtime>>::take();
// This MUST come after all changes to storage are done. Otherwise we will fail the
// “Storage root does not match that calculated” assertion.
@@ -280,7 +313,7 @@ fn execute_store(data: Vec<u8>) -> ApplyExtrinsicResult {
}
fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyExtrinsicResult {
NewAuthorities::put(new_authorities.to_vec());
<NewAuthorities<Runtime>>::put(new_authorities.to_vec());
Ok(Ok(()))
}
@@ -27,4 +27,6 @@ sp-storage = { version = "6.0.0", path = "../../../../primitives/storage" }
scale-info = "2.1.1"
jsonrpsee = { version = "0.15.1", features = ["ws-client", "jsonrpsee-types"] }
tokio = "1.17.0"
sp-core = { version = "6.0.0", path = "../../../../primitives/core" }
sp-runtime = { version = "6.0.0", path = "../../../../primitives/runtime" }
frame-system = { version = "4.0.0-dev", path = "../../../../frame/system" }
+74 -20
View File
@@ -34,50 +34,104 @@ use sp_storage::{StorageData, StorageKey};
/// # use jsonrpsee::core::Error as RpcError;
/// # use jsonrpsee::ws_client::WsClientBuilder;
/// # use codec::Encode;
/// # use frame_support::{decl_storage, decl_module};
/// # use frame_support::{construct_runtime, traits::ConstU32};
/// # use substrate_frame_rpc_support::StorageQuery;
/// # use frame_system::Config;
/// # use sc_rpc_api::state::StateApiClient;
/// # use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::Header};
/// #
/// # // Hash would normally be <TestRuntime as frame_system::Config>::Hash, but we don't have
/// # // frame_system::Config implemented for TestRuntime. Here we just pretend.
/// # type Hash = ();
/// # construct_runtime!(
/// # pub enum TestRuntime where
/// # Block = frame_system::mocking::MockBlock<TestRuntime>,
/// # NodeBlock = frame_system::mocking::MockBlock<TestRuntime>,
/// # UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>,
/// # {
/// # System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
/// # Test: pallet_test::{Pallet, Storage},
/// # }
/// # );
/// #
/// # type Hash = sp_core::H256;
/// #
/// # struct TestRuntime;
/// #
/// # decl_module! {
/// # pub struct Module<T: Config> for enum Call where origin: T::RuntimeOrigin {}
/// # impl frame_system::Config for TestRuntime {
/// # type BaseCallFilter = ();
/// # type BlockWeights = ();
/// # type BlockLength = ();
/// # type RuntimeOrigin = RuntimeOrigin;
/// # type RuntimeCall = RuntimeCall;
/// # type Index = u64;
/// # type BlockNumber = u64;
/// # type Hash = Hash;
/// # type Hashing = BlakeTwo256;
/// # type AccountId = u64;
/// # type Lookup = IdentityLookup<Self::AccountId>;
/// # type Header = Header;
/// # type RuntimeEvent = RuntimeEvent;
/// # type BlockHashCount = ();
/// # type DbWeight = ();
/// # type Version = ();
/// # type PalletInfo = PalletInfo;
/// # type AccountData = ();
/// # type OnNewAccount = ();
/// # type OnKilledAccount = ();
/// # type SystemWeightInfo = ();
/// # type SS58Prefix = ();
/// # type OnSetCode = ();
/// # type MaxConsumers = ConstU32<16>;
/// # }
/// #
/// # impl pallet_test::Config for TestRuntime {}
/// #
///
/// pub type Loc = (i64, i64, i64);
/// pub type Block = u8;
///
/// // Note that all fields are marked pub.
/// decl_storage! {
/// trait Store for Module<T: Config> as TestRuntime {
/// pub LastActionId: u64;
/// pub Voxels: map hasher(blake2_128_concat) Loc => Block;
/// pub Actions: map hasher(blake2_128_concat) u64 => Loc;
/// pub Prefab: double_map hasher(blake2_128_concat) u128, hasher(blake2_128_concat) (i8, i8, i8) => Block;
/// }
/// pub use self::pallet_test::*;
///
/// #[frame_support::pallet]
/// mod pallet_test {
/// use super::*;
/// use frame_support::pallet_prelude::*;
///
/// #[pallet::pallet]
/// #[pallet::generate_store(pub(super) trait Store)]
/// pub struct Pallet<T>(PhantomData<T>);
///
/// #[pallet::config]
/// pub trait Config: frame_system::Config {}
///
/// #[pallet::storage]
/// pub type LastActionId<T> = StorageValue<_, u64, ValueQuery>;
///
/// #[pallet::storage]
/// pub type Voxels<T> = StorageMap<_, Blake2_128Concat, Loc, Block>;
///
/// #[pallet::storage]
/// pub type Actions<T> = StorageMap<_, Blake2_128Concat, u64, Loc>;
///
/// #[pallet::storage]
/// pub type Prefab<T> = StorageDoubleMap<
/// _,
/// Blake2_128Concat, u128,
/// Blake2_128Concat, (i8, i8, i8), Block
/// >;
/// }
///
/// #[tokio::main]
/// async fn main() -> Result<(), RpcError> {
/// let cl = WsClientBuilder::default().build("ws://[::1]:9944").await?;
///
/// let q = StorageQuery::value::<LastActionId>();
/// let q = StorageQuery::value::<LastActionId<TestRuntime>>();
/// let hash = None::<Hash>;
/// let _: Option<u64> = q.get(&cl, hash).await?;
///
/// let q = StorageQuery::map::<Voxels, _>((0, 0, 0));
/// let q = StorageQuery::map::<Voxels<TestRuntime>, _>((0, 0, 0));
/// let _: Option<Block> = q.get(&cl, hash).await?;
///
/// let q = StorageQuery::map::<Actions, _>(12);
/// let q = StorageQuery::map::<Actions<TestRuntime>, _>(12);
/// let _: Option<Loc> = q.get(&cl, hash).await?;
///
/// let q = StorageQuery::double_map::<Prefab, _, _>(3, (0, 0, 0));
/// let q = StorageQuery::double_map::<Prefab<TestRuntime>, _, _>(3, (0, 0, 0));
/// let _: Option<Block> = q.get(&cl, hash).await?;
///
/// Ok(())