Skip to content
Snippets Groups Projects
Commit 83de3b7d authored by asynchronous rob's avatar asynchronous rob Committed by GitHub
Browse files

Relay-parent digest logs for parachains (#2552)


* add digest item for relay-parent to primitives

* add a relay-parent-storage-root digest as a workaround

* more docs

* deposit log in pallet-parachain-system

* even more docs

* fix duplicate imports after botched mertge

* fix hyperlinks in docs

* clean up match

Co-authored-by: default avatarBastian Köcher <git@kchr.de>

* improve docs

* fix typo

* add number to the digest item

---------

Co-authored-by: default avatarBastian Köcher <git@kchr.de>
parent 0bab3ce6
Branches
No related merge requests found
...@@ -385,6 +385,16 @@ pub mod pallet { ...@@ -385,6 +385,16 @@ pub mod pallet {
) )
.expect("Invalid relay chain state proof"); .expect("Invalid relay chain state proof");
// Deposit a log indicating the relay-parent storage root.
// TODO: remove this in favor of the relay-parent's hash after
// https://github.com/paritytech/cumulus/issues/303
frame_system::Pallet::<T>::deposit_log(
cumulus_primitives_core::rpsr_digest::relay_parent_storage_root_item(
vfp.relay_parent_storage_root,
vfp.relay_parent_number,
),
);
// initialization logic: we know that this runs exactly once every block, // initialization logic: we know that this runs exactly once every block,
// which means we can put the initialization logic here to remove the // which means we can put the initialization logic here to remove the
// sequencing problem. // sequencing problem.
......
...@@ -1006,3 +1006,18 @@ fn upgrade_version_checks_should_work() { ...@@ -1006,3 +1006,18 @@ fn upgrade_version_checks_should_work() {
}); });
} }
} }
#[test]
fn deposits_relay_parent_storage_root() {
BlockTests::new().add_with_post_test(
123,
|| {},
|| {
let digest = System::digest();
assert!(cumulus_primitives_core::rpsr_digest::extract_relay_parent_storage_root(
&digest
)
.is_some());
},
);
}
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use polkadot_parachain::primitives::HeadData; use polkadot_parachain::primitives::HeadData;
use scale_info::TypeInfo; use scale_info::TypeInfo;
use sp_runtime::{traits::Block as BlockT, RuntimeDebug}; use sp_runtime::RuntimeDebug;
use sp_std::prelude::*; use sp_std::prelude::*;
pub use polkadot_core_primitives::InboundDownwardMessage; pub use polkadot_core_primitives::InboundDownwardMessage;
...@@ -33,6 +33,12 @@ pub use polkadot_primitives::{ ...@@ -33,6 +33,12 @@ pub use polkadot_primitives::{
AbridgedHostConfiguration, AbridgedHrmpChannel, PersistedValidationData, AbridgedHostConfiguration, AbridgedHrmpChannel, PersistedValidationData,
}; };
pub use sp_runtime::{
generic::{Digest, DigestItem},
traits::Block as BlockT,
ConsensusEngineId,
};
pub use xcm::latest::prelude::*; pub use xcm::latest::prelude::*;
/// A module that re-exports relevant relay chain definitions. /// A module that re-exports relevant relay chain definitions.
...@@ -198,6 +204,88 @@ impl<B: BlockT> ParachainBlockData<B> { ...@@ -198,6 +204,88 @@ impl<B: BlockT> ParachainBlockData<B> {
} }
} }
/// A consensus engine ID indicating that this is a Cumulus Parachain.
pub const CUMULUS_CONSENSUS_ID: ConsensusEngineId = *b"CMLS";
/// Consensus header digests for Cumulus parachains.
#[derive(Clone, RuntimeDebug, Decode, Encode, PartialEq)]
pub enum CumulusDigestItem {
/// A digest item indicating the relay-parent a parachain block was built against.
#[codec(index = 0)]
RelayParent(relay_chain::Hash),
}
impl CumulusDigestItem {
/// Encode this as a Substrate [`DigestItem`].
pub fn to_digest_item(&self) -> DigestItem {
DigestItem::Consensus(CUMULUS_CONSENSUS_ID, self.encode())
}
}
/// Extract the relay-parent from the provided header digest. Returns `None` if none were found.
///
/// If there are multiple valid digests, this returns the value of the first one, although
/// well-behaving runtimes should not produce headers with more than one.
pub fn extract_relay_parent(digest: &Digest) -> Option<relay_chain::Hash> {
digest.convert_first(|d| match d {
DigestItem::Consensus(id, val) if id == &CUMULUS_CONSENSUS_ID =>
match CumulusDigestItem::decode(&mut &val[..]) {
Ok(CumulusDigestItem::RelayParent(hash)) => Some(hash),
_ => None,
},
_ => None,
})
}
/// Utilities for handling the relay-parent storage root as a digest item.
///
/// This is not intended to be part of the public API, as it is a workaround for
/// <https://github.com/paritytech/cumulus/issues/303> via
/// <https://github.com/paritytech/polkadot/issues/7191>.
///
/// Runtimes using the parachain-system pallet are expected to produce this digest item,
/// but will stop as soon as they are able to provide the relay-parent hash directly.
///
/// The relay-chain storage root is, in practice, a unique identifier of a block
/// in the absence of equivocations (which are slashable). This assumes that the relay chain
/// uses BABE or SASSAFRAS, because the slot and the author's VRF randomness are both included
/// in the relay-chain storage root in both cases.
///
/// Therefore, the relay-parent storage root is a suitable identifier of unique relay chain
/// blocks in low-value scenarios such as performance optimizations.
#[doc(hidden)]
pub mod rpsr_digest {
use super::{relay_chain, ConsensusEngineId, Decode, Digest, DigestItem, Encode};
use codec::Compact;
/// A consensus engine ID for relay-parent storage root digests.
pub const RPSR_CONSENSUS_ID: ConsensusEngineId = *b"RPSR";
/// Construct a digest item for relay-parent storage roots.
pub fn relay_parent_storage_root_item(
storage_root: relay_chain::Hash,
number: impl Into<Compact<relay_chain::BlockNumber>>,
) -> DigestItem {
DigestItem::Consensus(RPSR_CONSENSUS_ID, (storage_root, number.into()).encode())
}
/// Extract the relay-parent storage root and number from the provided header digest. Returns `None`
/// if none were found.
pub fn extract_relay_parent_storage_root(
digest: &Digest,
) -> Option<(relay_chain::Hash, relay_chain::BlockNumber)> {
digest.convert_first(|d| match d {
DigestItem::Consensus(id, val) if id == &RPSR_CONSENSUS_ID => {
let (h, n): (relay_chain::Hash, Compact<relay_chain::BlockNumber>) =
Decode::decode(&mut &val[..]).ok()?;
Some((h, n.0))
},
_ => None,
})
}
}
/// Information about a collation. /// Information about a collation.
/// ///
/// This was used in version 1 of the [`CollectCollationInfo`] runtime api. /// This was used in version 1 of the [`CollectCollationInfo`] runtime api.
......
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