1use crate::{ChainId, HeaderIdProvider};
18
19use codec::{Codec, Decode, Encode, MaxEncodedLen};
20use frame_support::{weights::Weight, Parameter};
21use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero};
22use sp_runtime::{
23 traits::{
24 AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay,
25 MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify,
26 },
27 FixedPointOperand, StateVersion,
28};
29use sp_std::{fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec};
30
31#[derive(Debug, Clone, PartialEq)]
33pub enum EncodedOrDecodedCall<ChainCall> {
34 Encoded(Vec<u8>),
39 Decoded(ChainCall),
41}
42
43impl<ChainCall: Clone + Codec> EncodedOrDecodedCall<ChainCall> {
44 pub fn to_decoded(&self) -> Result<ChainCall, codec::Error> {
46 match self {
47 Self::Encoded(ref encoded_call) =>
48 ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into),
49 Self::Decoded(ref decoded_call) => Ok(decoded_call.clone()),
50 }
51 }
52
53 pub fn into_decoded(self) -> Result<ChainCall, codec::Error> {
55 match self {
56 Self::Encoded(encoded_call) =>
57 ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into),
58 Self::Decoded(decoded_call) => Ok(decoded_call),
59 }
60 }
61
62 pub fn into_encoded(self) -> Vec<u8> {
64 match self {
65 Self::Encoded(encoded_call) => encoded_call,
66 Self::Decoded(decoded_call) => decoded_call.encode(),
67 }
68 }
69}
70
71impl<ChainCall> From<ChainCall> for EncodedOrDecodedCall<ChainCall> {
72 fn from(call: ChainCall) -> EncodedOrDecodedCall<ChainCall> {
73 EncodedOrDecodedCall::Decoded(call)
74 }
75}
76
77impl<ChainCall: Decode> Decode for EncodedOrDecodedCall<ChainCall> {
78 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
79 match input.remaining_len()? {
82 Some(remaining_len) => {
83 let mut encoded_call = vec![0u8; remaining_len];
84 input.read(&mut encoded_call)?;
85 Ok(EncodedOrDecodedCall::Encoded(encoded_call))
86 },
87 None => Ok(EncodedOrDecodedCall::Decoded(ChainCall::decode(input)?)),
88 }
89 }
90}
91
92impl<ChainCall: Encode> Encode for EncodedOrDecodedCall<ChainCall> {
93 fn encode(&self) -> Vec<u8> {
94 match *self {
95 Self::Encoded(ref encoded_call) => encoded_call.clone(),
96 Self::Decoded(ref decoded_call) => decoded_call.encode(),
97 }
98 }
99}
100
101pub trait Chain: Send + Sync + 'static {
103 const ID: ChainId;
105
106 type BlockNumber: Parameter
114 + Member
115 + MaybeSerializeDeserialize
116 + Hash
117 + Copy
118 + Default
119 + MaybeDisplay
120 + AtLeast32BitUnsigned
121 + FromStr
122 + AsPrimitive<usize>
123 + Default
124 + Saturating
125 + MaxEncodedLen;
126
127 type Hash: Parameter
132 + Member
133 + MaybeSerializeDeserialize
134 + Hash
135 + Ord
136 + Copy
137 + MaybeDisplay
138 + Default
139 + SimpleBitOps
140 + AsRef<[u8]>
141 + AsMut<[u8]>
142 + MaxEncodedLen;
143
144 type Hasher: HashT<Output = Self::Hash>;
150
151 type Header: Parameter
155 + HeaderT<Number = Self::BlockNumber, Hash = Self::Hash>
156 + HeaderIdProvider<Self::Header>
157 + MaybeSerializeDeserialize;
158
159 type AccountId: Parameter
161 + Member
162 + MaybeSerializeDeserialize
163 + Debug
164 + MaybeDisplay
165 + Ord
166 + MaxEncodedLen;
167 type Balance: AtLeast32BitUnsigned
172 + FixedPointOperand
173 + Parameter
174 + Member
175 + MaybeSerializeDeserialize
176 + Clone
177 + Copy
178 + Bounded
179 + CheckedSub
180 + PartialOrd
181 + SaturatingAdd
182 + Zero
183 + TryFrom<sp_core::U256>
184 + MaxEncodedLen;
185 type Nonce: Parameter
187 + Member
188 + MaybeSerialize
189 + Debug
190 + Default
191 + MaybeDisplay
192 + MaybeSerializeDeserialize
193 + AtLeast32Bit
194 + Copy
195 + MaxEncodedLen;
196 type Signature: Parameter + Verify;
198
199 const STATE_VERSION: StateVersion;
202
203 fn max_extrinsic_size() -> u32;
205 fn max_extrinsic_weight() -> Weight;
207}
208
209pub trait UnderlyingChainProvider: Send + Sync + 'static {
211 type Chain: Chain;
213}
214
215impl<T> Chain for T
216where
217 T: Send + Sync + 'static + UnderlyingChainProvider,
218{
219 const ID: ChainId = <T::Chain as Chain>::ID;
220
221 type BlockNumber = <T::Chain as Chain>::BlockNumber;
222 type Hash = <T::Chain as Chain>::Hash;
223 type Hasher = <T::Chain as Chain>::Hasher;
224 type Header = <T::Chain as Chain>::Header;
225 type AccountId = <T::Chain as Chain>::AccountId;
226 type Balance = <T::Chain as Chain>::Balance;
227 type Nonce = <T::Chain as Chain>::Nonce;
228 type Signature = <T::Chain as Chain>::Signature;
229
230 const STATE_VERSION: StateVersion = <T::Chain as Chain>::STATE_VERSION;
231
232 fn max_extrinsic_size() -> u32 {
233 <T::Chain as Chain>::max_extrinsic_size()
234 }
235
236 fn max_extrinsic_weight() -> Weight {
237 <T::Chain as Chain>::max_extrinsic_weight()
238 }
239}
240
241pub trait Parachain: Chain {
243 const PARACHAIN_ID: u32;
245 const MAX_HEADER_SIZE: u32;
251}
252
253impl<T> Parachain for T
254where
255 T: Chain + UnderlyingChainProvider,
256 <T as UnderlyingChainProvider>::Chain: Parachain,
257{
258 const PARACHAIN_ID: u32 = <<T as UnderlyingChainProvider>::Chain as Parachain>::PARACHAIN_ID;
259 const MAX_HEADER_SIZE: u32 =
260 <<T as UnderlyingChainProvider>::Chain as Parachain>::MAX_HEADER_SIZE;
261}
262
263pub struct ParachainIdOf<Para>(sp_std::marker::PhantomData<Para>);
265impl<Para: Parachain> frame_support::traits::Get<u32> for ParachainIdOf<Para> {
266 fn get() -> u32 {
267 Para::PARACHAIN_ID
268 }
269}
270
271pub type UnderlyingChainOf<C> = <C as UnderlyingChainProvider>::Chain;
273
274pub type BlockNumberOf<C> = <C as Chain>::BlockNumber;
276
277pub type HashOf<C> = <C as Chain>::Hash;
279
280pub type HasherOf<C> = <C as Chain>::Hasher;
282
283pub type HeaderOf<C> = <C as Chain>::Header;
285
286pub type AccountIdOf<C> = <C as Chain>::AccountId;
288
289pub type BalanceOf<C> = <C as Chain>::Balance;
291
292pub type NonceOf<C> = <C as Chain>::Nonce;
294
295pub type SignatureOf<C> = <C as Chain>::Signature;
297
298pub type AccountPublicOf<C> = <SignatureOf<C> as Verify>::Signer;
300
301pub type TransactionEraOf<C> = crate::TransactionEra<BlockNumberOf<C>, HashOf<C>>;
303
304#[macro_export]
313macro_rules! decl_bridge_finality_runtime_apis {
314 ($chain: ident $(, $consensus: ident => $justification_type: ty)?) => {
315 bp_runtime::paste::item! {
316 mod [<$chain _finality_api>] {
317 use super::*;
318
319 pub const [<BEST_FINALIZED_ $chain:upper _HEADER_METHOD>]: &str =
321 stringify!([<$chain:camel FinalityApi_best_finalized>]);
322
323 pub const [<FREE_HEADERS_INTERVAL_FOR_ $chain:upper _METHOD>]: &str =
325 stringify!([<$chain:camel FinalityApi_free_headers_interval>]);
326
327
328 $(
329 pub const [<$chain:upper _SYNCED_HEADERS_ $consensus:upper _INFO_METHOD>]: &str =
332 stringify!([<$chain:camel FinalityApi_synced_headers_ $consensus:lower _info>]);
333 )?
334
335 sp_api::decl_runtime_apis! {
336 pub trait [<$chain:camel FinalityApi>] {
341 fn best_finalized() -> Option<bp_runtime::HeaderId<Hash, BlockNumber>>;
343
344 fn free_headers_interval() -> Option<BlockNumber>;
350
351 $(
352 fn [<synced_headers_ $consensus:lower _info>](
354 ) -> $crate::private::Vec<$justification_type>;
355 )?
356 }
357 }
358 }
359
360 pub use [<$chain _finality_api>]::*;
361 }
362 };
363 ($chain: ident, grandpa) => {
364 decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::StoredHeaderGrandpaInfo<Header>);
365 };
366}
367
368#[doc(hidden)]
370pub mod __private {
371 pub use codec;
372}
373
374#[macro_export]
383macro_rules! decl_bridge_messages_runtime_apis {
384 ($chain: ident, $lane_id_type:ty) => {
385 bp_runtime::paste::item! {
386 mod [<$chain _messages_api>] {
387 use super::*;
388
389 pub const [<TO_ $chain:upper _MESSAGE_DETAILS_METHOD>]: &str =
391 stringify!([<To $chain:camel OutboundLaneApi_message_details>]);
392
393 pub const [<FROM_ $chain:upper _MESSAGE_DETAILS_METHOD>]: &str =
395 stringify!([<From $chain:camel InboundLaneApi_message_details>]);
396
397 sp_api::decl_runtime_apis! {
398 pub trait [<To $chain:camel OutboundLaneApi>] {
403 fn message_details(
409 lane: $lane_id_type,
410 begin: bp_messages::MessageNonce,
411 end: bp_messages::MessageNonce,
412 ) -> $crate::private::Vec<bp_messages::OutboundMessageDetails>;
413 }
414
415 pub trait [<From $chain:camel InboundLaneApi>] {
423 fn message_details(
425 lane: $lane_id_type,
426 messages: $crate::private::Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>,
427 ) -> $crate::private::Vec<bp_messages::InboundMessageDetails>;
428 }
429 }
430 }
431
432 pub use [<$chain _messages_api>]::*;
433 }
434 };
435}
436
437#[macro_export]
441macro_rules! decl_bridge_runtime_apis {
442 ($chain: ident $(, $consensus: ident, $lane_id_type:ident)?) => {
443 bp_runtime::decl_bridge_finality_runtime_apis!($chain $(, $consensus)?);
444 bp_runtime::decl_bridge_messages_runtime_apis!($chain, $lane_id_type);
445 };
446}