Skip to content

Commit

Permalink
Merge pull request #3340 from autonomys/consistent-fraud-proof
Browse files Browse the repository at this point in the history
Get some runtime API values from combined fraud proof storage
  • Loading branch information
teor2345 authored Jan 9, 2025
2 parents a9c459d + 27f3bb6 commit 9ce216e
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 72 deletions.
85 changes: 66 additions & 19 deletions crates/pallet-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use frame_support::ensure;
use frame_support::pallet_prelude::StorageVersion;
use frame_support::traits::fungible::{Inspect, InspectHold};
use frame_support::traits::tokens::{Fortitude, Preservation};
use frame_support::traits::{Get, Randomness as RandomnessT};
use frame_support::traits::{Get, Randomness as RandomnessT, Time};
use frame_support::weights::Weight;
use frame_system::offchain::SubmitTransaction;
use frame_system::pallet_prelude::*;
Expand Down Expand Up @@ -86,6 +86,7 @@ use sp_subspace_mmr::{ConsensusChainMmrLeafProof, MmrProofVerifier};
pub use staking::OperatorConfig;
use subspace_core_primitives::pot::PotOutput;
use subspace_core_primitives::{BlockHash, SlotNumber, U256};
use subspace_runtime_primitives::{Balance, Moment, StorageFee};

/// Maximum number of nominators to slash within a give operator at a time.
pub const MAX_NOMINATORS_TO_SLASH: u32 = 10;
Expand Down Expand Up @@ -201,7 +202,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::storage_proof::InherentExtrinsicData;
use crate::weights::WeightInfo;
#[cfg(not(feature = "runtime-benchmarks"))]
use crate::DomainHashingFor;
Expand Down Expand Up @@ -248,10 +249,10 @@ mod pallet {
use sp_std::fmt::Debug;
use sp_subspace_mmr::MmrProofVerifier;
use subspace_core_primitives::{Randomness, U256};
use subspace_runtime_primitives::{Balance, StorageFee};
use subspace_runtime_primitives::StorageFee;

#[pallet::config]
pub trait Config: frame_system::Config<Hash: Into<H256>> {
pub trait Config: frame_system::Config<Hash: Into<H256> + From<H256>> {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

// TODO: `DomainHash` can be derived from `DomainHeader`, it is still needed just for
Expand Down Expand Up @@ -1856,7 +1857,7 @@ mod pallet {

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

#[pallet::hooks]
// TODO: proper benchmark
Expand Down Expand Up @@ -1907,7 +1908,7 @@ mod pallet {
}
}

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

Weight::zero()
}
Expand All @@ -1919,31 +1920,23 @@ mod pallet {
|| !DomainRuntimeUpgrades::<T>::get().is_empty()
{
let extrinsics_shuffling_seed = Randomness::from(
Into::<H256>::into(Self::extrinsics_shuffling_seed()).to_fixed_bytes(),
Into::<H256>::into(Self::extrinsics_shuffling_seed_value()).to_fixed_bytes(),
);

// There are no actual conversions here, but the trait bounds required to prove that
// (and debug-print the error in expect()) are very verbose.
let timestamp = T::BlockTimestamp::now()
.try_into()
.map_err(|_| ())
.expect("Moment is the same type in both pallets; qed");
let transaction_byte_fee: Balance = T::StorageFee::transaction_byte_fee()
.try_into()
.map_err(|_| ())
.expect("Balance is the same type in both pallets; qed");
let timestamp = Self::timestamp_value();

// The value returned by the consensus_chain_byte_fee() runtime API
let consensus_transaction_byte_fee =
sp_domains::DOMAIN_STORAGE_FEE_MULTIPLIER * transaction_byte_fee;
let consensus_transaction_byte_fee = Self::consensus_transaction_byte_fee_value();

let invalid_inherent_extrinsic_data = InvalidInherentExtrinsicData {
let inherent_extrinsic_data = InherentExtrinsicData {
extrinsics_shuffling_seed,
timestamp,
consensus_transaction_byte_fee,
};

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

let _ = LastEpochStakingDistribution::<T>::clear(u32::MAX, None);
Expand Down Expand Up @@ -2770,12 +2763,66 @@ impl<T: Config> Pallet<T> {
false
}

/// The external function used to access the extrinsics shuffling seed stored in
/// `BlockInherentExtrinsicData`.
pub fn extrinsics_shuffling_seed() -> T::Hash {
// Fall back to recalculating if it hasn't been stored yet.
BlockInherentExtrinsicData::<T>::get()
.map(|data| H256::from(*data.extrinsics_shuffling_seed).into())
.unwrap_or_else(|| Self::extrinsics_shuffling_seed_value())
}

/// The internal function used to calculate the extrinsics shuffling seed for storage into
/// `BlockInherentExtrinsicData`.
fn extrinsics_shuffling_seed_value() -> T::Hash {
let subject = DOMAIN_EXTRINSICS_SHUFFLING_SEED_SUBJECT;
let (randomness, _) = T::Randomness::random(subject);
randomness
}

/// The external function used to access the timestamp stored in
/// `BlockInherentExtrinsicData`.
pub fn timestamp() -> Moment {
// Fall back to recalculating if it hasn't been stored yet.
BlockInherentExtrinsicData::<T>::get()
.map(|data| data.timestamp)
.unwrap_or_else(|| Self::timestamp_value())
}

/// The internal function used to access the timestamp for storage into
/// `BlockInherentExtrinsicData`.
fn timestamp_value() -> Moment {
// There are no actual conversions here, but the trait bounds required to prove that
// (and debug-print the error in expect()) are very verbose.
T::BlockTimestamp::now()
.try_into()
.map_err(|_| ())
.expect("Moment is the same type in both pallets; qed")
}

/// The external function used to access the consensus transaction byte fee stored in
/// `BlockInherentExtrinsicData`.
/// This value is returned by the consensus_chain_byte_fee() runtime API
pub fn consensus_transaction_byte_fee() -> Balance {
// Fall back to recalculating if it hasn't been stored yet.
BlockInherentExtrinsicData::<T>::get()
.map(|data| data.consensus_transaction_byte_fee)
.unwrap_or_else(|| Self::consensus_transaction_byte_fee_value())
}

/// The internal function used to calculate the consensus transaction byte fee for storage into
/// `BlockInherentExtrinsicData`.
fn consensus_transaction_byte_fee_value() -> Balance {
// There are no actual conversions here, but the trait bounds required to prove that
// (and debug-print the error in expect()) are very verbose.
let transaction_byte_fee: Balance = T::StorageFee::transaction_byte_fee()
.try_into()
.map_err(|_| ())
.expect("Balance is the same type in both pallets; qed");

sp_domains::DOMAIN_STORAGE_FEE_MULTIPLIER * transaction_byte_fee
}

pub fn execution_receipt(receipt_hash: ReceiptHashFor<T>) -> Option<ExecutionReceiptOf<T>> {
BlockTreeNodes::<T>::get(receipt_hash).map(|db| db.execution_receipt)
}
Expand Down
6 changes: 3 additions & 3 deletions crates/sp-domains-fraud-proof/src/storage_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ impl MaybeDomainRuntimeUpgradedProof {
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct InvalidInherentExtrinsicData {
pub struct InherentExtrinsicData {
/// Extrinsics shuffling seed, derived from block randomness
pub extrinsics_shuffling_seed: Randomness,

Expand All @@ -380,7 +380,7 @@ pub struct InvalidInherentExtrinsicData {
pub consensus_transaction_byte_fee: Balance,
}

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

Expand All @@ -389,7 +389,7 @@ pub struct InvalidInherentExtrinsicDataProof(StorageProof);

impl_storage_proof!(InvalidInherentExtrinsicDataProof);
impl<Block: BlockT> BasicStorageProof<Block> for InvalidInherentExtrinsicDataProof {
type StorageValue = InvalidInherentExtrinsicData;
type StorageValue = InherentExtrinsicData;
fn storage_key_request(_key: Self::Key) -> FraudProofStorageKeyRequest<NumberFor<Block>> {
FraudProofStorageKeyRequest::InvalidInherentExtrinsicData
}
Expand Down
11 changes: 0 additions & 11 deletions crates/sp-domains/src/extrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#[cfg(not(feature = "std"))]
extern crate alloc;

use crate::DOMAIN_EXTRINSICS_SHUFFLING_SEED_SUBJECT;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use domain_runtime_primitives::opaque::AccountId;
use hash_db::Hasher;
use rand::seq::SliceRandom;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
Expand All @@ -15,15 +13,6 @@ use sp_std::collections::vec_deque::VecDeque;
use sp_std::fmt::Debug;
use subspace_core_primitives::Randomness;

pub fn extrinsics_shuffling_seed<Hashing>(block_randomness: Randomness) -> Hashing::Out
where
Hashing: Hasher,
{
let mut subject = DOMAIN_EXTRINSICS_SHUFFLING_SEED_SUBJECT.to_vec();
subject.extend_from_slice(block_randomness.as_ref());
Hashing::hash(&subject)
}

pub fn deduplicate_and_shuffle_extrinsics<Extrinsic>(
mut extrinsics: Vec<(Option<AccountId>, Extrinsic)>,
shuffling_seed: Randomness,
Expand Down
24 changes: 18 additions & 6 deletions crates/sp-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1470,8 +1470,9 @@ pub enum OperatorRewardSource<Number> {
sp_api::decl_runtime_apis! {
/// 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)]
// TODO: when removing this version, also remove "Only present in API versions" comments and
// deprecated attributes.
#[api_version(3)]
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 Down Expand Up @@ -1502,8 +1503,23 @@ sp_api::decl_runtime_apis! {
fn domain_instance_data(domain_id: DomainId) -> Option<(DomainInstanceData, NumberFor<Block>)>;

/// Returns the current timestamp at the current height.
fn domain_timestamp() -> Moment;

/// Returns the current timestamp at the current height.
#[allow(clippy::deprecated_semver)]
#[deprecated(since = "3", note = "Use `domain_timestamp()` instead")]
fn timestamp() -> Moment;

/// Returns the consensus transaction byte fee that will used to charge the domain
/// transaction for consensus chain storage fees.
fn consensus_transaction_byte_fee() -> Balance;

/// Returns the consensus chain byte fee that will used to charge the domain transaction
/// for consensus chain storage fees.
#[allow(clippy::deprecated_semver)]
#[deprecated(since = "3", note = "Use `consensus_transaction_byte_fee()` instead")]
fn consensus_chain_byte_fee() -> Balance;

/// Returns the current Tx range for the given domain Id.
fn domain_tx_range(domain_id: DomainId) -> U256;

Expand Down Expand Up @@ -1534,10 +1550,6 @@ sp_api::decl_runtime_apis! {
/// Returns the execution receipt hash of the given domain and domain block number.
fn receipt_hash(domain_id: DomainId, domain_number: HeaderNumberFor<DomainHeader>) -> Option<HeaderHashFor<DomainHeader>>;

/// Returns the consensus chain byte fee that will used to charge the domain transaction for consensus
/// chain storage fees.
fn consensus_chain_byte_fee() -> Balance;

/// Returns the latest confirmed domain block number and hash.
fn latest_confirmed_domain_block(domain_id: DomainId) -> Option<(HeaderNumberFor<DomainHeader>, HeaderHashFor<DomainHeader>)>;

Expand Down
18 changes: 13 additions & 5 deletions crates/subspace-fake-runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,19 @@ sp_api::impl_runtime_apis! {
unreachable!()
}

fn timestamp() -> Moment{
fn domain_timestamp() -> Moment {
unreachable!()
}

fn timestamp() -> Moment {
unreachable!()
}

fn consensus_transaction_byte_fee() -> Balance {
unreachable!()
}

fn consensus_chain_byte_fee() -> Balance {
unreachable!()
}

Expand Down Expand Up @@ -262,10 +274,6 @@ sp_api::impl_runtime_apis! {
unreachable!()
}

fn consensus_chain_byte_fee() -> Balance {
unreachable!()
}

fn latest_confirmed_domain_block(_domain_id: DomainId) -> Option<(DomainNumber, DomainHash)>{
unreachable!()
}
Expand Down
20 changes: 14 additions & 6 deletions crates/subspace-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,7 @@ impl FraudProofStorageKeyProvider<NumberFor<Block>> for StorageKeyProvider {
fn storage_key(req: FraudProofStorageKeyRequest<NumberFor<Block>>) -> Vec<u8> {
match req {
FraudProofStorageKeyRequest::InvalidInherentExtrinsicData => {
pallet_domains::BlockInvalidInherentExtrinsicData::<Runtime>::hashed_key().to_vec()
pallet_domains::BlockInherentExtrinsicData::<Runtime>::hashed_key().to_vec()
}
FraudProofStorageKeyRequest::SuccessfulBundles(domain_id) => {
pallet_domains::SuccessfulBundles::<Runtime>::hashed_key_for(domain_id)
Expand Down Expand Up @@ -1278,10 +1278,22 @@ impl_runtime_apis! {
Domains::domain_instance_data(domain_id)
}

fn timestamp() -> Moment{
fn domain_timestamp() -> Moment {
Domains::timestamp()
}

fn timestamp() -> Moment {
Timestamp::now()
}

fn consensus_transaction_byte_fee() -> Balance {
Domains::consensus_transaction_byte_fee()
}

fn consensus_chain_byte_fee() -> Balance {
DOMAIN_STORAGE_FEE_MULTIPLIER * TransactionFees::transaction_byte_fee()
}

fn domain_tx_range(domain_id: DomainId) -> U256 {
Domains::domain_tx_range(domain_id)
}
Expand Down Expand Up @@ -1325,10 +1337,6 @@ impl_runtime_apis! {
Domains::receipt_hash(domain_id, domain_number)
}

fn consensus_chain_byte_fee() -> Balance {
DOMAIN_STORAGE_FEE_MULTIPLIER * TransactionFees::transaction_byte_fee()
}

fn latest_confirmed_domain_block(domain_id: DomainId) -> Option<(DomainNumber, DomainHash)>{
Domains::latest_confirmed_domain_block(domain_id)
}
Expand Down
24 changes: 21 additions & 3 deletions domains/client/block-preprocessor/src/inherents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,22 @@ where
let consensus_block_hash = self
.maybe_consensus_block_hash
.unwrap_or(self.consensus_client.info().best_hash);

let runtime_api = self.consensus_client.runtime_api();
let timestamp = runtime_api.timestamp(consensus_block_hash)?;
// Some APIs are only present in API versions 3 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 timestamp = if domains_api_version >= 3 {
runtime_api.domain_timestamp(consensus_block_hash)?
} else {
#[allow(deprecated)]
runtime_api.timestamp(consensus_block_hash)?
};
let timestamp_provider =
sp_timestamp::InherentDataProvider::new(InherentType::new(timestamp));

Expand All @@ -208,8 +222,12 @@ where
let runtime_upgrade_provider =
sp_executive::InherentDataProvider::new(maybe_runtime_upgrade_code);

let consensus_chain_byte_fee =
runtime_api.consensus_chain_byte_fee(consensus_block_hash)?;
let consensus_chain_byte_fee = if domains_api_version >= 3 {
runtime_api.consensus_transaction_byte_fee(consensus_block_hash)?
} else {
#[allow(deprecated)]
runtime_api.consensus_chain_byte_fee(consensus_block_hash)?
};
let storage_price_provider =
sp_block_fees::InherentDataProvider::new(consensus_chain_byte_fee);

Expand Down
Loading

0 comments on commit 9ce216e

Please sign in to comment.