Skip to content

Commit

Permalink
Add compatibility code for runtime_upgrades() calls in inherents
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Jan 7, 2025
1 parent d798e1d commit b0800cb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 16 deletions.
6 changes: 5 additions & 1 deletion crates/sp-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1476,7 +1476,10 @@ pub enum OperatorRewardSource<Number> {
}

sp_api::decl_runtime_apis! {
/// API necessary for domains pallet.
/// APIs used to access the domains pallet.
// When updating this version, document new APIs with "Only present in API versions" comments.
// TODO: when removing this version, also remove "Only present in API versions" comments.
#[api_version(2)]
pub trait DomainsApi<DomainHeader: HeaderT> {
/// Submits the transaction bundle via an unsigned extrinsic.
fn submit_bundle_unsigned(opaque_bundle: OpaqueBundle<NumberFor<Block>, Block::Hash, DomainHeader, Balance>);
Expand All @@ -1500,6 +1503,7 @@ sp_api::decl_runtime_apis! {
fn runtime_id(domain_id: DomainId) -> Option<RuntimeId>;

/// Returns the list of runtime upgrades in the current block.
/// Only present in API versions 2 and later.
fn runtime_upgrades() -> Vec<RuntimeId>;

/// Returns the domain instance data for the given `domain_id`.
Expand Down
48 changes: 33 additions & 15 deletions domains/client/block-preprocessor/src/inherents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
//! Deriving these extrinsics during fraud proof verification should be possible since
//! verification environment will have access to consensus chain.
use sp_api::ProvideRuntimeApi;
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_blockchain::HeaderBackend;
use sp_domains::{DomainId, DomainsApi};
use sp_domains::{DomainId, DomainsApi, DomainsDigestItem};
use sp_inherents::{CreateInherentDataProviders, InherentData, InherentDataProvider};
use sp_messenger::MessengerApi;
use sp_runtime::traits::{Block as BlockT, NumberFor};
use sp_runtime::traits::{Block as BlockT, Header, NumberFor};
use sp_timestamp::InherentType;
use std::error::Error;
use std::sync::Arc;
Expand Down Expand Up @@ -70,14 +70,39 @@ where
Block: BlockT,
{
let runtime_api = consensus_client.runtime_api();

let runtime_id = runtime_api
.runtime_id(consensus_block_hash, domain_id)?
.ok_or(sp_blockchain::Error::Application(Box::from(format!(
"No RuntimeId found for {domain_id:?}"
))))?;
let runtime_upgrades = runtime_api.runtime_upgrades(consensus_block_hash)?;

Ok(runtime_upgrades.contains(&runtime_id))
// The runtime_upgrades() API is only present in API versions 2 and later. On earlier versions,
// we need to call legacy code.
// TODO: remove version check before next network
let domains_api_version = runtime_api
.api_version::<dyn DomainsApi<CBlock, CBlock::Header>>(consensus_block_hash)?
// It is safe to return a default version of 1, since there will always be version 1.
.unwrap_or(1);

let is_upgraded = if domains_api_version >= 2 {
let runtime_upgrades = runtime_api.runtime_upgrades(consensus_block_hash)?;
runtime_upgrades.contains(&runtime_id)
} else {
let header = consensus_client.header(consensus_block_hash)?.ok_or(
sp_blockchain::Error::MissingHeader(format!(
"No header found for {consensus_block_hash:?}"
)),
)?;
header
.digest()
.logs
.iter()
.filter_map(|log| log.as_domain_runtime_upgrade())
.any(|upgraded_runtime_id| upgraded_runtime_id == runtime_id)
};

Ok(is_upgraded)
}

/// Returns new upgraded runtime if upgraded did happen in the provided consensus block.
Expand All @@ -92,16 +117,9 @@ where
CBlock: BlockT,
Block: BlockT,
{
let runtime_api = consensus_client.runtime_api();
let runtime_id = runtime_api
.runtime_id(consensus_block_hash, domain_id)?
.ok_or(sp_blockchain::Error::Application(Box::from(format!(
"No RuntimeId found for {domain_id:?}"
))))?;
let runtime_upgrades = runtime_api.runtime_upgrades(consensus_block_hash)?;

if runtime_upgrades.contains(&runtime_id) {
let new_domain_runtime = runtime_api
if is_runtime_upgraded::<_, _, Block>(consensus_client, consensus_block_hash, domain_id)? {
let new_domain_runtime = consensus_client
.runtime_api()
.domain_runtime_code(consensus_block_hash, domain_id)?
.ok_or_else(|| {
sp_blockchain::Error::Application(Box::from(format!(
Expand Down
4 changes: 4 additions & 0 deletions domains/client/domain-operator/src/fraud_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,10 @@ where
.ok_or(sp_blockchain::Error::Application(Box::from(format!(
"No RuntimeId found for {domain_id:?}"
))))?;
// This API is only present in API versions 2 and later, but it is safe to call
// unconditionally, because:
// - on Mainnet, there are no domains yet, and
// - on Taurus, there are no invalid execution receipts yet.
let runtime_upgrades = self.consensus_client.runtime_api().runtime_upgrades(at)?;

let is_runtime_upgraded = runtime_upgrades.contains(&runtime_id);
Expand Down

0 comments on commit b0800cb

Please sign in to comment.