mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 13:17:56 +00:00
Add block announce validator. (#3346)
* Add `BlockAnnounceValidator` trait. * Add associated data to block announcement. * Make tests compile. * Move validator into `sync.rs`. * Smaller changes. * Update core/network/src/protocol.rs Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Update core/network/src/protocol.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update core/network/src/test/sync.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Formatting. * Remove assoc. data from `BlockImportNotification`. * Use `Option<Vec<u8>>` for associated data. * Update core/network/src/protocol/sync.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Fix type error.
This commit is contained in:
committed by
Bastian Köcher
parent
4888c253a3
commit
af0d71d389
@@ -273,6 +273,8 @@ pub mod generic {
|
||||
pub header: H,
|
||||
/// Block state. TODO: Remove `Option` and custom encoding when v4 becomes common.
|
||||
pub state: Option<BlockState>,
|
||||
/// Data associated with this block announcement, e.g. a candidate message.
|
||||
pub data: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
// Custom Encode/Decode impl to maintain backwards compatibility with v3.
|
||||
@@ -284,6 +286,9 @@ pub mod generic {
|
||||
if let Some(state) = &self.state {
|
||||
state.encode_to(dest);
|
||||
}
|
||||
if let Some(data) = &self.data {
|
||||
data.encode_to(dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,9 +296,11 @@ pub mod generic {
|
||||
fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
|
||||
let header = H::decode(input)?;
|
||||
let state = BlockState::decode(input).ok();
|
||||
let data = Vec::decode(input).ok();
|
||||
Ok(BlockAnnounce {
|
||||
header,
|
||||
state,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,15 @@
|
||||
//!
|
||||
|
||||
use blocks::BlockCollection;
|
||||
use client::{BlockStatus, ClientInfo, error::Error as ClientError};
|
||||
use consensus::{BlockOrigin, import_queue::{IncomingBlock, BlockImportResult, BlockImportError}};
|
||||
use client::{ClientInfo, error::Error as ClientError};
|
||||
use consensus::{BlockOrigin, BlockStatus,
|
||||
block_validation::{BlockAnnounceValidator, Validation},
|
||||
import_queue::{IncomingBlock, BlockImportResult, BlockImportError}
|
||||
};
|
||||
use crate::{
|
||||
config::{Roles, BoxFinalityProofRequestBuilder},
|
||||
message::{self, generic::FinalityProofRequest, BlockAttributes, BlockRequest, BlockResponse, FinalityProofResponse},
|
||||
message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse,
|
||||
FinalityProofResponse},
|
||||
protocol
|
||||
};
|
||||
use either::Either;
|
||||
@@ -122,6 +126,8 @@ pub struct ChainSync<B: BlockT> {
|
||||
request_builder: Option<BoxFinalityProofRequestBuilder<B>>,
|
||||
/// A flag that caches idle state with no pending requests.
|
||||
is_idle: bool,
|
||||
/// A type to check incoming block announcements.
|
||||
block_announce_validator: Box<dyn BlockAnnounceValidator<B> + Send>
|
||||
}
|
||||
|
||||
/// All the data we have about a Peer that we are trying to sync with
|
||||
@@ -271,7 +277,8 @@ impl<B: BlockT> ChainSync<B> {
|
||||
role: Roles,
|
||||
client: Arc<dyn crate::chain::Client<B>>,
|
||||
info: &ClientInfo<B>,
|
||||
request_builder: Option<BoxFinalityProofRequestBuilder<B>>
|
||||
request_builder: Option<BoxFinalityProofRequestBuilder<B>>,
|
||||
block_announce_validator: Box<dyn BlockAnnounceValidator<B> + Send>
|
||||
) -> Self {
|
||||
let mut required_block_attributes = BlockAttributes::HEADER | BlockAttributes::JUSTIFICATION;
|
||||
|
||||
@@ -293,6 +300,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
best_importing_number: Zero::zero(),
|
||||
request_builder,
|
||||
is_idle: false,
|
||||
block_announce_validator,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,9 +893,10 @@ impl<B: BlockT> ChainSync<B> {
|
||||
/// header (call `on_block_data`). The network request isn't sent
|
||||
/// in this case. Both hash and header is passed as an optimization
|
||||
/// to avoid rehashing the header.
|
||||
pub fn on_block_announce(&mut self, who: PeerId, hash: B::Hash, header: &B::Header, is_best: bool)
|
||||
pub fn on_block_announce(&mut self, who: PeerId, hash: B::Hash, announce: &BlockAnnounce<B::Header>, is_best: bool)
|
||||
-> OnBlockAnnounce<B>
|
||||
{
|
||||
let header = &announce.header;
|
||||
let number = *header.number();
|
||||
debug!(target: "sync", "Received block announcement with number {:?}", number);
|
||||
if number.is_zero() {
|
||||
@@ -932,6 +941,20 @@ impl<B: BlockT> ChainSync<B> {
|
||||
return OnBlockAnnounce::Nothing
|
||||
}
|
||||
|
||||
// Let external validator check the block announcement.
|
||||
let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice());
|
||||
match self.block_announce_validator.validate(&header, assoc_data) {
|
||||
Ok(Validation::Success) => (),
|
||||
Ok(Validation::Failure) => {
|
||||
debug!(target: "sync", "block announcement validation of block {} from {} failed", hash, who);
|
||||
return OnBlockAnnounce::Nothing
|
||||
}
|
||||
Err(e) => {
|
||||
error!(target: "sync", "block announcement validation errored: {}", e);
|
||||
return OnBlockAnnounce::Nothing
|
||||
}
|
||||
}
|
||||
|
||||
// stale block case
|
||||
let requires_additional_data = !self.role.is_light();
|
||||
if number <= self.best_queued_number {
|
||||
|
||||
Reference in New Issue
Block a user