Skip to content

Commit

Permalink
Merge pull request #2884 from subspace/sudo_extrinsic
Browse files Browse the repository at this point in the history
Domains: Sudo on Domains
  • Loading branch information
vedhavyas authored Jul 3, 2024
2 parents 30253d2 + 85dfef2 commit 71099af
Show file tree
Hide file tree
Showing 34 changed files with 891 additions and 93 deletions.
34 changes: 31 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions crates/pallet-domains/src/domain_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::runtime_registry::DomainRuntimeInfo;
use crate::staking::StakingSummary;
use crate::{
into_complete_raw_genesis, BalanceOf, Config, DomainHashingFor, DomainRegistry,
ExecutionReceiptOf, HoldIdentifier, NextDomainId, RuntimeRegistry,
DomainSudoCalls, ExecutionReceiptOf, HoldIdentifier, NextDomainId, RuntimeRegistry,
};
#[cfg(not(feature = "std"))]
use alloc::string::String;
Expand All @@ -26,8 +26,8 @@ use scale_info::TypeInfo;
use sp_core::Get;
use sp_domains::{
calculate_max_bundle_weight_and_size, derive_domain_block_hash, DomainBundleLimit, DomainId,
DomainsDigestItem, DomainsTransfersTracker, OnDomainInstantiated, OperatorAllowList, RuntimeId,
RuntimeType,
DomainSudoCall, DomainsDigestItem, DomainsTransfersTracker, OnDomainInstantiated,
OperatorAllowList, RuntimeId, RuntimeType,
};
use sp_runtime::traits::{CheckedAdd, Zero};
use sp_runtime::DigestItem;
Expand Down Expand Up @@ -305,6 +305,8 @@ pub(crate) fn do_instantiate_domain<T: Config>(
import_genesis_receipt::<T>(domain_id, genesis_receipt);
T::OnDomainInstantiated::on_domain_instantiated(domain_id);

DomainSudoCalls::<T>::insert(domain_id, DomainSudoCall { maybe_call: None });

frame_system::Pallet::<T>::deposit_log(DigestItem::domain_instantiation(domain_id));

Ok(domain_id)
Expand Down
59 changes: 57 additions & 2 deletions crates/pallet-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,14 @@ mod pallet {
use sp_core::H256;
use sp_domains::bundle_producer_election::ProofOfElectionError;
use sp_domains::{
BundleDigest, ConfirmedDomainBlock, DomainBundleSubmitted, DomainId,
BundleDigest, ConfirmedDomainBlock, DomainBundleSubmitted, DomainId, DomainSudoCall,
DomainsTransfersTracker, EpochIndex, GenesisDomain, OnChainRewards, OnDomainInstantiated,
OperatorAllowList, OperatorId, OperatorPublicKey, OperatorSignature, RuntimeId,
RuntimeObject, RuntimeType,
};
use sp_domains_fraud_proof::fraud_proof_runtime_interface::domain_runtime_call;
use sp_domains_fraud_proof::storage_proof::{self, FraudProofStorageKeyProvider};
use sp_domains_fraud_proof::InvalidTransactionCode;
use sp_domains_fraud_proof::{InvalidTransactionCode, StatelessDomainRuntimeCall};
use sp_runtime::traits::{
AtLeast32BitUnsigned, BlockNumberProvider, CheckEqual, CheckedAdd, Header as HeaderT,
MaybeDisplay, One, SimpleBitOps, Zero,
Expand Down Expand Up @@ -705,6 +706,13 @@ mod pallet {
#[pallet::storage]
pub type DomainRuntimeUpgrades<T> = StorageValue<_, Vec<RuntimeId>, ValueQuery>;

/// Temporary storage to hold the sudo calls meant for the Domains.
/// Storage is cleared when there are any successful bundles in the next block.
/// Only one sudo call is allowed per domain per consensus block.
#[pallet::storage]
pub type DomainSudoCalls<T: Config> =
StorageMap<_, Identity, DomainId, DomainSudoCall, ValueQuery>;

#[derive(TypeInfo, Encode, Decode, PalletError, Debug, PartialEq)]
pub enum BundleError {
/// Can not find the operator for given operator id.
Expand Down Expand Up @@ -868,6 +876,10 @@ mod pallet {
BundleStorageFund(BundleStorageFundError),
/// Permissioned action is not allowed by the caller.
PermissionedActionNotAllowed,
/// Domain Sudo already exists.
DomainSudoCallExists,
/// Invalid Domain sudo call.
InvalidDomainSudoCall,
}

/// Reason for slashing an operator
Expand Down Expand Up @@ -1494,6 +1506,41 @@ mod pallet {
PermissionedActionAllowedBy::<T>::put(permissioned_action_allowed_by);
Ok(())
}

/// Submit a domain sudo call.
#[pallet::call_index(16)]
#[pallet::weight(<T as frame_system::Config>::DbWeight::get().reads_writes(3, 1))]
pub fn send_domain_sudo_call(
origin: OriginFor<T>,
domain_id: DomainId,
call: Vec<u8>,
) -> DispatchResult {
ensure_root(origin)?;
ensure!(
DomainSudoCalls::<T>::get(domain_id).maybe_call.is_none(),
Error::<T>::DomainSudoCallExists
);

let domain_runtime = Self::domain_runtime_code(domain_id).ok_or(
Error::<T>::DomainRegistry(DomainRegistryError::DomainNotFound),
)?;
ensure!(
domain_runtime_call(
domain_runtime,
StatelessDomainRuntimeCall::IsValidDomainSudoCall(call.clone()),
)
.unwrap_or(false),
Error::<T>::InvalidDomainSudoCall
);

DomainSudoCalls::<T>::set(
domain_id,
DomainSudoCall {
maybe_call: Some(call),
},
);
Ok(())
}
}

#[pallet::genesis_config]
Expand Down Expand Up @@ -1609,6 +1656,9 @@ mod pallet {
for (domain_id, _) in SuccessfulBundles::<T>::drain() {
ConsensusBlockHash::<T>::insert(domain_id, parent_number, parent_hash);
T::DomainBundleSubmitted::domain_bundle_submitted(domain_id);
DomainSudoCalls::<T>::mutate(domain_id, |sudo_call| {
sudo_call.clear();
});
}

for (operator_id, slot_set) in OperatorBundleSlot::<T>::drain() {
Expand Down Expand Up @@ -2573,6 +2623,11 @@ impl<T: Config> Pallet<T> {
pub fn is_domain_registered(domain_id: DomainId) -> bool {
DomainStakingSummary::<T>::contains_key(domain_id)
}

/// Returns domain's sudo call if any.
pub fn domain_sudo_call(domain_id: DomainId) -> Option<Vec<u8>> {
DomainSudoCalls::<T>::get(domain_id).maybe_call
}
}

impl<T: Config> sp_domains::DomainOwner<T::AccountId> for Pallet<T> {
Expand Down
29 changes: 16 additions & 13 deletions crates/pallet-domains/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV0ToV1<T> {

pub(super) mod runtime_registry_instance_count_migration {
use crate::pallet::{DomainRegistry, RuntimeRegistry as RuntimeRegistryV1};
use crate::Config;
use crate::{Config, DomainSudoCalls};
#[cfg(not(feature = "std"))]
use alloc::string::String;
use codec::{Decode, Encode};
Expand All @@ -22,7 +22,7 @@ pub(super) mod runtime_registry_instance_count_migration {
use frame_system::pallet_prelude::BlockNumberFor;
use sp_core::Get;
use sp_domains::storage::RawGenesis;
use sp_domains::{RuntimeId, RuntimeObject as RuntimeObjectV1, RuntimeType};
use sp_domains::{DomainSudoCall, RuntimeId, RuntimeObject as RuntimeObjectV1, RuntimeType};
use sp_version::RuntimeVersion;

#[derive(TypeInfo, Debug, Encode, Decode, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -50,23 +50,24 @@ pub(super) mod runtime_registry_instance_count_migration {

// Return the number of domain instance that instantiated with the given runtime
fn domain_instance_count<T: Config>(runtime_id: RuntimeId) -> (u32, u64) {
let mut read_count = 0;
let mut read_write_count = 0;
(
DomainRegistry::<T>::iter()
.filter(|(_, domain_obj)| {
read_count += 1;
.filter(|(domain_id, domain_obj)| {
read_write_count += 1;
DomainSudoCalls::<T>::insert(domain_id, DomainSudoCall { maybe_call: None });
domain_obj.domain_config.runtime_id == runtime_id
})
.count() as u32,
read_count,
read_write_count,
)
}

/// Indexes the currently used operator's signing keys into v2 domains storage.
pub(super) fn migrate_runtime_registry_storages<T: Config>() -> Weight {
let (mut read_count, mut write_count) = (0, 0);
RuntimeRegistry::<T>::drain().for_each(|(runtime_id, runtime_obj)| {
let (instance_count, domain_read_count) = domain_instance_count::<T>(runtime_id);
let (instance_count, domain_read_write_count) = domain_instance_count::<T>(runtime_id);
RuntimeRegistryV1::<T>::set(
runtime_id,
Some(RuntimeObjectV1 {
Expand All @@ -83,9 +84,9 @@ pub(super) mod runtime_registry_instance_count_migration {
);

// domain_read_count + 1 since we read the old runtime registry as well
read_count += domain_read_count + 1;
// 1 write to new registry and 1 for old registry.
write_count += 2;
read_count += domain_read_write_count + 1;
// 1 write to new registry and 1 for old registry + domain_write_count to load Sudo Domain runtime call.
write_count += 2 + domain_read_write_count;
});

T::DbWeight::get().reads_writes(read_count, write_count)
Expand All @@ -100,13 +101,13 @@ mod tests {
};
use crate::pallet::RuntimeRegistry as RuntimeRegistryV1;
use crate::tests::{new_test_ext, Balances, Test};
use crate::Config;
use crate::{Config, DomainSudoCalls};
use domain_runtime_primitives::{AccountId20, AccountId20Converter};
use frame_support::pallet_prelude::Weight;
use frame_support::traits::Currency;
use hex_literal::hex;
use sp_domains::storage::RawGenesis;
use sp_domains::{OperatorAllowList, RuntimeObject as RuntimeObjectV1};
use sp_domains::{DomainId, OperatorAllowList, RuntimeObject as RuntimeObjectV1};
use sp_runtime::traits::Convert;
use sp_version::RuntimeVersion;
use subspace_runtime_primitives::SSC;
Expand Down Expand Up @@ -194,13 +195,15 @@ mod tests {
crate::migrations::runtime_registry_instance_count_migration::migrate_runtime_registry_storages::<Test>();
assert_eq!(
weights,
<Test as frame_system::Config>::DbWeight::get().reads_writes(2, 2),
<Test as frame_system::Config>::DbWeight::get().reads_writes(2, 3),
);

assert_eq!(
RuntimeRegistryV1::<Test>::get(0).unwrap().instance_count,
1
);

assert!(DomainSudoCalls::<Test>::contains_key(DomainId::new(0)));
});
}
}
17 changes: 17 additions & 0 deletions crates/sp-domains-fraud-proof/src/host_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ where
maybe_domain_runtime_upgrade,
consensus_transaction_byte_fee,
domain_chain_allowlist,
maybe_sudo_runtime_call,
} = domain_inherent_extrinsic_data;

let domain_stateless_runtime = StatelessRuntime::<DomainBlock, _>::new(
Expand Down Expand Up @@ -781,11 +782,22 @@ where
),
};

let maybe_domain_sudo_call_extrinsic = match maybe_sudo_runtime_call {
None => None,
Some(call) => Some(
domain_stateless_runtime
.construct_domain_sudo_extrinsic(call)
.ok()
.map(|call| call.encode())?,
),
};

Some(DomainInherentExtrinsic {
domain_timestamp_extrinsic,
maybe_domain_chain_allowlist_extrinsic,
consensus_chain_byte_fee_extrinsic,
maybe_domain_set_code_extrinsic,
maybe_domain_sudo_call_extrinsic,
})
}

Expand Down Expand Up @@ -843,6 +855,11 @@ where
domain_stateless_runtime.decode_extrinsic(opaque_extrinsic),
Ok(Ok(_))
)),
StatelessDomainRuntimeCall::IsValidDomainSudoCall(encoded_extrinsic) => {
domain_stateless_runtime
.is_valid_sudo_call(encoded_extrinsic)
.ok()
}
}
}

Expand Down
Loading

0 comments on commit 71099af

Please sign in to comment.