mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 21:11:07 +00:00
grandpa: remove light-client specific block import pipeline (#7546)
* grandpa: remove light-client specific block import * consensus, network: remove finality proofs
This commit is contained in:
@@ -15,9 +15,9 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
config::{ProtocolId, Role}, block_requests, light_client_handler, finality_requests,
|
||||
config::{ProtocolId, Role}, block_requests, light_client_handler,
|
||||
peer_info, request_responses, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut},
|
||||
protocol::{message::{self, Roles}, CustomMessageOutcome, NotificationsSink, Protocol},
|
||||
protocol::{message::Roles, CustomMessageOutcome, NotificationsSink, Protocol},
|
||||
ObservedRole, DhtEvent, ExHashT,
|
||||
};
|
||||
|
||||
@@ -58,8 +58,6 @@ pub struct Behaviour<B: BlockT, H: ExHashT> {
|
||||
request_responses: request_responses::RequestResponsesBehaviour,
|
||||
/// Block request handling.
|
||||
block_requests: block_requests::BlockRequests<B>,
|
||||
/// Finality proof request handling.
|
||||
finality_proof_requests: finality_requests::FinalityProofRequests<B>,
|
||||
/// Light client request handling.
|
||||
light_client_handler: light_client_handler::LightClientHandler<B>,
|
||||
|
||||
@@ -76,7 +74,6 @@ pub struct Behaviour<B: BlockT, H: ExHashT> {
|
||||
pub enum BehaviourOut<B: BlockT> {
|
||||
BlockImport(BlockOrigin, Vec<IncomingBlock<B>>),
|
||||
JustificationImport(Origin, B::Hash, NumberFor<B>, Justification),
|
||||
FinalityProofImport(Origin, B::Hash, NumberFor<B>, Vec<u8>),
|
||||
|
||||
/// Started a random iterative Kademlia discovery query.
|
||||
RandomKademliaStarted(ProtocolId),
|
||||
@@ -182,7 +179,6 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
||||
user_agent: String,
|
||||
local_public_key: PublicKey,
|
||||
block_requests: block_requests::BlockRequests<B>,
|
||||
finality_proof_requests: finality_requests::FinalityProofRequests<B>,
|
||||
light_client_handler: light_client_handler::LightClientHandler<B>,
|
||||
disco_config: DiscoveryConfig,
|
||||
request_response_protocols: Vec<request_responses::ProtocolConfig>,
|
||||
@@ -194,7 +190,6 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
||||
request_responses:
|
||||
request_responses::RequestResponsesBehaviour::new(request_response_protocols.into_iter())?,
|
||||
block_requests,
|
||||
finality_proof_requests,
|
||||
light_client_handler,
|
||||
events: VecDeque::new(),
|
||||
role,
|
||||
@@ -334,8 +329,6 @@ Behaviour<B, H> {
|
||||
self.events.push_back(BehaviourOut::BlockImport(origin, blocks)),
|
||||
CustomMessageOutcome::JustificationImport(origin, hash, nb, justification) =>
|
||||
self.events.push_back(BehaviourOut::JustificationImport(origin, hash, nb, justification)),
|
||||
CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) =>
|
||||
self.events.push_back(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)),
|
||||
CustomMessageOutcome::BlockRequest { target, request } => {
|
||||
match self.block_requests.send_request(&target, request) {
|
||||
block_requests::SendRequestOutcome::Ok => {
|
||||
@@ -359,9 +352,6 @@ Behaviour<B, H> {
|
||||
block_requests::SendRequestOutcome::EncodeError(_) => {},
|
||||
}
|
||||
},
|
||||
CustomMessageOutcome::FinalityProofRequest { target, block_hash, request } => {
|
||||
self.finality_proof_requests.send_request(&target, block_hash, request);
|
||||
},
|
||||
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles, notifications_sink } => {
|
||||
let role = reported_roles_to_observed_role(&self.role, &remote, roles);
|
||||
for protocol in protocols {
|
||||
@@ -454,26 +444,6 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<block_requests::Event<B
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<finality_requests::Event<B>> for Behaviour<B, H> {
|
||||
fn inject_event(&mut self, event: finality_requests::Event<B>) {
|
||||
match event {
|
||||
finality_requests::Event::Response { peer, block_hash, proof } => {
|
||||
let response = message::FinalityProofResponse {
|
||||
id: 0,
|
||||
block: block_hash,
|
||||
proof: if !proof.is_empty() {
|
||||
Some(proof)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
};
|
||||
let ev = self.substrate.on_finality_proof_response(peer, response);
|
||||
self.inject_event(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<peer_info::PeerInfoEvent>
|
||||
for Behaviour<B, H> {
|
||||
fn inject_event(&mut self, event: peer_info::PeerInfoEvent) {
|
||||
|
||||
@@ -32,15 +32,3 @@ impl<Block: BlockT, T> Client<Block> for T
|
||||
T: HeaderBackend<Block> + ProofProvider<Block> + BlockIdTo<Block, Error = Error>
|
||||
+ BlockBackend<Block> + HeaderMetadata<Block, Error = Error> + Send + Sync
|
||||
{}
|
||||
|
||||
/// Finality proof provider.
|
||||
pub trait FinalityProofProvider<Block: BlockT>: Send + Sync {
|
||||
/// Prove finality of the block.
|
||||
fn prove_finality(&self, for_block: Block::Hash, request: &[u8]) -> Result<Option<Vec<u8>>, Error>;
|
||||
}
|
||||
|
||||
impl<Block: BlockT> FinalityProofProvider<Block> for () {
|
||||
fn prove_finality(&self, _for_block: Block::Hash, _request: &[u8]) -> Result<Option<Vec<u8>>, Error> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
//! The [`Params`] struct is the struct that must be passed in order to initialize the networking.
|
||||
//! See the documentation of [`Params`].
|
||||
|
||||
pub use crate::chain::{Client, FinalityProofProvider};
|
||||
pub use crate::chain::Client;
|
||||
pub use crate::on_demand_layer::{AlwaysBadChecker, OnDemand};
|
||||
pub use crate::request_responses::{IncomingRequest, ProtocolConfig as RequestResponseConfig};
|
||||
pub use libp2p::{identity, core::PublicKey, wasm_ext::ExtTransport, build_multiaddr};
|
||||
@@ -70,17 +70,6 @@ pub struct Params<B: BlockT, H: ExHashT> {
|
||||
/// Client that contains the blockchain.
|
||||
pub chain: Arc<dyn Client<B>>,
|
||||
|
||||
/// Finality proof provider.
|
||||
///
|
||||
/// This object, if `Some`, is used when a node on the network requests a proof of finality
|
||||
/// from us.
|
||||
pub finality_proof_provider: Option<Arc<dyn FinalityProofProvider<B>>>,
|
||||
|
||||
/// How to build requests for proofs of finality.
|
||||
///
|
||||
/// This object, if `Some`, is used when we need a proof of finality from another node.
|
||||
pub finality_proof_request_builder: Option<BoxFinalityProofRequestBuilder<B>>,
|
||||
|
||||
/// The `OnDemand` object acts as a "receiver" for block data requests from the client.
|
||||
/// If `Some`, the network worker will process these requests and answer them.
|
||||
/// Normally used only for light clients.
|
||||
@@ -153,25 +142,6 @@ impl fmt::Display for Role {
|
||||
}
|
||||
}
|
||||
|
||||
/// Finality proof request builder.
|
||||
pub trait FinalityProofRequestBuilder<B: BlockT>: Send {
|
||||
/// Build data blob, associated with the request.
|
||||
fn build_request_data(&mut self, hash: &B::Hash) -> Vec<u8>;
|
||||
}
|
||||
|
||||
/// Implementation of `FinalityProofRequestBuilder` that builds a dummy empty request.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DummyFinalityProofRequestBuilder;
|
||||
|
||||
impl<B: BlockT> FinalityProofRequestBuilder<B> for DummyFinalityProofRequestBuilder {
|
||||
fn build_request_data(&mut self, _: &B::Hash) -> Vec<u8> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Shared finality proof request builder struct used by the queue.
|
||||
pub type BoxFinalityProofRequestBuilder<B> = Box<dyn FinalityProofRequestBuilder<B> + Send + Sync>;
|
||||
|
||||
/// Result of the transaction import.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TransactionImport {
|
||||
|
||||
@@ -1,403 +0,0 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
//
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! `NetworkBehaviour` implementation which handles incoming finality proof requests.
|
||||
//!
|
||||
//! Every request is coming in on a separate connection substream which gets
|
||||
//! closed after we have sent the response back. Incoming requests are encoded
|
||||
//! as protocol buffers (cf. `finality.v1.proto`).
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use bytes::Bytes;
|
||||
use codec::{Encode, Decode};
|
||||
use crate::{
|
||||
chain::FinalityProofProvider,
|
||||
config::ProtocolId,
|
||||
protocol::message,
|
||||
schema,
|
||||
};
|
||||
use futures::{future::BoxFuture, prelude::*, stream::FuturesUnordered};
|
||||
use libp2p::{
|
||||
core::{
|
||||
ConnectedPoint,
|
||||
Multiaddr,
|
||||
PeerId,
|
||||
connection::ConnectionId,
|
||||
upgrade::{InboundUpgrade, OutboundUpgrade, ReadOneError, UpgradeInfo, Negotiated},
|
||||
upgrade::{DeniedUpgrade, read_one, write_one}
|
||||
},
|
||||
swarm::{
|
||||
NegotiatedSubstream,
|
||||
NetworkBehaviour,
|
||||
NetworkBehaviourAction,
|
||||
NotifyHandler,
|
||||
OneShotHandler,
|
||||
OneShotHandlerConfig,
|
||||
PollParameters,
|
||||
SubstreamProtocol
|
||||
}
|
||||
};
|
||||
use prost::Message;
|
||||
use sp_runtime::{generic::BlockId, traits::{Block, Header, One, Zero}};
|
||||
use std::{
|
||||
cmp::min,
|
||||
collections::VecDeque,
|
||||
io,
|
||||
iter,
|
||||
marker::PhantomData,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
task::{Context, Poll}
|
||||
};
|
||||
use void::{Void, unreachable};
|
||||
|
||||
// Type alias for convenience.
|
||||
pub type Error = Box<dyn std::error::Error + 'static>;
|
||||
|
||||
/// Event generated by the finality proof requests behaviour.
|
||||
#[derive(Debug)]
|
||||
pub enum Event<B: Block> {
|
||||
/// A response to a finality proof request has arrived.
|
||||
Response {
|
||||
peer: PeerId,
|
||||
/// Block hash originally passed to `send_request`.
|
||||
block_hash: B::Hash,
|
||||
/// Finality proof returned by the remote.
|
||||
proof: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Configuration options for `FinalityProofRequests`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
max_request_len: usize,
|
||||
max_response_len: usize,
|
||||
inactivity_timeout: Duration,
|
||||
protocol: Bytes,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Create a fresh configuration with the following options:
|
||||
///
|
||||
/// - max. request size = 1 MiB
|
||||
/// - max. response size = 1 MiB
|
||||
/// - inactivity timeout = 15s
|
||||
pub fn new(id: &ProtocolId) -> Self {
|
||||
let mut c = Config {
|
||||
max_request_len: 1024 * 1024,
|
||||
max_response_len: 1024 * 1024,
|
||||
inactivity_timeout: Duration::from_secs(15),
|
||||
protocol: Bytes::new(),
|
||||
};
|
||||
c.set_protocol(id);
|
||||
c
|
||||
}
|
||||
|
||||
/// Limit the max. length of incoming finality proof request bytes.
|
||||
pub fn set_max_request_len(&mut self, v: usize) -> &mut Self {
|
||||
self.max_request_len = v;
|
||||
self
|
||||
}
|
||||
|
||||
/// Limit the max. length of incoming finality proof response bytes.
|
||||
pub fn set_max_response_len(&mut self, v: usize) -> &mut Self {
|
||||
self.max_response_len = v;
|
||||
self
|
||||
}
|
||||
|
||||
/// Limit the max. duration the substream may remain inactive before closing it.
|
||||
pub fn set_inactivity_timeout(&mut self, v: Duration) -> &mut Self {
|
||||
self.inactivity_timeout = v;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set protocol to use for upgrade negotiation.
|
||||
pub fn set_protocol(&mut self, id: &ProtocolId) -> &mut Self {
|
||||
let mut v = Vec::new();
|
||||
v.extend_from_slice(b"/");
|
||||
v.extend_from_slice(id.as_ref().as_bytes());
|
||||
v.extend_from_slice(b"/finality-proof/1");
|
||||
self.protocol = v.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The finality proof request handling behaviour.
|
||||
pub struct FinalityProofRequests<B: Block> {
|
||||
/// This behaviour's configuration.
|
||||
config: Config,
|
||||
/// How to construct finality proofs.
|
||||
finality_proof_provider: Option<Arc<dyn FinalityProofProvider<B>>>,
|
||||
/// Futures sending back the finality proof request responses.
|
||||
outgoing: FuturesUnordered<BoxFuture<'static, ()>>,
|
||||
/// Events to return as soon as possible from `poll`.
|
||||
pending_events: VecDeque<NetworkBehaviourAction<OutboundProtocol<B>, Event<B>>>,
|
||||
}
|
||||
|
||||
impl<B> FinalityProofRequests<B>
|
||||
where
|
||||
B: Block,
|
||||
{
|
||||
/// Initializes the behaviour.
|
||||
///
|
||||
/// If the proof provider is `None`, then the behaviour will not support the finality proof
|
||||
/// requests protocol.
|
||||
pub fn new(cfg: Config, finality_proof_provider: Option<Arc<dyn FinalityProofProvider<B>>>) -> Self {
|
||||
FinalityProofRequests {
|
||||
config: cfg,
|
||||
finality_proof_provider,
|
||||
outgoing: FuturesUnordered::new(),
|
||||
pending_events: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Issue a new finality proof request.
|
||||
///
|
||||
/// If the response doesn't arrive in time, or if the remote answers improperly, the target
|
||||
/// will be disconnected.
|
||||
pub fn send_request(&mut self, target: &PeerId, block_hash: B::Hash, request: Vec<u8>) {
|
||||
let protobuf_rq = schema::v1::finality::FinalityProofRequest {
|
||||
block_hash: block_hash.encode(),
|
||||
request,
|
||||
};
|
||||
|
||||
let mut buf = Vec::with_capacity(protobuf_rq.encoded_len());
|
||||
if let Err(err) = protobuf_rq.encode(&mut buf) {
|
||||
log::warn!("failed to encode finality proof request {:?}: {:?}", protobuf_rq, err);
|
||||
return;
|
||||
}
|
||||
|
||||
log::trace!("enqueueing finality proof request to {:?}: {:?}", target, protobuf_rq);
|
||||
self.pending_events.push_back(NetworkBehaviourAction::NotifyHandler {
|
||||
peer_id: target.clone(),
|
||||
handler: NotifyHandler::Any,
|
||||
event: OutboundProtocol {
|
||||
request: buf,
|
||||
block_hash,
|
||||
max_response_size: self.config.max_response_len,
|
||||
protocol: self.config.protocol.clone(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/// Callback, invoked when a new finality request has been received from remote.
|
||||
fn on_finality_request(&mut self, peer: &PeerId, request: &schema::v1::finality::FinalityProofRequest)
|
||||
-> Result<schema::v1::finality::FinalityProofResponse, Error>
|
||||
{
|
||||
let block_hash = Decode::decode(&mut request.block_hash.as_ref())?;
|
||||
|
||||
log::trace!(target: "sync", "Finality proof request from {} for {}", peer, block_hash);
|
||||
|
||||
// Note that an empty Vec is sent if no proof is available.
|
||||
let finality_proof = if let Some(provider) = &self.finality_proof_provider {
|
||||
provider
|
||||
.prove_finality(block_hash, &request.request)?
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
log::error!("Answering a finality proof request while finality provider is empty");
|
||||
return Err(From::from("Empty finality proof provider".to_string()))
|
||||
};
|
||||
|
||||
Ok(schema::v1::finality::FinalityProofResponse { proof: finality_proof })
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> NetworkBehaviour for FinalityProofRequests<B>
|
||||
where
|
||||
B: Block
|
||||
{
|
||||
type ProtocolsHandler = OneShotHandler<InboundProtocol<B>, OutboundProtocol<B>, NodeEvent<B, NegotiatedSubstream>>;
|
||||
type OutEvent = Event<B>;
|
||||
|
||||
fn new_handler(&mut self) -> Self::ProtocolsHandler {
|
||||
let p = InboundProtocol {
|
||||
max_request_len: self.config.max_request_len,
|
||||
protocol: if self.finality_proof_provider.is_some() {
|
||||
Some(self.config.protocol.clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
marker: PhantomData,
|
||||
};
|
||||
let mut cfg = OneShotHandlerConfig::default();
|
||||
cfg.keep_alive_timeout = self.config.inactivity_timeout;
|
||||
OneShotHandler::new(SubstreamProtocol::new(p, ()), cfg)
|
||||
}
|
||||
|
||||
fn addresses_of_peer(&mut self, _: &PeerId) -> Vec<Multiaddr> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn inject_connected(&mut self, _peer: &PeerId) {
|
||||
}
|
||||
|
||||
fn inject_disconnected(&mut self, _peer: &PeerId) {
|
||||
}
|
||||
|
||||
fn inject_event(
|
||||
&mut self,
|
||||
peer: PeerId,
|
||||
connection: ConnectionId,
|
||||
event: NodeEvent<B, NegotiatedSubstream>
|
||||
) {
|
||||
match event {
|
||||
NodeEvent::Request(request, mut stream) => {
|
||||
match self.on_finality_request(&peer, &request) {
|
||||
Ok(res) => {
|
||||
log::trace!("enqueueing finality response for peer {}", peer);
|
||||
let mut data = Vec::with_capacity(res.encoded_len());
|
||||
if let Err(e) = res.encode(&mut data) {
|
||||
log::debug!("error encoding finality response for peer {}: {}", peer, e)
|
||||
} else {
|
||||
let future = async move {
|
||||
if let Err(e) = write_one(&mut stream, data).await {
|
||||
log::debug!("error writing finality response: {}", e)
|
||||
}
|
||||
};
|
||||
self.outgoing.push(future.boxed())
|
||||
}
|
||||
}
|
||||
Err(e) => log::debug!("error handling finality request from peer {}: {}", peer, e)
|
||||
}
|
||||
}
|
||||
NodeEvent::Response(response, block_hash) => {
|
||||
let ev = Event::Response {
|
||||
peer,
|
||||
block_hash,
|
||||
proof: response.proof,
|
||||
};
|
||||
self.pending_events.push_back(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn poll(&mut self, cx: &mut Context, _: &mut impl PollParameters)
|
||||
-> Poll<NetworkBehaviourAction<OutboundProtocol<B>, Event<B>>>
|
||||
{
|
||||
if let Some(ev) = self.pending_events.pop_front() {
|
||||
return Poll::Ready(ev);
|
||||
}
|
||||
|
||||
while let Poll::Ready(Some(_)) = self.outgoing.poll_next_unpin(cx) {}
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
/// Output type of inbound and outbound substream upgrades.
|
||||
#[derive(Debug)]
|
||||
pub enum NodeEvent<B: Block, T> {
|
||||
/// Incoming request from remote and substream to use for the response.
|
||||
Request(schema::v1::finality::FinalityProofRequest, T),
|
||||
/// Incoming response from remote.
|
||||
Response(schema::v1::finality::FinalityProofResponse, B::Hash),
|
||||
}
|
||||
|
||||
/// Substream upgrade protocol.
|
||||
///
|
||||
/// We attempt to parse an incoming protobuf encoded request (cf. `Request`)
|
||||
/// which will be handled by the `FinalityProofRequests` behaviour, i.e. the request
|
||||
/// will become visible via `inject_node_event` which then dispatches to the
|
||||
/// relevant callback to process the message and prepare a response.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InboundProtocol<B> {
|
||||
/// The max. request length in bytes.
|
||||
max_request_len: usize,
|
||||
/// The protocol to use during upgrade negotiation. If `None`, then the incoming protocol
|
||||
/// is simply disabled.
|
||||
protocol: Option<Bytes>,
|
||||
/// Marker to pin the block type.
|
||||
marker: PhantomData<B>,
|
||||
}
|
||||
|
||||
impl<B: Block> UpgradeInfo for InboundProtocol<B> {
|
||||
type Info = Bytes;
|
||||
// This iterator will return either 0 elements if `self.protocol` is `None`, or 1 element if
|
||||
// it is `Some`.
|
||||
type InfoIter = std::option::IntoIter<Self::Info>;
|
||||
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
self.protocol.clone().into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, T> InboundUpgrade<T> for InboundProtocol<B>
|
||||
where
|
||||
B: Block,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static
|
||||
{
|
||||
type Output = NodeEvent<B, T>;
|
||||
type Error = ReadOneError;
|
||||
type Future = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||
|
||||
fn upgrade_inbound(self, mut s: T, _: Self::Info) -> Self::Future {
|
||||
async move {
|
||||
let len = self.max_request_len;
|
||||
let vec = read_one(&mut s, len).await?;
|
||||
match schema::v1::finality::FinalityProofRequest::decode(&vec[..]) {
|
||||
Ok(r) => Ok(NodeEvent::Request(r, s)),
|
||||
Err(e) => Err(ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e)))
|
||||
}
|
||||
}.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
/// Substream upgrade protocol.
|
||||
///
|
||||
/// Sends a request to remote and awaits the response.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OutboundProtocol<B: Block> {
|
||||
/// The serialized protobuf request.
|
||||
request: Vec<u8>,
|
||||
/// Block hash that has been requested.
|
||||
block_hash: B::Hash,
|
||||
/// The max. response length in bytes.
|
||||
max_response_size: usize,
|
||||
/// The protocol to use for upgrade negotiation.
|
||||
protocol: Bytes,
|
||||
}
|
||||
|
||||
impl<B: Block> UpgradeInfo for OutboundProtocol<B> {
|
||||
type Info = Bytes;
|
||||
type InfoIter = iter::Once<Self::Info>;
|
||||
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
iter::once(self.protocol.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, T> OutboundUpgrade<T> for OutboundProtocol<B>
|
||||
where
|
||||
B: Block,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static
|
||||
{
|
||||
type Output = NodeEvent<B, T>;
|
||||
type Error = ReadOneError;
|
||||
type Future = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||
|
||||
fn upgrade_outbound(self, mut s: T, _: Self::Info) -> Self::Future {
|
||||
async move {
|
||||
write_one(&mut s, &self.request).await?;
|
||||
let vec = read_one(&mut s, self.max_response_size).await?;
|
||||
|
||||
schema::v1::finality::FinalityProofResponse::decode(&vec[..])
|
||||
.map(|r| NodeEvent::Response(r, self.block_hash))
|
||||
.map_err(|e| {
|
||||
ReadOneError::Io(io::Error::new(io::ErrorKind::Other, e))
|
||||
})
|
||||
}.boxed()
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,6 @@ fn build_test_full_node(config: config::NetworkConfiguration)
|
||||
PassThroughVerifier(false),
|
||||
Box::new(client.clone()),
|
||||
None,
|
||||
None,
|
||||
&sp_core::testing::TaskExecutor::new(),
|
||||
None,
|
||||
));
|
||||
@@ -96,8 +95,6 @@ fn build_test_full_node(config: config::NetworkConfiguration)
|
||||
executor: None,
|
||||
network_config: config,
|
||||
chain: client.clone(),
|
||||
finality_proof_provider: None,
|
||||
finality_proof_request_builder: None,
|
||||
on_demand: None,
|
||||
transaction_pool: Arc::new(crate::config::EmptyTransactionPool),
|
||||
protocol_id: config::ProtocolId::from("/test-protocol-name"),
|
||||
|
||||
@@ -249,7 +249,6 @@ mod block_requests;
|
||||
mod chain;
|
||||
mod peer_info;
|
||||
mod discovery;
|
||||
mod finality_requests;
|
||||
mod light_client_handler;
|
||||
mod on_demand_layer;
|
||||
mod protocol;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
use crate::{
|
||||
ExHashT,
|
||||
chain::Client,
|
||||
config::{BoxFinalityProofRequestBuilder, ProtocolId, TransactionPool, TransactionImportFuture, TransactionImport},
|
||||
config::{ProtocolId, TransactionPool, TransactionImportFuture, TransactionImport},
|
||||
error,
|
||||
utils::{interval, LruHashSet},
|
||||
};
|
||||
@@ -131,7 +131,6 @@ struct Metrics {
|
||||
peers: Gauge<U64>,
|
||||
queued_blocks: Gauge<U64>,
|
||||
fork_targets: Gauge<U64>,
|
||||
finality_proofs: GaugeVec<U64>,
|
||||
justifications: GaugeVec<U64>,
|
||||
propagated_transactions: Counter<U64>,
|
||||
}
|
||||
@@ -165,16 +164,6 @@ impl Metrics {
|
||||
)?;
|
||||
register(g, r)?
|
||||
},
|
||||
finality_proofs: {
|
||||
let g = GaugeVec::new(
|
||||
Opts::new(
|
||||
"sync_extra_finality_proofs",
|
||||
"Number of extra finality proof requests",
|
||||
),
|
||||
&["status"],
|
||||
)?;
|
||||
register(g, r)?
|
||||
},
|
||||
propagated_transactions: register(Counter::new(
|
||||
"sync_propagated_transactions",
|
||||
"Number of transactions propagated to at least one peer",
|
||||
@@ -365,7 +354,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
||||
local_peer_id: PeerId,
|
||||
chain: Arc<dyn Client<B>>,
|
||||
transaction_pool: Arc<dyn TransactionPool<H, B>>,
|
||||
finality_proof_request_builder: Option<BoxFinalityProofRequestBuilder<B>>,
|
||||
protocol_id: ProtocolId,
|
||||
peerset_config: sc_peerset::PeersetConfig,
|
||||
block_announce_validator: Box<dyn BlockAnnounceValidator<B> + Send>,
|
||||
@@ -377,7 +365,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
||||
config.roles,
|
||||
chain.clone(),
|
||||
&info,
|
||||
finality_proof_request_builder,
|
||||
block_announce_validator,
|
||||
config.max_parallel_downloads,
|
||||
);
|
||||
@@ -614,10 +601,7 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
||||
warn!(target: "sub-libp2p", "Received unexpected RemoteHeaderResponse"),
|
||||
GenericMessage::RemoteChangesResponse(_) =>
|
||||
warn!(target: "sub-libp2p", "Received unexpected RemoteChangesResponse"),
|
||||
GenericMessage::FinalityProofResponse(_) =>
|
||||
warn!(target: "sub-libp2p", "Received unexpected FinalityProofResponse"),
|
||||
GenericMessage::BlockRequest(_) |
|
||||
GenericMessage::FinalityProofRequest(_) |
|
||||
GenericMessage::RemoteReadChildRequest(_) |
|
||||
GenericMessage::RemoteCallRequest(_) |
|
||||
GenericMessage::RemoteReadRequest(_) |
|
||||
@@ -1314,13 +1298,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
||||
self.sync.on_justification_import(hash, number, success)
|
||||
}
|
||||
|
||||
/// Request a finality proof for the given block.
|
||||
///
|
||||
/// Queues a new finality proof request and tries to dispatch all pending requests.
|
||||
pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
self.sync.request_finality_proof(&hash, number)
|
||||
}
|
||||
|
||||
/// Notify the protocol that we have learned about the existence of nodes.
|
||||
///
|
||||
/// Can be called multiple times with the same `PeerId`s.
|
||||
@@ -1328,34 +1305,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
||||
self.behaviour.add_discovered_nodes(peer_ids)
|
||||
}
|
||||
|
||||
pub fn finality_proof_import_result(
|
||||
&mut self,
|
||||
request_block: (B::Hash, NumberFor<B>),
|
||||
finalization_result: Result<(B::Hash, NumberFor<B>), ()>,
|
||||
) {
|
||||
self.sync.on_finality_proof_import(request_block, finalization_result)
|
||||
}
|
||||
|
||||
/// Must be called after a [`CustomMessageOutcome::FinalityProofRequest`] has been emitted,
|
||||
/// to notify of the response having arrived.
|
||||
pub fn on_finality_proof_response(
|
||||
&mut self,
|
||||
who: PeerId,
|
||||
response: message::FinalityProofResponse<B::Hash>,
|
||||
) -> CustomMessageOutcome<B> {
|
||||
trace!(target: "sync", "Finality proof response from {} for {}", who, response.block);
|
||||
match self.sync.on_block_finality_proof(who, response) {
|
||||
Ok(sync::OnBlockFinalityProof::Nothing) => CustomMessageOutcome::None,
|
||||
Ok(sync::OnBlockFinalityProof::Import { peer, hash, number, proof }) =>
|
||||
CustomMessageOutcome::FinalityProofImport(peer, hash, number, proof),
|
||||
Err(sync::BadPeer(id, repu)) => {
|
||||
self.behaviour.disconnect_peer(&id);
|
||||
self.peerset_handle.report_peer(id, repu);
|
||||
CustomMessageOutcome::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn format_stats(&self) -> String {
|
||||
let mut out = String::new();
|
||||
for (id, stats) in &self.context_data.stats {
|
||||
@@ -1399,15 +1348,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
||||
.set(m.justifications.failed_requests.into());
|
||||
metrics.justifications.with_label_values(&["importing"])
|
||||
.set(m.justifications.importing_requests.into());
|
||||
|
||||
metrics.finality_proofs.with_label_values(&["pending"])
|
||||
.set(m.finality_proofs.pending_requests.into());
|
||||
metrics.finality_proofs.with_label_values(&["active"])
|
||||
.set(m.finality_proofs.active_requests.into());
|
||||
metrics.finality_proofs.with_label_values(&["failed"])
|
||||
.set(m.finality_proofs.failed_requests.into());
|
||||
metrics.finality_proofs.with_label_values(&["importing"])
|
||||
.set(m.finality_proofs.importing_requests.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1418,7 +1358,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
|
||||
pub enum CustomMessageOutcome<B: BlockT> {
|
||||
BlockImport(BlockOrigin, Vec<IncomingBlock<B>>),
|
||||
JustificationImport(Origin, B::Hash, NumberFor<B>, Justification),
|
||||
FinalityProofImport(Origin, B::Hash, NumberFor<B>, Vec<u8>),
|
||||
/// Notification protocols have been opened with a remote.
|
||||
NotificationStreamOpened {
|
||||
remote: PeerId,
|
||||
@@ -1443,12 +1382,6 @@ pub enum CustomMessageOutcome<B: BlockT> {
|
||||
/// must be silently discarded.
|
||||
/// It is the responsibility of the handler to ensure that a timeout exists.
|
||||
BlockRequest { target: PeerId, request: message::BlockRequest<B> },
|
||||
/// A new finality proof request must be emitted.
|
||||
/// Once you have the response, you must call `Protocol::on_finality_proof_response`.
|
||||
/// It is the responsibility of the handler to ensure that a timeout exists.
|
||||
/// If the request times out, or the peer responds in an invalid way, the peer has to be
|
||||
/// disconnect. This will inform the state machine that the request it has emitted is stale.
|
||||
FinalityProofRequest { target: PeerId, block_hash: B::Hash, request: Vec<u8> },
|
||||
/// Peer has a reported a new head of chain.
|
||||
PeerNewBest(PeerId, NumberFor<B>),
|
||||
None,
|
||||
@@ -1545,14 +1478,6 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviour for Protocol<B, H> {
|
||||
};
|
||||
self.pending_messages.push_back(event);
|
||||
}
|
||||
for (id, r) in self.sync.finality_proof_requests() {
|
||||
let event = CustomMessageOutcome::FinalityProofRequest {
|
||||
target: id,
|
||||
block_hash: r.block,
|
||||
request: r.request,
|
||||
};
|
||||
self.pending_messages.push_back(event);
|
||||
}
|
||||
if let Poll::Ready(Some((tx_hash, result))) = self.pending_transactions.poll_next_unpin(cx) {
|
||||
if let Some(peers) = self.pending_transactions_peers.remove(&tx_hash) {
|
||||
peers.into_iter().for_each(|p| self.on_handle_transaction_import(p, result));
|
||||
|
||||
@@ -25,7 +25,6 @@ pub use self::generic::{
|
||||
BlockAnnounce, RemoteCallRequest, RemoteReadRequest,
|
||||
RemoteHeaderRequest, RemoteHeaderResponse,
|
||||
RemoteChangesRequest, RemoteChangesResponse,
|
||||
FinalityProofRequest, FinalityProofResponse,
|
||||
FromBlock, RemoteReadChildRequest, Roles,
|
||||
};
|
||||
use sc_client_api::StorageProof;
|
||||
@@ -280,11 +279,10 @@ pub mod generic {
|
||||
RemoteChangesResponse(RemoteChangesResponse<Number, Hash>),
|
||||
/// Remote child storage read request.
|
||||
RemoteReadChildRequest(RemoteReadChildRequest<Hash>),
|
||||
/// Finality proof request.
|
||||
FinalityProofRequest(FinalityProofRequest<Hash>),
|
||||
/// Finality proof response.
|
||||
FinalityProofResponse(FinalityProofResponse<Hash>),
|
||||
/// Batch of consensus protocol messages.
|
||||
// NOTE: index is incremented by 2 due to finality proof related
|
||||
// messages that were removed.
|
||||
#[codec(index = "17")]
|
||||
ConsensusBatch(Vec<ConsensusMessage>),
|
||||
}
|
||||
|
||||
@@ -307,8 +305,6 @@ pub mod generic {
|
||||
Message::RemoteChangesRequest(_) => "RemoteChangesRequest",
|
||||
Message::RemoteChangesResponse(_) => "RemoteChangesResponse",
|
||||
Message::RemoteReadChildRequest(_) => "RemoteReadChildRequest",
|
||||
Message::FinalityProofRequest(_) => "FinalityProofRequest",
|
||||
Message::FinalityProofResponse(_) => "FinalityProofResponse",
|
||||
Message::ConsensusBatch(_) => "ConsensusBatch",
|
||||
}
|
||||
}
|
||||
@@ -546,26 +542,4 @@ pub mod generic {
|
||||
/// Missing changes tries roots proof.
|
||||
pub roots_proof: StorageProof,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
||||
/// Finality proof request.
|
||||
pub struct FinalityProofRequest<H> {
|
||||
/// Unique request id.
|
||||
pub id: RequestId,
|
||||
/// Hash of the block to request proof for.
|
||||
pub block: H,
|
||||
/// Additional data blob (that both requester and provider understood) required for proving finality.
|
||||
pub request: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
|
||||
/// Finality proof response.
|
||||
pub struct FinalityProofResponse<H> {
|
||||
/// Id of a request this response was made for.
|
||||
pub id: RequestId,
|
||||
/// Hash of the block (the same as in the FinalityProofRequest).
|
||||
pub block: H,
|
||||
/// Finality proof (if available).
|
||||
pub proof: Option<Vec<u8>>,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,7 @@ use sp_consensus::{BlockOrigin, BlockStatus,
|
||||
import_queue::{IncomingBlock, BlockImportResult, BlockImportError}
|
||||
};
|
||||
use crate::{
|
||||
config::BoxFinalityProofRequestBuilder,
|
||||
protocol::message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse,
|
||||
FinalityProofResponse, Roles},
|
||||
protocol::message::{self, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse, Roles},
|
||||
};
|
||||
use either::Either;
|
||||
use extra_requests::ExtraRequests;
|
||||
@@ -116,9 +114,6 @@ mod rep {
|
||||
/// Reputation change for peers which send us a block with bad justifications.
|
||||
pub const BAD_JUSTIFICATION: Rep = Rep::new(-(1 << 16), "Bad justification");
|
||||
|
||||
/// Reputation change for peers which send us a block with bad finality proof.
|
||||
pub const BAD_FINALITY_PROOF: Rep = Rep::new(-(1 << 16), "Bad finality proof");
|
||||
|
||||
/// Reputation change when a peer sent us invlid ancestry result.
|
||||
pub const UNKNOWN_ANCESTOR:Rep = Rep::new(-(1 << 16), "DB Error");
|
||||
}
|
||||
@@ -185,8 +180,6 @@ pub struct ChainSync<B: BlockT> {
|
||||
/// What block attributes we require for this node, usually derived from
|
||||
/// what role we are, but could be customized
|
||||
required_block_attributes: message::BlockAttributes,
|
||||
/// Any extra finality proof requests.
|
||||
extra_finality_proofs: ExtraRequests<B>,
|
||||
/// Any extra justification requests.
|
||||
extra_justifications: ExtraRequests<B>,
|
||||
/// A set of hashes of blocks that are being downloaded or have been
|
||||
@@ -195,8 +188,6 @@ pub struct ChainSync<B: BlockT> {
|
||||
/// The best block number that was successfully imported into the chain.
|
||||
/// This can not decrease.
|
||||
best_imported_number: NumberFor<B>,
|
||||
/// Finality proof handler.
|
||||
request_builder: Option<BoxFinalityProofRequestBuilder<B>>,
|
||||
/// Fork sync targets.
|
||||
fork_targets: HashMap<B::Hash, ForkTarget<B>>,
|
||||
/// A set of peers for which there might be potential block requests
|
||||
@@ -270,8 +261,6 @@ pub enum PeerSyncState<B: BlockT> {
|
||||
DownloadingStale(B::Hash),
|
||||
/// Downloading justification for given block hash.
|
||||
DownloadingJustification(B::Hash),
|
||||
/// Downloading finality proof for given block hash.
|
||||
DownloadingFinalityProof(B::Hash)
|
||||
}
|
||||
|
||||
impl<B: BlockT> PeerSyncState<B> {
|
||||
@@ -402,20 +391,6 @@ pub enum OnBlockJustification<B: BlockT> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of [`ChainSync::on_block_finality_proof`].
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum OnBlockFinalityProof<B: BlockT> {
|
||||
/// The proof needs no further handling.
|
||||
Nothing,
|
||||
/// The proof should be imported.
|
||||
Import {
|
||||
peer: PeerId,
|
||||
hash: B::Hash,
|
||||
number: NumberFor<B>,
|
||||
proof: Vec<u8>
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of [`ChainSync::has_slot_for_block_announce_validation`].
|
||||
enum HasSlotForBlockAnnounceValidation {
|
||||
/// Yes, there is a slot for the block announce validation.
|
||||
@@ -432,7 +407,6 @@ impl<B: BlockT> ChainSync<B> {
|
||||
role: Roles,
|
||||
client: Arc<dyn crate::chain::Client<B>>,
|
||||
info: &BlockchainInfo<B>,
|
||||
request_builder: Option<BoxFinalityProofRequestBuilder<B>>,
|
||||
block_announce_validator: Box<dyn BlockAnnounceValidator<B> + Send>,
|
||||
max_parallel_downloads: u32,
|
||||
) -> Self {
|
||||
@@ -449,12 +423,10 @@ impl<B: BlockT> ChainSync<B> {
|
||||
best_queued_hash: info.best_hash,
|
||||
best_queued_number: info.best_number,
|
||||
best_imported_number: info.best_number,
|
||||
extra_finality_proofs: ExtraRequests::new("finality proof"),
|
||||
extra_justifications: ExtraRequests::new("justification"),
|
||||
role,
|
||||
required_block_attributes,
|
||||
queue_blocks: Default::default(),
|
||||
request_builder,
|
||||
fork_targets: Default::default(),
|
||||
pending_requests: Default::default(),
|
||||
block_announce_validator,
|
||||
@@ -613,14 +585,6 @@ impl<B: BlockT> ChainSync<B> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Schedule a finality proof request for the given block.
|
||||
pub fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
let client = &self.client;
|
||||
self.extra_finality_proofs.schedule((*hash, number), |base, block| {
|
||||
is_descendent_of(&**client, base, block)
|
||||
})
|
||||
}
|
||||
|
||||
/// Request syncing for the given block from given set of peers.
|
||||
// The implementation is similar to on_block_announce with unknown parent hash.
|
||||
pub fn set_sync_fork_request(
|
||||
@@ -700,30 +664,6 @@ impl<B: BlockT> ChainSync<B> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get an iterator over all scheduled finality proof requests.
|
||||
pub fn finality_proof_requests(&mut self) -> impl Iterator<Item = (PeerId, FinalityProofRequest<B::Hash>)> + '_ {
|
||||
let peers = &mut self.peers;
|
||||
let request_builder = &mut self.request_builder;
|
||||
let mut matcher = self.extra_finality_proofs.matcher();
|
||||
std::iter::from_fn(move || {
|
||||
if let Some((peer, request)) = matcher.next(&peers) {
|
||||
peers.get_mut(&peer)
|
||||
.expect("`Matcher::next` guarantees the `PeerId` comes from the given peers; qed")
|
||||
.state = PeerSyncState::DownloadingFinalityProof(request.0);
|
||||
let req = message::generic::FinalityProofRequest {
|
||||
id: 0,
|
||||
block: request.0,
|
||||
request: request_builder.as_mut()
|
||||
.map(|builder| builder.build_request_data(&request.0))
|
||||
.unwrap_or_default()
|
||||
};
|
||||
Some((peer, req))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Get an iterator over all block requests of all peers.
|
||||
pub fn block_requests(&mut self) -> impl Iterator<Item = (&PeerId, BlockRequest<B>)> + '_ {
|
||||
if self.pending_requests.is_empty() {
|
||||
@@ -920,8 +860,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
}
|
||||
|
||||
| PeerSyncState::Available
|
||||
| PeerSyncState::DownloadingJustification(..)
|
||||
| PeerSyncState::DownloadingFinalityProof(..) => Vec::new()
|
||||
| PeerSyncState::DownloadingJustification(..) => Vec::new()
|
||||
}
|
||||
} else {
|
||||
// When request.is_none() this is a block announcement. Just accept blocks.
|
||||
@@ -1033,41 +972,6 @@ impl<B: BlockT> ChainSync<B> {
|
||||
Ok(OnBlockJustification::Nothing)
|
||||
}
|
||||
|
||||
/// Handle new finality proof data.
|
||||
pub fn on_block_finality_proof
|
||||
(&mut self, who: PeerId, resp: FinalityProofResponse<B::Hash>) -> Result<OnBlockFinalityProof<B>, BadPeer>
|
||||
{
|
||||
let peer =
|
||||
if let Some(peer) = self.peers.get_mut(&who) {
|
||||
peer
|
||||
} else {
|
||||
error!(target: "sync", "💔 Called on_block_finality_proof_data with a bad peer ID");
|
||||
return Ok(OnBlockFinalityProof::Nothing)
|
||||
};
|
||||
|
||||
self.pending_requests.add(&who);
|
||||
if let PeerSyncState::DownloadingFinalityProof(hash) = peer.state {
|
||||
peer.state = PeerSyncState::Available;
|
||||
|
||||
// We only request one finality proof at a time.
|
||||
if hash != resp.block {
|
||||
info!(
|
||||
target: "sync",
|
||||
"💔 Invalid block finality proof provided: requested: {:?} got: {:?}",
|
||||
hash,
|
||||
resp.block
|
||||
);
|
||||
return Err(BadPeer(who, rep::BAD_FINALITY_PROOF));
|
||||
}
|
||||
|
||||
if let Some((peer, hash, number, p)) = self.extra_finality_proofs.on_response(who, resp.proof) {
|
||||
return Ok(OnBlockFinalityProof::Import { peer, hash, number, proof: p })
|
||||
}
|
||||
}
|
||||
|
||||
Ok(OnBlockFinalityProof::Nothing)
|
||||
}
|
||||
|
||||
/// A batch of blocks have been processed, with or without errors.
|
||||
///
|
||||
/// Call this when a batch of blocks have been processed by the import
|
||||
@@ -1122,11 +1026,6 @@ impl<B: BlockT> ChainSync<B> {
|
||||
}
|
||||
}
|
||||
|
||||
if aux.needs_finality_proof {
|
||||
trace!(target: "sync", "Block imported but requires finality proof {}: {:?}", number, hash);
|
||||
self.request_finality_proof(&hash, number);
|
||||
}
|
||||
|
||||
if number > self.best_imported_number {
|
||||
self.best_imported_number = number;
|
||||
}
|
||||
@@ -1178,22 +1077,8 @@ impl<B: BlockT> ChainSync<B> {
|
||||
self.pending_requests.set_all();
|
||||
}
|
||||
|
||||
pub fn on_finality_proof_import(&mut self, req: (B::Hash, NumberFor<B>), res: Result<(B::Hash, NumberFor<B>), ()>) {
|
||||
self.extra_finality_proofs.try_finalize_root(req, res, true);
|
||||
self.pending_requests.set_all();
|
||||
}
|
||||
|
||||
/// Notify about finalization of the given block.
|
||||
pub fn on_block_finalized(&mut self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
let client = &self.client;
|
||||
let r = self.extra_finality_proofs.on_block_finalized(hash, number, |base, block| {
|
||||
is_descendent_of(&**client, base, block)
|
||||
});
|
||||
|
||||
if let Err(err) = r {
|
||||
warn!(target: "sync", "💔 Error cleaning up pending extra finality proof data requests: {:?}", err)
|
||||
}
|
||||
|
||||
let client = &self.client;
|
||||
let r = self.extra_justifications.on_block_finalized(hash, number, |base, block| {
|
||||
is_descendent_of(&**client, base, block)
|
||||
@@ -1506,14 +1391,12 @@ impl<B: BlockT> ChainSync<B> {
|
||||
self.blocks.clear_peer_download(who);
|
||||
self.peers.remove(who);
|
||||
self.extra_justifications.peer_disconnected(who);
|
||||
self.extra_finality_proofs.peer_disconnected(who);
|
||||
self.pending_requests.set_all();
|
||||
}
|
||||
|
||||
/// Restart the sync process. This will reset all pending block requests and return an iterator
|
||||
/// of new block requests to make to peers. Peers that were downloading finality data (i.e.
|
||||
/// their state was `DownloadingJustification` or `DownloadingFinalityProof`) are unaffected and
|
||||
/// will stay in the same state.
|
||||
/// their state was `DownloadingJustification`) are unaffected and will stay in the same state.
|
||||
fn restart<'a>(
|
||||
&'a mut self,
|
||||
) -> impl Iterator<Item = Result<(PeerId, BlockRequest<B>), BadPeer>> + 'a {
|
||||
@@ -1526,11 +1409,10 @@ impl<B: BlockT> ChainSync<B> {
|
||||
let old_peers = std::mem::take(&mut self.peers);
|
||||
|
||||
old_peers.into_iter().filter_map(move |(id, p)| {
|
||||
// peers that were downloading justifications or finality proofs
|
||||
// peers that were downloading justifications
|
||||
// should be kept in that state.
|
||||
match p.state {
|
||||
PeerSyncState::DownloadingJustification(_)
|
||||
| PeerSyncState::DownloadingFinalityProof(_) => {
|
||||
PeerSyncState::DownloadingJustification(_) => {
|
||||
self.peers.insert(id, p);
|
||||
return None;
|
||||
}
|
||||
@@ -1570,7 +1452,6 @@ impl<B: BlockT> ChainSync<B> {
|
||||
Metrics {
|
||||
queued_blocks: self.queue_blocks.len().try_into().unwrap_or(std::u32::MAX),
|
||||
fork_targets: self.fork_targets.len().try_into().unwrap_or(std::u32::MAX),
|
||||
finality_proofs: self.extra_finality_proofs.metrics(),
|
||||
justifications: self.extra_justifications.metrics(),
|
||||
_priv: ()
|
||||
}
|
||||
@@ -1581,7 +1462,6 @@ impl<B: BlockT> ChainSync<B> {
|
||||
pub(crate) struct Metrics {
|
||||
pub(crate) queued_blocks: u32,
|
||||
pub(crate) fork_targets: u32,
|
||||
pub(crate) finality_proofs: extra_requests::Metrics,
|
||||
pub(crate) justifications: extra_requests::Metrics,
|
||||
_priv: ()
|
||||
}
|
||||
@@ -1835,7 +1715,6 @@ mod test {
|
||||
Roles::AUTHORITY,
|
||||
client.clone(),
|
||||
&info,
|
||||
None,
|
||||
block_announce_validator,
|
||||
1,
|
||||
);
|
||||
@@ -1907,7 +1786,6 @@ mod test {
|
||||
Roles::AUTHORITY,
|
||||
client.clone(),
|
||||
&info,
|
||||
None,
|
||||
Box::new(DefaultBlockAnnounceValidator),
|
||||
1,
|
||||
);
|
||||
@@ -1915,7 +1793,6 @@ mod test {
|
||||
let peer_id1 = PeerId::random();
|
||||
let peer_id2 = PeerId::random();
|
||||
let peer_id3 = PeerId::random();
|
||||
let peer_id4 = PeerId::random();
|
||||
|
||||
let mut new_blocks = |n| {
|
||||
for _ in 0..n {
|
||||
@@ -1928,7 +1805,6 @@ mod test {
|
||||
};
|
||||
|
||||
let (b1_hash, b1_number) = new_blocks(50);
|
||||
let (b2_hash, b2_number) = new_blocks(10);
|
||||
|
||||
// add 2 peers at blocks that we don't have locally
|
||||
sync.new_peer(peer_id1.clone(), Hash::random(), 42).unwrap();
|
||||
@@ -1958,38 +1834,16 @@ mod test {
|
||||
PeerSyncState::DownloadingJustification(b1_hash),
|
||||
);
|
||||
|
||||
// add another peer at a known later block
|
||||
sync.new_peer(peer_id4.clone(), b2_hash, b2_number).unwrap();
|
||||
|
||||
// we request a finality proof for a block we have locally
|
||||
sync.request_finality_proof(&b2_hash, b2_number);
|
||||
|
||||
// the finality proof request should be scheduled to peer 4
|
||||
// which is at that block
|
||||
assert!(
|
||||
sync.finality_proof_requests().any(|(p, r)| { p == peer_id4 && r.block == b2_hash })
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sync.peers.get(&peer_id4).unwrap().state,
|
||||
PeerSyncState::DownloadingFinalityProof(b2_hash),
|
||||
);
|
||||
|
||||
// we restart the sync state
|
||||
let block_requests = sync.restart();
|
||||
|
||||
// which should make us send out block requests to the first two peers
|
||||
assert!(block_requests.map(|r| r.unwrap()).all(|(p, _)| { p == peer_id1 || p == peer_id2 }));
|
||||
|
||||
// peer 3 and 4 should be unaffected as they were downloading finality data
|
||||
// peer 3 should be unaffected it was downloading finality data
|
||||
assert_eq!(
|
||||
sync.peers.get(&peer_id3).unwrap().state,
|
||||
PeerSyncState::DownloadingJustification(b1_hash),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sync.peers.get(&peer_id4).unwrap().state,
|
||||
PeerSyncState::DownloadingFinalityProof(b2_hash),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,13 +528,12 @@ mod tests {
|
||||
|
||||
impl Arbitrary for ArbitraryPeerSyncState {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||
let s = match g.gen::<u8>() % 5 {
|
||||
let s = match g.gen::<u8>() % 4 {
|
||||
0 => PeerSyncState::Available,
|
||||
// TODO: 1 => PeerSyncState::AncestorSearch(g.gen(), AncestorSearchState<B>),
|
||||
1 => PeerSyncState::DownloadingNew(g.gen::<BlockNumber>()),
|
||||
2 => PeerSyncState::DownloadingStale(Hash::random()),
|
||||
3 => PeerSyncState::DownloadingJustification(Hash::random()),
|
||||
_ => PeerSyncState::DownloadingFinalityProof(Hash::random())
|
||||
_ => PeerSyncState::DownloadingJustification(Hash::random()),
|
||||
};
|
||||
ArbitraryPeerSyncState(s)
|
||||
}
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
|
||||
pub mod v1 {
|
||||
include!(concat!(env!("OUT_DIR"), "/api.v1.rs"));
|
||||
pub mod finality {
|
||||
include!(concat!(env!("OUT_DIR"), "/api.v1.finality.rs"));
|
||||
}
|
||||
pub mod light {
|
||||
include!(concat!(env!("OUT_DIR"), "/api.v1.light.rs"));
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// Schema definition for finality proof request/responses.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package api.v1.finality;
|
||||
|
||||
// Request a finality proof from a peer.
|
||||
message FinalityProofRequest {
|
||||
// SCALE-encoded hash of the block to request.
|
||||
bytes block_hash = 1;
|
||||
// Opaque chain-specific additional request data.
|
||||
bytes request = 2;
|
||||
}
|
||||
|
||||
// Response to a finality proof request.
|
||||
message FinalityProofResponse {
|
||||
// Opaque chain-specific finality proof. Empty if no such proof exists.
|
||||
bytes proof = 1; // optional
|
||||
}
|
||||
@@ -38,7 +38,7 @@ use crate::{
|
||||
NetworkState, NotConnectedPeer as NetworkStateNotConnectedPeer, Peer as NetworkStatePeer,
|
||||
},
|
||||
on_demand_layer::AlwaysBadChecker,
|
||||
light_client_handler, block_requests, finality_requests,
|
||||
light_client_handler, block_requests,
|
||||
protocol::{self, event::Event, NotifsHandlerError, NotificationsSink, Ready, sync::SyncState, PeerInfo, Protocol},
|
||||
transport, ReputationChange,
|
||||
};
|
||||
@@ -248,7 +248,6 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
|
||||
local_peer_id.clone(),
|
||||
params.chain.clone(),
|
||||
params.transaction_pool,
|
||||
params.finality_proof_request_builder,
|
||||
params.protocol_id.clone(),
|
||||
peerset_config,
|
||||
params.block_announce_validator,
|
||||
@@ -267,10 +266,6 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
|
||||
let config = block_requests::Config::new(¶ms.protocol_id);
|
||||
block_requests::BlockRequests::new(config, params.chain.clone())
|
||||
};
|
||||
let finality_proof_requests = {
|
||||
let config = finality_requests::Config::new(¶ms.protocol_id);
|
||||
finality_requests::FinalityProofRequests::new(config, params.finality_proof_provider.clone())
|
||||
};
|
||||
let light_client_handler = {
|
||||
let config = light_client_handler::Config::new(¶ms.protocol_id);
|
||||
light_client_handler::LightClientHandler::new(
|
||||
@@ -310,7 +305,6 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
|
||||
user_agent,
|
||||
local_public,
|
||||
block_requests,
|
||||
finality_proof_requests,
|
||||
light_client_handler,
|
||||
discovery_config,
|
||||
params.network_config.request_response_protocols,
|
||||
@@ -1361,12 +1355,6 @@ impl<B: BlockT + 'static, H: ExHashT> Future for NetworkWorker<B, H> {
|
||||
}
|
||||
this.import_queue.import_justification(origin, hash, nb, justification);
|
||||
},
|
||||
Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::FinalityProofImport(origin, hash, nb, proof))) => {
|
||||
if let Some(metrics) = this.metrics.as_ref() {
|
||||
metrics.import_queue_finality_proofs_submitted.inc();
|
||||
}
|
||||
this.import_queue.import_finality_proof(origin, hash, nb, proof);
|
||||
},
|
||||
Poll::Ready(SwarmEvent::Behaviour(BehaviourOut::InboundRequest { protocol, result, .. })) => {
|
||||
if let Some(metrics) = this.metrics.as_ref() {
|
||||
match result {
|
||||
@@ -1563,11 +1551,11 @@ impl<B: BlockT + 'static, H: ExHashT> Future for NetworkWorker<B, H> {
|
||||
let reason = match cause {
|
||||
Some(ConnectionError::IO(_)) => "transport-error",
|
||||
Some(ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A(
|
||||
EitherError::A(EitherError::A(EitherError::A(EitherError::B(
|
||||
EitherError::A(PingFailure::Timeout)))))))))) => "ping-timeout",
|
||||
EitherError::A(EitherError::A(EitherError::B(
|
||||
EitherError::A(PingFailure::Timeout))))))))) => "ping-timeout",
|
||||
Some(ConnectionError::Handler(NodeHandlerWrapperError::Handler(EitherError::A(EitherError::A(
|
||||
EitherError::A(EitherError::A(EitherError::A(EitherError::A(
|
||||
NotifsHandlerError::SyncNotificationsClogged))))))))) => "sync-notifications-clogged",
|
||||
EitherError::A(EitherError::A(EitherError::A(
|
||||
NotifsHandlerError::SyncNotificationsClogged)))))))) => "sync-notifications-clogged",
|
||||
Some(ConnectionError::Handler(NodeHandlerWrapperError::Handler(_))) => "protocol-error",
|
||||
Some(ConnectionError::Handler(NodeHandlerWrapperError::KeepAliveTimeout)) => "keep-alive-timeout",
|
||||
None => "actively-closed",
|
||||
@@ -1752,23 +1740,6 @@ impl<'a, B: BlockT, H: ExHashT> Link<B> for NetworkLink<'a, B, H> {
|
||||
fn request_justification(&mut self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
self.protocol.user_protocol_mut().request_justification(hash, number)
|
||||
}
|
||||
fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
self.protocol.user_protocol_mut().request_finality_proof(hash, number)
|
||||
}
|
||||
fn finality_proof_imported(
|
||||
&mut self,
|
||||
who: PeerId,
|
||||
request_block: (B::Hash, NumberFor<B>),
|
||||
finalization_result: Result<(B::Hash, NumberFor<B>), ()>,
|
||||
) {
|
||||
let success = finalization_result.is_ok();
|
||||
self.protocol.user_protocol_mut().finality_proof_import_result(request_block, finalization_result);
|
||||
if !success {
|
||||
info!("💔 Invalid finality proof provided by {} for #{}", who, request_block.0);
|
||||
self.protocol.user_protocol_mut().disconnect_peer(&who);
|
||||
self.protocol.user_protocol_mut().report_peer(who, ReputationChange::new_fatal("Invalid finality proof"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_addresses_consistent_with_transport<'a>(
|
||||
|
||||
@@ -56,7 +56,6 @@ pub struct Metrics {
|
||||
pub distinct_peers_connections_closed_total: Counter<U64>,
|
||||
pub distinct_peers_connections_opened_total: Counter<U64>,
|
||||
pub import_queue_blocks_submitted: Counter<U64>,
|
||||
pub import_queue_finality_proofs_submitted: Counter<U64>,
|
||||
pub import_queue_justifications_submitted: Counter<U64>,
|
||||
pub incoming_connections_errors_total: CounterVec<U64>,
|
||||
pub incoming_connections_total: Counter<U64>,
|
||||
@@ -112,10 +111,6 @@ impl Metrics {
|
||||
"import_queue_blocks_submitted",
|
||||
"Number of blocks submitted to the import queue.",
|
||||
)?, registry)?,
|
||||
import_queue_finality_proofs_submitted: prometheus::register(Counter::new(
|
||||
"import_queue_finality_proofs_submitted",
|
||||
"Number of finality proofs submitted to the import queue.",
|
||||
)?, registry)?,
|
||||
import_queue_justifications_submitted: prometheus::register(Counter::new(
|
||||
"import_queue_justifications_submitted",
|
||||
"Number of justifications submitted to the import queue.",
|
||||
|
||||
@@ -87,7 +87,6 @@ fn build_test_full_node(config: config::NetworkConfiguration)
|
||||
PassThroughVerifier(false),
|
||||
Box::new(client.clone()),
|
||||
None,
|
||||
None,
|
||||
&sp_core::testing::TaskExecutor::new(),
|
||||
None,
|
||||
));
|
||||
@@ -97,8 +96,6 @@ fn build_test_full_node(config: config::NetworkConfiguration)
|
||||
executor: None,
|
||||
network_config: config,
|
||||
chain: client.clone(),
|
||||
finality_proof_provider: None,
|
||||
finality_proof_request_builder: None,
|
||||
on_demand: None,
|
||||
transaction_pool: Arc::new(crate::config::EmptyTransactionPool),
|
||||
protocol_id: config::ProtocolId::from("/test-protocol-name"),
|
||||
|
||||
Reference in New Issue
Block a user