diff --git a/crates/pallet-domains/src/lib.rs b/crates/pallet-domains/src/lib.rs index 161fce8e6c..b03d5dd70e 100644 --- a/crates/pallet-domains/src/lib.rs +++ b/crates/pallet-domains/src/lib.rs @@ -201,6 +201,7 @@ mod pallet { #[cfg(not(feature = "runtime-benchmarks"))] use crate::staking_epoch::do_slash_operator; use crate::staking_epoch::{do_finalize_domain_current_epoch, Error as StakingEpochError}; + use crate::storage_proof::InvalidInherentExtrinsicData; use crate::weights::WeightInfo; #[cfg(not(feature = "runtime-benchmarks"))] use crate::DomainHashingFor; @@ -1850,6 +1851,10 @@ mod pallet { } } + /// Combined fraud proof data for the InvalidInherentExtrinsic fraud proof + #[pallet::storage] + pub type BlockInvalidInherentExtrinsicData = StorageValue<_, InvalidInherentExtrinsicData>; + #[pallet::hooks] // TODO: proper benchmark impl Hooks> for Pallet { diff --git a/crates/sp-domains-fraud-proof/src/fraud_proof.rs b/crates/sp-domains-fraud-proof/src/fraud_proof.rs index 157b4c3280..149a960d6b 100644 --- a/crates/sp-domains-fraud-proof/src/fraud_proof.rs +++ b/crates/sp-domains-fraud-proof/src/fraud_proof.rs @@ -494,7 +494,11 @@ pub struct InvalidExtrinsicsRootProof { /// Valid Bundle digests pub valid_bundle_digests: Vec, - /// The storage proof used during verification + /// The combined storage proofs used during verification + pub invalid_inherent_extrinsic_proofs: InvalidInherentExtrinsicDataProof, + + /// The individual storage proofs used during verification + // TODO: combine these proofs into `InvalidInherentExtrinsicDataProof` pub invalid_inherent_extrinsic_proof: InvalidInherentExtrinsicProof, /// Optional sudo extrinsic call storage proof diff --git a/crates/sp-domains-fraud-proof/src/host_functions.rs b/crates/sp-domains-fraud-proof/src/host_functions.rs index 21add775b0..ad6dd97412 100644 --- a/crates/sp-domains-fraud-proof/src/host_functions.rs +++ b/crates/sp-domains-fraud-proof/src/host_functions.rs @@ -1,6 +1,7 @@ #[cfg(not(feature = "std"))] extern crate alloc; +use crate::storage_proof::InvalidInherentExtrinsicData; use crate::{ DomainInherentExtrinsic, DomainInherentExtrinsicData, DomainStorageKeyRequest, StatelessDomainRuntimeCall, @@ -75,6 +76,7 @@ pub trait FraudProofHostFunctions: Send + Sync { fn construct_domain_inherent_extrinsic( &self, domain_runtime_code: Vec, + invalid_inherent_extrinsic_data: InvalidInherentExtrinsicData, domain_inherent_extrinsic_data: DomainInherentExtrinsicData, ) -> Option; @@ -259,11 +261,14 @@ where fn construct_domain_inherent_extrinsic( &self, domain_runtime_code: Vec, + invalid_inherent_extrinsic_data: InvalidInherentExtrinsicData, domain_inherent_extrinsic_data: DomainInherentExtrinsicData, ) -> Option { - let DomainInherentExtrinsicData { + let InvalidInherentExtrinsicData { // Used by caller block_randomness: _, + } = invalid_inherent_extrinsic_data; + let DomainInherentExtrinsicData { timestamp, maybe_domain_runtime_upgrade, consensus_transaction_byte_fee, diff --git a/crates/sp-domains-fraud-proof/src/lib.rs b/crates/sp-domains-fraud-proof/src/lib.rs index 24f30cfa7c..f061c28796 100644 --- a/crates/sp-domains-fraud-proof/src/lib.rs +++ b/crates/sp-domains-fraud-proof/src/lib.rs @@ -54,7 +54,7 @@ use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity}; use sp_runtime::OpaqueExtrinsic; use sp_runtime_interface::pass_by; use sp_runtime_interface::pass_by::PassBy; -use subspace_core_primitives::{Randomness, U256}; +use subspace_core_primitives::U256; use subspace_runtime_primitives::{Balance, Moment}; /// Custom invalid validity code for the extrinsics in pallet-domains. @@ -108,7 +108,6 @@ pub enum DomainChainAllowlistUpdateExtrinsic { #[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)] pub struct DomainInherentExtrinsicData { - pub block_randomness: Randomness, pub timestamp: Moment, pub maybe_domain_runtime_upgrade: Option>, pub consensus_transaction_byte_fee: Balance, diff --git a/crates/sp-domains-fraud-proof/src/runtime_interface.rs b/crates/sp-domains-fraud-proof/src/runtime_interface.rs index 4a85e8970e..b2198d4fab 100644 --- a/crates/sp-domains-fraud-proof/src/runtime_interface.rs +++ b/crates/sp-domains-fraud-proof/src/runtime_interface.rs @@ -1,6 +1,7 @@ #[cfg(not(feature = "std"))] extern crate alloc; +use crate::storage_proof::InvalidInherentExtrinsicData; #[cfg(feature = "std")] use crate::FraudProofExtension; use crate::{ @@ -75,12 +76,14 @@ pub trait FraudProofRuntimeInterface { fn construct_domain_inherent_extrinsic( &mut self, domain_runtime_code: Vec, + invalid_inherent_extrinsic_data: InvalidInherentExtrinsicData, domain_inherent_extrinsic_data: DomainInherentExtrinsicData, ) -> Option { self.extension::() .expect("No `FraudProofExtension` associated for the current context!") .construct_domain_inherent_extrinsic( domain_runtime_code, + invalid_inherent_extrinsic_data, domain_inherent_extrinsic_data, ) } diff --git a/crates/sp-domains-fraud-proof/src/storage_proof.rs b/crates/sp-domains-fraud-proof/src/storage_proof.rs index e0c15e3db7..a50d06962c 100644 --- a/crates/sp-domains-fraud-proof/src/storage_proof.rs +++ b/crates/sp-domains-fraud-proof/src/storage_proof.rs @@ -13,6 +13,8 @@ use sp_domains::{ }; use sp_runtime::generic::Digest; use sp_runtime::traits::{Block as BlockT, HashingFor, Header as HeaderT, NumberFor}; +use sp_runtime_interface::pass_by; +use sp_runtime_interface::pass_by::PassBy; use sp_std::marker::PhantomData; use sp_std::vec::Vec; use sp_trie::StorageProof; @@ -36,7 +38,7 @@ pub enum VerificationError { InvalidBundleStorageProof, RuntimeCodeNotFound, UnexpectedDomainRuntimeUpgrade, - BlockRandomnessStorageProof(StorageProofVerificationError), + InvalidInherentExtrinsicStorageProof(StorageProofVerificationError), TimestampStorageProof(StorageProofVerificationError), SuccessfulBundlesStorageProof(StorageProofVerificationError), TransactionByteFeeStorageProof(StorageProofVerificationError), @@ -54,7 +56,7 @@ pub enum VerificationError { #[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] pub enum FraudProofStorageKeyRequest { - BlockRandomness, + InvalidInherentExtrinsicData, Timestamp, SuccessfulBundles(DomainId), TransactionByteFee, @@ -69,7 +71,9 @@ pub enum FraudProofStorageKeyRequest { impl FraudProofStorageKeyRequest { fn into_error(self, err: StorageProofVerificationError) -> VerificationError { match self { - Self::BlockRandomness => VerificationError::BlockRandomnessStorageProof(err), + Self::InvalidInherentExtrinsicData => { + VerificationError::InvalidInherentExtrinsicStorageProof(err) + } Self::Timestamp => VerificationError::TimestampStorageProof(err), Self::SuccessfulBundles(_) => VerificationError::SuccessfulBundlesStorageProof(err), Self::TransactionByteFee => VerificationError::TransactionByteFeeStorageProof(err), @@ -173,17 +177,6 @@ impl BasicStorageProof for SuccessfulBundlesProof { } } -#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] -pub struct BlockRandomnessProof(StorageProof); - -impl_storage_proof!(BlockRandomnessProof); -impl BasicStorageProof for BlockRandomnessProof { - type StorageValue = Randomness; - fn storage_key_request(_key: Self::Key) -> FraudProofStorageKeyRequest> { - FraudProofStorageKeyRequest::BlockRandomness - } -} - #[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] pub struct DomainChainsAllowlistUpdateStorageProof(StorageProof); @@ -414,10 +407,28 @@ impl MaybeDomainRuntimeUpgradedProof { } #[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] -pub struct InvalidInherentExtrinsicProof { - /// Block randomness storage proof - pub block_randomness_proof: BlockRandomnessProof, +pub struct InvalidInherentExtrinsicData { + /// Block randomness + pub block_randomness: Randomness, +} +impl PassBy for InvalidInherentExtrinsicData { + type PassBy = pass_by::Codec; +} + +#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] +pub struct InvalidInherentExtrinsicDataProof(StorageProof); + +impl_storage_proof!(InvalidInherentExtrinsicDataProof); +impl BasicStorageProof for InvalidInherentExtrinsicDataProof { + type StorageValue = InvalidInherentExtrinsicData; + fn storage_key_request(_key: Self::Key) -> FraudProofStorageKeyRequest> { + FraudProofStorageKeyRequest::InvalidInherentExtrinsicData + } +} + +#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)] +pub struct InvalidInherentExtrinsicProof { /// Block timestamp storage proof pub timestamp_proof: TimestampStorageProof, @@ -448,8 +459,6 @@ impl InvalidInherentExtrinsicProof { block_hash: Block::Hash, maybe_runtime_id: Option, ) -> Result { - let block_randomness_proof = - BlockRandomnessProof::generate(proof_provider, block_hash, (), storage_key_provider)?; let timestamp_proof = TimestampStorageProof::generate(proof_provider, block_hash, (), storage_key_provider)?; let maybe_domain_runtime_upgrade_proof = MaybeDomainRuntimeUpgradedProof::generate( @@ -478,7 +487,6 @@ impl InvalidInherentExtrinsicProof { )?; Ok(Self { - block_randomness_proof, timestamp_proof, maybe_domain_runtime_upgrade_proof, dynamic_cost_of_storage_proof, @@ -493,12 +501,6 @@ impl InvalidInherentExtrinsicProof { runtime_id: RuntimeId, state_root: &Block::Hash, ) -> Result { - let block_randomness = >::verify::( - self.block_randomness_proof.clone(), - (), - state_root, - )?; - let timestamp = >::verify::( self.timestamp_proof.clone(), (), @@ -536,7 +538,6 @@ impl InvalidInherentExtrinsicProof { )?; Ok(DomainInherentExtrinsicData { - block_randomness, timestamp, maybe_domain_runtime_upgrade, consensus_transaction_byte_fee, diff --git a/crates/sp-domains-fraud-proof/src/verification.rs b/crates/sp-domains-fraud-proof/src/verification.rs index af8715cadb..a883521c1a 100644 --- a/crates/sp-domains-fraud-proof/src/verification.rs +++ b/crates/sp-domains-fraud-proof/src/verification.rs @@ -65,10 +65,18 @@ where { let InvalidExtrinsicsRootProof { valid_bundle_digests, + invalid_inherent_extrinsic_proofs, invalid_inherent_extrinsic_proof, domain_sudo_call_proof, } = fraud_proof; + let invalid_inherent_extrinsic_data = + >::verify::( + invalid_inherent_extrinsic_proofs.clone(), + (), + &state_root, + )?; + let mut domain_inherent_extrinsic_data = invalid_inherent_extrinsic_proof .verify::(domain_id, runtime_id, &state_root)?; @@ -80,7 +88,7 @@ where domain_inherent_extrinsic_data.maybe_sudo_runtime_call = domain_sudo_call.maybe_call; let shuffling_seed = H256::from_slice( - extrinsics_shuffling_seed::(domain_inherent_extrinsic_data.block_randomness) + extrinsics_shuffling_seed::(invalid_inherent_extrinsic_data.block_randomness) .as_ref(), ); @@ -92,6 +100,7 @@ where maybe_domain_sudo_call_extrinsic, } = fraud_proof_runtime_interface::construct_domain_inherent_extrinsic( domain_runtime_code, + invalid_inherent_extrinsic_data, domain_inherent_extrinsic_data, ) .ok_or(VerificationError::FailedToDeriveDomainInherentExtrinsic)?; diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index 76382a21ab..2ee201c0a1 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -1038,8 +1038,8 @@ pub struct StorageKeyProvider; impl FraudProofStorageKeyProvider> for StorageKeyProvider { fn storage_key(req: FraudProofStorageKeyRequest>) -> Vec { match req { - FraudProofStorageKeyRequest::BlockRandomness => { - pallet_subspace::BlockRandomness::::hashed_key().to_vec() + FraudProofStorageKeyRequest::InvalidInherentExtrinsicData => { + pallet_domains::BlockInvalidInherentExtrinsicData::::hashed_key().to_vec() } FraudProofStorageKeyRequest::Timestamp => { pallet_timestamp::Now::::hashed_key().to_vec() diff --git a/domains/client/domain-operator/src/fraud_proof.rs b/domains/client/domain-operator/src/fraud_proof.rs index 7236273d35..3f82ba8eb7 100644 --- a/domains/client/domain-operator/src/fraud_proof.rs +++ b/domains/client/domain-operator/src/fraud_proof.rs @@ -382,6 +382,13 @@ where let maybe_runtime_id = self.is_domain_runtime_upgraded_at(domain_id, consensus_block_hash)?; + let invalid_inherent_extrinsic_proofs = InvalidInherentExtrinsicDataProof::generate( + self.consensus_client.as_ref(), + consensus_block_hash, + (), + &self.storage_key_provider, + )?; + let invalid_inherent_extrinsic_proof = InvalidInherentExtrinsicProof::generate( &self.storage_key_provider, self.consensus_client.as_ref(), @@ -404,6 +411,7 @@ where maybe_domain_runtime_code_proof, proof: FraudProofVariant::InvalidExtrinsicsRoot(InvalidExtrinsicsRootProof { valid_bundle_digests, + invalid_inherent_extrinsic_proofs, invalid_inherent_extrinsic_proof, domain_sudo_call_proof, }), diff --git a/test/subspace-test-runtime/src/lib.rs b/test/subspace-test-runtime/src/lib.rs index b1bf2008d3..ee36d26082 100644 --- a/test/subspace-test-runtime/src/lib.rs +++ b/test/subspace-test-runtime/src/lib.rs @@ -1115,8 +1115,8 @@ pub struct StorageKeyProvider; impl FraudProofStorageKeyProvider> for StorageKeyProvider { fn storage_key(req: FraudProofStorageKeyRequest>) -> Vec { match req { - FraudProofStorageKeyRequest::BlockRandomness => { - pallet_subspace::BlockRandomness::::hashed_key().to_vec() + FraudProofStorageKeyRequest::InvalidInherentExtrinsicData => { + pallet_domains::BlockInvalidInherentExtrinsicData::::hashed_key().to_vec() } FraudProofStorageKeyRequest::Timestamp => { pallet_timestamp::Now::::hashed_key().to_vec()