@@ -34,7 +34,7 @@ use jsonrpsee_ws_client::{
3434 } ,
3535 WsClient as RpcClient , WsClientBuilder as RpcClientBuilder ,
3636} ;
37- use num_traits:: { Bounded , Zero } ;
37+ use num_traits:: { Bounded , CheckedSub , One , Zero } ;
3838use pallet_balances:: AccountData ;
3939use pallet_transaction_payment:: InclusionFee ;
4040use relay_utils:: { relay_loop:: RECONNECT_DELAY , HeaderId } ;
@@ -349,7 +349,17 @@ impl<C: Chain> Client<C> {
349349 let _guard = self . submit_signed_extrinsic_lock . lock ( ) . await ;
350350 let transaction_nonce = self . next_account_index ( extrinsic_signer) . await ?;
351351 let best_header = self . best_header ( ) . await ?;
352- let best_header_id = HeaderId ( * best_header. number ( ) , best_header. hash ( ) ) ;
352+
353+ // By using parent of best block here, we are protecing again best-block reorganizations.
354+ // E.g. transaction my have been submitted when the best block was `A[num=100]`. Then it has
355+ // been changed to `B[num=100]`. Hash of `A` has been included into transaction signature
356+ // payload. So when signature will be checked, the check will fail and transaction will be
357+ // dropped from the pool.
358+ let best_header_id = match best_header. number ( ) . checked_sub ( & One :: one ( ) ) {
359+ Some ( parent_block_number) => HeaderId ( parent_block_number, * best_header. parent_hash ( ) ) ,
360+ None => HeaderId ( * best_header. number ( ) , best_header. hash ( ) ) ,
361+ } ;
362+
353363 self . jsonrpsee_execute ( move |client| async move {
354364 let extrinsic = prepare_extrinsic ( best_header_id, transaction_nonce) ;
355365 let tx_hash = Substrate :: < C > :: author_submit_extrinsic ( & * client, extrinsic) . await ?;
0 commit comments