Skip to content

Commit

Permalink
Implement solochain state proofs
Browse files Browse the repository at this point in the history
  • Loading branch information
tmpolaczyk committed Aug 22, 2024
1 parent 87a34ef commit 6021f39
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 13 deletions.
42 changes: 32 additions & 10 deletions container-chain-pallets/authorities-noting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,26 @@ pub mod pallet {

let relay_storage_root =
T::RelayChainStateProvider::current_relay_chain_state().state_root;

let para_id = OrchestratorParaId::<T>::get();
let relay_chain_state_proof =
GenericStateProof::new(relay_storage_root, relay_chain_state_proof)
.expect("Invalid relay chain state proof");

// Fetch authorities
let authorities = {
// This pallet needs to support both solochains like starlight and parachains like
// dancebox without any config changes because we want the templates to work on both.
// To detect whether we should fetch authorities from the orchestrator state proof or
// from the relay state proof, we use an empty orchestrator_chain_state_proof as a
// sentinel value to indicate that this container chain is running under a solochain.
let authorities = if orchestrator_chain_state_proof.is_empty() {
// starlight: need to fetch authorities from relay state proof
Self::fetch_authorities_from_proof(
&relay_chain_state_proof,
T::SelfParaId::get(),
true,
)
} else {
// dancebox: need to fetch orchestrator state root from paras->heads, and then fetch
// authorities from the orchestrator state proof
let para_id = OrchestratorParaId::<T>::get();
let orchestrator_root = Self::fetch_orchestrator_header_from_relay_proof(
&relay_chain_state_proof,
para_id,
Expand All @@ -193,9 +205,10 @@ pub mod pallet {
GenericStateProof::new(orchestrator_root, orchestrator_chain_state_proof)
.expect("Invalid orchestrator chain state proof");

Self::fetch_authorities_from_orchestrator_proof(
Self::fetch_authorities_from_proof(
&orchestrator_chain_state_proof,
T::SelfParaId::get(),
false,
)
};

Expand Down Expand Up @@ -325,22 +338,31 @@ impl<T: Config> Pallet<T> {
}

/// Fetch author slot from a proof of header
fn fetch_authorities_from_orchestrator_proof(
orchestrator_state_proof: &GenericStateProof<cumulus_primitives_core::relay_chain::Block>,
fn fetch_authorities_from_proof(
state_proof: &GenericStateProof<cumulus_primitives_core::relay_chain::Block>,
para_id: ParaId,
solochain: bool,
) -> Result<Vec<T::AuthorityId>, Error<T>> {
// Read orchestrator session index
let session_index = orchestrator_state_proof
let session_index = state_proof
.read_entry::<u32>(well_known_keys::SESSION_INDEX, None)
.map_err(|e| match e {
ReadEntryErr::Proof => panic!("Invalid proof: cannot read session index"),
_ => Error::<T>::FailedReading,
})?;
let pallet_authorities_prefix = if solochain {
Some(well_known_keys::SOLOCHAIN_AUTHORITY_ASSIGNMENT_PREFIX)
} else {
None
};

// Read the assignment from the orchestrator
let assignment = orchestrator_state_proof
let assignment = state_proof
.read_entry::<AssignedCollators<T::AuthorityId>>(
&well_known_keys::authority_assignment_for_session(session_index),
&well_known_keys::authority_assignment_for_session(
session_index,
pallet_authorities_prefix,
),
None,
)
.map_err(|e| match e {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ async fn collect_orchestrator_storage_proof(
relevant_keys.push(well_known_keys::SESSION_INDEX.to_vec());
relevant_keys.push(well_known_keys::authority_assignment_for_session(
session_index,
None,
));

orchestrator_chain_interface
.prove_read(orchestrator_parent, &relevant_keys)
.await
.ok()
}

/// Collect the relevant solochain chain state in form of a proof
/// for putting it into the authorities noting inherent
async fn collect_solochain_storage_proof(
orchestrator_chain_interface: &impl RelayChainInterface,
orchestrator_parent: PHash,
) -> Option<sp_state_machine::StorageProof> {
// We need to fetch the actual session index to build the key for the
// authorities.
let session_index = orchestrator_chain_interface
.get_storage_by_key(orchestrator_parent, well_known_keys::SESSION_INDEX)
.await
.ok()??;
let session_index = u32::decode(&mut session_index.as_slice()).ok()?;

let mut relevant_keys = Vec::new();
relevant_keys.push(well_known_keys::SESSION_INDEX.to_vec());
relevant_keys.push(well_known_keys::authority_assignment_for_session(
session_index,
Some(well_known_keys::SOLOCHAIN_AUTHORITY_ASSIGNMENT_PREFIX),
));

orchestrator_chain_interface
Expand Down Expand Up @@ -134,6 +162,22 @@ impl ContainerChainAuthoritiesInherentData {
})
}

/// Create the [`ContainerChainAuthoritiesInherentData`] at the given `relay_parent`.
///
/// Returns `None` if the creation failed.
pub async fn create_at_solochain(
relay_parent: PHash,
relay_chain_interface: &impl RelayChainInterface,
) -> Option<ContainerChainAuthoritiesInherentData> {
let relay_chain_state =
collect_solochain_storage_proof(relay_chain_interface, relay_parent).await?;

Some(ContainerChainAuthoritiesInherentData {
relay_chain_state,
orchestrator_chain_state: sp_trie::StorageProof::empty(),
})
}

pub async fn get_latest_orchestrator_head_info(
relay_parent: PHash,
relay_chain_interface: &impl RelayChainInterface,
Expand Down
14 changes: 12 additions & 2 deletions primitives/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,22 @@ pub mod well_known_keys {
})
}

/// authorityAssignment pallet prefix
pub const AUTHORITY_ASSIGNMENT_PREFIX: &[u8] =
&hex_literal::hex!["ebe78423c7e3ed25234f80d54547285a170f16afec7d161bc6acec3964492a0c"];

pub fn authority_assignment_for_session(session_index: u32) -> Vec<u8> {
/// tanssiAuthorityAssignment instead of authorityAssignment for solochain
pub const SOLOCHAIN_AUTHORITY_ASSIGNMENT_PREFIX: &[u8] =
&hex_literal::hex!["7a201242ca61564279dc11734e3f8772170f16afec7d161bc6acec3964492a0c"];

pub fn authority_assignment_for_session(
session_index: u32,
custom_prefix: Option<&[u8]>,
) -> Vec<u8> {
session_index.using_encoded(|index| {
AUTHORITY_ASSIGNMENT_PREFIX
let prefix = custom_prefix.unwrap_or(AUTHORITY_ASSIGNMENT_PREFIX);

prefix
.iter()
.chain(twox_64(index).iter())
.chain(index.iter())
Expand Down
2 changes: 1 addition & 1 deletion test-sproof-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl<T: Encode> AuthorityAssignmentSproofBuilder<T> {
self.session_index.encode(),
);
insert(
well_known_keys::authority_assignment_for_session(self.session_index).to_vec(),
well_known_keys::authority_assignment_for_session(self.session_index, None).to_vec(),
self.authority_assignment.encode(),
);

Expand Down

0 comments on commit 6021f39

Please sign in to comment.