substrate_relay_helper/equivocation/
source.rs1use crate::{
20 equivocation::{
21 EquivocationDetectionPipelineAdapter, EquivocationProofOf, ReportEquivocationCallBuilder,
22 SubstrateEquivocationDetectionPipeline,
23 },
24 finality_base::{engine::Engine, finality_proofs, SubstrateFinalityProofsStream},
25 TransactionParams,
26};
27
28use async_trait::async_trait;
29use bp_runtime::{HashOf, TransactionEra};
30use equivocation_detector::SourceClient;
31use finality_relay::SourceClientBase;
32use relay_substrate_client::{
33 AccountKeyPairOf, Client, Error, TransactionTracker, UnsignedTransaction,
34};
35use relay_utils::relay_loop::Client as RelayClient;
36
37pub struct SubstrateEquivocationSource<P: SubstrateEquivocationDetectionPipeline, SourceClnt> {
39 client: SourceClnt,
40 transaction_params: TransactionParams<AccountKeyPairOf<P::SourceChain>>,
41}
42
43impl<P: SubstrateEquivocationDetectionPipeline, SourceClnt: Client<P::SourceChain>>
44 SubstrateEquivocationSource<P, SourceClnt>
45{
46 pub fn new(
48 client: SourceClnt,
49 transaction_params: TransactionParams<AccountKeyPairOf<P::SourceChain>>,
50 ) -> Self {
51 Self { client, transaction_params }
52 }
53}
54
55impl<P: SubstrateEquivocationDetectionPipeline, SourceClnt: Client<P::SourceChain>> Clone
56 for SubstrateEquivocationSource<P, SourceClnt>
57{
58 fn clone(&self) -> Self {
59 Self { client: self.client.clone(), transaction_params: self.transaction_params.clone() }
60 }
61}
62
63#[async_trait]
64impl<P: SubstrateEquivocationDetectionPipeline, SourceClnt: Client<P::SourceChain>> RelayClient
65 for SubstrateEquivocationSource<P, SourceClnt>
66{
67 type Error = Error;
68
69 async fn reconnect(&mut self) -> Result<(), Error> {
70 self.client.reconnect().await
71 }
72}
73
74#[async_trait]
75impl<P: SubstrateEquivocationDetectionPipeline, SourceClnt: Client<P::SourceChain>>
76 SourceClientBase<EquivocationDetectionPipelineAdapter<P>>
77 for SubstrateEquivocationSource<P, SourceClnt>
78{
79 type FinalityProofsStream = SubstrateFinalityProofsStream<P>;
80
81 async fn finality_proofs(&self) -> Result<Self::FinalityProofsStream, Error> {
82 finality_proofs::<P>(&self.client).await
83 }
84}
85
86#[async_trait]
87impl<P: SubstrateEquivocationDetectionPipeline, SourceClnt: Client<P::SourceChain>>
88 SourceClient<EquivocationDetectionPipelineAdapter<P>>
89 for SubstrateEquivocationSource<P, SourceClnt>
90{
91 type TransactionTracker = TransactionTracker<P::SourceChain, SourceClnt>;
92
93 async fn report_equivocation(
94 &self,
95 at: HashOf<P::SourceChain>,
96 equivocation: EquivocationProofOf<P>,
97 ) -> Result<Self::TransactionTracker, Self::Error> {
98 let key_owner_proof =
99 P::FinalityEngine::generate_source_key_ownership_proof(&self.client, at, &equivocation)
100 .await?;
101
102 let mortality = self.transaction_params.mortality;
103 let call = P::ReportEquivocationCallBuilder::build_report_equivocation_call(
104 equivocation,
105 key_owner_proof,
106 );
107 self.client
108 .submit_and_watch_signed_extrinsic(
109 &self.transaction_params.signer,
110 move |best_block_id, transaction_nonce| {
111 Ok(UnsignedTransaction::new(call.into(), transaction_nonce)
112 .era(TransactionEra::new(best_block_id, mortality)))
113 },
114 )
115 .await
116 }
117}