Skip to content

Commit

Permalink
Move BlockRandomness into a combined storage proof
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Dec 18, 2024
1 parent 2d31849 commit ae33c81
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 55 deletions.
24 changes: 23 additions & 1 deletion crates/pallet-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -246,7 +247,7 @@ mod pallet {
use sp_std::collections::btree_set::BTreeSet;
use sp_std::fmt::Debug;
use sp_subspace_mmr::MmrProofVerifier;
use subspace_core_primitives::U256;
use subspace_core_primitives::{Randomness, U256};
use subspace_runtime_primitives::StorageFee;

#[pallet::config]
Expand Down Expand Up @@ -1850,6 +1851,10 @@ mod pallet {
}
}

/// Combined fraud proof data for the InvalidInherentExtrinsic fraud proof
#[pallet::storage]
pub type BlockInvalidInherentExtrinsicData<T> = StorageValue<_, InvalidInherentExtrinsicData>;

#[pallet::hooks]
// TODO: proper benchmark
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
Expand Down Expand Up @@ -1894,10 +1899,27 @@ mod pallet {
}
}

BlockInvalidInherentExtrinsicData::<T>::kill();

Weight::zero()
}

fn on_finalize(_: BlockNumberFor<T>) {
// If this consensus block will derive any domain block, gather the necessary storage for potential fraud proof usage
if SuccessfulBundles::<T>::iter_keys().count() > 0
|| DomainRuntimeUpgrades::<T>::exists()
{
let extrinsics_shuffling_seed = Randomness::from(
Into::<H256>::into(Self::extrinsics_shuffling_seed()).to_fixed_bytes(),
);

let invalid_inherent_extrinsic_data = InvalidInherentExtrinsicData {
extrinsics_shuffling_seed,
};

BlockInvalidInherentExtrinsicData::<T>::set(Some(invalid_inherent_extrinsic_data));
}

let _ = LastEpochStakingDistribution::<T>::clear(u32::MAX, None);
let _ = NewAddedHeadReceipt::<T>::clear(u32::MAX, None);
}
Expand Down
6 changes: 5 additions & 1 deletion crates/sp-domains-fraud-proof/src/fraud_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,11 @@ pub struct InvalidExtrinsicsRootProof {
/// Valid Bundle digests
pub valid_bundle_digests: Vec<ValidBundleDigest>,

/// 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
Expand Down
2 changes: 1 addition & 1 deletion crates/sp-domains-fraud-proof/src/host_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ where
) -> Option<DomainInherentExtrinsic> {
let DomainInherentExtrinsicData {
// Used by caller
block_randomness: _,
extrinsics_shuffling_seed: _,
timestamp,
maybe_domain_runtime_upgrade,
consensus_transaction_byte_fee,
Expand Down
2 changes: 1 addition & 1 deletion crates/sp-domains-fraud-proof/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub enum DomainChainAllowlistUpdateExtrinsic {

#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
pub struct DomainInherentExtrinsicData {
pub block_randomness: Randomness,
pub extrinsics_shuffling_seed: Randomness,
pub timestamp: Moment,
pub maybe_domain_runtime_upgrade: Option<Vec<u8>>,
pub consensus_transaction_byte_fee: Balance,
Expand Down
71 changes: 39 additions & 32 deletions crates/sp-domains-fraud-proof/src/storage_proof.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::DomainInherentExtrinsicData;
use codec::{Decode, Encode};
use frame_support::PalletError;
use scale_info::TypeInfo;
Expand All @@ -13,6 +12,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;
Expand All @@ -36,7 +37,7 @@ pub enum VerificationError {
InvalidBundleStorageProof,
RuntimeCodeNotFound,
UnexpectedDomainRuntimeUpgrade,
BlockRandomnessStorageProof(StorageProofVerificationError),
InvalidInherentExtrinsicStorageProof(StorageProofVerificationError),
TimestampStorageProof(StorageProofVerificationError),
SuccessfulBundlesStorageProof(StorageProofVerificationError),
TransactionByteFeeStorageProof(StorageProofVerificationError),
Expand All @@ -54,7 +55,7 @@ pub enum VerificationError {

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub enum FraudProofStorageKeyRequest<Number> {
BlockRandomness,
InvalidInherentExtrinsicData,
Timestamp,
SuccessfulBundles(DomainId),
TransactionByteFee,
Expand All @@ -69,7 +70,9 @@ pub enum FraudProofStorageKeyRequest<Number> {
impl<Number> FraudProofStorageKeyRequest<Number> {
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),
Expand Down Expand Up @@ -173,17 +176,6 @@ impl<Block: BlockT> BasicStorageProof<Block> for SuccessfulBundlesProof {
}
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct BlockRandomnessProof(StorageProof);

impl_storage_proof!(BlockRandomnessProof);
impl<Block: BlockT> BasicStorageProof<Block> for BlockRandomnessProof {
type StorageValue = Randomness;
fn storage_key_request(_key: Self::Key) -> FraudProofStorageKeyRequest<NumberFor<Block>> {
FraudProofStorageKeyRequest::BlockRandomness
}
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct DomainChainsAllowlistUpdateStorageProof(StorageProof);

Expand Down Expand Up @@ -414,10 +406,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 {
/// Extrinsics shuffling seed, derived from block randomness
pub extrinsics_shuffling_seed: Randomness,
}

impl PassBy for InvalidInherentExtrinsicData {
type PassBy = pass_by::Codec<Self>;
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct InvalidInherentExtrinsicDataProof(StorageProof);

impl_storage_proof!(InvalidInherentExtrinsicDataProof);
impl<Block: BlockT> BasicStorageProof<Block> for InvalidInherentExtrinsicDataProof {
type StorageValue = InvalidInherentExtrinsicData;
fn storage_key_request(_key: Self::Key) -> FraudProofStorageKeyRequest<NumberFor<Block>> {
FraudProofStorageKeyRequest::InvalidInherentExtrinsicData
}
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct InvalidInherentExtrinsicProof {
/// Block timestamp storage proof
pub timestamp_proof: TimestampStorageProof,

Expand All @@ -434,6 +444,15 @@ pub struct InvalidInherentExtrinsicProof {
pub domain_chain_allowlist_proof: DomainChainsAllowlistUpdateStorageProof,
}

/// The verified data from an `InvalidInherentExtrinsicProof`
#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct InvalidInherentExtrinsicVerified {
pub timestamp: Moment,
pub maybe_domain_runtime_upgrade: Option<Vec<u8>>,
pub consensus_transaction_byte_fee: Balance,
pub domain_chain_allowlist: DomainAllowlistUpdates,
}

impl InvalidInherentExtrinsicProof {
#[cfg(feature = "std")]
#[allow(clippy::let_and_return)]
Expand All @@ -448,8 +467,6 @@ impl InvalidInherentExtrinsicProof {
block_hash: Block::Hash,
maybe_runtime_id: Option<RuntimeId>,
) -> Result<Self, GenerationError> {
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(
Expand Down Expand Up @@ -478,7 +495,6 @@ impl InvalidInherentExtrinsicProof {
)?;

Ok(Self {
block_randomness_proof,
timestamp_proof,
maybe_domain_runtime_upgrade_proof,
dynamic_cost_of_storage_proof,
Expand All @@ -492,13 +508,7 @@ impl InvalidInherentExtrinsicProof {
domain_id: DomainId,
runtime_id: RuntimeId,
state_root: &Block::Hash,
) -> Result<DomainInherentExtrinsicData, VerificationError> {
let block_randomness = <BlockRandomnessProof as BasicStorageProof<Block>>::verify::<SKP>(
self.block_randomness_proof.clone(),
(),
state_root,
)?;

) -> Result<InvalidInherentExtrinsicVerified, VerificationError> {
let timestamp = <TimestampStorageProof as BasicStorageProof<Block>>::verify::<SKP>(
self.timestamp_proof.clone(),
(),
Expand Down Expand Up @@ -535,14 +545,11 @@ impl InvalidInherentExtrinsicProof {
state_root,
)?;

Ok(DomainInherentExtrinsicData {
block_randomness,
Ok(InvalidInherentExtrinsicVerified {
timestamp,
maybe_domain_runtime_upgrade,
consensus_transaction_byte_fee,
domain_chain_allowlist,
// Populated by caller
maybe_sudo_runtime_call: None,
})
}
}
Expand Down
44 changes: 29 additions & 15 deletions crates/sp-domains-fraud-proof/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use crate::fraud_proof::{
};
use crate::storage_proof::{self, *};
use crate::{
fraud_proof_runtime_interface, DomainInherentExtrinsic, DomainStorageKeyRequest,
StatelessDomainRuntimeCall,
fraud_proof_runtime_interface, DomainInherentExtrinsic, DomainInherentExtrinsicData,
DomainStorageKeyRequest, StatelessDomainRuntimeCall,
};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
Expand All @@ -17,7 +17,7 @@ use domain_runtime_primitives::BlockNumber;
use hash_db::Hasher;
use sp_core::storage::StorageKey;
use sp_core::H256;
use sp_domains::extrinsics::{deduplicate_and_shuffle_extrinsics, extrinsics_shuffling_seed};
use sp_domains::extrinsics::deduplicate_and_shuffle_extrinsics;
use sp_domains::proof_provider_and_verifier::StorageProofVerifier;
use sp_domains::valued_trie::valued_ordered_trie_root;
use sp_domains::{
Expand All @@ -32,7 +32,7 @@ use sp_runtime::traits::{
use sp_runtime::{OpaqueExtrinsic, SaturatedConversion};
use sp_subspace_mmr::{ConsensusChainMmrLeafProof, MmrProofVerifier};
use sp_trie::{LayoutV1, StorageProof};
use subspace_core_primitives::{Randomness, U256};
use subspace_core_primitives::U256;
use trie_db::node::Value;

/// Verifies invalid domain extrinsic root fraud proof.
Expand Down Expand Up @@ -65,24 +65,40 @@ where
{
let InvalidExtrinsicsRootProof {
valid_bundle_digests,
invalid_inherent_extrinsic_proofs,
invalid_inherent_extrinsic_proof,
domain_sudo_call_proof,
} = fraud_proof;

let mut domain_inherent_extrinsic_data = invalid_inherent_extrinsic_proof
.verify::<CBlock, SKP>(domain_id, runtime_id, &state_root)?;
let invalid_inherent_extrinsic_data =
<InvalidInherentExtrinsicDataProof as BasicStorageProof<CBlock>>::verify::<SKP>(
invalid_inherent_extrinsic_proofs.clone(),
(),
&state_root,
)?;

let inherent_extrinsic_verified = invalid_inherent_extrinsic_proof.verify::<CBlock, SKP>(
domain_id,
runtime_id,
&state_root,
)?;

let domain_sudo_call = <DomainSudoCallStorageProof as BasicStorageProof<CBlock>>::verify::<SKP>(
domain_sudo_call_proof.clone(),
domain_id,
&state_root,
)?;
domain_inherent_extrinsic_data.maybe_sudo_runtime_call = domain_sudo_call.maybe_call;

let shuffling_seed = H256::from_slice(
extrinsics_shuffling_seed::<Hashing>(domain_inherent_extrinsic_data.block_randomness)
.as_ref(),
);
let shuffling_seed = invalid_inherent_extrinsic_data.extrinsics_shuffling_seed;

let domain_inherent_extrinsic_data = DomainInherentExtrinsicData {
extrinsics_shuffling_seed: invalid_inherent_extrinsic_data.extrinsics_shuffling_seed,
timestamp: inherent_extrinsic_verified.timestamp,
maybe_domain_runtime_upgrade: inherent_extrinsic_verified.maybe_domain_runtime_upgrade,
consensus_transaction_byte_fee: inherent_extrinsic_verified.consensus_transaction_byte_fee,
domain_chain_allowlist: inherent_extrinsic_verified.domain_chain_allowlist,
maybe_sudo_runtime_call: domain_sudo_call.maybe_call,
};

let DomainInherentExtrinsic {
domain_timestamp_extrinsic,
Expand Down Expand Up @@ -115,10 +131,8 @@ where
bundle_extrinsics_digests.extend(bundle_digest.bundle_digest.clone());
}

let mut ordered_extrinsics = deduplicate_and_shuffle_extrinsics(
bundle_extrinsics_digests,
Randomness::from(shuffling_seed.to_fixed_bytes()),
);
let mut ordered_extrinsics =
deduplicate_and_shuffle_extrinsics(bundle_extrinsics_digests, shuffling_seed);

// NOTE: the order of the inherent extrinsic MUST aligned with the
// pallets order defined in `construct_runtime` macro for domains.
Expand Down
4 changes: 2 additions & 2 deletions crates/subspace-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1038,8 +1038,8 @@ pub struct StorageKeyProvider;
impl FraudProofStorageKeyProvider<NumberFor<Block>> for StorageKeyProvider {
fn storage_key(req: FraudProofStorageKeyRequest<NumberFor<Block>>) -> Vec<u8> {
match req {
FraudProofStorageKeyRequest::BlockRandomness => {
pallet_subspace::BlockRandomness::<Runtime>::hashed_key().to_vec()
FraudProofStorageKeyRequest::InvalidInherentExtrinsicData => {
pallet_domains::BlockInvalidInherentExtrinsicData::<Runtime>::hashed_key().to_vec()
}
FraudProofStorageKeyRequest::Timestamp => {
pallet_timestamp::Now::<Runtime>::hashed_key().to_vec()
Expand Down
8 changes: 8 additions & 0 deletions domains/client/domain-operator/src/fraud_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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,
}),
Expand Down
4 changes: 2 additions & 2 deletions test/subspace-test-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1115,8 +1115,8 @@ pub struct StorageKeyProvider;
impl FraudProofStorageKeyProvider<NumberFor<Block>> for StorageKeyProvider {
fn storage_key(req: FraudProofStorageKeyRequest<NumberFor<Block>>) -> Vec<u8> {
match req {
FraudProofStorageKeyRequest::BlockRandomness => {
pallet_subspace::BlockRandomness::<Runtime>::hashed_key().to_vec()
FraudProofStorageKeyRequest::InvalidInherentExtrinsicData => {
pallet_domains::BlockInvalidInherentExtrinsicData::<Runtime>::hashed_key().to_vec()
}
FraudProofStorageKeyRequest::Timestamp => {
pallet_timestamp::Now::<Runtime>::hashed_key().to_vec()
Expand Down

0 comments on commit ae33c81

Please sign in to comment.