Skip to content

Commit 8f02e23

Browse files
authored
Ensure relay chain parent is the relay chain head (#103)
1 parent adc88bf commit 8f02e23

File tree

7 files changed

+615
-60
lines changed

7 files changed

+615
-60
lines changed

Cargo.lock

Lines changed: 91 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

collator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ edition = "2018"
66

77
[dependencies]
88
# Substrate dependencies
9+
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
910
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
1011
sp-core = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
1112
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }

collator/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use cumulus_primitives::{
2525
};
2626
use cumulus_runtime::ParachainBlockData;
2727

28+
use sp_blockchain::HeaderBackend;
2829
use sp_consensus::{
2930
BlockImport, BlockImportParams, BlockOrigin, Environment, Error as ConsensusError,
3031
ForkChoiceStrategy, Proposal, Proposer, RecordProof,
@@ -350,14 +351,15 @@ where
350351
polkadot_network: impl CollatorNetwork + Clone + 'static,
351352
) -> Result<Self::ParachainContext, ()>
352353
where
353-
PClient: ProvideRuntimeApi<PBlock> + Send + Sync + BlockchainEvents<PBlock> + 'static,
354+
PClient: ProvideRuntimeApi<PBlock> + BlockchainEvents<PBlock> + HeaderBackend<PBlock>
355+
+ Send + Sync + 'static,
354356
PClient::Api: RuntimeApiCollection<Extrinsic>,
355357
<PClient::Api as ApiExt<PBlock>>::StateBackend: StateBackend<HashFor<PBlock>>,
356358
Spawner: Spawn + Clone + Send + Sync + 'static,
357359
Extrinsic: codec::Codec + Send + Sync + 'static,
358360
{
359361
self.delayed_block_announce_validator.set(
360-
Box::new(JustifiedBlockAnnounceValidator::new(Vec::new(), polkadot_client.clone())),
362+
Box::new(JustifiedBlockAnnounceValidator::new(polkadot_client.clone())),
361363
);
362364

363365
let follow =

network/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,14 @@ codec = { package = "parity-scale-codec", version = "1.3.0", features = [ "deriv
2424
futures = { version = "0.3.1", features = ["compat"] }
2525
log = "0.4.8"
2626
parking_lot = "0.10.2"
27+
28+
[dev-dependencies]
29+
cumulus-test-runtime = { path = "../test/runtime" }
30+
31+
# substrate deps
32+
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
33+
sp-core = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
34+
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" }
35+
36+
# polkadot deps
37+
polkadot-test-runtime-client = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }

network/src/lib.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818
//!
1919
//! Contains message send between collators and logic to process them.
2020
21+
#[cfg(test)]
22+
mod tests;
23+
2124
use sp_api::ProvideRuntimeApi;
22-
use sp_blockchain::Error as ClientError;
25+
use sp_blockchain::{Error as ClientError, HeaderBackend};
2326
use sp_consensus::block_validation::{BlockAnnounceValidator, Validation};
2427
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
2528

2629
use polkadot_collator::Network as CollatorNetwork;
2730
use polkadot_network::legacy::gossip::{GossipMessage, GossipStatement};
2831
use polkadot_primitives::{
29-
parachain::{ParachainHost, ValidatorId},
32+
parachain::ParachainHost,
3033
Block as PBlock, Hash as PHash,
3134
};
3235
use polkadot_statement_table::{SignedStatement, Statement};
@@ -49,15 +52,13 @@ use parking_lot::Mutex;
4952
///
5053
/// Note: if no justification is provided the annouce is considered valid.
5154
pub struct JustifiedBlockAnnounceValidator<B, P> {
52-
authorities: Vec<ValidatorId>,
5355
phantom: PhantomData<B>,
5456
polkadot_client: Arc<P>,
5557
}
5658

5759
impl<B, P> JustifiedBlockAnnounceValidator<B, P> {
58-
pub fn new(authorities: Vec<ValidatorId>, polkadot_client: Arc<P>) -> Self {
60+
pub fn new(polkadot_client: Arc<P>) -> Self {
5961
Self {
60-
authorities,
6162
phantom: Default::default(),
6263
polkadot_client,
6364
}
@@ -66,7 +67,7 @@ impl<B, P> JustifiedBlockAnnounceValidator<B, P> {
6667

6768
impl<B: BlockT, P> BlockAnnounceValidator<B> for JustifiedBlockAnnounceValidator<B, P>
6869
where
69-
P: ProvideRuntimeApi<PBlock>,
70+
P: ProvideRuntimeApi<PBlock> + HeaderBackend<PBlock>,
7071
P::Api: ParachainHost<PBlock>,
7172
{
7273
fn validate(
@@ -106,14 +107,42 @@ where
106107
},
107108
} = gossip_statement;
108109

109-
let signing_context = self
110-
.polkadot_client
111-
.runtime_api()
112-
.signing_context(&BlockId::Hash(relay_chain_leaf))
110+
// Check that the relay chain parent of the block is the relay chain head
111+
let best_number = self.polkadot_client.info().best_number;
112+
113+
match self.polkadot_client.number(relay_chain_leaf) {
114+
Err(err) => {
115+
return Err(Box::new(ClientError::Backend(format!(
116+
"could not find block number for {}: {}",
117+
relay_chain_leaf, err,
118+
))));
119+
},
120+
Ok(Some(x)) if x == best_number => {},
121+
Ok(None) => {
122+
return Err(Box::new(ClientError::UnknownBlock(relay_chain_leaf.to_string())));
123+
},
124+
Ok(Some(_)) => {
125+
trace!(
126+
target: "cumulus-network",
127+
"validation failed because the relay chain parent ({}) is not the relay chain \
128+
head ({})",
129+
relay_chain_leaf, best_number,
130+
);
131+
132+
return Ok(Validation::Failure);
133+
},
134+
}
135+
136+
let runtime_api = self.polkadot_client.runtime_api();
137+
let runtime_api_block_id = BlockId::Hash(relay_chain_leaf);
138+
let signing_context = runtime_api
139+
.signing_context(&runtime_api_block_id)
113140
.map_err(|e| Box::new(ClientError::Msg(format!("{:?}", e))) as Box<_>)?;
114141

115142
// Check that the signer is a legit validator.
116-
let signer = self.authorities.get(sender as usize).ok_or_else(|| {
143+
let authorities = runtime_api.validators(&runtime_api_block_id)
144+
.map_err(|e| Box::new(ClientError::Msg(format!("{:?}", e))) as Box<_>)?;
145+
let signer = authorities.get(sender as usize).ok_or_else(|| {
117146
Box::new(ClientError::BadJustification(
118147
"block accounced justification signer is a validator index out of bound"
119148
.to_string(),

0 commit comments

Comments
 (0)