pallet_bridge_relayers/extension/
grandpa_adapter.rs1use crate::{
21 extension::verify_messages_call_succeeded, Config as BridgeRelayersConfig, LOG_TARGET,
22};
23
24use bp_relayers::{BatchCallUnpacker, ExtensionCallData, ExtensionCallInfo, ExtensionConfig};
25use bp_runtime::{Chain, StaticStrProvider};
26use core::marker::PhantomData;
27use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
28use frame_system::Config as SystemConfig;
29use pallet_bridge_grandpa::{
30 CallSubType as BridgeGrandpaCallSubtype, Config as BridgeGrandpaConfig,
31 SubmitFinalityProofHelper,
32};
33use pallet_bridge_messages::{
34 CallSubType as BridgeMessagesCallSubType, Config as BridgeMessagesConfig, LaneIdOf,
35};
36use sp_runtime::{
37 traits::{Dispatchable, Get},
38 transaction_validity::{TransactionPriority, TransactionValidityError},
39 Saturating,
40};
41
42pub struct WithGrandpaChainExtensionConfig<
45 IdProvider,
47 Runtime,
51 BatchCallUnpacker,
53 BridgeGrandpaPalletInstance,
55 BridgeMessagesPalletInstance,
57 BridgeRelayersPalletInstance,
59 PriorityBoostPerMessage,
61>(
62 PhantomData<(
63 IdProvider,
64 Runtime,
65 BatchCallUnpacker,
66 BridgeGrandpaPalletInstance,
67 BridgeMessagesPalletInstance,
68 BridgeRelayersPalletInstance,
69 PriorityBoostPerMessage,
70 )>,
71);
72
73impl<ID, R, BCU, GI, MI, RI, P> ExtensionConfig
74 for WithGrandpaChainExtensionConfig<ID, R, BCU, GI, MI, RI, P>
75where
76 ID: StaticStrProvider,
77 R: BridgeRelayersConfig<RI>
78 + BridgeMessagesConfig<MI, BridgedChain = pallet_bridge_grandpa::BridgedChain<R, GI>>
79 + BridgeGrandpaConfig<GI>,
80 BCU: BatchCallUnpacker<R>,
81 GI: 'static,
82 MI: 'static,
83 RI: 'static,
84 P: Get<TransactionPriority>,
85 R::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>
86 + BridgeGrandpaCallSubtype<R, GI>
87 + BridgeMessagesCallSubType<R, MI>,
88{
89 type IdProvider = ID;
90 type Runtime = R;
91 type BridgeMessagesPalletInstance = MI;
92 type BridgeRelayersPalletInstance = RI;
93 type PriorityBoostPerMessage = P;
94 type RemoteGrandpaChainBlockNumber = pallet_bridge_grandpa::BridgedBlockNumber<R, GI>;
95 type LaneId = LaneIdOf<R, Self::BridgeMessagesPalletInstance>;
96
97 fn parse_and_check_for_obsolete_call(
98 call: &R::RuntimeCall,
99 ) -> Result<
100 Option<ExtensionCallInfo<Self::RemoteGrandpaChainBlockNumber, Self::LaneId>>,
101 TransactionValidityError,
102 > {
103 let calls = BCU::unpack(call, 2);
104 let total_calls = calls.len();
105 let mut calls = calls.into_iter().map(Self::check_obsolete_parsed_call).rev();
106
107 let msgs_call = calls.next().transpose()?.and_then(|c| c.call_info());
108 let relay_finality_call =
109 calls.next().transpose()?.and_then(|c| c.submit_finality_proof_info());
110
111 Ok(match (total_calls, relay_finality_call, msgs_call) {
112 (2, Some(relay_finality_call), Some(msgs_call)) =>
113 Some(ExtensionCallInfo::RelayFinalityAndMsgs(relay_finality_call, msgs_call)),
114 (1, None, Some(msgs_call)) => Some(ExtensionCallInfo::Msgs(msgs_call)),
115 _ => None,
116 })
117 }
118
119 fn check_obsolete_parsed_call(
120 call: &R::RuntimeCall,
121 ) -> Result<&R::RuntimeCall, TransactionValidityError> {
122 call.check_obsolete_submit_finality_proof()?;
123 call.check_obsolete_call()?;
124 Ok(call)
125 }
126
127 fn check_call_result(
128 call_info: &ExtensionCallInfo<Self::RemoteGrandpaChainBlockNumber, Self::LaneId>,
129 call_data: &mut ExtensionCallData,
130 relayer: &R::AccountId,
131 ) -> bool {
132 verify_submit_finality_proof_succeeded::<Self, GI>(call_info, call_data, relayer) &&
133 verify_messages_call_succeeded::<Self>(call_info, call_data, relayer)
134 }
135}
136
137pub(crate) fn verify_submit_finality_proof_succeeded<C, GI>(
142 call_info: &ExtensionCallInfo<C::RemoteGrandpaChainBlockNumber, C::LaneId>,
143 call_data: &mut ExtensionCallData,
144 relayer: &<C::Runtime as SystemConfig>::AccountId,
145) -> bool
146where
147 C: ExtensionConfig,
148 GI: 'static,
149 C::Runtime: BridgeGrandpaConfig<GI>,
150 <C::Runtime as BridgeGrandpaConfig<GI>>::BridgedChain:
151 Chain<BlockNumber = C::RemoteGrandpaChainBlockNumber>,
152{
153 let Some(finality_proof_info) = call_info.submit_finality_proof_info() else { return true };
154
155 if !SubmitFinalityProofHelper::<C::Runtime, GI>::was_successful(
156 finality_proof_info.block_number,
157 ) {
158 tracing::trace!(
160 target: LOG_TARGET,
161 id_provider=%C::IdProvider::STR,
162 lane_id=?call_info.messages_call_info().lane_id(),
163 ?relayer,
164 "Relayer has submitted invalid GRANDPA chain finality proof"
165 );
166 return false
167 }
168
169 call_data.extra_weight.saturating_accrue(finality_proof_info.extra_weight);
179 call_data.extra_size.saturating_accrue(finality_proof_info.extra_size);
180
181 true
182}