Follow-up on #1068 (#1567)

* BestParaHead small changes

Signed-off-by: Serban Iorga <serban@parity.io>

* Renamings

Signed-off-by: Serban Iorga <serban@parity.io>

* Use ParaInfo in parachains loop

Signed-off-by: Serban Iorga <serban@parity.io>

* Define StorageMapKeyProvider

Signed-off-by: Serban Iorga <serban@parity.io>

* CR fixes

Signed-off-by: Serban Iorga <serban@parity.io>
This commit is contained in:
Serban Iorga
2022-09-05 13:13:31 +03:00
committed by Bastian Köcher
parent 1c94fbeafc
commit ad38cdb873
6 changed files with 190 additions and 113 deletions
+9 -6
View File
@@ -56,7 +56,7 @@ where
_ => return Ok(ValidTransaction::default()), _ => return Ok(ValidTransaction::default()),
}; };
let maybe_stored_best_head = crate::BestParaHeads::<T, I>::get(parachain); let maybe_stored_best_head = crate::ParasInfo::<T, I>::get(parachain);
Self::validate_updated_parachain_head( Self::validate_updated_parachain_head(
parachain, parachain,
&maybe_stored_best_head, &maybe_stored_best_head,
@@ -72,8 +72,9 @@ mod tests {
use crate::{ use crate::{
extension::FilterCall, extension::FilterCall,
mock::{run_test, Call, TestRuntime}, mock::{run_test, Call, TestRuntime},
BestParaHead, BestParaHeads, RelayBlockNumber, ParaInfo, ParasInfo, RelayBlockNumber,
}; };
use bp_parachains::BestParaHeadHash;
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
fn validate_submit_parachain_heads( fn validate_submit_parachain_heads(
@@ -91,11 +92,13 @@ mod tests {
} }
fn sync_to_relay_header_10() { fn sync_to_relay_header_10() {
BestParaHeads::<TestRuntime, ()>::insert( ParasInfo::<TestRuntime, ()>::insert(
ParaId(1), ParaId(1),
BestParaHead { ParaInfo {
at_relay_block_number: 10, best_head_hash: BestParaHeadHash {
head_hash: [1u8; 32].into(), at_relay_block_number: 10,
head_hash: [1u8; 32].into(),
},
next_imported_hash_position: 0, next_imported_hash_position: 0,
}, },
); );
+103 -77
View File
@@ -26,12 +26,10 @@
pub use weights::WeightInfo; pub use weights::WeightInfo;
pub use weights_ext::WeightInfoExt; pub use weights_ext::WeightInfoExt;
use bp_parachains::parachain_head_storage_key_at_source; use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo};
use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId};
use bp_runtime::StorageProofError; use bp_runtime::StorageProofError;
use codec::{Decode, Encode}; use frame_support::{traits::Contains, weights::PostDispatchInfo};
use frame_support::{traits::Contains, weights::PostDispatchInfo, RuntimeDebug};
use scale_info::TypeInfo;
use sp_runtime::traits::Header as HeaderT; use sp_runtime::traits::Header as HeaderT;
use sp_std::vec::Vec; use sp_std::vec::Vec;
@@ -58,21 +56,10 @@ pub type RelayBlockNumber = bp_polkadot_core::BlockNumber;
/// Hasher of the bridged relay chain. /// Hasher of the bridged relay chain.
pub type RelayBlockHasher = bp_polkadot_core::Hasher; pub type RelayBlockHasher = bp_polkadot_core::Hasher;
/// Best known parachain head as it is stored in the runtime storage.
#[derive(Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)]
pub struct BestParaHead {
/// Number of relay block where this head has been updated.
pub at_relay_block_number: RelayBlockNumber,
/// Hash of parachain head.
pub head_hash: ParaHash,
/// Current ring buffer position for this parachain.
pub next_imported_hash_position: u32,
}
/// Artifacts of the parachains head update. /// Artifacts of the parachains head update.
struct UpdateParachainHeadArtifacts { struct UpdateParachainHeadArtifacts {
/// New best head of the parachain. /// New best head of the parachain.
pub best_head: BestParaHead, pub best_head: ParaInfo,
/// If `true`, some old parachain head has been pruned during update. /// If `true`, some old parachain head has been pruned during update.
pub prune_happened: bool, pub prune_happened: bool,
} }
@@ -80,8 +67,10 @@ struct UpdateParachainHeadArtifacts {
#[frame_support::pallet] #[frame_support::pallet]
pub mod pallet { pub mod pallet {
use super::*; use super::*;
use bp_parachains::ImportedParaHeadsKeyProvider; use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider};
use bp_runtime::{BasicOperatingMode, OwnedBridgeModule, StorageDoubleMapKeyProvider}; use bp_runtime::{
BasicOperatingMode, OwnedBridgeModule, StorageDoubleMapKeyProvider, StorageMapKeyProvider,
};
use frame_support::pallet_prelude::*; use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*; use frame_system::pallet_prelude::*;
@@ -159,10 +148,18 @@ pub mod pallet {
pub type PalletOperatingMode<T: Config<I>, I: 'static = ()> = pub type PalletOperatingMode<T: Config<I>, I: 'static = ()> =
StorageValue<_, BasicOperatingMode, ValueQuery>; StorageValue<_, BasicOperatingMode, ValueQuery>;
/// Best parachain heads. /// Parachains info.
///
/// Contains the following info:
/// - best parachain head hash
/// - the head of the `ImportedParaHashes` ring buffer
#[pallet::storage] #[pallet::storage]
pub type BestParaHeads<T: Config<I>, I: 'static = ()> = pub type ParasInfo<T: Config<I>, I: 'static = ()> = StorageMap<
StorageMap<_, Blake2_128Concat, ParaId, BestParaHead>; _,
<ParasInfoKeyProvider as StorageMapKeyProvider>::Hasher,
<ParasInfoKeyProvider as StorageMapKeyProvider>::Key,
<ParasInfoKeyProvider as StorageMapKeyProvider>::Value,
>;
/// Parachain heads which have been imported into the pallet. /// Parachain heads which have been imported into the pallet.
#[pallet::storage] #[pallet::storage]
@@ -261,7 +258,7 @@ pub mod pallet {
target: LOG_TARGET, target: LOG_TARGET,
"The head of parachain {:?} is None. {}", "The head of parachain {:?} is None. {}",
parachain, parachain,
if BestParaHeads::<T, I>::contains_key(&parachain) { if ParasInfo::<T, I>::contains_key(&parachain) {
"Looks like it is not yet registered at the source relay chain" "Looks like it is not yet registered at the source relay chain"
} else { } else {
"Looks like it has been deregistered from the source relay chain" "Looks like it has been deregistered from the source relay chain"
@@ -294,7 +291,7 @@ pub mod pallet {
continue; continue;
} }
let update_result: Result<_, ()> = BestParaHeads::<T, I>::try_mutate(parachain, |stored_best_head| { let update_result: Result<_, ()> = ParasInfo::<T, I>::try_mutate(parachain, |stored_best_head| {
let artifacts = Pallet::<T, I>::update_parachain_head( let artifacts = Pallet::<T, I>::update_parachain_head(
parachain, parachain,
stored_best_head.take(), stored_best_head.take(),
@@ -348,7 +345,7 @@ pub mod pallet {
impl<T: Config<I>, I: 'static> Pallet<T, I> { impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Get best finalized header of the given parachain. /// Get best finalized header of the given parachain.
pub fn best_parachain_head(parachain: ParaId) -> Option<ParaHead> { pub fn best_parachain_head(parachain: ParaId) -> Option<ParaHead> {
let best_para_head_hash = BestParaHeads::<T, I>::get(parachain)?.head_hash; let best_para_head_hash = ParasInfo::<T, I>::get(parachain)?.best_head_hash.head_hash;
ImportedParaHeads::<T, I>::get(parachain, best_para_head_hash) ImportedParaHeads::<T, I>::get(parachain, best_para_head_hash)
} }
@@ -392,7 +389,7 @@ pub mod pallet {
/// Without this check, we may import heads in random order. /// Without this check, we may import heads in random order.
pub fn validate_updated_parachain_head( pub fn validate_updated_parachain_head(
parachain: ParaId, parachain: ParaId,
maybe_stored_best_head: &Option<BestParaHead>, maybe_stored_best_head: &Option<ParaInfo>,
updated_at_relay_block_number: RelayBlockNumber, updated_at_relay_block_number: RelayBlockNumber,
updated_head_hash: ParaHash, updated_head_hash: ParaHash,
err_log_prefix: &str, err_log_prefix: &str,
@@ -402,26 +399,28 @@ pub mod pallet {
None => return Ok(ValidTransaction::default()), None => return Ok(ValidTransaction::default()),
}; };
if stored_best_head.at_relay_block_number >= updated_at_relay_block_number { if stored_best_head.best_head_hash.at_relay_block_number >=
updated_at_relay_block_number
{
log::trace!( log::trace!(
target: LOG_TARGET, target: LOG_TARGET,
"{}. The parachain head for {:?} was already updated at better relay chain block {} >= {}.", "{}. The parachain head for {:?} was already updated at better relay chain block {} >= {}.",
err_log_prefix, err_log_prefix,
parachain, parachain,
stored_best_head.at_relay_block_number, stored_best_head.best_head_hash.at_relay_block_number,
updated_at_relay_block_number updated_at_relay_block_number
); );
return InvalidTransaction::Stale.into() return InvalidTransaction::Stale.into()
} }
if stored_best_head.head_hash == updated_head_hash { if stored_best_head.best_head_hash.head_hash == updated_head_hash {
log::trace!( log::trace!(
target: LOG_TARGET, target: LOG_TARGET,
"{}. The parachain head hash for {:?} was already updated to {} at block {} < {}.", "{}. The parachain head hash for {:?} was already updated to {} at block {} < {}.",
err_log_prefix, err_log_prefix,
parachain, parachain,
updated_head_hash, updated_head_hash,
stored_best_head.at_relay_block_number, stored_best_head.best_head_hash.at_relay_block_number,
updated_at_relay_block_number updated_at_relay_block_number
); );
return InvalidTransaction::Stale.into() return InvalidTransaction::Stale.into()
@@ -433,7 +432,7 @@ pub mod pallet {
/// Try to update parachain head. /// Try to update parachain head.
pub(super) fn update_parachain_head( pub(super) fn update_parachain_head(
parachain: ParaId, parachain: ParaId,
stored_best_head: Option<BestParaHead>, stored_best_head: Option<ParaInfo>,
updated_at_relay_block_number: RelayBlockNumber, updated_at_relay_block_number: RelayBlockNumber,
updated_head: ParaHead, updated_head: ParaHead,
updated_head_hash: ParaHash, updated_head_hash: ParaHash,
@@ -454,9 +453,11 @@ pub mod pallet {
// insert updated best parachain head // insert updated best parachain head
let head_hash_to_prune = let head_hash_to_prune =
ImportedParaHashes::<T, I>::try_get(parachain, next_imported_hash_position); ImportedParaHashes::<T, I>::try_get(parachain, next_imported_hash_position);
let updated_best_para_head = BestParaHead { let updated_best_para_head = ParaInfo {
at_relay_block_number: updated_at_relay_block_number, best_head_hash: BestParaHeadHash {
head_hash: updated_head_hash, at_relay_block_number: updated_at_relay_block_number,
head_hash: updated_head_hash,
},
next_imported_hash_position: (next_imported_hash_position + 1) % next_imported_hash_position: (next_imported_hash_position + 1) %
T::HeadsToKeep::get(), T::HeadsToKeep::get(),
}; };
@@ -527,9 +528,13 @@ mod tests {
use crate::mock::{ use crate::mock::{
run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID,
}; };
use codec::Encode;
use bp_parachains::ImportedParaHeadsKeyProvider; use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider};
use bp_runtime::{BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider}; use bp_runtime::{
BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider,
StorageMapKeyProvider,
};
use bp_test_utils::{ use bp_test_utils::{
authority_list, generate_owned_bridge_module_tests, make_default_justification, authority_list, generate_owned_bridge_module_tests, make_default_justification,
}; };
@@ -606,10 +611,12 @@ mod tests {
(root, ParaHeadsProof(storage_proof), parachains) (root, ParaHeadsProof(storage_proof), parachains)
} }
fn initial_best_head(parachain: u32) -> BestParaHead { fn initial_best_head(parachain: u32) -> ParaInfo {
BestParaHead { ParaInfo {
at_relay_block_number: 0, best_head_hash: BestParaHeadHash {
head_hash: head_data(parachain, 0).hash(), at_relay_block_number: 0,
head_hash: head_data(parachain, 0).hash(),
},
next_imported_hash_position: 1, next_imported_hash_position: 1,
} }
} }
@@ -697,23 +704,31 @@ mod tests {
assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight));
// but only 1 and 2 are updated, because proof is missing head of parachain#2 // but only 1 and 2 are updated, because proof is missing head of parachain#2
assert_eq!(BestParaHeads::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1))); assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1)));
assert_eq!(BestParaHeads::<TestRuntime>::get(ParaId(2)), None); assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(2)), None);
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::get(ParaId(3)), ParasInfo::<TestRuntime>::get(ParaId(3)),
Some(BestParaHead { Some(ParaInfo {
at_relay_block_number: 0, best_head_hash: BestParaHeadHash {
head_hash: head_data(3, 10).hash(), at_relay_block_number: 0,
head_hash: head_data(3, 10).hash()
},
next_imported_hash_position: 1, next_imported_hash_position: 1,
}) })
); );
assert_eq!( assert_eq!(
ImportedParaHeads::<TestRuntime>::get(ParaId(1), initial_best_head(1).head_hash), ImportedParaHeads::<TestRuntime>::get(
ParaId(1),
initial_best_head(1).best_head_hash.head_hash
),
Some(head_data(1, 0)) Some(head_data(1, 0))
); );
assert_eq!( assert_eq!(
ImportedParaHeads::<TestRuntime>::get(ParaId(2), initial_best_head(2).head_hash), ImportedParaHeads::<TestRuntime>::get(
ParaId(2),
initial_best_head(2).best_head_hash.head_hash
),
None None
); );
assert_eq!( assert_eq!(
@@ -734,10 +749,12 @@ mod tests {
initialize(state_root_5); initialize(state_root_5);
assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5)); assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5));
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::get(ParaId(1)), ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(BestParaHead { Some(ParaInfo {
at_relay_block_number: 0, best_head_hash: BestParaHeadHash {
head_hash: head_data(1, 5).hash(), at_relay_block_number: 0,
head_hash: head_data(1, 5).hash()
},
next_imported_hash_position: 1, next_imported_hash_position: 1,
}) })
); );
@@ -754,10 +771,12 @@ mod tests {
proceed(1, state_root_10); proceed(1, state_root_10);
assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10));
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::get(ParaId(1)), ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(BestParaHead { Some(ParaInfo {
at_relay_block_number: 1, best_head_hash: BestParaHeadHash {
head_hash: head_data(1, 10).hash(), at_relay_block_number: 1,
head_hash: head_data(1, 10).hash()
},
next_imported_hash_position: 2, next_imported_hash_position: 2,
}) })
); );
@@ -797,19 +816,23 @@ mod tests {
assert_ok!(result); assert_ok!(result);
assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight));
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::get(ParaId(1)), ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(BestParaHead { Some(ParaInfo {
at_relay_block_number: 0, best_head_hash: BestParaHeadHash {
head_hash: head_data(1, 5).hash(), at_relay_block_number: 0,
head_hash: head_data(1, 5).hash()
},
next_imported_hash_position: 1, next_imported_hash_position: 1,
}) })
); );
assert_eq!(BestParaHeads::<TestRuntime>::get(ParaId(UNTRACKED_PARACHAIN_ID)), None,); assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(UNTRACKED_PARACHAIN_ID)), None,);
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::get(ParaId(2)), ParasInfo::<TestRuntime>::get(ParaId(2)),
Some(BestParaHead { Some(ParaInfo {
at_relay_block_number: 0, best_head_hash: BestParaHeadHash {
head_hash: head_data(1, 5).hash(), at_relay_block_number: 0,
head_hash: head_data(1, 5).hash()
},
next_imported_hash_position: 1, next_imported_hash_position: 1,
}) })
); );
@@ -824,13 +847,13 @@ mod tests {
// import head#0 of parachain#1 at relay block#0 // import head#0 of parachain#1 at relay block#0
initialize(state_root); initialize(state_root);
assert_ok!(import_parachain_1_head(0, state_root, parachains.clone(), proof.clone())); assert_ok!(import_parachain_1_head(0, state_root, parachains.clone(), proof.clone()));
assert_eq!(BestParaHeads::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1))); assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1)));
// try to import head#0 of parachain#1 at relay block#1 // try to import head#0 of parachain#1 at relay block#1
// => call succeeds, but nothing is changed // => call succeeds, but nothing is changed
proceed(1, state_root); proceed(1, state_root);
assert_ok!(import_parachain_1_head(1, state_root, parachains, proof)); assert_ok!(import_parachain_1_head(1, state_root, parachains, proof));
assert_eq!(BestParaHeads::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1))); assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(1)), Some(initial_best_head(1)));
}); });
} }
@@ -848,10 +871,12 @@ mod tests {
proceed(1, state_root_10); proceed(1, state_root_10);
assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10));
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::get(ParaId(1)), ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(BestParaHead { Some(ParaInfo {
at_relay_block_number: 1, best_head_hash: BestParaHeadHash {
head_hash: head_data(1, 10).hash(), at_relay_block_number: 1,
head_hash: head_data(1, 10).hash()
},
next_imported_hash_position: 1, next_imported_hash_position: 1,
}) })
); );
@@ -860,10 +885,12 @@ mod tests {
// => nothing is changed, because better head has already been imported // => nothing is changed, because better head has already been imported
assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5)); assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5));
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::get(ParaId(1)), ParasInfo::<TestRuntime>::get(ParaId(1)),
Some(BestParaHead { Some(ParaInfo {
at_relay_block_number: 1, best_head_hash: BestParaHeadHash {
head_hash: head_data(1, 10).hash(), at_relay_block_number: 1,
head_hash: head_data(1, 10).hash()
},
next_imported_hash_position: 1, next_imported_hash_position: 1,
}) })
); );
@@ -1003,9 +1030,8 @@ mod tests {
#[test] #[test]
fn storage_keys_computed_properly() { fn storage_keys_computed_properly() {
assert_eq!( assert_eq!(
BestParaHeads::<TestRuntime>::storage_map_final_key(ParaId(42)).to_vec(), ParasInfo::<TestRuntime>::storage_map_final_key(ParaId(42)).to_vec(),
bp_parachains::best_parachain_head_hash_storage_key_at_target("Parachains", ParaId(42)) ParasInfoKeyProvider::final_key("Parachains", &ParaId(42)).0
.0,
); );
assert_eq!( assert_eq!(
+19 -12
View File
@@ -22,7 +22,7 @@ use bp_polkadot_core::{
parachains::{ParaHash, ParaHead, ParaId}, parachains::{ParaHash, ParaHead, ParaId},
BlockNumber as RelayBlockNumber, BlockNumber as RelayBlockNumber,
}; };
use bp_runtime::StorageDoubleMapKeyProvider; use bp_runtime::{StorageDoubleMapKeyProvider, StorageMapKeyProvider};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat}; use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat};
use scale_info::TypeInfo; use scale_info::TypeInfo;
@@ -44,6 +44,15 @@ pub struct BestParaHeadHash {
pub head_hash: ParaHash, pub head_hash: ParaHash,
} }
/// Best known parachain head as it is stored in the runtime storage.
#[derive(Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)]
pub struct ParaInfo {
/// Best known parachain head hash.
pub best_head_hash: BestParaHeadHash,
/// Current ring buffer position for this parachain.
pub next_imported_hash_position: u32,
}
/// Returns runtime storage key of given parachain head at the source chain. /// Returns runtime storage key of given parachain head at the source chain.
/// ///
/// The head is stored by the `paras` pallet in the `Heads` map. /// The head is stored by the `paras` pallet in the `Heads` map.
@@ -54,18 +63,16 @@ pub fn parachain_head_storage_key_at_source(
bp_runtime::storage_map_final_key::<Twox64Concat>(paras_pallet_name, "Heads", &para_id.encode()) bp_runtime::storage_map_final_key::<Twox64Concat>(paras_pallet_name, "Heads", &para_id.encode())
} }
/// Returns runtime storage key of best known parachain head at the target chain. /// Can be use to access the runtime storage key of the parachains info at the target chain.
/// ///
/// The head is stored by the `pallet-bridge-parachains` pallet in the `BestParaHeads` map. /// The info is stored by the `pallet-bridge-parachains` pallet in the `ParasInfo` map.
pub fn best_parachain_head_hash_storage_key_at_target( pub struct ParasInfoKeyProvider;
bridge_parachains_pallet_name: &str, impl StorageMapKeyProvider for ParasInfoKeyProvider {
para_id: ParaId, const MAP_NAME: &'static str = "ParasInfo";
) -> StorageKey {
bp_runtime::storage_map_final_key::<Blake2_128Concat>( type Hasher = Blake2_128Concat;
bridge_parachains_pallet_name, type Key = ParaId;
"BestParaHeads", type Value = ParaInfo;
&para_id.encode(),
)
} }
/// Can be use to access the runtime storage key of the parachain head at the target chain. /// Can be use to access the runtime storage key of the parachain head at the target chain.
+30 -8
View File
@@ -285,20 +285,42 @@ pub fn storage_value_key(pallet_prefix: &str, value_name: &str) -> StorageKey {
StorageKey(final_key) StorageKey(final_key)
} }
/// Can be use to access the runtime storage key of a `StorageDoubleMap`. /// Can be use to access the runtime storage key of a `StorageMap`.
pub trait StorageDoubleMapKeyProvider { pub trait StorageMapKeyProvider {
// The name of the variable that holds the `StorageDoubleMap` /// The name of the variable that holds the `StorageMap`.
const MAP_NAME: &'static str; const MAP_NAME: &'static str;
// The same as `StorageDoubleMap::Hasher1` /// The same as `StorageMap::Hasher1`.
type Hasher: StorageHasher;
/// The same as `StorageMap::Key1`.
type Key: FullCodec;
/// The same as `StorageMap::Value`.
type Value: FullCodec;
/// This is a copy of the
/// `frame_support::storage::generator::StorageMap::storage_map_final_key`.
///
/// We're using it because to call `storage_map_final_key` directly, we need access
/// to the runtime and pallet instance, which (sometimes) is impossible.
fn final_key(pallet_prefix: &str, key: &Self::Key) -> StorageKey {
storage_map_final_key::<Self::Hasher>(pallet_prefix, Self::MAP_NAME, &key.encode())
}
}
/// Can be use to access the runtime storage key of a `StorageDoubleMap`.
pub trait StorageDoubleMapKeyProvider {
/// The name of the variable that holds the `StorageDoubleMap`.
const MAP_NAME: &'static str;
/// The same as `StorageDoubleMap::Hasher1`.
type Hasher1: StorageHasher; type Hasher1: StorageHasher;
// The same as `StorageDoubleMap::Key1` /// The same as `StorageDoubleMap::Key1`.
type Key1: FullCodec; type Key1: FullCodec;
// The same as `StorageDoubleMap::Hasher2` /// The same as `StorageDoubleMap::Hasher2`.
type Hasher2: StorageHasher; type Hasher2: StorageHasher;
// The same as `StorageDoubleMap::Key2` /// The same as `StorageDoubleMap::Key2`.
type Key2: FullCodec; type Key2: FullCodec;
// The same as `StorageDoubleMap::Value` /// The same as `StorageDoubleMap::Value`.
type Value: FullCodec; type Value: FullCodec;
/// This is a copy of the /// This is a copy of the
+18 -1
View File
@@ -29,7 +29,7 @@ use crate::{
use async_std::sync::{Arc, Mutex}; use async_std::sync::{Arc, Mutex};
use async_trait::async_trait; use async_trait::async_trait;
use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider}; use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider, StorageMapKeyProvider};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_system::AccountInfo; use frame_system::AccountInfo;
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
@@ -320,6 +320,23 @@ impl<C: Chain> Client<C> {
.transpose() .transpose()
} }
/// Read `MapStorage` value from runtime storage.
pub async fn storage_map_value<T: StorageMapKeyProvider>(
&self,
pallet_prefix: &str,
key: &T::Key,
block_hash: Option<C::Hash>,
) -> Result<Option<T::Value>> {
let storage_key = T::final_key(pallet_prefix, key);
self.raw_storage_value(storage_key, block_hash)
.await?
.map(|encoded_value| {
T::Value::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)
})
.transpose()
}
/// Read `DoubleMapStorage` value from runtime storage. /// Read `DoubleMapStorage` value from runtime storage.
pub async fn storage_double_map_value<T: StorageDoubleMapKeyProvider>( pub async fn storage_double_map_value<T: StorageDoubleMapKeyProvider>(
&self, &self,
@@ -24,9 +24,7 @@ use crate::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use bp_parachains::{ use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider};
best_parachain_head_hash_storage_key_at_target, BestParaHeadHash, ImportedParaHeadsKeyProvider,
};
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
use bp_runtime::HeaderIdProvider; use bp_runtime::HeaderIdProvider;
use codec::Decode; use codec::Decode;
@@ -122,12 +120,16 @@ where
metrics: Option<&ParachainsLoopMetrics>, metrics: Option<&ParachainsLoopMetrics>,
para_id: ParaId, para_id: ParaId,
) -> Result<Option<BestParaHeadHash>, Self::Error> { ) -> Result<Option<BestParaHeadHash>, Self::Error> {
let best_para_head_hash_key = best_parachain_head_hash_storage_key_at_target( let best_para_head_hash: Option<BestParaHeadHash> = self
P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, .client
para_id, .storage_map_value::<ParasInfoKeyProvider>(
); P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME,
let best_para_head_hash: Option<BestParaHeadHash> = &para_id,
self.client.storage_value(best_para_head_hash_key, Some(at_block.1)).await?; Some(at_block.1),
)
.await?
.map(|para_info| para_info.best_head_hash);
if let (Some(metrics), &Some(ref best_para_head_hash)) = (metrics, &best_para_head_hash) { if let (Some(metrics), &Some(ref best_para_head_hash)) = (metrics, &best_para_head_hash) {
let imported_para_head = self let imported_para_head = self
.client .client