Skip to content

Commit

Permalink
Merge pull request #2562 from subspace/xdm_mmr_2
Browse files Browse the repository at this point in the history
XDM: Relayer and Fraud proof updates
  • Loading branch information
vedhavyas authored Mar 5, 2024
2 parents 8fff19c + bfb2d38 commit 0d22229
Show file tree
Hide file tree
Showing 40 changed files with 1,367 additions and 664 deletions.
22 changes: 21 additions & 1 deletion Cargo.lock

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

7 changes: 7 additions & 0 deletions crates/pallet-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1988,6 +1988,13 @@ impl<T: Config> Pallet<T> {
.unwrap_or_default()
}

pub fn latest_confirmed_domain_block(
domain_id: DomainId,
) -> Option<(DomainBlockNumberFor<T>, T::DomainHash)> {
LatestConfirmedDomainBlock::<T>::get(domain_id)
.map(|block| (block.block_number, block.block_hash))
}

/// Returns the domain block limit of the given domain.
pub fn domain_block_limit(domain_id: DomainId) -> Option<DomainBlockLimit> {
DomainRegistry::<T>::get(domain_id).map(|domain_obj| DomainBlockLimit {
Expand Down
7 changes: 7 additions & 0 deletions crates/pallet-domains/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ pub(crate) struct MockDomainFraudProofExtension {
bundle_slot_probability: (u64, u64),
operator_stake: Balance,
maybe_illegal_extrinsic_index: Option<u32>,
is_valid_xdm: Option<bool>,
}

impl FraudProofHostFunctions for MockDomainFraudProofExtension {
Expand Down Expand Up @@ -432,6 +433,9 @@ impl FraudProofHostFunctions for MockDomainFraudProofExtension {
FraudProofVerificationInfoRequest::StorageKey { .. } => {
FraudProofVerificationInfoResponse::StorageKey(None)
}
FraudProofVerificationInfoRequest::XDMValidationCheck { .. } => {
FraudProofVerificationInfoResponse::XDMValidationCheck(self.is_valid_xdm)
}
};

Some(response)
Expand Down Expand Up @@ -1016,6 +1020,7 @@ fn test_invalid_domain_extrinsic_root_proof() {
operator_stake: 10 * SSC,
bundle_slot_probability: (0, 0),
maybe_illegal_extrinsic_index: None,
is_valid_xdm: None,
}));
ext.register_extension(fraud_proof_ext);

Expand Down Expand Up @@ -1097,6 +1102,7 @@ fn test_true_invalid_bundles_inherent_extrinsic_proof() {
operator_stake: 10 * SSC,
bundle_slot_probability: (0, 0),
maybe_illegal_extrinsic_index: None,
is_valid_xdm: None,
}));
ext.register_extension(fraud_proof_ext);

Expand Down Expand Up @@ -1164,6 +1170,7 @@ fn test_false_invalid_bundles_inherent_extrinsic_proof() {
operator_stake: 10 * SSC,
bundle_slot_probability: (0, 0),
maybe_illegal_extrinsic_index: None,
is_valid_xdm: None,
}));
ext.register_extension(fraud_proof_ext);

Expand Down
3 changes: 3 additions & 0 deletions crates/sp-domains-fraud-proof/src/fraud_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ pub enum VerificationError<DomainHash> {
error("Failed to check if a given extrinsic is inherent or not")
)]
FailedToCheckInherentExtrinsic,
/// Failed to check if a given extrinsic is inherent or not.
#[cfg_attr(feature = "thiserror", error("Failed to validate given XDM"))]
FailedToValidateXDM,
/// Failed to check if a given extrinsic is decodable or not.
#[cfg_attr(
feature = "thiserror",
Expand Down
66 changes: 53 additions & 13 deletions crates/sp-domains-fraud-proof/src/host_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,33 +85,33 @@ impl FraudProofExtension {
}

/// Trait Impl to query and verify Domains Fraud proof.
pub struct FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor> {
pub struct FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor, EFC> {
consensus_client: Arc<Client>,
executor: Arc<Executor>,
domain_extensions_factory: Box<dyn ExtensionsFactory<DomainBlock>>,
domain_extensions_factory_creator: EFC,
_phantom: PhantomData<(Block, DomainBlock)>,
}

impl<Block, Client, DomainBlock, Executor>
FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor>
impl<Block, Client, DomainBlock, Executor, EFC>
FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor, EFC>
{
pub fn new(
consensus_client: Arc<Client>,
executor: Arc<Executor>,
domain_extensions_factory: Box<dyn ExtensionsFactory<DomainBlock>>,
domain_extensions_factory_creator: EFC,
) -> Self {
FraudProofHostFunctionsImpl {
consensus_client,
executor,
domain_extensions_factory,
domain_extensions_factory_creator,
_phantom: Default::default(),
}
}
}

// TODO: Revisit the host function implementation once we decide best strategy to structure them.
impl<Block, Client, DomainBlock, Executor>
FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor>
impl<Block, Client, DomainBlock, Executor, EFC>
FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor, EFC>
where
Block: BlockT,
Block::Hash: From<H256>,
Expand All @@ -120,6 +120,7 @@ where
Client: BlockBackend<Block> + HeaderBackend<Block> + ProvideRuntimeApi<Block>,
Client::Api: DomainsApi<Block, DomainBlock::Header> + BundleProducerElectionApi<Block, Balance>,
Executor: CodeExecutor + RuntimeVersionOf,
EFC: Fn(Arc<Client>, Arc<Executor>) -> Box<dyn ExtensionsFactory<DomainBlock>> + Send + Sync,
{
fn get_block_randomness(&self, consensus_block_hash: H256) -> Option<Randomness> {
let runtime_api = self.consensus_client.runtime_api();
Expand Down Expand Up @@ -297,6 +298,36 @@ where
.ok()
}

fn is_valid_xdm(
&self,
consensus_block_hash: H256,
domain_id: DomainId,
opaque_extrinsic: OpaqueExtrinsic,
) -> Option<bool> {
let runtime_code = self.get_domain_runtime_code(consensus_block_hash, domain_id)?;
let mut domain_stateless_runtime =
StatelessRuntime::<DomainBlock, _>::new(self.executor.clone(), runtime_code.into());
let extension_factory = (self.domain_extensions_factory_creator)(
self.consensus_client.clone(),
self.executor.clone(),
);
domain_stateless_runtime.set_extension_factory(extension_factory);

let consensus_api = self.consensus_client.runtime_api();
let domain_initial_state = consensus_api
.domain_instance_data(consensus_block_hash.into(), domain_id)
.expect("Runtime Api must not fail. This is unrecoverable error")?
.0
.raw_genesis
.into_storage();
domain_stateless_runtime.set_storage(domain_initial_state);

let encoded_extrinsic = opaque_extrinsic.encode();
domain_stateless_runtime
.is_valid_xdm(encoded_extrinsic)
.expect("Runtime api must not fail. This is an unrecoverable error")
}

fn is_decodable_extrinsic(
&self,
consensus_block_hash: H256,
Expand Down Expand Up @@ -389,8 +420,8 @@ where
}
}

impl<Block, Client, DomainBlock, Executor> FraudProofHostFunctions
for FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor>
impl<Block, Client, DomainBlock, Executor, EFC> FraudProofHostFunctions
for FraudProofHostFunctionsImpl<Block, Client, DomainBlock, Executor, EFC>
where
Block: BlockT,
Block::Hash: From<H256>,
Expand All @@ -400,6 +431,7 @@ where
Client: BlockBackend<Block> + HeaderBackend<Block> + ProvideRuntimeApi<Block>,
Client::Api: DomainsApi<Block, DomainBlock::Header> + BundleProducerElectionApi<Block, Balance>,
Executor: CodeExecutor + RuntimeVersionOf,
EFC: Fn(Arc<Client>, Arc<Executor>) -> Box<dyn ExtensionsFactory<DomainBlock>> + Send + Sync,
{
fn get_fraud_proof_verification_info(
&self,
Expand Down Expand Up @@ -515,6 +547,12 @@ where
self.storage_key(consensus_block_hash, domain_id, req),
))
}
FraudProofVerificationInfoRequest::XDMValidationCheck {
domain_id,
opaque_extrinsic,
} => Some(FraudProofVerificationInfoResponse::XDMValidationCheck(
self.is_valid_xdm(consensus_block_hash, domain_id, opaque_extrinsic),
)),
}
}

Expand Down Expand Up @@ -574,9 +612,11 @@ where
};

let (domain_block_number, domain_block_hash) = domain_block_id;
let mut domain_extensions = self
.domain_extensions_factory
.extensions_for(domain_block_hash.into(), domain_block_number.into());
let mut domain_extensions = (self.domain_extensions_factory_creator)(
self.consensus_client.clone(),
self.executor.clone(),
)
.extensions_for(domain_block_hash.into(), domain_block_number.into());

execution_proof_check::<<DomainBlock::Header as HeaderT>::Hashing, _>(
pre_state_root.into(),
Expand Down
16 changes: 16 additions & 0 deletions crates/sp-domains-fraud-proof/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ pub enum FraudProofVerificationInfoRequest {
/// Extrinsic for which we need to if it is decodable or not.
opaque_extrinsic: OpaqueExtrinsic,
},
/// Request to check if the XDM is valid
XDMValidationCheck {
domain_id: DomainId,
/// Encoded XDM extrinsic that needs to be validated.
opaque_extrinsic: OpaqueExtrinsic,
},
/// Request to get Domain election params.
DomainElectionParams { domain_id: DomainId },
/// Request to get Operator stake.
Expand Down Expand Up @@ -186,6 +192,9 @@ pub enum FraudProofVerificationInfoResponse {
TxRangeCheck(bool),
/// If the particular extrinsic provided is either inherent or not.
InherentExtrinsicCheck(bool),
/// If the particular xdm extrinsic is valid or not.
/// Returns None if extrinsic is not an XDM
XDMValidationCheck(Option<bool>),
/// If the domain extrinsic is decodable or not.
ExtrinsicDecodableCheck(bool),
/// Domain's total stake at a given Consensus hash.
Expand Down Expand Up @@ -264,6 +273,13 @@ impl FraudProofVerificationInfoResponse {
}
}

pub fn into_xdm_validation_check(self) -> Option<bool> {
match self {
FraudProofVerificationInfoResponse::XDMValidationCheck(maybe_valid) => maybe_valid,
_ => None,
}
}

pub fn into_extrinsic_decodable_check(self) -> Option<bool> {
match self {
FraudProofVerificationInfoResponse::ExtrinsicDecodableCheck(is_decodable) => {
Expand Down
27 changes: 25 additions & 2 deletions crates/sp-domains-fraud-proof/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,9 +633,32 @@ where
}
Ok(())
}
InvalidBundleType::InvalidXDM(extrinsic_index) => {
let extrinsic = get_extrinsic_from_proof::<DomainHeader>(
*extrinsic_index,
invalid_bundle_entry.extrinsics_root,
invalid_bundles_fraud_proof.proof_data.clone(),
)?;

// TODO: implement the other invalid bundle types
_ => Err(VerificationError::InvalidProof),
let is_valid_xdm = get_fraud_proof_verification_info(
H256::from_slice(bad_receipt.consensus_block_hash.as_ref()),
FraudProofVerificationInfoRequest::XDMValidationCheck {
domain_id: invalid_bundles_fraud_proof.domain_id,
opaque_extrinsic: extrinsic,
},
)
.and_then(FraudProofVerificationInfoResponse::into_xdm_validation_check)
.ok_or(VerificationError::FailedToValidateXDM)?;

// Proof to be considered valid only,
// If it is true invalid fraud proof then extrinsic must be an invalid xdm and
// If it is false invalid fraud proof then extrinsic must be a valid xdm
if is_valid_xdm != invalid_bundles_fraud_proof.is_true_invalid_fraud_proof {
Ok(())
} else {
Err(VerificationError::InvalidProof)
}
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions crates/sp-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,8 +1007,8 @@ impl InvalidBundleType {
Self::UndecodableTx(_) => 1,
Self::OutOfRangeTx(_) => 2,
Self::InherentExtrinsic(_) => 3,
Self::IllegalTx(_) => 4,
Self::InvalidXDM(_) => 5,
Self::InvalidXDM(_) => 4,
Self::IllegalTx(_) => 5,
}
}

Expand Down Expand Up @@ -1248,10 +1248,13 @@ 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>>;

/// Reture the consensus chain byte fee that will used to charge the domain transaction for consensus
/// Return the consensus chain byte fee that will used to charge the domain transaction for consensus
/// chain storage fee
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>)>;

/// Return if the receipt is exist and pending to prune
fn is_bad_er_pending_to_prune(domain_id: DomainId, receipt_hash: HeaderHashFor<DomainHeader>) -> bool;
}
Expand Down
Loading

0 comments on commit 0d22229

Please sign in to comment.