Add block data size check (#230)

* Add block data size check

* Pass max_block_data_size everywhere

* Fix build after merge

* Fix ParachainWork initialization

* Fix tests compilation
This commit is contained in:
Stanislav Tkach
2019-05-24 14:02:13 +03:00
committed by Gavin Wood
parent 7a123fe8e9
commit 10ae8d48f5
6 changed files with 64 additions and 9 deletions
+1
View File
@@ -413,5 +413,6 @@ fn make_table(data: &ApiData, local_key: &AuthorityKeyring, parent_hash: Hash) -
Arc::new(local_key.pair()), Arc::new(local_key.pair()),
parent_hash, parent_hash,
store, store,
None,
)) ))
} }
+5
View File
@@ -85,6 +85,9 @@ pub struct CustomConfiguration {
grandpa::LinkHalfForService<Factory> grandpa::LinkHalfForService<Factory>
)>, )>,
/// Maximal `block_data` size.
pub max_block_data_size: Option<u64>,
inherent_data_providers: InherentDataProviders, inherent_data_providers: InherentDataProviders,
} }
@@ -94,6 +97,7 @@ impl Default for CustomConfiguration {
collating_for: None, collating_for: None,
grandpa_import_setup: None, grandpa_import_setup: None,
inherent_data_providers: InherentDataProviders::new(), inherent_data_providers: InherentDataProviders::new(),
max_block_data_size: None,
} }
} }
} }
@@ -311,6 +315,7 @@ construct_service_factory! {
key.clone(), key.clone(),
extrinsic_store, extrinsic_store,
SlotDuration::get_or_compute(&*client)?, SlotDuration::get_or_compute(&*client)?,
service.config.custom.max_block_data_size,
); );
info!("Using authority key {}", key.public()); info!("Using authority key {}", key.public());
@@ -110,6 +110,7 @@ pub(crate) fn start<C, N, P, SC>(
thread_pool: TaskExecutor, thread_pool: TaskExecutor,
key: Arc<ed25519::Pair>, key: Arc<ed25519::Pair>,
extrinsic_store: ExtrinsicStore, extrinsic_store: ExtrinsicStore,
max_block_data_size: Option<u64>,
) -> ServiceHandle ) -> ServiceHandle
where where
C: Collators + Send + Sync + 'static, C: Collators + Send + Sync + 'static,
@@ -147,6 +148,7 @@ pub(crate) fn start<C, N, P, SC>(
notification.header.parent_hash().clone(), notification.header.parent_hash().clone(),
&authorities, &authorities,
key.clone(), key.clone(),
max_block_data_size,
) )
}); });
+17 -2
View File
@@ -64,6 +64,7 @@ pub struct CollationFetch<C: Collators, P> {
collators: C, collators: C,
live_fetch: Option<<C::Collation as IntoFuture>::Future>, live_fetch: Option<<C::Collation as IntoFuture>::Future>,
client: Arc<P>, client: Arc<P>,
max_block_data_size: Option<u64>,
} }
impl<C: Collators, P> CollationFetch<C, P> { impl<C: Collators, P> CollationFetch<C, P> {
@@ -73,6 +74,7 @@ impl<C: Collators, P> CollationFetch<C, P> {
relay_parent_hash: Hash, relay_parent_hash: Hash,
collators: C, collators: C,
client: Arc<P>, client: Arc<P>,
max_block_data_size: Option<u64>,
) -> Self { ) -> Self {
CollationFetch { CollationFetch {
relay_parent: BlockId::hash(relay_parent_hash), relay_parent: BlockId::hash(relay_parent_hash),
@@ -81,6 +83,7 @@ impl<C: Collators, P> CollationFetch<C, P> {
client, client,
parachain, parachain,
live_fetch: None, live_fetch: None,
max_block_data_size,
} }
} }
@@ -113,7 +116,7 @@ impl<C: Collators, P: ProvideRuntimeApi> Future for CollationFetch<C, P>
try_ready!(poll) try_ready!(poll)
}; };
let res = validate_collation(&*self.client, &self.relay_parent, &collation); let res = validate_collation(&*self.client, &self.relay_parent, &collation, self.max_block_data_size);
match res { match res {
Ok(e) => { Ok(e) => {
@@ -179,7 +182,11 @@ error_chain! {
} }
WrongHeadData(expected: Vec<u8>, got: Vec<u8>) { WrongHeadData(expected: Vec<u8>, got: Vec<u8>) {
description("Parachain validation produced wrong head data."), description("Parachain validation produced wrong head data."),
display("Parachain validation produced wrong head data (expected: {:?}, got {:?}", expected, got), display("Parachain validation produced wrong head data (expected: {:?}, got {:?})", expected, got),
}
BlockDataTooBig(size: u64, max_size: u64) {
description("Block data is too big."),
display("Block data is too big (maximum allowed size: {}, actual size: {})", max_size, size),
} }
} }
} }
@@ -331,12 +338,20 @@ pub fn validate_collation<P>(
client: &P, client: &P,
relay_parent: &BlockId, relay_parent: &BlockId,
collation: &Collation, collation: &Collation,
max_block_data_size: Option<u64>,
) -> Result<Extrinsic, Error> where ) -> Result<Extrinsic, Error> where
P: ProvideRuntimeApi, P: ProvideRuntimeApi,
P::Api: ParachainHost<Block>, P::Api: ParachainHost<Block>,
{ {
use parachain::{IncomingMessage, ValidationParams}; use parachain::{IncomingMessage, ValidationParams};
if let Some(max_size) = max_block_data_size {
let block_data_size = collation.pov.block_data.0.len() as u64;
if block_data_size > max_size {
return Err(ErrorKind::BlockDataTooBig(block_data_size, max_size).into());
}
}
let api = client.runtime_api(); let api = client.runtime_api();
let para_id = collation.receipt.parachain_index; let para_id = collation.receipt.parachain_index;
let validation_code = api.parachain_code(relay_parent, para_id)? let validation_code = api.parachain_code(relay_parent, para_id)?
+19 -3
View File
@@ -300,6 +300,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
grandparent_hash: Hash, grandparent_hash: Hash,
authorities: &[AuthorityId], authorities: &[AuthorityId],
sign_with: Arc<ed25519::Pair>, sign_with: Arc<ed25519::Pair>,
max_block_data_size: Option<u64>,
) )
-> Result<Arc<AttestationTracker>, Error> -> Result<Arc<AttestationTracker>, Error>
{ {
@@ -351,7 +352,14 @@ impl<C, N, P> ParachainValidation<C, N, P> where
debug!(target: "validation", "Active parachains: {:?}", active_parachains); debug!(target: "validation", "Active parachains: {:?}", active_parachains);
let table = Arc::new(SharedTable::new(authorities, group_info, sign_with.clone(), parent_hash, self.extrinsic_store.clone())); let table = Arc::new(SharedTable::new(
authorities,
group_info,
sign_with.clone(),
parent_hash,
self.extrinsic_store.clone(),
max_block_data_size,
));
let router = self.network.communication_for( let router = self.network.communication_for(
table.clone(), table.clone(),
authorities, authorities,
@@ -362,6 +370,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
parent_hash, parent_hash,
id, id,
router, router,
max_block_data_size,
)), )),
Chain::Relay => None, Chain::Relay => None,
}; };
@@ -387,7 +396,8 @@ impl<C, N, P> ParachainValidation<C, N, P> where
&self, &self,
relay_parent: Hash, relay_parent: Hash,
validation_para: ParaId, validation_para: ParaId,
build_router: N::BuildTableRouter build_router: N::BuildTableRouter,
max_block_data_size: Option<u64>,
) -> exit_future::Signal { ) -> exit_future::Signal {
use extrinsic_store::Data; use extrinsic_store::Data;
@@ -402,6 +412,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
relay_parent, relay_parent,
collators, collators,
client, client,
max_block_data_size,
); );
collation_work.then(move |result| match result { collation_work.then(move |result| match result {
@@ -466,6 +477,7 @@ pub struct ProposerFactory<C, N, P, SC, TxApi: PoolChainApi> {
_service_handle: ServiceHandle, _service_handle: ServiceHandle,
aura_slot_duration: SlotDuration, aura_slot_duration: SlotDuration,
select_chain: SC, select_chain: SC,
max_block_data_size: Option<u64>,
} }
impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
@@ -491,6 +503,7 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
key: Arc<ed25519::Pair>, key: Arc<ed25519::Pair>,
extrinsic_store: ExtrinsicStore, extrinsic_store: ExtrinsicStore,
aura_slot_duration: SlotDuration, aura_slot_duration: SlotDuration,
max_block_data_size: Option<u64>,
) -> Self { ) -> Self {
let parachain_validation = Arc::new(ParachainValidation { let parachain_validation = Arc::new(ParachainValidation {
client: client.clone(), client: client.clone(),
@@ -508,6 +521,7 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
thread_pool, thread_pool,
key.clone(), key.clone(),
extrinsic_store, extrinsic_store,
max_block_data_size,
); );
ProposerFactory { ProposerFactory {
@@ -516,7 +530,8 @@ impl<C, N, P, SC, TxApi> ProposerFactory<C, N, P, SC, TxApi> where
key, key,
_service_handle: service_handle, _service_handle: service_handle,
aura_slot_duration, aura_slot_duration,
select_chain select_chain,
max_block_data_size,
} }
} }
} }
@@ -548,6 +563,7 @@ impl<C, N, P, SC, TxApi> consensus::Environment<Block> for ProposerFactory<C, N,
parent_header.parent_hash().clone(), parent_header.parent_hash().clone(),
authorities, authorities,
sign_with, sign_with,
self.max_block_data_size,
)?; )?;
Ok(Proposer { Ok(Proposer {
+20 -4
View File
@@ -136,6 +136,7 @@ impl SharedTableInner {
context: &TableContext, context: &TableContext,
router: &R, router: &R,
statement: table::SignedStatement, statement: table::SignedStatement,
max_block_data_size: Option<u64>,
) -> Option<ParachainWork< ) -> Option<ParachainWork<
<R::FetchValidationProof as IntoFuture>::Future, <R::FetchValidationProof as IntoFuture>::Future,
>> { >> {
@@ -191,7 +192,8 @@ impl SharedTableInner {
work.map(|work| ParachainWork { work.map(|work| ParachainWork {
extrinsic_store: self.extrinsic_store.clone(), extrinsic_store: self.extrinsic_store.clone(),
relay_parent: context.parent_hash.clone(), relay_parent: context.parent_hash.clone(),
work work,
max_block_data_size,
}) })
} }
@@ -265,6 +267,7 @@ pub struct ParachainWork<Fetch> {
work: Work<Fetch>, work: Work<Fetch>,
relay_parent: Hash, relay_parent: Hash,
extrinsic_store: ExtrinsicStore, extrinsic_store: ExtrinsicStore,
max_block_data_size: Option<u64>,
} }
impl<Fetch: Future> ParachainWork<Fetch> { impl<Fetch: Future> ParachainWork<Fetch> {
@@ -279,11 +282,13 @@ impl<Fetch: Future> ParachainWork<Fetch> {
P: Send + Sync + 'static, P: Send + Sync + 'static,
P::Api: ParachainHost<Block>, P::Api: ParachainHost<Block>,
{ {
let max_block_data_size = self.max_block_data_size;
let validate = move |id: &_, collation: &_| { let validate = move |id: &_, collation: &_| {
let res = ::collation::validate_collation( let res = ::collation::validate_collation(
&*api, &*api,
id, id,
collation, collation,
max_block_data_size,
); );
match res { match res {
@@ -373,13 +378,15 @@ impl<Fetch, F, Err> Future for PrimedParachainWork<Fetch, F>
pub struct SharedTable { pub struct SharedTable {
context: Arc<TableContext>, context: Arc<TableContext>,
inner: Arc<Mutex<SharedTableInner>>, inner: Arc<Mutex<SharedTableInner>>,
max_block_data_size: Option<u64>,
} }
impl Clone for SharedTable { impl Clone for SharedTable {
fn clone(&self) -> Self { fn clone(&self) -> Self {
SharedTable { Self {
context: self.context.clone(), context: self.context.clone(),
inner: self.inner.clone(), inner: self.inner.clone(),
max_block_data_size: self.max_block_data_size,
} }
} }
} }
@@ -395,10 +402,12 @@ impl SharedTable {
key: Arc<ed25519::Pair>, key: Arc<ed25519::Pair>,
parent_hash: Hash, parent_hash: Hash,
extrinsic_store: ExtrinsicStore, extrinsic_store: ExtrinsicStore,
max_block_data_size: Option<u64>,
) -> Self { ) -> Self {
let index_mapping = authorities.iter().enumerate().map(|(i, k)| (i as ValidatorIndex, k.clone())).collect(); let index_mapping = authorities.iter().enumerate().map(|(i, k)| (i as ValidatorIndex, k.clone())).collect();
Self { Self {
context: Arc::new(TableContext { groups, key, parent_hash, index_mapping, }), context: Arc::new(TableContext { groups, key, parent_hash, index_mapping, }),
max_block_data_size,
inner: Arc::new(Mutex::new(SharedTableInner { inner: Arc::new(Mutex::new(SharedTableInner {
table: Table::default(), table: Table::default(),
validated: HashMap::new(), validated: HashMap::new(),
@@ -447,7 +456,7 @@ impl SharedTable {
) -> Option<ParachainWork< ) -> Option<ParachainWork<
<R::FetchValidationProof as IntoFuture>::Future, <R::FetchValidationProof as IntoFuture>::Future,
>> { >> {
self.inner.lock().import_remote_statement(&*self.context, router, statement) self.inner.lock().import_remote_statement(&*self.context, router, statement, self.max_block_data_size)
} }
/// Import many statements at once. /// Import many statements at once.
@@ -467,7 +476,7 @@ impl SharedTable {
let mut inner = self.inner.lock(); let mut inner = self.inner.lock();
iterable.into_iter().map(move |statement| { iterable.into_iter().map(move |statement| {
inner.import_remote_statement(&*self.context, router, statement) inner.import_remote_statement(&*self.context, router, statement, self.max_block_data_size)
}).collect() }).collect()
} }
@@ -612,6 +621,7 @@ mod tests {
local_key.clone(), local_key.clone(),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None,
); );
let candidate = CandidateReceipt { let candidate = CandidateReceipt {
@@ -665,6 +675,7 @@ mod tests {
local_key.clone(), local_key.clone(),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None,
); );
let candidate = CandidateReceipt { let candidate = CandidateReceipt {
@@ -720,6 +731,7 @@ mod tests {
}, },
relay_parent, relay_parent,
extrinsic_store: store.clone(), extrinsic_store: store.clone(),
max_block_data_size: None,
}; };
let validated = producer.prime_with(|_, _| Ok(Extrinsic { outgoing_messages: Vec::new() })) let validated = producer.prime_with(|_, _| Ok(Extrinsic { outgoing_messages: Vec::new() }))
@@ -760,6 +772,7 @@ mod tests {
}, },
relay_parent, relay_parent,
extrinsic_store: store.clone(), extrinsic_store: store.clone(),
max_block_data_size: None,
}; };
let validated = producer.prime_with(|_, _| Ok(Extrinsic { outgoing_messages: Vec::new() })) let validated = producer.prime_with(|_, _| Ok(Extrinsic { outgoing_messages: Vec::new() }))
@@ -797,6 +810,7 @@ mod tests {
local_key.clone(), local_key.clone(),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None,
); );
let candidate = CandidateReceipt { let candidate = CandidateReceipt {
@@ -861,6 +875,7 @@ mod tests {
local_key.clone(), local_key.clone(),
parent_hash, parent_hash,
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None,
); );
let candidate = CandidateReceipt { let candidate = CandidateReceipt {
@@ -909,6 +924,7 @@ mod tests {
Arc::new(AuthorityKeyring::Alice.pair()), Arc::new(AuthorityKeyring::Alice.pair()),
Default::default(), Default::default(),
ExtrinsicStore::new_in_memory(), ExtrinsicStore::new_in_memory(),
None,
); );
let expected_mapping = authorities.iter().enumerate().map(|(i, k)| (i as ValidatorIndex, k.clone())).collect(); let expected_mapping = authorities.iter().enumerate().map(|(i, k)| (i as ValidatorIndex, k.clone())).collect();
assert_eq!(shared_table.context.index_mapping, expected_mapping); assert_eq!(shared_table.context.index_mapping, expected_mapping);