mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
Reject blocks without justification which don't have the best number (#105)
* Initial commit Forked at:6c74beab7bParent branch: origin/master * Reject blocks without justification * Revert "Reject blocks without justification" This reverts commit ee60e12097939d4ccfe987a71db9a876319ae5ba. * WIP Forked at:6c74beab7bParent branch: origin/master * WIP Forked at:6c74beab7bParent branch: origin/master * WIP Forked at:6c74beab7bParent branch: origin/master * CLEANUP Forked at:6c74beab7bParent branch: origin/master * WIP Forked at:6c74beab7bParent branch: origin/master * WIP Forked at:6c74beab7bParent branch: origin/master * CLEANUP Forked at:6c74beab7bParent branch: origin/master * WIP Forked at:6c74beab7bParent branch: origin/master * WIP Forked at:6c74beab7bParent branch: origin/master * Move HeadData to primitives * Update network/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update network/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * CLEANUP Forked at:6c74beab7bParent branch: origin/master * fix * CLEANUP Forked at:6c74beab7bParent branch: origin/master * messages * for the greater good * Update primitives/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update network/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update network/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update network/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Generated
+1
@@ -930,6 +930,7 @@ dependencies = [
|
|||||||
name = "cumulus-network"
|
name = "cumulus-network"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cumulus-primitives",
|
||||||
"cumulus-test-runtime",
|
"cumulus-test-runtime",
|
||||||
"futures 0.3.4",
|
"futures 0.3.4",
|
||||||
"log 0.4.8",
|
"log 0.4.8",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use cumulus_network::{
|
|||||||
DelayedBlockAnnounceValidator, JustifiedBlockAnnounceValidator, WaitToAnnounce,
|
DelayedBlockAnnounceValidator, JustifiedBlockAnnounceValidator, WaitToAnnounce,
|
||||||
};
|
};
|
||||||
use cumulus_primitives::{
|
use cumulus_primitives::{
|
||||||
inherents::VALIDATION_FUNCTION_PARAMS_IDENTIFIER as VFP_IDENT,
|
HeadData, inherents::VALIDATION_FUNCTION_PARAMS_IDENTIFIER as VFP_IDENT,
|
||||||
validation_function_params::ValidationFunctionParams,
|
validation_function_params::ValidationFunctionParams,
|
||||||
};
|
};
|
||||||
use cumulus_runtime::ParachainBlockData;
|
use cumulus_runtime::ParachainBlockData;
|
||||||
@@ -56,12 +56,6 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc, time::Duration, pin::Pin};
|
|||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
/// The head data of the parachain, stored in the relay chain.
|
|
||||||
#[derive(Decode, Encode, Debug)]
|
|
||||||
struct HeadData<Block: BlockT> {
|
|
||||||
header: Block::Header,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The implementation of the Cumulus `Collator`.
|
/// The implementation of the Cumulus `Collator`.
|
||||||
pub struct Collator<Block: BlockT, PF, BI> {
|
pub struct Collator<Block: BlockT, PF, BI> {
|
||||||
proposer_factory: Arc<Mutex<PF>>,
|
proposer_factory: Arc<Mutex<PF>>,
|
||||||
@@ -340,7 +334,10 @@ where
|
|||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
Backend: sc_client_api::Backend<Block> + 'static,
|
Backend: sc_client_api::Backend<Block> + 'static,
|
||||||
Client: Finalizer<Block, Backend> + UsageProvider<Block> + Send + Sync + 'static,
|
Client: Finalizer<Block, Backend> + UsageProvider<Block> + HeaderBackend<Block>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
{
|
{
|
||||||
type ParachainContext = Collator<Block, PF, BI>;
|
type ParachainContext = Collator<Block, PF, BI>;
|
||||||
|
|
||||||
@@ -359,7 +356,7 @@ where
|
|||||||
Extrinsic: codec::Codec + Send + Sync + 'static,
|
Extrinsic: codec::Codec + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.delayed_block_announce_validator.set(
|
self.delayed_block_announce_validator.set(
|
||||||
Box::new(JustifiedBlockAnnounceValidator::new(polkadot_client.clone())),
|
Box::new(JustifiedBlockAnnounceValidator::new(polkadot_client.clone(), self.para_id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let follow =
|
let follow =
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ polkadot-statement-table = { git = "https://github.com/paritytech/polkadot", bra
|
|||||||
polkadot-validation = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
polkadot-validation = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||||
polkadot-network = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
polkadot-network = { git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch" }
|
||||||
|
|
||||||
|
# cumulus deps
|
||||||
|
cumulus-primitives = { path = "../primitives" }
|
||||||
|
|
||||||
# other deps
|
# other deps
|
||||||
codec = { package = "parity-scale-codec", version = "1.3.0", features = [ "derive" ] }
|
codec = { package = "parity-scale-codec", version = "1.3.0", features = [ "derive" ] }
|
||||||
futures = { version = "0.3.1", features = ["compat"] }
|
futures = { version = "0.3.1", features = ["compat"] }
|
||||||
|
|||||||
@@ -24,17 +24,19 @@ mod tests;
|
|||||||
use sp_api::ProvideRuntimeApi;
|
use sp_api::ProvideRuntimeApi;
|
||||||
use sp_blockchain::{Error as ClientError, HeaderBackend};
|
use sp_blockchain::{Error as ClientError, HeaderBackend};
|
||||||
use sp_consensus::block_validation::{BlockAnnounceValidator, Validation};
|
use sp_consensus::block_validation::{BlockAnnounceValidator, Validation};
|
||||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
|
use sp_runtime::{generic::BlockId, traits::{Block as BlockT, Header as HeaderT}};
|
||||||
|
|
||||||
use polkadot_collator::Network as CollatorNetwork;
|
use polkadot_collator::Network as CollatorNetwork;
|
||||||
use polkadot_network::legacy::gossip::{GossipMessage, GossipStatement};
|
use polkadot_network::legacy::gossip::{GossipMessage, GossipStatement};
|
||||||
use polkadot_primitives::{
|
use polkadot_primitives::{
|
||||||
parachain::ParachainHost,
|
parachain::{ParachainHost, Id as ParaId},
|
||||||
Block as PBlock, Hash as PHash,
|
Block as PBlock, Hash as PHash,
|
||||||
};
|
};
|
||||||
use polkadot_statement_table::{SignedStatement, Statement};
|
use polkadot_statement_table::{SignedStatement, Statement};
|
||||||
use polkadot_validation::check_statement;
|
use polkadot_validation::check_statement;
|
||||||
|
|
||||||
|
use cumulus_primitives::HeadData;
|
||||||
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use futures::{pin_mut, select, StreamExt};
|
use futures::{pin_mut, select, StreamExt};
|
||||||
use futures::channel::oneshot;
|
use futures::channel::oneshot;
|
||||||
@@ -54,13 +56,15 @@ use parking_lot::Mutex;
|
|||||||
pub struct JustifiedBlockAnnounceValidator<B, P> {
|
pub struct JustifiedBlockAnnounceValidator<B, P> {
|
||||||
phantom: PhantomData<B>,
|
phantom: PhantomData<B>,
|
||||||
polkadot_client: Arc<P>,
|
polkadot_client: Arc<P>,
|
||||||
|
para_id: ParaId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, P> JustifiedBlockAnnounceValidator<B, P> {
|
impl<B, P> JustifiedBlockAnnounceValidator<B, P> {
|
||||||
pub fn new(polkadot_client: Arc<P>) -> Self {
|
pub fn new(polkadot_client: Arc<P>, para_id: ParaId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
phantom: Default::default(),
|
phantom: Default::default(),
|
||||||
polkadot_client,
|
polkadot_client,
|
||||||
|
para_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,9 +79,34 @@ where
|
|||||||
header: &B::Header,
|
header: &B::Header,
|
||||||
mut data: &[u8],
|
mut data: &[u8],
|
||||||
) -> Result<Validation, Box<dyn std::error::Error + Send>> {
|
) -> Result<Validation, Box<dyn std::error::Error + Send>> {
|
||||||
// If no data is provided the announce is valid.
|
let runtime_api = self.polkadot_client.runtime_api();
|
||||||
|
let polkadot_info = self.polkadot_client.info();
|
||||||
|
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
return Ok(Validation::Success);
|
// Check if block is equal or higher than best (this requires a justification)
|
||||||
|
let runtime_api_block_id = BlockId::Hash(polkadot_info.best_hash);
|
||||||
|
let block_number = header.number();
|
||||||
|
|
||||||
|
let local_validation_data = runtime_api
|
||||||
|
.local_validation_data(&runtime_api_block_id, self.para_id)
|
||||||
|
.map_err(|e| Box::new(ClientError::Msg(format!("{:?}", e))) as Box<_>)?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Box::new(ClientError::Msg("Could not find parachain head in relay chain".into())) as Box<_>
|
||||||
|
})?;
|
||||||
|
let parent_head = HeadData::<B>::decode(&mut &local_validation_data.parent_head.0[..])
|
||||||
|
.map_err(|e| Box::new(ClientError::Msg(format!("Failed to decode parachain head: {:?}", e))) as Box<_>)?;
|
||||||
|
let known_best_number = parent_head.header.number();
|
||||||
|
|
||||||
|
return Ok(if block_number >= known_best_number {
|
||||||
|
trace!(
|
||||||
|
target: "cumulus-network",
|
||||||
|
"validation failed because a justification is needed if the block at the top of the chain."
|
||||||
|
);
|
||||||
|
|
||||||
|
Validation::Failure
|
||||||
|
} else {
|
||||||
|
Validation::Success
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check data is a gossip message.
|
// Check data is a gossip message.
|
||||||
@@ -108,7 +137,7 @@ where
|
|||||||
} = gossip_statement;
|
} = gossip_statement;
|
||||||
|
|
||||||
// Check that the relay chain parent of the block is the relay chain head
|
// Check that the relay chain parent of the block is the relay chain head
|
||||||
let best_number = self.polkadot_client.info().best_number;
|
let best_number = polkadot_info.best_number;
|
||||||
|
|
||||||
match self.polkadot_client.number(relay_chain_leaf) {
|
match self.polkadot_client.number(relay_chain_leaf) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -133,7 +162,6 @@ where
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let runtime_api = self.polkadot_client.runtime_api();
|
|
||||||
let runtime_api_block_id = BlockId::Hash(relay_chain_leaf);
|
let runtime_api_block_id = BlockId::Hash(relay_chain_leaf);
|
||||||
let signing_context = runtime_api
|
let signing_context = runtime_api
|
||||||
.signing_context(&runtime_api_block_id)
|
.signing_context(&runtime_api_block_id)
|
||||||
|
|||||||
@@ -48,12 +48,15 @@ fn make_validator_and_client() -> (
|
|||||||
let builder = TestClientBuilder::new();
|
let builder = TestClientBuilder::new();
|
||||||
let client = Arc::new(TestApi::new(Arc::new(builder.build())));
|
let client = Arc::new(TestApi::new(Arc::new(builder.build())));
|
||||||
|
|
||||||
(JustifiedBlockAnnounceValidator::new(client.clone()), client)
|
(
|
||||||
|
JustifiedBlockAnnounceValidator::new(client.clone(), ParaId::from(56)),
|
||||||
|
client,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_header() -> Header {
|
fn default_header() -> Header {
|
||||||
Header {
|
Header {
|
||||||
number: Default::default(),
|
number: 1,
|
||||||
digest: Default::default(),
|
digest: Default::default(),
|
||||||
extrinsics_root: Default::default(),
|
extrinsics_root: Default::default(),
|
||||||
parent_hash: Default::default(),
|
parent_hash: Default::default(),
|
||||||
@@ -91,13 +94,34 @@ fn make_gossip_message_and_header(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn valid_if_no_data() {
|
fn valid_if_no_data_and_less_than_best_known_number() {
|
||||||
let mut validator = make_validator();
|
let mut validator = make_validator();
|
||||||
let header = default_header();
|
let header = Header {
|
||||||
|
number: 0,
|
||||||
|
..default_header()
|
||||||
|
};
|
||||||
|
let res = validator.validate(&header, &[]);
|
||||||
|
|
||||||
assert!(
|
assert_eq!(
|
||||||
matches!(validator.validate(&header, &[]), Ok(Validation::Success)),
|
res.unwrap(),
|
||||||
"validating without data is always a success",
|
Validation::Success,
|
||||||
|
"validating without data with block number < best known number is always a success",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_if_no_data_exceeds_best_known_number() {
|
||||||
|
let mut validator = make_validator();
|
||||||
|
let header = Header {
|
||||||
|
number: 1,
|
||||||
|
..default_header()
|
||||||
|
};
|
||||||
|
let res = validator.validate(&header, &[]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
res.unwrap(),
|
||||||
|
Validation::Failure,
|
||||||
|
"validation fails if no justification and block number >= best known number",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +423,10 @@ sp_api::mock_impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn local_validation_data(_: ParaId) -> Option<LocalValidationData> {
|
fn local_validation_data(_: ParaId) -> Option<LocalValidationData> {
|
||||||
Some(Default::default())
|
Some(LocalValidationData {
|
||||||
|
parent_head: HeadData::<Block> { header: default_header() }.encode().into(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_heads(_: Vec<<PBlock as BlockT>::Extrinsic>) -> Option<Vec<AbridgedCandidateReceipt>> {
|
fn get_heads(_: Vec<<PBlock as BlockT>::Extrinsic>) -> Option<Vec<AbridgedCandidateReceipt>> {
|
||||||
|
|||||||
@@ -20,6 +20,9 @@
|
|||||||
|
|
||||||
pub mod validation_function_params;
|
pub mod validation_function_params;
|
||||||
|
|
||||||
|
use codec::{Decode, Encode};
|
||||||
|
use sp_runtime::traits::Block as BlockT;
|
||||||
|
|
||||||
/// Identifiers and types related to Cumulus Inherents
|
/// Identifiers and types related to Cumulus Inherents
|
||||||
pub mod inherents {
|
pub mod inherents {
|
||||||
use sp_inherents::InherentIdentifier;
|
use sp_inherents::InherentIdentifier;
|
||||||
@@ -64,3 +67,9 @@ pub trait UpwardMessageSender {
|
|||||||
/// Returns an error if sending failed.
|
/// Returns an error if sending failed.
|
||||||
fn send_upward_message(msg: &()) -> Result<(), ()>;
|
fn send_upward_message(msg: &()) -> Result<(), ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The head data of the parachain, stored in the relay chain.
|
||||||
|
#[derive(Decode, Encode, Debug)]
|
||||||
|
pub struct HeadData<Block: BlockT> {
|
||||||
|
pub header: Block::Header,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user