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 (2, None, Some(para_finality_call), Some(msgs_call)) =>
132 Some(ExtensionCallInfo::ParachainFinalityAndMsgs(para_finality_call, msgs_call)),
133 (1, None, None, Some(msgs_call)) => Some(ExtensionCallInfo::Msgs(msgs_call)),
134 _ => None,
135 })
136 }
137
138 fn check_obsolete_parsed_call(
139 call: &R::RuntimeCall,
140 ) -> Result<&R::RuntimeCall, TransactionValidityError> {
141 call.check_obsolete_submit_finality_proof()?;
142 call.check_obsolete_submit_parachain_heads()?;
143 call.check_obsolete_call()?;
144 Ok(call)
145 }
146
147 fn check_call_result(
148 call_info: &ExtensionCallInfo<Self::RemoteGrandpaChainBlockNumber, Self::LaneId>,
149 call_data: &mut ExtensionCallData,
150 relayer: &R::AccountId,
151 ) -> bool {
152 verify_submit_finality_proof_succeeded::<Self, R::BridgesGrandpaPalletInstance>(
153 call_info, call_data, relayer,
154 ) && verify_submit_parachain_head_succeeded::<Self, PI>(call_info, call_data, relayer) &&
155 verify_messages_call_succeeded::<Self>(call_info, call_data, relayer)
156 }
157}
158
159pub(crate) fn verify_submit_parachain_head_succeeded<C, PI>(
164 call_info: &ExtensionCallInfo<C::RemoteGrandpaChainBlockNumber, C::LaneId>,
165 _call_data: &mut ExtensionCallData,
166 relayer: &<C::Runtime as SystemConfig>::AccountId,
167) -> bool
168where
169 C: ExtensionConfig,
170 PI: 'static,
171 C::Runtime: BridgeParachainsConfig<PI>,
172{
173 let Some(para_proof_info) = call_info.submit_parachain_heads_info() else { return true };
174
175 if !SubmitParachainHeadsHelper::<C::Runtime, PI>::was_successful(para_proof_info) {
176 tracing::trace!(
178 target: LOG_TARGET,
179 id_provider=%C::IdProvider::STR,
180 lane_id=?call_info.messages_call_info().lane_id(),
181 ?relayer,
182 "Relayer has submitted invalid parachain finality proof"
183 );
184 return false
185 }
186
187 true
188}