,
enable_version_guard: bool,
) -> relay_substrate_client::Result<()> {
if enable_version_guard {
relay_substrate_client::guard::abort_on_spec_version_change(
source_client.clone(),
source_client.simple_runtime_version().await?.spec_version,
);
}
Ok(())
}
}
type FinalityProoffOf = <
::FinalityEngine as Engine<
::SourceChain,
>>::FinalityProof;
type FinalityVerificationContextfOf
=
<
::FinalityEngine as Engine<
::SourceChain,
>>::FinalityVerificationContext;
/// The type of the equivocation proof used by the `SubstrateEquivocationDetectionPipeline`
pub type EquivocationProofOf
= <
::FinalityEngine as Engine<
::SourceChain,
>>::EquivocationProof;
type EquivocationsFinderOf
= <
::FinalityEngine as Engine<
::SourceChain,
>>::EquivocationsFinder;
/// The type of the key owner proof used by the `SubstrateEquivocationDetectionPipeline`
pub type KeyOwnerProofOf
= <
::FinalityEngine as Engine<
::SourceChain,
>>::KeyOwnerProof;
/// Adapter that allows a `SubstrateEquivocationDetectionPipeline` to act as an
/// `EquivocationDetectionPipeline`.
#[derive(Clone, Debug)]
pub struct EquivocationDetectionPipelineAdapter {
_phantom: PhantomData,
}
impl FinalityPipeline
for EquivocationDetectionPipelineAdapter
{
const SOURCE_NAME: &'static str = P::SourceChain::NAME;
const TARGET_NAME: &'static str = P::TargetChain::NAME;
type Hash = HashOf;
type Number = BlockNumberOf;
type FinalityProof = SubstrateFinalityProof;
}
impl EquivocationDetectionPipeline
for EquivocationDetectionPipelineAdapter
{
type TargetNumber = BlockNumberOf;
type FinalityVerificationContext = FinalityVerificationContextfOf;
type EquivocationProof = EquivocationProofOf
;
type EquivocationsFinder = EquivocationsFinderOf
;
}
/// Different ways of building `report_equivocation` calls.
pub trait ReportEquivocationCallBuilder {
/// Build a `report_equivocation` call to be executed on the source chain.
fn build_report_equivocation_call(
equivocation_proof: EquivocationProofOf,
key_owner_proof: KeyOwnerProofOf
,
) -> CallOf;
}
/// Building the `report_equivocation` call when having direct access to the target chain runtime.
pub struct DirectReportGrandpaEquivocationCallBuilder {
_phantom: PhantomData<(P, R)>,
}
impl
ReportEquivocationCallBuilder
for DirectReportGrandpaEquivocationCallBuilder
where
P: SubstrateEquivocationDetectionPipeline,
P::FinalityEngine: Engine<
P::SourceChain,
EquivocationProof = sp_consensus_grandpa::EquivocationProof<
HashOf,
BlockNumberOf,
>,
>,
R: frame_system::Config>
+ GrandpaConfig>,
::Header: Header>,
CallOf: From>,
{
fn build_report_equivocation_call(
equivocation_proof: EquivocationProofOf,
key_owner_proof: KeyOwnerProofOf
,
) -> CallOf {
GrandpaCall::::report_equivocation {
equivocation_proof: Box::new(equivocation_proof),
key_owner_proof,
}
.into()
}
}
/// Macro that generates `ReportEquivocationCallBuilder` implementation for the case where
/// we only have access to the mocked version of the source chain runtime.
#[rustfmt::skip]
#[macro_export]
macro_rules! generate_report_equivocation_call_builder {
($pipeline:ident, $mocked_builder:ident, $grandpa:path, $report_equivocation:path) => {
pub struct $mocked_builder;
impl $crate::equivocation::ReportEquivocationCallBuilder<$pipeline>
for $mocked_builder
{
fn build_report_equivocation_call(
equivocation_proof: $crate::equivocation::EquivocationProofOf<$pipeline>,
key_owner_proof: $crate::equivocation::KeyOwnerProofOf<$pipeline>,
) -> relay_substrate_client::CallOf<
<$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain
> {
bp_runtime::paste::item! {
$grandpa($report_equivocation {
equivocation_proof: Box::new(equivocation_proof),
key_owner_proof: key_owner_proof
})
}
}
}
};
}
/// Run Substrate-to-Substrate equivocations detection loop.
pub async fn run(
source_client: Client,
target_client: Client,
source_transaction_params: TransactionParams>,
metrics_params: MetricsParams,
) -> anyhow::Result<()> {
log::info!(
target: "bridge",
"Starting {} -> {} equivocations detection loop",
P::SourceChain::NAME,
P::TargetChain::NAME,
);
equivocation_detector::run(
SubstrateEquivocationSource::::new(source_client, source_transaction_params),
SubstrateEquivocationTarget::
::new(target_client),
P::TargetChain::AVERAGE_BLOCK_INTERVAL,
metrics_params,
futures::future::pending(),
)
.await
.map_err(|e| anyhow::format_err!("{}", e))
}