mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 22:11:02 +00:00
* 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:
committed by
Bastian Köcher
parent
1c94fbeafc
commit
ad38cdb873
@@ -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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 10,
|
at_relay_block_number: 10,
|
||||||
head_hash: [1u8; 32].into(),
|
head_hash: [1u8; 32].into(),
|
||||||
|
},
|
||||||
next_imported_hash_position: 0,
|
next_imported_hash_position: 0,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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(¶chain) {
|
if ParasInfo::<T, I>::contains_key(¶chain) {
|
||||||
"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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: updated_at_relay_block_number,
|
at_relay_block_number: updated_at_relay_block_number,
|
||||||
head_hash: updated_head_hash,
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 0,
|
at_relay_block_number: 0,
|
||||||
head_hash: head_data(parachain, 0).hash(),
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 0,
|
at_relay_block_number: 0,
|
||||||
head_hash: head_data(3, 10).hash(),
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 0,
|
at_relay_block_number: 0,
|
||||||
head_hash: head_data(1, 5).hash(),
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 1,
|
at_relay_block_number: 1,
|
||||||
head_hash: head_data(1, 10).hash(),
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 0,
|
at_relay_block_number: 0,
|
||||||
head_hash: head_data(1, 5).hash(),
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 0,
|
at_relay_block_number: 0,
|
||||||
head_hash: head_data(1, 5).hash(),
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 1,
|
at_relay_block_number: 1,
|
||||||
head_hash: head_data(1, 10).hash(),
|
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 {
|
||||||
|
best_head_hash: BestParaHeadHash {
|
||||||
at_relay_block_number: 1,
|
at_relay_block_number: 1,
|
||||||
head_hash: head_data(1, 10).hash(),
|
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!(
|
||||||
|
|||||||
@@ -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", ¶_id.encode())
|
bp_runtime::storage_map_final_key::<Twox64Concat>(paras_pallet_name, "Heads", ¶_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;
|
||||||
¶_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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
.client
|
||||||
|
.storage_map_value::<ParasInfoKeyProvider>(
|
||||||
P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME,
|
P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME,
|
||||||
para_id,
|
¶_id,
|
||||||
);
|
Some(at_block.1),
|
||||||
let best_para_head_hash: Option<BestParaHeadHash> =
|
)
|
||||||
self.client.storage_value(best_para_head_hash_key, Some(at_block.1)).await?;
|
.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
|
||||||
|
|||||||
Reference in New Issue
Block a user