Skip to content

Commit 4689dfa

Browse files
svyatonikbkchr
authored andcommitted
Do not read parachain heads from ancient relay headers (#1827)
* do not read parachain heads from ancient relay headers * revert test change
1 parent 48425b2 commit 4689dfa

File tree

4 files changed

+36
-15
lines changed

4 files changed

+36
-15
lines changed

bridges/relays/client-substrate/src/client.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use jsonrpsee::{
3737
core::DeserializeOwned,
3838
ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder},
3939
};
40-
use num_traits::{Bounded, Zero};
40+
use num_traits::{Bounded, Saturating, Zero};
4141
use pallet_balances::AccountData;
4242
use pallet_transaction_payment::InclusionFee;
4343
use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT};
@@ -69,6 +69,11 @@ const MAX_SUBSCRIPTION_CAPACITY: usize = 4096;
6969
/// half of this value.
7070
pub const ANCIENT_BLOCK_THRESHOLD: u32 = 128;
7171

72+
/// Returns `true` if we think that the state is already discarded for given block.
73+
pub fn is_ancient_block<N: From<u32> + PartialOrd + Saturating>(block: N, best: N) -> bool {
74+
best.saturating_sub(block) >= N::from(ANCIENT_BLOCK_THRESHOLD)
75+
}
76+
7277
/// Opaque justifications subscription type.
7378
pub struct Subscription<T>(pub(crate) Mutex<futures::channel::mpsc::Receiver<Option<T>>>);
7479

bridges/relays/client-substrate/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ pub use crate::{
4040
UnsignedTransaction, UtilityPallet,
4141
},
4242
client::{
43-
ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, SimpleRuntimeVersion,
44-
Subscription, ANCIENT_BLOCK_THRESHOLD,
43+
is_ancient_block, ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet,
44+
SimpleRuntimeVersion, Subscription, ANCIENT_BLOCK_THRESHOLD,
4545
},
4646
error::{Error, Result},
4747
rpc::{SubstrateBeefyFinalityClient, SubstrateFinalityClient, SubstrateGrandpaFinalityClient},

bridges/relays/lib-substrate-relay/src/on_demand/parachains.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ use parachains_relay::parachains_loop::{
4040
AvailableHeader, ParachainSyncParams, SourceClient, TargetClient,
4141
};
4242
use relay_substrate_client::{
43-
AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError,
44-
HashOf, HeaderIdOf, ParachainBase, ANCIENT_BLOCK_THRESHOLD,
43+
is_ancient_block, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client,
44+
Error as SubstrateError, HashOf, HeaderIdOf, ParachainBase,
4545
};
4646
use relay_utils::{
4747
metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient,
@@ -501,10 +501,18 @@ where
501501
.await
502502
.map_err(map_target_err)?;
503503

504-
let para_header_at_relay_header_at_target = source
505-
.on_chain_para_head_id(relay_header_at_target, P::SourceParachain::PARACHAIN_ID.into())
506-
.await
507-
.map_err(map_source_err)?;
504+
// if relay header at target is too old, then its state may already be discarded at the source
505+
// => just use `None` in this case
506+
let is_relay_header_at_target_ancient =
507+
is_ancient_block(relay_header_at_target.number(), relay_header_at_source);
508+
let para_header_at_relay_header_at_target = if is_relay_header_at_target_ancient {
509+
None
510+
} else {
511+
source
512+
.on_chain_para_head_id(relay_header_at_target, P::SourceParachain::PARACHAIN_ID.into())
513+
.await
514+
.map_err(map_source_err)?
515+
};
508516

509517
Ok(RelayData {
510518
required_para_header: required_header_number,
@@ -677,11 +685,10 @@ where
677685
// we don't require source node to be archive, so we can't craft storage proofs using
678686
// ancient headers. So if the `best_finalized_relay_block_at_target` is too ancient, we
679687
// can't craft storage proofs using it
680-
let may_use_state_at_best_finalized_relay_block_at_target =
681-
best_finalized_relay_block_at_source
682-
.number()
683-
.saturating_sub(best_finalized_relay_block_at_target.number()) <=
684-
RBN::from(ANCIENT_BLOCK_THRESHOLD);
688+
let may_use_state_at_best_finalized_relay_block_at_target = !is_ancient_block(
689+
best_finalized_relay_block_at_target.number(),
690+
best_finalized_relay_block_at_source.number(),
691+
);
685692

686693
// now let's check if `required_header` may be proved using
687694
// `best_finalized_relay_block_at_target`

bridges/relays/lib-substrate-relay/src/parachains/source.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ use parachains_relay::{
2929
parachains_loop_metrics::ParachainsLoopMetrics,
3030
};
3131
use relay_substrate_client::{
32-
Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase, RelayChain,
32+
is_ancient_block, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase,
33+
RelayChain,
3334
};
3435
use relay_utils::relay_loop::Client as RelayClient;
3536

@@ -115,6 +116,14 @@ where
115116
)))
116117
}
117118

119+
// if requested relay header is ancient, then we don't even want to try to read the
120+
// parachain head - we simply return `Unavailable`
121+
let best_block_number = self.client.best_finalized_header_number().await?;
122+
if is_ancient_block(at_block.number(), best_block_number) {
123+
return Ok(AvailableHeader::Unavailable)
124+
}
125+
126+
// else - try to read head from the source client
118127
let mut para_head_id = AvailableHeader::Missing;
119128
if let Some(on_chain_para_head_id) = self.on_chain_para_head_id(at_block, para_id).await? {
120129
// Never return head that is larger than requested. This way we'll never sync

0 commit comments

Comments
 (0)