Skip to content

Commit

Permalink
Merge branch 'main' into remove-history-seeding
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 authored Dec 16, 2024
2 parents 3a0ca7f + 3d5483e commit fa3ae47
Show file tree
Hide file tree
Showing 31 changed files with 657 additions and 361 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/rustsec-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ jobs:
- uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998 #v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
# TODO: Remove once Substrate upgrades litep2p and we no longer have rustls 0.20.9 in our dependencies
ignore: RUSTSEC-2024-0336
# TODO: Remove first once Substrate upgrades litep2p and we no longer have rustls 0.20.9 in our dependencies
# TODO: Remove second once Substrate upgrades libp2p and we no longer have old idna in our dependencies
ignore: RUSTSEC-2024-0336,RUSTSEC-2024-0421
2 changes: 1 addition & 1 deletion crates/pallet-domains/src/block_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ pub(crate) fn prune_receipt<T: Config>(
// If the pruned ER is the operator's `latest_submitted_er` for this domain, it means either:
//
// - All the ER the operator submitted for this domain are confirmed and pruned, so the operator
// can't be targetted by fraud proof later unless it submit other new ERs.
// can't be targeted by fraud proof later unless it submit other new ERs.
//
// - All the bad ER the operator submitted for this domain are pruned and the operator is already
// slashed, so wwe don't need `LatestSubmittedER` to determine if the operator is pending slash.
Expand Down
2 changes: 1 addition & 1 deletion crates/pallet-domains/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ fn test_basic_fraud_proof_processing() {

for block_number in bad_receipt_at..=head_domain_number {
if block_number == bad_receipt_at {
// The targetted ER should be removed from the block tree
// The targeted ER should be removed from the block tree
assert!(BlockTree::<Test>::get(domain_id, block_number).is_none());
} else {
// All the bad ER's descendants should be marked as pending to prune and the submitter
Expand Down
16 changes: 9 additions & 7 deletions crates/sp-domains-fraud-proof/src/fraud_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,13 @@ pub struct FraudProof<Number, Hash, DomainHeader: HeaderT, MmrHash> {
pub domain_id: DomainId,
/// Hash of the bad receipt this fraud proof targeted
pub bad_receipt_hash: HeaderHashFor<DomainHeader>,
/// The MMR proof for the consensus state root that used to verify the storage proof
/// The MMR proof for the consensus state root that is used to verify the storage proof
///
/// It is set `None` if the specific fraud proof variant doesn't contains storage proof
/// It is set `None` if the specific fraud proof variant doesn't contain a storage proof
pub maybe_mmr_proof: Option<ConsensusChainMmrLeafProof<Number, Hash, MmrHash>>,
/// The domain runtime code storage proof
///
/// It is set `None` if the specific fraud proof variant doesn't required domain runtime code
/// It is set `None` if the specific fraud proof variant doesn't require domain runtime code
/// or the required domain runtime code is available from the current runtime state.
pub maybe_domain_runtime_code_proof: Option<DomainRuntimeCodeAt<Number, Hash, MmrHash>>,
/// The specific fraud proof variant
Expand Down Expand Up @@ -485,18 +485,20 @@ pub struct InvalidStateTransitionProof {
/// Fraud proof for the valid bundles in `ExecutionReceipt::inboxed_bundles`
#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct ValidBundleProof<Number, Hash, DomainHeader: HeaderT> {
/// The targetted bundle with proof
/// The targeted bundle with proof
pub bundle_with_proof: OpaqueBundleWithProof<Number, Hash, DomainHeader, Balance>,
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct InvalidExtrinsicsRootProof {
/// Valid Bundle digests
pub valid_bundle_digests: Vec<ValidBundleDigest>,
/// Block randomness storage proof
pub block_randomness_proof: BlockRandomnessProof,

/// The storage proof used during verification
pub domain_inherent_extrinsic_data_proof: DomainInherentExtrinsicDataProof,
pub invalid_inherent_extrinsic_proof: InvalidInherentExtrinsicProof,

/// Optional sudo extrinsic call storage proof
pub domain_sudo_call_proof: DomainSudoCallStorageProof,
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
Expand Down
2 changes: 2 additions & 0 deletions crates/sp-domains-fraud-proof/src/host_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ where
domain_inherent_extrinsic_data: DomainInherentExtrinsicData,
) -> Option<DomainInherentExtrinsic> {
let DomainInherentExtrinsicData {
// Used by caller
block_randomness: _,
timestamp,
maybe_domain_runtime_upgrade,
consensus_transaction_byte_fee,
Expand Down
3 changes: 2 additions & 1 deletion crates/sp-domains-fraud-proof/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::U256;
use subspace_core_primitives::{Randomness, U256};
use subspace_runtime_primitives::{Balance, Moment};

/// Custom invalid validity code for the extrinsics in pallet-domains.
Expand Down Expand Up @@ -108,6 +108,7 @@ 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<Vec<u8>>,
pub consensus_transaction_byte_fee: Balance,
Expand Down
46 changes: 27 additions & 19 deletions crates/sp-domains-fraud-proof/src/storage_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub enum VerificationError {
RuntimeRegistryStorageProof(StorageProofVerificationError),
DynamicCostOfStorageStorageProof(StorageProofVerificationError),
DigestStorageProof(StorageProofVerificationError),
BlockFessStorageProof(StorageProofVerificationError),
BlockFeesStorageProof(StorageProofVerificationError),
TransfersStorageProof(StorageProofVerificationError),
ExtrinsicStorageProof(StorageProofVerificationError),
DomainSudoCallStorageProof(StorageProofVerificationError),
Expand Down Expand Up @@ -414,16 +414,27 @@ impl MaybeDomainRuntimeUpgradedProof {
}

#[derive(Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo)]
pub struct DomainInherentExtrinsicDataProof {
pub struct InvalidInherentExtrinsicProof {
/// Block randomness storage proof
pub block_randomness_proof: BlockRandomnessProof,

/// Block timestamp storage proof
pub timestamp_proof: TimestampStorageProof,

/// Optional domain runtime code upgrade storage proof
pub maybe_domain_runtime_upgrade_proof: MaybeDomainRuntimeUpgradedProof,

/// Boolean indicating if dynamic cost of storage was used (but as a storage proof)
pub dynamic_cost_of_storage_proof: DynamicCostOfStorageProof,

/// Transaction fee storage proof
pub consensus_chain_byte_fee_proof: ConsensusTransactionByteFeeProof,

/// Change in the allowed chains storage proof
pub domain_chain_allowlist_proof: DomainChainsAllowlistUpdateStorageProof,
pub domain_sudo_call_proof: DomainSudoCallStorageProof,
}

impl DomainInherentExtrinsicDataProof {
impl InvalidInherentExtrinsicProof {
#[cfg(feature = "std")]
#[allow(clippy::let_and_return)]
pub fn generate<
Expand All @@ -437,6 +448,8 @@ impl DomainInherentExtrinsicDataProof {
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 @@ -464,20 +477,13 @@ impl DomainInherentExtrinsicDataProof {
storage_key_provider,
)?;

let domain_sudo_call_proof = DomainSudoCallStorageProof::generate(
proof_provider,
block_hash,
domain_id,
storage_key_provider,
)?;

Ok(Self {
block_randomness_proof,
timestamp_proof,
maybe_domain_runtime_upgrade_proof,
dynamic_cost_of_storage_proof,
consensus_chain_byte_fee_proof,
domain_chain_allowlist_proof,
domain_sudo_call_proof,
})
}

Expand All @@ -487,6 +493,12 @@ impl DomainInherentExtrinsicDataProof {
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,
)?;

let timestamp = <TimestampStorageProof as BasicStorageProof<Block>>::verify::<SKP>(
self.timestamp_proof.clone(),
(),
Expand Down Expand Up @@ -523,18 +535,14 @@ impl DomainInherentExtrinsicDataProof {
state_root,
)?;

let domain_sudo_call = <DomainSudoCallStorageProof as BasicStorageProof<Block>>::verify::<
SKP,
>(
self.domain_sudo_call_proof.clone(), domain_id, state_root
)?;

Ok(DomainInherentExtrinsicData {
block_randomness,
timestamp,
maybe_domain_runtime_upgrade,
consensus_transaction_byte_fee,
domain_chain_allowlist,
maybe_sudo_runtime_call: domain_sudo_call.maybe_call,
// Populated by caller
maybe_sudo_runtime_call: None,
})
}
}
Expand Down
24 changes: 13 additions & 11 deletions crates/sp-domains-fraud-proof/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,24 @@ where
{
let InvalidExtrinsicsRootProof {
valid_bundle_digests,
block_randomness_proof,
domain_inherent_extrinsic_data_proof,
..
invalid_inherent_extrinsic_proof,
domain_sudo_call_proof,
} = fraud_proof;

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

let block_randomness = <BlockRandomnessProof as BasicStorageProof<CBlock>>::verify::<SKP>(
block_randomness_proof.clone(),
(),
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 DomainInherentExtrinsic {
domain_timestamp_extrinsic,
Expand Down Expand Up @@ -110,9 +115,6 @@ where
bundle_extrinsics_digests.extend(bundle_digest.bundle_digest.clone());
}

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

let mut ordered_extrinsics = deduplicate_and_shuffle_extrinsics(
bundle_extrinsics_digests,
Randomness::from(shuffling_seed.to_fixed_bytes()),
Expand Down Expand Up @@ -379,7 +381,7 @@ where
)
.map_err(|err| {
VerificationError::StorageProof(
storage_proof::VerificationError::BlockFessStorageProof(err),
storage_proof::VerificationError::BlockFeesStorageProof(err),
)
})?;

Expand Down
48 changes: 34 additions & 14 deletions crates/subspace-core-primitives/src/pieces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ impl PieceIndex {
/// Piece index 1.
pub const ONE: PieceIndex = PieceIndex(1);

/// Create new instance
#[inline]
pub const fn new(n: u64) -> Self {
Self(n)
}

/// Create piece index from bytes.
#[inline]
pub const fn from_bytes(bytes: [u8; Self::SIZE]) -> Self {
Expand All @@ -114,8 +120,8 @@ impl PieceIndex {

/// Segment index piece index corresponds to
#[inline]
pub fn segment_index(&self) -> SegmentIndex {
SegmentIndex::from(self.0 / ArchivedHistorySegment::NUM_PIECES as u64)
pub const fn segment_index(&self) -> SegmentIndex {
SegmentIndex::new(self.0 / ArchivedHistorySegment::NUM_PIECES as u64)
}

/// Position of a piece in a segment
Expand All @@ -130,28 +136,42 @@ impl PieceIndex {
#[inline]
pub const fn source_position(&self) -> u32 {
assert!(self.is_source());
self.position() / (Self::source_ratio() as u32)

let source_start = self.position() / RecordedHistorySegment::ERASURE_CODING_RATE.1 as u32
* RecordedHistorySegment::ERASURE_CODING_RATE.0 as u32;
let source_offset = self.position() % RecordedHistorySegment::ERASURE_CODING_RATE.1 as u32;

source_start + source_offset
}

/// Returns the piece index for a source position and segment index.
/// Overflows to the next segment if the position is greater than the last source position.
#[inline]
pub const fn from_source_position(
source_position: u32,
segment_index: SegmentIndex,
) -> PieceIndex {
let source_position = source_position as u64;
let start = source_position / RecordedHistorySegment::ERASURE_CODING_RATE.0 as u64
* RecordedHistorySegment::ERASURE_CODING_RATE.1 as u64;
let offset = source_position % RecordedHistorySegment::ERASURE_CODING_RATE.0 as u64;

PieceIndex(segment_index.first_piece_index().0 + start + offset)
}

/// Is this piece index a source piece?
#[inline]
pub const fn is_source(&self) -> bool {
// Source pieces are interleaved with parity pieces, source first
self.0 % Self::source_ratio() == 0
self.0 % (RecordedHistorySegment::ERASURE_CODING_RATE.1 as u64)
< (RecordedHistorySegment::ERASURE_CODING_RATE.0 as u64)
}

/// Returns the next source piece index
/// Returns the next source piece index.
/// Panics if the piece is not a source piece.
#[inline]
pub const fn next_source_index(&self) -> PieceIndex {
PieceIndex(self.0.next_multiple_of(Self::source_ratio()))
}

/// The ratio of source pieces to all pieces
#[inline]
const fn source_ratio() -> u64 {
// Assumes the result is an integer
(RecordedHistorySegment::ERASURE_CODING_RATE.1
/ RecordedHistorySegment::ERASURE_CODING_RATE.0) as u64
PieceIndex::from_source_position(self.source_position() + 1, self.segment_index())
}
}

Expand Down
10 changes: 6 additions & 4 deletions crates/subspace-core-primitives/src/segments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,15 @@ impl SegmentIndex {
}

/// Get the first piece index in this segment.
pub fn first_piece_index(&self) -> PieceIndex {
PieceIndex::from(self.0 * ArchivedHistorySegment::NUM_PIECES as u64)
#[inline]
pub const fn first_piece_index(&self) -> PieceIndex {
PieceIndex::new(self.0 * ArchivedHistorySegment::NUM_PIECES as u64)
}

/// Get the last piece index in this segment.
pub fn last_piece_index(&self) -> PieceIndex {
PieceIndex::from((self.0 + 1) * ArchivedHistorySegment::NUM_PIECES as u64 - 1)
#[inline]
pub const fn last_piece_index(&self) -> PieceIndex {
PieceIndex::new((self.0 + 1) * ArchivedHistorySegment::NUM_PIECES as u64 - 1)
}

/// List of piece indexes that belong to this segment.
Expand Down
Loading

0 comments on commit fa3ae47

Please sign in to comment.