substrate_relay_helper/finality/
initialize.rs1use crate::{error::Error, finality_base::engine::Engine};
25use sp_core::Pair;
26
27use bp_runtime::HeaderIdOf;
28use relay_substrate_client::{
29 AccountKeyPairOf, Chain, ChainWithTransactions, Client, Error as SubstrateError,
30 UnsignedTransaction,
31};
32use relay_utils::{TrackedTransactionStatus, TransactionTracker};
33use sp_runtime::traits::Header as HeaderT;
34
35pub async fn initialize<
37 E: Engine<SourceChain>,
38 SourceChain: Chain,
39 TargetChain: ChainWithTransactions,
40 F,
41>(
42 source_client: impl Client<SourceChain>,
43 target_client: impl Client<TargetChain>,
44 target_signer: AccountKeyPairOf<TargetChain>,
45 prepare_initialize_transaction: F,
46 dry_run: bool,
47) where
48 F: FnOnce(
49 TargetChain::Nonce,
50 E::InitializationData,
51 ) -> Result<UnsignedTransaction<TargetChain>, SubstrateError>
52 + Send
53 + 'static,
54 TargetChain::AccountId: From<<TargetChain::AccountKeyPair as Pair>::Public>,
55{
56 let result = do_initialize::<E, _, _, _>(
57 source_client,
58 target_client,
59 target_signer,
60 prepare_initialize_transaction,
61 dry_run,
62 )
63 .await;
64
65 match result {
66 Ok(Some(tx_status)) => match tx_status {
67 TrackedTransactionStatus::Lost => {
68 log::error!(
69 target: "bridge",
70 "Failed to execute {}-headers bridge initialization transaction on {}: {:?}.",
71 SourceChain::NAME,
72 TargetChain::NAME,
73 tx_status
74 )
75 },
76 TrackedTransactionStatus::Finalized(_) => {
77 log::info!(
78 target: "bridge",
79 "Successfully executed {}-headers bridge initialization transaction on {}: {:?}.",
80 SourceChain::NAME,
81 TargetChain::NAME,
82 tx_status
83 )
84 },
85 },
86 Ok(None) => (),
87 Err(err) => log::error!(
88 target: "bridge",
89 "Failed to submit {}-headers bridge initialization transaction to {}: {:?}",
90 SourceChain::NAME,
91 TargetChain::NAME,
92 err,
93 ),
94 }
95}
96
97async fn do_initialize<
99 E: Engine<SourceChain>,
100 SourceChain: Chain,
101 TargetChain: ChainWithTransactions,
102 F,
103>(
104 source_client: impl Client<SourceChain>,
105 target_client: impl Client<TargetChain>,
106 target_signer: AccountKeyPairOf<TargetChain>,
107 prepare_initialize_transaction: F,
108 dry_run: bool,
109) -> Result<
110 Option<TrackedTransactionStatus<HeaderIdOf<TargetChain>>>,
111 Error<SourceChain::Hash, <SourceChain::Header as HeaderT>::Number>,
112>
113where
114 F: FnOnce(
115 TargetChain::Nonce,
116 E::InitializationData,
117 ) -> Result<UnsignedTransaction<TargetChain>, SubstrateError>
118 + Send
119 + 'static,
120 TargetChain::AccountId: From<<TargetChain::AccountKeyPair as Pair>::Public>,
121{
122 let is_initialized = E::is_initialized(&target_client)
123 .await
124 .map_err(|e| Error::IsInitializedRetrieve(SourceChain::NAME, TargetChain::NAME, e))?;
125 if is_initialized {
126 log::info!(
127 target: "bridge",
128 "{}-headers bridge at {} is already initialized. Skipping",
129 SourceChain::NAME,
130 TargetChain::NAME,
131 );
132 if !dry_run {
133 return Ok(None)
134 }
135 }
136
137 let initialization_data = E::prepare_initialization_data(source_client).await?;
138 log::info!(
139 target: "bridge",
140 "Prepared initialization data for {}-headers bridge at {}: {:?}",
141 SourceChain::NAME,
142 TargetChain::NAME,
143 initialization_data,
144 );
145
146 let tx_status = target_client
147 .submit_and_watch_signed_extrinsic(&target_signer, move |_, transaction_nonce| {
148 let tx = prepare_initialize_transaction(transaction_nonce, initialization_data);
149 if dry_run {
150 Err(SubstrateError::Custom(
151 "Not submitting extrinsic in `dry-run` mode!".to_string(),
152 ))
153 } else {
154 tx
155 }
156 })
157 .await
158 .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?
159 .wait()
160 .await;
161
162 Ok(Some(tx_status))
163}