pallet_bridge_relayers/extension/
parachain_adapter.rs1use crate::{
21 extension::{
22 grandpa_adapter::verify_submit_finality_proof_succeeded, verify_messages_call_succeeded,
23 },
24 Config as BridgeRelayersConfig, LOG_TARGET,
25};
26
27use bp_relayers::{BatchCallUnpacker, ExtensionCallData, ExtensionCallInfo, ExtensionConfig};
28use bp_runtime::{Parachain, StaticStrProvider};
29use core::marker::PhantomData;
30use frame_support::dispatch::{DispatchInfo, PostDispatchInfo};
31use frame_system::Config as SystemConfig;
32use pallet_bridge_grandpa::{
33 CallSubType as BridgeGrandpaCallSubtype, Config as BridgeGrandpaConfig,
34};
35use pallet_bridge_messages::{
36 CallSubType as BridgeMessagesCallSubType, Config as BridgeMessagesConfig, LaneIdOf,
37};
38use pallet_bridge_parachains::{
39 CallSubType as BridgeParachainsCallSubtype, Config as BridgeParachainsConfig,
40 SubmitParachainHeadsHelper,
41};
42use sp_runtime::{
43 traits::{Dispatchable, Get},
44 transaction_validity::{TransactionPriority, TransactionValidityError},
45};
46
47pub struct WithParachainExtensionConfig<
49 IdProvider,
51 Runtime,
55 BatchCallUnpacker,
57 BridgeParachainsPalletInstance,
59 BridgeMessagesPalletInstance,
61 BridgeRelayersPalletInstance,
63 PriorityBoostPerMessage,
65>(
66 PhantomData<(
67 IdProvider,
68 Runtime,
69 BatchCallUnpacker,
70 BridgeParachainsPalletInstance,
71 BridgeMessagesPalletInstance,
72 BridgeRelayersPalletInstance,
73 PriorityBoostPerMessage,
74 )>,
75);
76
77impl<ID, R, BCU, PI, MI, RI, P> ExtensionConfig
78 for WithParachainExtensionConfig<ID, R, BCU, PI, MI, RI, P>
79where
80 ID: StaticStrProvider,
81 R: BridgeRelayersConfig<RI>
82 + BridgeMessagesConfig<MI>
83 + BridgeParachainsConfig<PI>
84 + BridgeGrandpaConfig<R::BridgesGrandpaPalletInstance>,
85 BCU: BatchCallUnpacker<R>,
86 PI: 'static,
87 MI: 'static,
88 RI: 'static,
89 P: Get<TransactionPriority>,
90 R::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>
91 + BridgeGrandpaCallSubtype<R, R::BridgesGrandpaPalletInstance>
92 + BridgeParachainsCallSubtype<R, PI>
93 + BridgeMessagesCallSubType<R, MI>,
94 <R as BridgeMessagesConfig<MI>>::BridgedChain: Parachain,
95{
96 type IdProvider = ID;
97 type Runtime = R;
98 type BridgeMessagesPalletInstance = MI;
99 type BridgeRelayersPalletInstance = RI;
100 type PriorityBoostPerMessage = P;
101 type RemoteGrandpaChainBlockNumber =
102 pallet_bridge_grandpa::BridgedBlockNumber<R, R::BridgesGrandpaPalletInstance>;
103 type LaneId = LaneIdOf<R, Self::BridgeMessagesPalletInstance>;
104
105 fn parse_and_check_for_obsolete_call(
106 call: &R::RuntimeCall,
107 ) -> Result<
108 Option<ExtensionCallInfo<Self::RemoteGrandpaChainBlockNumber, Self::LaneId>>,
109 TransactionValidityError,
110 > {
111 let calls = BCU::unpack(call, 3);
112 let total_calls = calls.len();
113 let mut calls = calls.into_iter().map(Self::check_obsolete_parsed_call).rev();
114
115 let msgs_call = calls.next().transpose()?.and_then(|c| c.call_info());
116 let para_finality_call = calls.next().transpose()?.and_then(|c| {
117 let r = c.submit_parachain_heads_info_for(
118 <R as BridgeMessagesConfig<Self::BridgeMessagesPalletInstance>>::BridgedChain::PARACHAIN_ID,
119 );
120 r
121 });
122 let relay_finality_call =
123 calls.next().transpose()?.and_then(|c| c.submit_finality_proof_info());
124 Ok(match (total_calls, relay_finality_call, para_finality_call, msgs_call) {
125 (3, Some(relay_finality_call), Some(para_finality_call), Some(msgs_call)) => {
126 Some(ExtensionCallInfo::AllFinalityAndMsgs(
127 relay_finality_call,
128 para_finality_call,
129 msgs_call,
130 ))
131 },
132 (2, None, Some(para_finality_call), Some(msgs_call)) => {
133 Some(ExtensionCallInfo::ParachainFinalityAndMsgs(para_finality_call, msgs_call))
134 },
135 (1, None, None, Some(msgs_call)) => Some(ExtensionCallInfo::Msgs(msgs_call)),
136 _ => None,
137 })
138 }
139
140 fn check_obsolete_parsed_call(
141 call: &R::RuntimeCall,
142 ) -> Result<&R::RuntimeCall, TransactionValidityError> {
143 call.check_obsolete_submit_finality_proof()?;
144 call.check_obsolete_submit_parachain_heads()?;
145 call.check_obsolete_call()?;
146 Ok(call)
147 }
148
149 fn check_call_result(
150 call_info: &ExtensionCallInfo<Self::RemoteGrandpaChainBlockNumber, Self::LaneId>,
151 call_data: &mut ExtensionCallData,
152 relayer: &R::AccountId,
153 ) -> bool {
154 verify_submit_finality_proof_succeeded::<Self, R::BridgesGrandpaPalletInstance>(
155 call_info, call_data, relayer,
156 ) && verify_submit_parachain_head_succeeded::<Self, PI>(call_info, call_data, relayer) &&
157 verify_messages_call_succeeded::<Self>(call_info, call_data, relayer)
158 }
159}
160
161pub(crate) fn verify_submit_parachain_head_succeeded<C, PI>(
166 call_info: &ExtensionCallInfo<C::RemoteGrandpaChainBlockNumber, C::LaneId>,
167 _call_data: &mut ExtensionCallData,
168 relayer: &<C::Runtime as SystemConfig>::AccountId,
169) -> bool
170where
171 C: ExtensionConfig,
172 PI: 'static,
173 C::Runtime: BridgeParachainsConfig<PI>,
174{
175 let Some(para_proof_info) = call_info.submit_parachain_heads_info() else { return true };
176
177 if !SubmitParachainHeadsHelper::<C::Runtime, PI>::was_successful(para_proof_info) {
178 tracing::trace!(
180 target: LOG_TARGET,
181 id_provider=%C::IdProvider::STR,
182 lane_id=?call_info.messages_call_info().lane_id(),
183 ?relayer,
184 "Relayer has submitted invalid parachain finality proof"
185 );
186 return false;
187 }
188
189 true
190}