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:
André Silva
2020-11-23 14:28:55 +00:00
committed by GitHub
parent cd2490f56d
commit 1871a95088
44 changed files with 96 additions and 2512 deletions
@@ -756,108 +756,6 @@
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 6,
"w": 6,
"x": 0,
"y": 12
},
"hiddenSeries": false,
"id": 23,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"dataLinks": []
},
"percentage": false,
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "[[metric_namespace]]_sync_extra_finality_proofs_active{instance=\"[[instance]]\",network=\"[[network]]\"}",
"legendFormat": "{{instance}} active",
"refId": "A"
},
{
"expr": "[[metric_namespace]]_sync_extra_finality_proofs_failed{instance=\"[[instance]]\",network=\"[[network]]\"}",
"legendFormat": "{{instance}} failed",
"refId": "B"
},
{
"expr": "[[metric_namespace]]_sync_extra_finality_proofs_importing{instance=\"[[instance]]\",network=\"[[network]]\"}",
"legendFormat": "{{instance}} importing",
"refId": "C"
},
{
"expr": "[[metric_namespace]]_sync_extra_finality_proofs_pending{instance=\"[[instance]]\",network=\"[[network]]\"}",
"legendFormat": "{{instance}} pending",
"refId": "D"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Sync Proof",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
@@ -9,7 +9,7 @@ use sp_inherents::InherentDataProviders;
use sc_executor::native_executor_instance;
pub use sc_executor::NativeExecutor;
use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState};
use sc_finality_grandpa::SharedVoterState;
// Our native executor instance.
native_executor_instance!(
@@ -64,7 +64,6 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
sc_consensus_aura::slot_duration(&*client)?,
aura_block_import.clone(),
Some(Box::new(grandpa_block_import.clone())),
None,
client.clone(),
inherent_data_providers.clone(),
&task_manager.spawn_handle(),
@@ -87,9 +86,6 @@ pub fn new_full(config: Configuration) -> Result<TaskManager, ServiceError> {
other: (block_import, grandpa_link),
} = new_partial(&config)?;
let finality_proof_provider =
GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
let (network, network_status_sinks, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
@@ -99,8 +95,6 @@ pub fn new_full(config: Configuration) -> Result<TaskManager, ServiceError> {
import_queue,
on_demand: None,
block_announce_validator_builder: None,
finality_proof_request_builder: None,
finality_proof_provider: Some(finality_proof_provider.clone()),
})?;
if config.offchain_worker.enabled {
@@ -229,6 +223,8 @@ pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
let (client, backend, keystore_container, mut task_manager, on_demand) =
sc_service::new_light_parts::<Block, RuntimeApi, Executor>(&config)?;
let select_chain = sc_consensus::LongestChain::new(backend.clone());
let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light(
config.transaction_pool.clone(),
config.prometheus_registry(),
@@ -237,19 +233,16 @@ pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
on_demand.clone(),
));
let grandpa_block_import = sc_finality_grandpa::light_block_import(
client.clone(), backend.clone(), &(client.clone() as Arc<_>),
Arc::new(on_demand.checker().clone()) as Arc<_>,
let (grandpa_block_import, _) = sc_finality_grandpa::block_import(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
)?;
let finality_proof_import = grandpa_block_import.clone();
let finality_proof_request_builder =
finality_proof_import.create_finality_proof_request_builder();
let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(
sc_consensus_aura::slot_duration(&*client)?,
grandpa_block_import,
None,
Some(Box::new(finality_proof_import)),
grandpa_block_import.clone(),
Some(Box::new(grandpa_block_import)),
client.clone(),
InherentDataProviders::new(),
&task_manager.spawn_handle(),
@@ -257,9 +250,6 @@ pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
sp_consensus::NeverCanAuthor,
)?;
let finality_proof_provider =
GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
let (network, network_status_sinks, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
@@ -269,8 +259,6 @@ pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
import_queue,
on_demand: Some(on_demand.clone()),
block_announce_validator_builder: None,
finality_proof_request_builder: Some(finality_proof_request_builder),
finality_proof_provider: Some(finality_proof_provider),
})?;
if config.offchain_worker.enabled {
+11 -26
View File
@@ -22,7 +22,6 @@
use std::sync::Arc;
use sc_consensus_babe;
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
use node_primitives::Block;
use node_runtime::RuntimeApi;
use sc_service::{
@@ -57,10 +56,7 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
sc_consensus_babe::BabeLink<Block>,
),
(
grandpa::SharedVoterState,
Arc<GrandpaFinalityProofProvider<FullBackend, Block>>,
),
grandpa::SharedVoterState,
)
>, ServiceError> {
let (client, backend, keystore_container, task_manager) =
@@ -93,7 +89,6 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
babe_link.clone(),
block_import.clone(),
Some(Box::new(justification_import)),
None,
client.clone(),
select_chain.clone(),
inherent_data_providers.clone(),
@@ -110,10 +105,10 @@ pub fn new_partial(config: &Configuration) -> Result<sc_service::PartialComponen
let justification_stream = grandpa_link.justification_stream();
let shared_authority_set = grandpa_link.shared_authority_set().clone();
let shared_voter_state = grandpa::SharedVoterState::empty();
let finality_proof_provider =
GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
let rpc_setup = shared_voter_state.clone();
let rpc_setup = (shared_voter_state.clone(), finality_proof_provider.clone());
let finality_proof_provider =
grandpa::FinalityProofProvider::new_for_service(backend.clone(), client.clone());
let babe_config = babe_link.config().clone();
let shared_epoch_changes = babe_link.epoch_changes().clone();
@@ -181,7 +176,7 @@ pub fn new_full_base(
other: (rpc_extensions_builder, import_setup, rpc_setup),
} = new_partial(&config)?;
let (shared_voter_state, finality_proof_provider) = rpc_setup;
let shared_voter_state = rpc_setup;
let (network, network_status_sinks, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
@@ -192,8 +187,6 @@ pub fn new_full_base(
import_queue,
on_demand: None,
block_announce_validator_builder: None,
finality_proof_request_builder: None,
finality_proof_provider: Some(finality_proof_provider.clone()),
})?;
if config.offchain_worker.enabled {
@@ -363,14 +356,12 @@ pub fn new_light_base(config: Configuration) -> Result<(
on_demand.clone(),
));
let grandpa_block_import = grandpa::light_block_import(
client.clone(), backend.clone(), &(client.clone() as Arc<_>),
Arc::new(on_demand.checker().clone()),
let (grandpa_block_import, _) = grandpa::block_import(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
)?;
let finality_proof_import = grandpa_block_import.clone();
let finality_proof_request_builder =
finality_proof_import.create_finality_proof_request_builder();
let justification_import = grandpa_block_import.clone();
let (babe_block_import, babe_link) = sc_consensus_babe::block_import(
sc_consensus_babe::Config::get_or_compute(&*client)?,
@@ -383,8 +374,7 @@ pub fn new_light_base(config: Configuration) -> Result<(
let import_queue = sc_consensus_babe::import_queue(
babe_link,
babe_block_import,
None,
Some(Box::new(finality_proof_import)),
Some(Box::new(justification_import)),
client.clone(),
select_chain.clone(),
inherent_data_providers.clone(),
@@ -393,9 +383,6 @@ pub fn new_light_base(config: Configuration) -> Result<(
sp_consensus::NeverCanAuthor,
)?;
let finality_proof_provider =
GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
let (network, network_status_sinks, system_rpc_tx, network_starter) =
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
@@ -405,8 +392,6 @@ pub fn new_light_base(config: Configuration) -> Result<(
import_queue,
on_demand: Some(on_demand.clone()),
block_announce_validator_builder: None,
finality_proof_request_builder: Some(finality_proof_request_builder),
finality_proof_provider: Some(finality_proof_provider),
})?;
network_starter.start_network();
-1
View File
@@ -695,7 +695,6 @@ impl BenchContext {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: false,
is_new_best: true,
}
)
+1 -3
View File
@@ -47,7 +47,7 @@ use sp_consensus::{
BlockOrigin, Error as ConsensusError, SelectChain, SlotData, BlockCheckParams, ImportResult
};
use sp_consensus::import_queue::{
Verifier, BasicQueue, DefaultImportQueue, BoxJustificationImport, BoxFinalityProofImport,
Verifier, BasicQueue, DefaultImportQueue, BoxJustificationImport,
};
use sc_client_api::{backend::AuxStore, BlockOf};
use sp_blockchain::{
@@ -836,7 +836,6 @@ pub fn import_queue<B, I, C, P, S, CAW>(
slot_duration: SlotDuration,
block_import: I,
justification_import: Option<BoxJustificationImport<B>>,
finality_proof_import: Option<BoxFinalityProofImport<B>>,
client: Arc<C>,
inherent_data_providers: InherentDataProviders,
spawner: &S,
@@ -868,7 +867,6 @@ pub fn import_queue<B, I, C, P, S, CAW>(
verifier,
Box::new(block_import),
justification_import,
finality_proof_import,
spawner,
registry,
))
+1 -5
View File
@@ -79,9 +79,7 @@ use std::{
any::Any, borrow::Cow, convert::TryInto,
};
use sp_consensus::{ImportResult, CanAuthorWith};
use sp_consensus::import_queue::{
BoxJustificationImport, BoxFinalityProofImport,
};
use sp_consensus::import_queue::BoxJustificationImport;
use sp_core::crypto::Public;
use sp_application_crypto::AppKey;
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
@@ -1484,7 +1482,6 @@ pub fn import_queue<Block: BlockT, Client, SelectChain, Inner, CAW>(
babe_link: BabeLink<Block>,
block_import: Inner,
justification_import: Option<BoxJustificationImport<Block>>,
finality_proof_import: Option<BoxFinalityProofImport<Block>>,
client: Arc<Client>,
select_chain: SelectChain,
inherent_data_providers: InherentDataProviders,
@@ -1516,7 +1513,6 @@ pub fn import_queue<Block: BlockT, Client, SelectChain, Inner, CAW>(
verifier,
Box::new(block_import),
justification_import,
finality_proof_import,
spawner,
registry,
))
+2 -6
View File
@@ -37,11 +37,11 @@ use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging;
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
use sp_consensus::{
NoNetwork as DummyOracle, Proposal, RecordProof, AlwaysCanAuthor,
import_queue::{BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport},
import_queue::{BoxBlockImport, BoxJustificationImport},
};
use sc_network_test::*;
use sc_network_test::{Block as TestBlock, PeersClient};
use sc_network::config::{BoxFinalityProofRequestBuilder, ProtocolConfig};
use sc_network::config::ProtocolConfig;
use sp_runtime::{generic::DigestItem, traits::{Block as BlockT, DigestFor}};
use sc_client_api::{BlockchainEvents, backend::TransactionFor};
use log::debug;
@@ -272,8 +272,6 @@ impl TestNetFactory for BabeTestNet {
-> (
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
Option<PeerData>,
)
{
@@ -295,8 +293,6 @@ impl TestNetFactory for BabeTestNet {
(
BlockImportAdapter::new_full(block_import),
None,
None,
None,
Some(PeerData { link, inherent_data_providers, block_import: data_block_import }),
)
}
@@ -84,7 +84,6 @@ pub fn import_queue<Block, Transaction>(
ManualSealVerifier,
block_import,
None,
None,
spawner,
registry,
)
@@ -349,7 +348,6 @@ mod tests {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: false,
is_new_best: true,
}
}
@@ -416,7 +414,6 @@ mod tests {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: false,
is_new_best: true,
}
}
@@ -494,7 +491,6 @@ mod tests {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: false,
is_new_best: true
}
}
+1 -3
View File
@@ -56,7 +56,7 @@ use sp_consensus::{
BlockCheckParams, ImportResult,
};
use sp_consensus::import_queue::{
BoxBlockImport, BasicQueue, Verifier, BoxJustificationImport, BoxFinalityProofImport,
BoxBlockImport, BasicQueue, Verifier, BoxJustificationImport,
};
use codec::{Encode, Decode};
use prometheus_endpoint::Registry;
@@ -503,7 +503,6 @@ pub type PowImportQueue<B, Transaction> = BasicQueue<B, Transaction>;
pub fn import_queue<B, Transaction, Algorithm>(
block_import: BoxBlockImport<B, Transaction>,
justification_import: Option<BoxJustificationImport<B>>,
finality_proof_import: Option<BoxFinalityProofImport<B>>,
algorithm: Algorithm,
inherent_data_providers: InherentDataProviders,
spawner: &impl sp_core::traits::SpawnNamed,
@@ -524,7 +523,6 @@ pub fn import_queue<B, Transaction, Algorithm>(
verifier,
block_import,
justification_import,
finality_proof_import,
spawner,
registry,
))
@@ -17,7 +17,6 @@
//! Schema for stuff in the aux-db.
use std::fmt::Debug;
use std::sync::Arc;
use parity_scale_codec::{Encode, Decode};
use sc_client_api::backend::AuxStore;
use sp_blockchain::{Result as ClientResult, Error as ClientError};
@@ -28,7 +27,6 @@ use log::{info, warn};
use sp_finality_grandpa::{AuthorityList, SetId, RoundNumber};
use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind};
use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges};
use crate::environment::{
CompletedRound, CompletedRounds, CurrentRounds, HasVoted, SharedVoterSetState, VoterSetState,
};
@@ -38,7 +36,6 @@ const VERSION_KEY: &[u8] = b"grandpa_schema_version";
const SET_STATE_KEY: &[u8] = b"grandpa_completed_round";
const CONCLUDED_ROUNDS: &[u8] = b"grandpa_concluded_rounds";
const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters";
const CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes";
const CURRENT_VERSION: u32 = 2;
@@ -122,7 +119,6 @@ pub(crate) fn load_decode<B: AuxStore, T: Decode>(backend: &B, key: &[u8]) -> Cl
/// Persistent data kept between runs.
pub(crate) struct PersistentData<Block: BlockT> {
pub(crate) authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
pub(crate) consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
pub(crate) set_state: SharedVoterSetState<Block>,
}
@@ -272,8 +268,6 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
G: FnOnce() -> ClientResult<AuthorityList>,
{
let version: Option<u32> = load_decode(backend, VERSION_KEY)?;
let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)?
.unwrap_or_else(ConsensusChanges::<Block::Hash, NumberFor<Block>>::empty);
let make_genesis_round = move || RoundState::genesis((genesis_hash, genesis_number));
@@ -282,7 +276,6 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
if let Some((new_set, set_state)) = migrate_from_version0::<Block, _, _>(backend, &make_genesis_round)? {
return Ok(PersistentData {
authority_set: new_set.into(),
consensus_changes: Arc::new(consensus_changes.into()),
set_state: set_state.into(),
});
}
@@ -291,7 +284,6 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
if let Some((new_set, set_state)) = migrate_from_version1::<Block, _, _>(backend, &make_genesis_round)? {
return Ok(PersistentData {
authority_set: new_set.into(),
consensus_changes: Arc::new(consensus_changes.into()),
set_state: set_state.into(),
});
}
@@ -321,7 +313,6 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
return Ok(PersistentData {
authority_set: set.into(),
consensus_changes: Arc::new(consensus_changes.into()),
set_state: set_state.into(),
});
}
@@ -359,7 +350,6 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
Ok(PersistentData {
authority_set: genesis_set.into(),
set_state: genesis_state.into(),
consensus_changes: Arc::new(consensus_changes.into()),
})
}
@@ -421,18 +411,6 @@ pub(crate) fn write_concluded_round<Block: BlockT, B: AuxStore>(
backend.insert_aux(&[(&key[..], round_data.encode().as_slice())], &[])
}
/// Update the consensus changes.
pub(crate) fn update_consensus_changes<H, N, F, R>(
set: &ConsensusChanges<H, N>,
write_aux: F
) -> R where
H: Encode + Clone,
N: Encode + Clone,
F: FnOnce(&[(&'static [u8], &[u8])]) -> R,
{
write_aux(&[(CONSENSUS_CHANGES_KEY, set.encode().as_slice())])
}
#[cfg(test)]
pub(crate) fn load_authorities<B: AuxStore, H: Decode, N: Decode>(backend: &B)
-> Option<AuthoritySet<H, N>> {
@@ -1,78 +0,0 @@
// Copyright 2018-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/>.
use std::sync::Arc;
use parity_scale_codec::{Encode, Decode};
/// Consensus-related data changes tracker.
#[derive(Clone, Debug, Encode, Decode)]
pub(crate) struct ConsensusChanges<H, N> {
pending_changes: Vec<(N, H)>,
}
impl<H, N> ConsensusChanges<H, N> {
/// Create empty consensus changes.
pub(crate) fn empty() -> Self {
ConsensusChanges { pending_changes: Vec::new(), }
}
}
impl<H: Copy + PartialEq, N: Copy + Ord> ConsensusChanges<H, N> {
/// Returns reference to all pending changes.
pub fn pending_changes(&self) -> &[(N, H)] {
&self.pending_changes
}
/// Note unfinalized change of consensus-related data.
pub(crate) fn note_change(&mut self, at: (N, H)) {
let idx = self.pending_changes
.binary_search_by_key(&at.0, |change| change.0)
.unwrap_or_else(|i| i);
self.pending_changes.insert(idx, at);
}
/// Finalize all pending consensus changes that are finalized by given block.
/// Returns true if there any changes were finalized.
pub(crate) fn finalize<F: Fn(N) -> ::sp_blockchain::Result<Option<H>>>(
&mut self,
block: (N, H),
canonical_at_height: F,
) -> ::sp_blockchain::Result<(bool, bool)> {
let (split_idx, has_finalized_changes) = self.pending_changes.iter()
.enumerate()
.take_while(|(_, &(at_height, _))| at_height <= block.0)
.fold((None, Ok(false)), |(_, has_finalized_changes), (idx, ref at)|
(
Some(idx),
has_finalized_changes
.and_then(|has_finalized_changes| if has_finalized_changes {
Ok(has_finalized_changes)
} else {
canonical_at_height(at.0).map(|can_hash| Some(at.1) == can_hash)
}),
));
let altered_changes = split_idx.is_some();
if let Some(split_idx) = split_idx {
self.pending_changes = self.pending_changes.split_off(split_idx + 1);
}
has_finalized_changes.map(|has_finalized_changes| (altered_changes, has_finalized_changes))
}
}
/// Thread-safe consensus changes tracker reference.
pub(crate) type SharedConsensusChanges<H, N> = Arc<parking_lot::Mutex<ConsensusChanges<H, N>>>;
@@ -34,10 +34,10 @@ use finality_grandpa::{
BlockNumberOps, Error as GrandpaError, round::State as RoundState,
voter, voter_set::VoterSet,
};
use sp_blockchain::{HeaderBackend, HeaderMetadata, Error as ClientError};
use sp_blockchain::HeaderMetadata;
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, NumberFor, One, Zero,
Block as BlockT, Header as HeaderT, NumberFor, Zero,
};
use sc_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO};
@@ -50,7 +50,6 @@ use sp_consensus::SelectChain;
use crate::authorities::{AuthoritySet, SharedAuthoritySet};
use crate::communication::Network as NetworkT;
use crate::consensus_changes::SharedConsensusChanges;
use crate::notification::GrandpaJustificationSender;
use crate::justification::GrandpaJustification;
use crate::until_imported::UntilVoteTargetImported;
@@ -440,7 +439,6 @@ pub(crate) struct Environment<Backend, Block: BlockT, C, N: NetworkT<Block>, SC,
pub(crate) voters: Arc<VoterSet<AuthorityId>>,
pub(crate) config: Config,
pub(crate) authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
pub(crate) consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
pub(crate) network: crate::communication::NetworkBridge<Block, N>,
pub(crate) set_id: SetId,
pub(crate) voter_set_state: SharedVoterSetState<Block>,
@@ -1115,7 +1113,6 @@ where
finalize_block(
self.client.clone(),
&self.authority_set,
&self.consensus_changes,
Some(self.config.justification_period.into()),
hash,
number,
@@ -1180,7 +1177,6 @@ impl<Block: BlockT> From<GrandpaJustification<Block>> for JustificationOrCommit<
pub(crate) fn finalize_block<BE, Block, Client>(
client: Arc<Client>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
justification_period: Option<NumberFor<Block>>,
hash: Block::Hash,
number: NumberFor<Block>,
@@ -1215,15 +1211,6 @@ where
// FIXME #1483: clone only when changed
let old_authority_set = authority_set.clone();
// holds the old consensus changes in case it is changed below, needed for
// reverting in case of failure
let mut old_consensus_changes = None;
let mut consensus_changes = consensus_changes.lock();
let canon_at_height = |canon_number| {
// "true" because the block is finalized
canonical_at_height(&*client, (hash, number), true, canon_number)
};
let update_res: Result<_, Error> = client.lock_import_and_run(|import_op| {
let status = authority_set.apply_standard_changes(
@@ -1233,26 +1220,6 @@ where
initial_sync,
).map_err(|e| Error::Safety(e.to_string()))?;
// check if this is this is the first finalization of some consensus changes
let (alters_consensus_changes, finalizes_consensus_changes) = consensus_changes
.finalize((number, hash), &canon_at_height)?;
if alters_consensus_changes {
old_consensus_changes = Some(consensus_changes.clone());
let write_result = crate::aux_schema::update_consensus_changes(
&*consensus_changes,
|insert| apply_aux(import_op, insert, &[]),
);
if let Err(e) = write_result {
warn!(target: "afg", "Failed to write updated consensus changes to disk. Bailing.");
warn!(target: "afg", "Node is in a potentially inconsistent state.");
return Err(e.into());
}
}
// send a justification notification if a sender exists and in case of error log it.
fn notify_justification<Block: BlockT>(
justification_sender: Option<&GrandpaJustificationSender<Block>>,
@@ -1280,9 +1247,7 @@ where
let mut justification_required =
// justification is always required when block that enacts new authorities
// set is finalized
status.new_set_block.is_some() ||
// justification is required when consensus changes are finalized
finalizes_consensus_changes;
status.new_set_block.is_some();
// justification is required every N blocks to be able to prove blocks
// finalization to remote nodes
@@ -1387,57 +1352,7 @@ where
Err(e) => {
*authority_set = old_authority_set;
if let Some(old_consensus_changes) = old_consensus_changes {
*consensus_changes = old_consensus_changes;
}
Err(CommandOrError::Error(e))
}
}
}
/// Using the given base get the block at the given height on this chain. The
/// target block must be an ancestor of base, therefore `height <= base.height`.
pub(crate) fn canonical_at_height<Block: BlockT, C: HeaderBackend<Block>>(
provider: &C,
base: (Block::Hash, NumberFor<Block>),
base_is_canonical: bool,
height: NumberFor<Block>,
) -> Result<Option<Block::Hash>, ClientError> {
if height > base.1 {
return Ok(None);
}
if height == base.1 {
if base_is_canonical {
return Ok(Some(base.0));
} else {
return Ok(provider.hash(height).unwrap_or(None));
}
} else if base_is_canonical {
return Ok(provider.hash(height).unwrap_or(None));
}
let one = NumberFor::<Block>::one();
// start by getting _canonical_ block with number at parent position and then iterating
// backwards by hash.
let mut current = match provider.header(BlockId::Number(base.1 - one))? {
Some(header) => header,
_ => return Ok(None),
};
// we've already checked that base > height above.
let mut steps = base.1 - height - one;
while steps > NumberFor::<Block>::zero() {
current = match provider.header(BlockId::Hash(*current.parent_hash()))? {
Some(header) => header,
_ => return Ok(None),
};
steps -= one;
}
Ok(Some(current.hash()))
}
@@ -16,6 +16,9 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// NOTE: should be removed with: https://github.com/paritytech/substrate/pull/7339
#![allow(dead_code)]
//! GRANDPA block finality proof generation and check.
//!
//! Finality of block B is proved by providing:
@@ -37,7 +40,7 @@
//! of the U) could be returned.
use std::sync::Arc;
use log::{trace, warn};
use log::trace;
use sp_blockchain::{Backend as BlockchainBackend, Error as ClientError, Result as ClientResult};
use sc_client_api::{
@@ -206,34 +209,6 @@ impl<B, Block> FinalityProofProvider<B, Block>
}
}
impl<B, Block> sc_network::config::FinalityProofProvider<Block> for FinalityProofProvider<B, Block>
where
Block: BlockT,
NumberFor<Block>: BlockNumberOps,
B: Backend<Block> + Send + Sync + 'static,
{
fn prove_finality(
&self,
for_block: Block::Hash,
request: &[u8],
) -> Result<Option<Vec<u8>>, ClientError> {
let request: FinalityProofRequest<Block::Hash> = Decode::decode(&mut &request[..])
.map_err(|e| {
warn!(target: "afg", "Unable to decode finality proof request: {}", e.what());
ClientError::Backend("Invalid finality proof request".to_string())
})?;
match request {
FinalityProofRequest::Original(request) => prove_finality::<_, _, GrandpaJustification<Block>>(
&*self.backend.blockchain(),
&*self.authority_provider,
request.authorities_set_id,
request.last_finalized,
for_block,
),
}
}
}
/// The effects of block finality.
#[derive(Debug, PartialEq)]
pub struct FinalityEffects<Header: HeaderT> {
@@ -290,14 +265,6 @@ struct OriginalFinalityProofRequest<H: Encode + Decode> {
pub last_finalized: H,
}
/// Prepare data blob associated with finality proof request.
pub(crate) fn make_finality_proof_request<H: Encode + Decode>(last_finalized: H, authorities_set_id: u64) -> Vec<u8> {
FinalityProofRequest::Original(OriginalFinalityProofRequest {
authorities_set_id,
last_finalized,
}).encode()
}
/// Prepare proof-of-finality for the best possible block in the range: (begin; end].
///
/// It is assumed that the caller already have a proof-of-finality for the block 'begin'.
@@ -41,7 +41,6 @@ use sp_runtime::traits::{
use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand};
use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange};
use crate::consensus_changes::SharedConsensusChanges;
use crate::environment::finalize_block;
use crate::justification::GrandpaJustification;
use crate::notification::GrandpaJustificationSender;
@@ -61,7 +60,6 @@ pub struct GrandpaBlockImport<Backend, Block: BlockT, Client, SC> {
select_chain: SC,
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
send_voter_commands: TracingUnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
authority_set_hard_forks: HashMap<Block::Hash, PendingChange<Block::Hash, NumberFor<Block>>>,
justification_sender: GrandpaJustificationSender<Block>,
_phantom: PhantomData<Backend>,
@@ -76,7 +74,6 @@ impl<Backend, Block: BlockT, Client, SC: Clone> Clone for
select_chain: self.select_chain.clone(),
authority_set: self.authority_set.clone(),
send_voter_commands: self.send_voter_commands.clone(),
consensus_changes: self.consensus_changes.clone(),
authority_set_hard_forks: self.authority_set_hard_forks.clone(),
justification_sender: self.justification_sender.clone(),
_phantom: PhantomData,
@@ -439,7 +436,6 @@ impl<BE, Block: BlockT, Client, SC> BlockImport<Block>
// we don't want to finalize on `inner.import_block`
let mut justification = block.justification.take();
let enacts_consensus_change = !new_cache.is_empty();
let import_result = (&*self.inner).import_block(block, new_cache);
let mut imported_aux = {
@@ -517,7 +513,7 @@ impl<BE, Block: BlockT, Client, SC> BlockImport<Block>
);
import_res.unwrap_or_else(|err| {
if needs_justification || enacts_consensus_change {
if needs_justification {
debug!(target: "afg", "Imported block #{} that enacts authority set change with \
invalid justification: {:?}, requesting justification from peers.", number, err);
imported_aux.bad_justification = true;
@@ -535,12 +531,6 @@ impl<BE, Block: BlockT, Client, SC> BlockImport<Block>
imported_aux.needs_justification = true;
}
// we have imported block with consensus data changes, but without justification
// => remember to create justification when next block will be finalized
if enacts_consensus_change {
self.consensus_changes.lock().note_change((number, hash));
}
}
}
@@ -561,7 +551,6 @@ impl<Backend, Block: BlockT, Client, SC> GrandpaBlockImport<Backend, Block, Clie
select_chain: SC,
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
send_voter_commands: TracingUnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
authority_set_hard_forks: Vec<(SetId, PendingChange<Block::Hash, NumberFor<Block>>)>,
justification_sender: GrandpaJustificationSender<Block>,
) -> GrandpaBlockImport<Backend, Block, Client, SC> {
@@ -605,7 +594,6 @@ impl<Backend, Block: BlockT, Client, SC> GrandpaBlockImport<Backend, Block, Clie
select_chain,
authority_set,
send_voter_commands,
consensus_changes,
authority_set_hard_forks,
justification_sender,
_phantom: PhantomData,
@@ -646,7 +634,6 @@ where
let result = finalize_block(
self.inner.clone(),
&self.authority_set,
&self.consensus_changes,
None,
hash,
number,
@@ -112,12 +112,10 @@ macro_rules! afg_log {
mod authorities;
mod aux_schema;
mod communication;
mod consensus_changes;
mod environment;
mod finality_proof;
mod import;
mod justification;
mod light_import;
mod notification;
mod observer;
mod until_imported;
@@ -128,7 +126,6 @@ pub use finality_proof::{FinalityProofFragment, FinalityProofProvider, StorageAn
pub use notification::{GrandpaJustificationSender, GrandpaJustificationStream};
pub use import::GrandpaBlockImport;
pub use justification::GrandpaJustification;
pub use light_import::{light_block_import, GrandpaLightBlockImport};
pub use voting_rule::{
BeforeBestBlockBy, ThreeQuartersOfTheUnfinalizedChain, VotingRule, VotingRulesBuilder
};
@@ -588,7 +585,6 @@ where
select_chain.clone(),
persistent_data.authority_set.clone(),
voter_commands_tx,
persistent_data.consensus_changes.clone(),
authority_set_hard_forks,
justification_sender.clone(),
),
@@ -844,7 +840,6 @@ where
network: network.clone(),
set_id: persistent_data.authority_set.set_id(),
authority_set: persistent_data.authority_set.clone(),
consensus_changes: persistent_data.consensus_changes.clone(),
voter_set_state: persistent_data.set_state,
metrics: metrics.as_ref().map(|m| m.environment.clone()),
justification_sender: Some(justification_sender),
@@ -989,7 +984,6 @@ where
select_chain: self.env.select_chain.clone(),
config: self.env.config.clone(),
authority_set: self.env.authority_set.clone(),
consensus_changes: self.env.consensus_changes.clone(),
network: self.env.network.clone(),
voting_rule: self.env.voting_rule.clone(),
metrics: self.env.metrics.clone(),
@@ -1,880 +0,0 @@
// Copyright 2019-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/>.
use std::collections::HashMap;
use std::sync::Arc;
use log::{info, trace, warn};
use parking_lot::RwLock;
use sc_client_api::backend::{AuxStore, Backend, Finalizer, TransactionFor};
use sp_blockchain::{HeaderBackend, Error as ClientError, well_known_cache_keys};
use parity_scale_codec::{Encode, Decode};
use sp_consensus::{
import_queue::Verifier,
BlockOrigin, BlockImport, FinalityProofImport, BlockImportParams, ImportResult, ImportedAux,
BlockCheckParams, Error as ConsensusError,
};
use sc_network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder};
use sp_runtime::Justification;
use sp_runtime::traits::{NumberFor, Block as BlockT, Header as HeaderT, DigestFor};
use sp_finality_grandpa::{self, AuthorityList};
use sp_runtime::generic::BlockId;
use crate::GenesisAuthoritySetProvider;
use crate::aux_schema::load_decode;
use crate::consensus_changes::ConsensusChanges;
use crate::environment::canonical_at_height;
use crate::finality_proof::{
AuthoritySetForFinalityChecker, ProvableJustification, make_finality_proof_request,
};
use crate::justification::GrandpaJustification;
/// LightAuthoritySet is saved under this key in aux storage.
const LIGHT_AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters";
/// ConsensusChanges is saver under this key in aux storage.
const LIGHT_CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes";
/// Create light block importer.
pub fn light_block_import<BE, Block: BlockT, Client>(
client: Arc<Client>,
backend: Arc<BE>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<GrandpaLightBlockImport<BE, Block, Client>, ClientError>
where
BE: Backend<Block>,
Client: crate::ClientForGrandpa<Block, BE>,
{
let info = client.info();
let import_data = load_aux_import_data(
info.finalized_hash,
&*client,
genesis_authorities_provider,
)?;
Ok(GrandpaLightBlockImport {
client,
backend,
authority_set_provider,
data: Arc::new(RwLock::new(import_data)),
})
}
/// A light block-import handler for GRANDPA.
///
/// It is responsible for:
/// - checking GRANDPA justifications;
/// - fetching finality proofs for blocks that are enacting consensus changes.
pub struct GrandpaLightBlockImport<BE, Block: BlockT, Client> {
client: Arc<Client>,
backend: Arc<BE>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
data: Arc<RwLock<LightImportData<Block>>>,
}
impl<BE, Block: BlockT, Client> Clone for GrandpaLightBlockImport<BE, Block, Client> {
fn clone(&self) -> Self {
GrandpaLightBlockImport {
client: self.client.clone(),
backend: self.backend.clone(),
authority_set_provider: self.authority_set_provider.clone(),
data: self.data.clone(),
}
}
}
/// Mutable data of light block importer.
struct LightImportData<Block: BlockT> {
last_finalized: Block::Hash,
authority_set: LightAuthoritySet,
consensus_changes: ConsensusChanges<Block::Hash, NumberFor<Block>>,
}
/// Latest authority set tracker.
#[derive(Debug, Encode, Decode)]
struct LightAuthoritySet {
set_id: u64,
authorities: AuthorityList,
}
impl<BE, Block: BlockT, Client> GrandpaLightBlockImport<BE, Block, Client> {
/// Create finality proof request builder.
pub fn create_finality_proof_request_builder(&self) -> BoxFinalityProofRequestBuilder<Block> {
Box::new(GrandpaFinalityProofRequestBuilder(self.data.clone())) as _
}
}
impl<BE, Block: BlockT, Client> BlockImport<Block>
for GrandpaLightBlockImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
DigestFor<Block>: Encode,
BE: Backend<Block> + 'static,
for<'a> &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
{
type Error = ConsensusError;
type Transaction = TransactionFor<BE, Block>;
fn import_block(
&mut self,
block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
do_import_block::<_, _, _, GrandpaJustification<Block>>(
&*self.client, &mut *self.data.write(), block, new_cache
)
}
fn check_block(
&mut self,
block: BlockCheckParams<Block>,
) -> Result<ImportResult, Self::Error> {
self.client.check_block(block)
}
}
impl<BE, Block: BlockT, Client> FinalityProofImport<Block>
for GrandpaLightBlockImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
DigestFor<Block>: Encode,
BE: Backend<Block> + 'static,
for<'a> &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
{
type Error = ConsensusError;
fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor<Block>)> {
let mut out = Vec::new();
let chain_info = (&*self.client).info();
let data = self.data.read();
for (pending_number, pending_hash) in data.consensus_changes.pending_changes() {
if *pending_number > chain_info.finalized_number
&& *pending_number <= chain_info.best_number
{
out.push((*pending_hash, *pending_number));
}
}
out
}
fn import_finality_proof(
&mut self,
hash: Block::Hash,
number: NumberFor<Block>,
finality_proof: Vec<u8>,
verifier: &mut dyn Verifier<Block>,
) -> Result<(Block::Hash, NumberFor<Block>), Self::Error> {
do_import_finality_proof::<_, _, _, GrandpaJustification<Block>>(
&*self.client,
self.backend.clone(),
&*self.authority_set_provider,
&mut *self.data.write(),
hash,
number,
finality_proof,
verifier,
)
}
}
impl LightAuthoritySet {
/// Get a genesis set with given authorities.
pub fn genesis(initial: AuthorityList) -> Self {
LightAuthoritySet {
set_id: sp_finality_grandpa::SetId::default(),
authorities: initial,
}
}
/// Get latest set id.
pub fn set_id(&self) -> u64 {
self.set_id
}
/// Get latest authorities set.
pub fn authorities(&self) -> AuthorityList {
self.authorities.clone()
}
/// Set new authorities set.
pub fn update(&mut self, set_id: u64, authorities: AuthorityList) {
self.set_id = set_id;
self.authorities = authorities;
}
}
struct GrandpaFinalityProofRequestBuilder<B: BlockT>(Arc<RwLock<LightImportData<B>>>);
impl<B: BlockT> FinalityProofRequestBuilder<B> for GrandpaFinalityProofRequestBuilder<B> {
fn build_request_data(&mut self, _hash: &B::Hash) -> Vec<u8> {
let data = self.0.read();
make_finality_proof_request(
data.last_finalized,
data.authority_set.set_id(),
)
}
}
/// Try to import new block.
fn do_import_block<B, C, Block: BlockT, J>(
mut client: C,
data: &mut LightImportData<Block>,
mut block: BlockImportParams<Block, TransactionFor<B, Block>>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, ConsensusError>
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, B>
+ BlockImport<Block, Transaction = TransactionFor<B, Block>>
+ Clone,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
DigestFor<Block>: Encode,
J: ProvableJustification<Block::Header>,
{
let hash = block.post_hash();
let number = *block.header.number();
// we don't want to finalize on `inner.import_block`
let justification = block.justification.take();
let enacts_consensus_change = !new_cache.is_empty();
let import_result = client.import_block(block, new_cache);
let mut imported_aux = match import_result {
Ok(ImportResult::Imported(aux)) => aux,
Ok(r) => return Ok(r),
Err(e) => return Err(ConsensusError::ClientImport(e.to_string())),
};
match justification {
Some(justification) => {
trace!(
target: "afg",
"Imported block {}{}. Importing justification.",
if enacts_consensus_change { " which enacts consensus changes" } else { "" },
hash,
);
do_import_justification::<_, _, _, J>(client, data, hash, number, justification)
},
None if enacts_consensus_change => {
trace!(
target: "afg",
"Imported block {} which enacts consensus changes. Requesting finality proof.",
hash,
);
// remember that we need finality proof for this block
imported_aux.needs_finality_proof = true;
data.consensus_changes.note_change((number, hash));
Ok(ImportResult::Imported(imported_aux))
},
None => Ok(ImportResult::Imported(imported_aux)),
}
}
/// Try to import finality proof.
fn do_import_finality_proof<B, C, Block: BlockT, J>(
client: C,
backend: Arc<B>,
authority_set_provider: &dyn AuthoritySetForFinalityChecker<Block>,
data: &mut LightImportData<Block>,
_hash: Block::Hash,
_number: NumberFor<Block>,
finality_proof: Vec<u8>,
verifier: &mut dyn Verifier<Block>,
) -> Result<(Block::Hash, NumberFor<Block>), ConsensusError>
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, B>
+ BlockImport<Block, Transaction = TransactionFor<B, Block>>
+ Clone,
B: Backend<Block> + 'static,
DigestFor<Block>: Encode,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
J: ProvableJustification<Block::Header>,
{
let authority_set_id = data.authority_set.set_id();
let authorities = data.authority_set.authorities();
let finality_effects = crate::finality_proof::check_finality_proof::<_, _, J>(
backend.blockchain(),
authority_set_id,
authorities,
authority_set_provider,
finality_proof,
).map_err(|e| ConsensusError::ClientImport(e.to_string()))?;
// try to import all new headers
let block_origin = BlockOrigin::NetworkBroadcast;
for header_to_import in finality_effects.headers_to_import {
let (block_to_import, new_authorities) = verifier.verify(
block_origin,
header_to_import,
None,
None,
).map_err(|e| ConsensusError::ClientImport(e))?;
assert!(
block_to_import.justification.is_none(),
"We have passed None as justification to verifier.verify",
);
let mut cache = HashMap::new();
if let Some(authorities) = new_authorities {
cache.insert(well_known_cache_keys::AUTHORITIES, authorities.encode());
}
do_import_block::<_, _, _, J>(
client.clone(),
data,
block_to_import.convert_transaction(),
cache,
)?;
}
// try to import latest justification
let finalized_block_hash = finality_effects.block;
let finalized_block_number = backend.blockchain()
.expect_block_number_from_id(&BlockId::Hash(finality_effects.block))
.map_err(|e| ConsensusError::ClientImport(e.to_string()))?;
do_finalize_block(
client.clone(),
data,
finalized_block_hash,
finalized_block_number,
finality_effects.justification.encode(),
)?;
// apply new authorities set
data.authority_set.update(
finality_effects.new_set_id,
finality_effects.new_authorities,
);
// store new authorities set
require_insert_aux(
&client,
LIGHT_AUTHORITY_SET_KEY,
&data.authority_set,
"authority set",
)?;
Ok((finalized_block_hash, finalized_block_number))
}
/// Try to import justification.
fn do_import_justification<B, C, Block: BlockT, J>(
client: C,
data: &mut LightImportData<Block>,
hash: Block::Hash,
number: NumberFor<Block>,
justification: Justification,
) -> Result<ImportResult, ConsensusError>
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, B>
+ Clone,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
J: ProvableJustification<Block::Header>,
{
// with justification, we have two cases
//
// optimistic: the same GRANDPA authorities set has generated intermediate justification
// => justification is verified using current authorities set + we could proceed further
//
// pessimistic scenario: the GRANDPA authorities set has changed
// => we need to fetch new authorities set (i.e. finality proof) from remote node
// first, try to behave optimistically
let authority_set_id = data.authority_set.set_id();
let justification = J::decode_and_verify(
&justification,
authority_set_id,
&data.authority_set.authorities(),
);
// BadJustification error means that justification has been successfully decoded, but
// it isn't valid within current authority set
let justification = match justification {
Err(ClientError::BadJustification(_)) => {
trace!(
target: "afg",
"Justification for {} is not valid within current authorities set. Requesting finality proof.",
hash,
);
let mut imported_aux = ImportedAux::default();
imported_aux.needs_finality_proof = true;
return Ok(ImportResult::Imported(imported_aux));
},
Err(e) => {
trace!(
target: "afg",
"Justification for {} is not valid. Bailing.",
hash,
);
return Err(ConsensusError::ClientImport(e.to_string()));
},
Ok(justification) => {
trace!(
target: "afg",
"Justification for {} is valid. Finalizing the block.",
hash,
);
justification
},
};
// finalize the block
do_finalize_block(client, data, hash, number, justification.encode())
}
/// Finalize the block.
fn do_finalize_block<B, C, Block: BlockT>(
client: C,
data: &mut LightImportData<Block>,
hash: Block::Hash,
number: NumberFor<Block>,
justification: Justification,
) -> Result<ImportResult, ConsensusError>
where
C: HeaderBackend<Block>
+ AuxStore
+ Finalizer<Block, B>
+ Clone,
B: Backend<Block> + 'static,
NumberFor<Block>: finality_grandpa::BlockNumberOps,
{
// finalize the block
client.finalize_block(BlockId::Hash(hash), Some(justification), true).map_err(|e| {
warn!(target: "afg", "Error applying finality to block {:?}: {:?}", (hash, number), e);
ConsensusError::ClientImport(e.to_string())
})?;
// forget obsoleted consensus changes
let consensus_finalization_res = data.consensus_changes
.finalize(
(number, hash),
|at_height| canonical_at_height(&client, (hash, number), true, at_height)
);
match consensus_finalization_res {
Ok((true, _)) => require_insert_aux(
&client,
LIGHT_CONSENSUS_CHANGES_KEY,
&data.consensus_changes,
"consensus changes",
)?,
Ok(_) => (),
Err(error) => return Err(on_post_finalization_error(error, "consensus changes")),
}
// update last finalized block reference
data.last_finalized = hash;
// we just finalized this block, so if we were importing it, it is now the new best
Ok(ImportResult::imported(true))
}
/// Load light import aux data from the store.
fn load_aux_import_data<B, Block>(
last_finalized: Block::Hash,
aux_store: &B,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
) -> Result<LightImportData<Block>, ClientError>
where
B: AuxStore,
Block: BlockT,
{
let authority_set = match load_decode(aux_store, LIGHT_AUTHORITY_SET_KEY)? {
Some(authority_set) => authority_set,
None => {
info!(target: "afg", "Loading GRANDPA authorities \
from genesis on what appears to be first startup.");
// no authority set on disk: fetch authorities from genesis state
let genesis_authorities = genesis_authorities_provider.get()?;
let authority_set = LightAuthoritySet::genesis(genesis_authorities);
let encoded = authority_set.encode();
aux_store.insert_aux(&[(LIGHT_AUTHORITY_SET_KEY, &encoded[..])], &[])?;
authority_set
},
};
let consensus_changes = match load_decode(aux_store, LIGHT_CONSENSUS_CHANGES_KEY)? {
Some(consensus_changes) => consensus_changes,
None => {
let consensus_changes = ConsensusChanges::<Block::Hash, NumberFor<Block>>::empty();
let encoded = authority_set.encode();
aux_store.insert_aux(&[(LIGHT_CONSENSUS_CHANGES_KEY, &encoded[..])], &[])?;
consensus_changes
},
};
Ok(LightImportData {
last_finalized,
authority_set,
consensus_changes,
})
}
/// Insert into aux store. If failed, return error && show inconsistency warning.
fn require_insert_aux<T: Encode, A: AuxStore>(
store: &A,
key: &[u8],
value: &T,
value_type: &str,
) -> Result<(), ConsensusError> {
let encoded = value.encode();
let update_res = store.insert_aux(&[(key, &encoded[..])], &[]);
if let Err(error) = update_res {
return Err(on_post_finalization_error(error, value_type));
}
Ok(())
}
/// Display inconsistency warning.
fn on_post_finalization_error(error: ClientError, value_type: &str) -> ConsensusError {
warn!(target: "afg", "Failed to write updated {} to disk. Bailing.", value_type);
warn!(target: "afg", "Node is in a potentially inconsistent state.");
ConsensusError::ClientImport(error.to_string())
}
#[cfg(test)]
pub mod tests {
use super::*;
use sp_consensus::{import_queue::CacheKeyId, ForkChoiceStrategy, BlockImport};
use sp_finality_grandpa::AuthorityId;
use sp_core::{H256, crypto::Public};
use sc_client_api::{in_mem::Blockchain as InMemoryAuxStore, StorageProof, BlockBackend};
use substrate_test_runtime_client::runtime::{Block, Header};
use crate::tests::TestApi;
use crate::finality_proof::{
FinalityProofFragment,
tests::{TestJustification, ClosureAuthoritySetForFinalityChecker},
};
struct OkVerifier;
impl Verifier<Block> for OkVerifier {
fn verify(
&mut self,
origin: BlockOrigin,
header: Header,
_justification: Option<Justification>,
_body: Option<Vec<<Block as BlockT>::Extrinsic>>,
) -> Result<(BlockImportParams<Block, ()>, Option<Vec<(CacheKeyId, Vec<u8>)>>), String> {
Ok((BlockImportParams::new(origin, header), None))
}
}
pub struct NoJustificationsImport<BE, Block: BlockT, Client>(
pub GrandpaLightBlockImport<BE, Block, Client>
);
impl<BE, Block: BlockT, Client> Clone
for NoJustificationsImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
DigestFor<Block>: Encode,
BE: Backend<Block> + 'static,
{
fn clone(&self) -> Self {
NoJustificationsImport(self.0.clone())
}
}
impl<BE, Block: BlockT, Client> BlockImport<Block>
for NoJustificationsImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
DigestFor<Block>: Encode,
BE: Backend<Block> + 'static,
for <'a > &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
GrandpaLightBlockImport<BE, Block, Client>:
BlockImport<Block, Transaction = TransactionFor<BE, Block>, Error = ConsensusError>
{
type Error = ConsensusError;
type Transaction = TransactionFor<BE, Block>;
fn import_block(
&mut self,
mut block: BlockImportParams<Block, Self::Transaction>,
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
block.justification.take();
self.0.import_block(block, new_cache)
}
fn check_block(
&mut self,
block: BlockCheckParams<Block>,
) -> Result<ImportResult, Self::Error> {
self.0.check_block(block)
}
}
impl<BE, Block: BlockT, Client> FinalityProofImport<Block>
for NoJustificationsImport<BE, Block, Client> where
NumberFor<Block>: finality_grandpa::BlockNumberOps,
BE: Backend<Block> + 'static,
DigestFor<Block>: Encode,
for <'a > &'a Client:
HeaderBackend<Block>
+ BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<BE, Block>>
+ Finalizer<Block, BE>
+ AuxStore,
{
type Error = ConsensusError;
fn on_start(&mut self) -> Vec<(Block::Hash, NumberFor<Block>)> {
self.0.on_start()
}
fn import_finality_proof(
&mut self,
hash: Block::Hash,
number: NumberFor<Block>,
finality_proof: Vec<u8>,
verifier: &mut dyn Verifier<Block>,
) -> Result<(Block::Hash, NumberFor<Block>), Self::Error> {
self.0.import_finality_proof(hash, number, finality_proof, verifier)
}
}
/// Creates light block import that ignores justifications that came outside of finality proofs.
pub fn light_block_import_without_justifications<BE, Block: BlockT, Client>(
client: Arc<Client>,
backend: Arc<BE>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
authority_set_provider: Arc<dyn AuthoritySetForFinalityChecker<Block>>,
) -> Result<NoJustificationsImport<BE, Block, Client>, ClientError>
where
BE: Backend<Block> + 'static,
Client: crate::ClientForGrandpa<Block, BE>,
{
light_block_import(client, backend, genesis_authorities_provider, authority_set_provider)
.map(NoJustificationsImport)
}
fn import_block(
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
justification: Option<Justification>,
) -> (
ImportResult,
substrate_test_runtime_client::client::Client<substrate_test_runtime_client::LightBackend, substrate_test_runtime_client::LightExecutor, Block, substrate_test_runtime_client::runtime::RuntimeApi>,
Arc<substrate_test_runtime_client::LightBackend>,
) {
let (client, backend) = substrate_test_runtime_client::new_light();
let mut import_data = LightImportData {
last_finalized: Default::default(),
authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 1)]),
consensus_changes: ConsensusChanges::empty(),
};
let mut block = BlockImportParams::new(
BlockOrigin::Own,
Header {
number: 1,
parent_hash: client.chain_info().best_hash,
state_root: Default::default(),
digest: Default::default(),
extrinsics_root: Default::default(),
},
);
block.justification = justification;
block.fork_choice = Some(ForkChoiceStrategy::LongestChain);
(
do_import_block::<_, _, _, TestJustification>(
&client,
&mut import_data,
block,
new_cache,
).unwrap(),
client,
backend,
)
}
#[test]
fn finality_proof_not_required_when_consensus_data_does_not_changes_and_no_justification_provided() {
assert_eq!(import_block(HashMap::new(), None).0, ImportResult::Imported(ImportedAux {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: false,
is_new_best: true,
header_only: false,
}));
}
#[test]
fn finality_proof_not_required_when_consensus_data_does_not_changes_and_correct_justification_provided() {
let justification = TestJustification((0, vec![(AuthorityId::from_slice(&[1; 32]), 1)]), Vec::new()).encode();
assert_eq!(import_block(HashMap::new(), Some(justification)).0, ImportResult::Imported(ImportedAux {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: false,
is_new_best: true,
header_only: false,
}));
}
#[test]
fn finality_proof_required_when_consensus_data_changes_and_no_justification_provided() {
let mut cache = HashMap::new();
cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode());
assert_eq!(import_block(cache, None).0, ImportResult::Imported(ImportedAux {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: true,
is_new_best: true,
header_only: false,
}));
}
#[test]
fn finality_proof_required_when_consensus_data_changes_and_incorrect_justification_provided() {
let justification = TestJustification((0, vec![]), Vec::new()).encode();
let mut cache = HashMap::new();
cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_slice(&[2; 32])].encode());
assert_eq!(
import_block(cache, Some(justification)).0,
ImportResult::Imported(ImportedAux {
clear_justification_requests: false,
needs_justification: false,
bad_justification: false,
needs_finality_proof: true,
is_new_best: false,
header_only: false,
},
));
}
#[test]
fn aux_data_updated_on_start() {
let aux_store = InMemoryAuxStore::<Block>::new();
let api = TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)]);
// when aux store is empty initially
assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_none());
assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_none());
// it is updated on importer start
load_aux_import_data(Default::default(), &aux_store, &api).unwrap();
assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_some());
assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_some());
}
#[test]
fn aux_data_loaded_on_restart() {
let aux_store = InMemoryAuxStore::<Block>::new();
let api = TestApi::new(vec![(AuthorityId::from_slice(&[1; 32]), 1)]);
// when aux store is non-empty initially
let mut consensus_changes = ConsensusChanges::<H256, u64>::empty();
consensus_changes.note_change((42, Default::default()));
aux_store.insert_aux(
&[
(
LIGHT_AUTHORITY_SET_KEY,
LightAuthoritySet::genesis(
vec![(AuthorityId::from_slice(&[42; 32]), 2)]
).encode().as_slice(),
),
(
LIGHT_CONSENSUS_CHANGES_KEY,
consensus_changes.encode().as_slice(),
),
],
&[],
).unwrap();
// importer uses it on start
let data = load_aux_import_data(Default::default(), &aux_store, &api).unwrap();
assert_eq!(data.authority_set.authorities(), vec![(AuthorityId::from_slice(&[42; 32]), 2)]);
assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]);
}
#[test]
fn authority_set_is_updated_on_finality_proof_import() {
let initial_set_id = 0;
let initial_set = vec![(AuthorityId::from_slice(&[1; 32]), 1)];
let updated_set = vec![(AuthorityId::from_slice(&[2; 32]), 2)];
let babe_set_signal = vec![AuthorityId::from_slice(&[42; 32])].encode();
// import block #1 without justification
let mut cache = HashMap::new();
cache.insert(well_known_cache_keys::AUTHORITIES, babe_set_signal);
let (_, client, backend) = import_block(cache, None);
// import finality proof for block #1
let hash = client.block_hash(1).unwrap().unwrap();
let mut verifier = OkVerifier;
let mut import_data = LightImportData {
last_finalized: Default::default(),
authority_set: LightAuthoritySet::genesis(initial_set.clone()),
consensus_changes: ConsensusChanges::empty(),
};
// import finality proof
do_import_finality_proof::<_, _, _, TestJustification>(
&client,
backend,
&ClosureAuthoritySetForFinalityChecker(
|_, _, _| Ok(updated_set.clone())
),
&mut import_data,
Default::default(),
Default::default(),
vec![
FinalityProofFragment::<Header> {
block: hash,
justification: TestJustification(
(initial_set_id, initial_set.clone()),
Vec::new(),
).encode(),
unknown_headers: Vec::new(),
authorities_proof: Some(StorageProof::new(vec![])),
},
].encode(),
&mut verifier,
).unwrap();
// verify that new authorities set has been saved to the aux storage
let data = load_aux_import_data(Default::default(), &client, &TestApi::new(initial_set)).unwrap();
assert_eq!(data.authority_set.authorities(), updated_set);
}
}
@@ -39,7 +39,6 @@ use crate::{
};
use crate::authorities::SharedAuthoritySet;
use crate::communication::{Network as NetworkT, NetworkBridge};
use crate::consensus_changes::SharedConsensusChanges;
use crate::notification::GrandpaJustificationSender;
use sp_finality_grandpa::AuthorityId;
use std::marker::{PhantomData, Unpin};
@@ -68,7 +67,6 @@ impl<'a, Block, Client> finality_grandpa::Chain<Block::Hash, NumberFor<Block>>
fn grandpa_observer<BE, Block: BlockT, Client, S, F>(
client: &Arc<Client>,
authority_set: &SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
consensus_changes: &SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
voters: &Arc<VoterSet<AuthorityId>>,
justification_sender: &Option<GrandpaJustificationSender<Block>>,
last_finalized_number: NumberFor<Block>,
@@ -83,7 +81,6 @@ where
Client: crate::ClientForGrandpa<Block, BE>,
{
let authority_set = authority_set.clone();
let consensus_changes = consensus_changes.clone();
let client = client.clone();
let voters = voters.clone();
let justification_sender = justification_sender.clone();
@@ -123,7 +120,6 @@ where
match environment::finalize_block(
client.clone(),
&authority_set,
&consensus_changes,
None,
finalized_hash,
finalized_number,
@@ -293,7 +289,6 @@ where
let observer = grandpa_observer(
&self.client,
&self.persistent_data.authority_set,
&self.persistent_data.consensus_changes,
&voters,
&self.justification_sender,
last_finalized_number,
+8 -178
View File
@@ -25,7 +25,7 @@ use sc_network_test::{
Block, BlockImportAdapter, Hash, PassThroughVerifier, Peer, PeersClient, PeersFullClient,
TestClient, TestNetFactory, FullPeerConfig,
};
use sc_network::config::{ProtocolConfig, BoxFinalityProofRequestBuilder};
use sc_network::config::ProtocolConfig;
use parking_lot::{RwLock, Mutex};
use futures_timer::Delay;
use tokio::runtime::{Runtime, Handle};
@@ -36,22 +36,21 @@ use sp_api::{ApiRef, StorageProof, ProvideRuntimeApi};
use substrate_test_runtime_client::runtime::BlockNumber;
use sp_consensus::{
BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, BlockImport,
import_queue::{BoxJustificationImport, BoxFinalityProofImport},
import_queue::BoxJustificationImport,
};
use std::{collections::{HashMap, HashSet}, pin::Pin};
use parity_scale_codec::Decode;
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, HashFor};
use sp_runtime::generic::{BlockId, DigestItem};
use sp_core::{H256, crypto::Public};
use sp_core::H256;
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, EquivocationProof, GrandpaApi, OpaqueKeyOwnershipProof};
use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check};
use authorities::AuthoritySet;
use finality_proof::{
FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker,
AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker,
};
use consensus_changes::ConsensusChanges;
use sc_block_builder::BlockBuilderProvider;
use sc_consensus::LongestChain;
use sc_keystore::LocalKeystore;
@@ -117,8 +116,6 @@ impl TestNetFactory for GrandpaTestNet {
-> (
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
PeerData,
)
{
@@ -133,48 +130,15 @@ impl TestNetFactory for GrandpaTestNet {
(
BlockImportAdapter::new_full(import),
Some(justification_import),
None,
None,
Mutex::new(Some(link)),
)
},
PeersClient::Light(ref client, ref backend) => {
use crate::light_import::tests::light_block_import_without_justifications;
let authorities_provider = Arc::new(self.test_config.clone());
// forbid direct finalization using justification that came with the block
// => light clients will try to fetch finality proofs
let import = light_block_import_without_justifications(
client.clone(),
backend.clone(),
&self.test_config,
authorities_provider,
).expect("Could not create block import for fresh peer.");
let finality_proof_req_builder = import.0.create_finality_proof_request_builder();
let proof_import = Box::new(import.clone());
(
BlockImportAdapter::new_light(import),
None,
Some(proof_import),
Some(finality_proof_req_builder),
Mutex::new(None),
)
PeersClient::Light(..) => {
panic!("Light client is not used in tests.");
},
}
}
fn make_finality_proof_provider(
&self,
client: PeersClient
) -> Option<Arc<dyn sc_network::config::FinalityProofProvider<Block>>> {
match client {
PeersClient::Full(_, ref backend) => {
Some(Arc::new(FinalityProofProvider::new(backend.clone(), self.test_config.clone())))
},
PeersClient::Light(_, _) => None,
}
}
fn peer(&mut self, i: usize) -> &mut GrandpaPeer {
&mut self.peers[i]
}
@@ -679,24 +643,6 @@ fn transition_3_voters_twice_1_full_observer() {
block_until_complete(wait_for, &net, &mut runtime);
}
#[test]
fn justification_is_emitted_when_consensus_data_changes() {
let mut runtime = Runtime::new().unwrap();
let peers = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3);
// import block#1 WITH consensus data change
let new_authorities = vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])];
net.peer(0).push_authorities_change_block(new_authorities);
net.block_until_sync();
let net = Arc::new(Mutex::new(net));
run_to_completion(&mut runtime, 1, net.clone(), peers);
// ... and check that there's justification for block#1
assert!(net.lock().peer(0).client().justification(&BlockId::Number(1)).unwrap().is_some(),
"Missing justification for block#1");
}
#[test]
fn justification_is_generated_periodically() {
let mut runtime = Runtime::new().unwrap();
@@ -717,25 +663,6 @@ fn justification_is_generated_periodically() {
}
}
#[test]
fn consensus_changes_works() {
let mut changes = ConsensusChanges::<H256, u64>::empty();
// pending changes are not finalized
changes.note_change((10, H256::from_low_u64_be(1)));
assert_eq!(changes.finalize((5, H256::from_low_u64_be(5)), |_| Ok(None)).unwrap(), (false, false));
// no change is selected from competing pending changes
changes.note_change((1, H256::from_low_u64_be(1)));
changes.note_change((1, H256::from_low_u64_be(101)));
assert_eq!(changes.finalize((10, H256::from_low_u64_be(10)), |_| Ok(Some(H256::from_low_u64_be(1001)))).unwrap(), (true, false));
// change is selected from competing pending changes
changes.note_change((1, H256::from_low_u64_be(1)));
changes.note_change((1, H256::from_low_u64_be(101)));
assert_eq!(changes.finalize((10, H256::from_low_u64_be(10)), |_| Ok(Some(H256::from_low_u64_be(1)))).unwrap(), (true, true));
}
#[test]
fn sync_justifications_on_change_blocks() {
let mut runtime = Runtime::new().unwrap();
@@ -944,7 +871,6 @@ fn allows_reimporting_change_blocks() {
needs_justification: true,
clear_justification_requests: false,
bad_justification: false,
needs_finality_proof: false,
is_new_best: true,
header_only: false,
}),
@@ -1069,7 +995,7 @@ fn voter_persists_its_votes() {
Poll::Pending => return Poll::Pending,
Poll::Ready(None) => return Poll::Ready(()),
Poll::Ready(Some(())) => {
let (_block_import, _, _, _, link) =
let (_block_import, _, link) =
this.net.lock()
.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
@@ -1144,7 +1070,7 @@ fn voter_persists_its_votes() {
};
let set_state = {
let (_, _, _, _, link) = net.lock()
let (_, _, link) = net.lock()
.make_block_import::<
TransactionFor<substrate_test_runtime_client::Backend, Block>
>(client);
@@ -1311,100 +1237,6 @@ fn finalize_3_voters_1_light_observer() {
});
}
#[test]
fn finality_proof_is_fetched_by_light_client_when_consensus_data_changes() {
sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
let peers = &[Ed25519Keyring::Alice];
let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 1);
net.add_light_peer();
// import block#1 WITH consensus data change. Light client ignores justification
// && instead fetches finality proof for block #1
net.peer(0).push_authorities_change_block(vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])]);
let net = Arc::new(Mutex::new(net));
run_to_completion(&mut runtime, 1, net.clone(), peers);
net.lock().block_until_sync();
// check that the block#1 is finalized on light client
runtime.block_on(futures::future::poll_fn(move |cx| {
if net.lock().peer(1).client().info().finalized_number == 1 {
Poll::Ready(())
} else {
net.lock().poll(cx);
Poll::Pending
}
}));
}
#[test]
fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_different() {
// for debug: to ensure that without forced change light client will sync finality proof
const FORCE_CHANGE: bool = true;
sp_tracing::try_init_simple();
let mut runtime = Runtime::new().unwrap();
// two of these guys are offline.
let genesis_authorities = if FORCE_CHANGE {
vec![
Ed25519Keyring::Alice,
Ed25519Keyring::Bob,
Ed25519Keyring::Charlie,
Ed25519Keyring::One,
Ed25519Keyring::Two,
]
} else {
vec![
Ed25519Keyring::Alice,
Ed25519Keyring::Bob,
Ed25519Keyring::Charlie,
]
};
let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
let api = TestApi::new(make_ids(&genesis_authorities));
let voters = make_ids(peers_a);
let net = GrandpaTestNet::new(api, 3);
let net = Arc::new(Mutex::new(net));
// best is #1
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
// add a forced transition at block 5.
let mut block = builder.build().unwrap().block;
if FORCE_CHANGE {
add_forced_change(&mut block, 0, ScheduledChange {
next_authorities: voters.clone(),
delay: 3,
});
}
block
});
// ensure block#10 enacts authorities set change => justification is generated
// normally it will reach light client, but because of the forced change, it will not
net.lock().peer(0).push_blocks(8, false); // best is #9
net.lock().peer(0).push_authorities_change_block(
vec![sp_consensus_babe::AuthorityId::from_slice(&[42; 32])]
); // #10
net.lock().peer(0).push_blocks(1, false); // best is #11
net.lock().block_until_sync();
// finalize block #11 on full clients
run_to_completion(&mut runtime, 11, net.clone(), peers_a);
// request finalization by light client
net.lock().add_light_peer();
net.lock().block_until_sync();
// check block, finalized on light client
assert_eq!(
net.lock().peer(3).client().info().finalized_number,
if FORCE_CHANGE { 0 } else { 10 },
);
}
#[test]
fn voter_catches_up_to_latest_round_when_behind() {
sp_tracing::try_init_simple();
@@ -1540,7 +1372,6 @@ where
{
let PersistentData {
ref authority_set,
ref consensus_changes,
ref set_state,
..
} = link.persistent_data;
@@ -1564,7 +1395,6 @@ where
Environment {
authority_set: authority_set.clone(),
config: config.clone(),
consensus_changes: consensus_changes.clone(),
client: link.client.clone(),
select_chain: link.select_chain.clone(),
set_id: authority_set.set_id(),
-1
View File
@@ -1,6 +1,5 @@
const PROTOS: &[&str] = &[
"src/schema/api.v1.proto",
"src/schema/finality.v1.proto",
"src/schema/light.v1.proto"
];
+2 -32
View File
@@ -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) {
-12
View File
@@ -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)
}
}
+1 -31
View File
@@ -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"),
-1
View File
@@ -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;
+1 -76
View File
@@ -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>>,
}
}
+6 -152
View File
@@ -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)
}
-3
View File
@@ -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
}
+5 -34
View File
@@ -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(&params.protocol_id);
block_requests::BlockRequests::new(config, params.chain.clone())
};
let finality_proof_requests = {
let config = finality_requests::Config::new(&params.protocol_id);
finality_requests::FinalityProofRequests::new(config, params.finality_proof_provider.clone())
};
let light_client_handler = {
let config = light_client_handler::Config::new(&params.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"),
@@ -107,7 +107,6 @@ fn async_import_queue_drops() {
verifier,
Box::new(substrate_test_runtime_client::new()),
None,
None,
&executor,
None,
);
+3 -32
View File
@@ -29,7 +29,6 @@ use std::{
use libp2p::build_multiaddr;
use log::trace;
use sc_network::config::FinalityProofProvider;
use sp_blockchain::{
HeaderBackend, Result as ClientResult,
well_known_cache_keys::{self, Id as CacheKeyId},
@@ -44,14 +43,14 @@ use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
use sc_network::config::Role;
use sp_consensus::block_validation::{DefaultBlockAnnounceValidator, BlockAnnounceValidator};
use sp_consensus::import_queue::{
BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport,
BasicQueue, BoxJustificationImport, Verifier,
};
use sp_consensus::block_import::{BlockImport, ImportResult};
use sp_consensus::Error as ConsensusError;
use sp_consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport};
use futures::prelude::*;
use sc_network::{NetworkWorker, NetworkService, config::ProtocolId};
use sc_network::config::{NetworkConfiguration, TransportConfig, BoxFinalityProofRequestBuilder};
use sc_network::config::{NetworkConfiguration, TransportConfig};
use libp2p::PeerId;
use parking_lot::Mutex;
use sp_core::H256;
@@ -586,20 +585,10 @@ pub trait TestNetFactory: Sized {
-> (
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
Self::PeerData,
)
{
(client.as_block_import(), None, None, None, Default::default())
}
/// Get finality proof provider (if supported).
fn make_finality_proof_provider(
&self,
_client: PeersClient,
) -> Option<Arc<dyn FinalityProofProvider<Block>>> {
None
(client.as_block_import(), None, Default::default())
}
fn default_config() -> ProtocolConfig {
@@ -636,8 +625,6 @@ pub trait TestNetFactory: Sized {
let (
block_import,
justification_import,
finality_proof_import,
finality_proof_request_builder,
data,
) = self.make_block_import(PeersClient::Full(client.clone(), backend.clone()));
@@ -652,7 +639,6 @@ pub trait TestNetFactory: Sized {
verifier.clone(),
Box::new(block_import.clone()),
justification_import,
finality_proof_import,
&sp_core::testing::TaskExecutor::new(),
None,
));
@@ -675,10 +661,6 @@ pub trait TestNetFactory: Sized {
executor: None,
network_config,
chain: client.clone(),
finality_proof_provider: self.make_finality_proof_provider(
PeersClient::Full(client.clone(), backend.clone()),
),
finality_proof_request_builder,
on_demand: None,
transaction_pool: Arc::new(EmptyTransactionPool),
protocol_id: ProtocolId::from("test-protocol-name"),
@@ -717,8 +699,6 @@ pub trait TestNetFactory: Sized {
let (
block_import,
justification_import,
finality_proof_import,
finality_proof_request_builder,
data,
) = self.make_block_import(PeersClient::Light(client.clone(), backend.clone()));
@@ -733,7 +713,6 @@ pub trait TestNetFactory: Sized {
verifier.clone(),
Box::new(block_import.clone()),
justification_import,
finality_proof_import,
&sp_core::testing::TaskExecutor::new(),
None,
));
@@ -755,10 +734,6 @@ pub trait TestNetFactory: Sized {
executor: None,
network_config,
chain: client.clone(),
finality_proof_provider: self.make_finality_proof_provider(
PeersClient::Light(client.clone(), backend.clone())
),
finality_proof_request_builder,
on_demand: None,
transaction_pool: Arc::new(EmptyTransactionPool),
protocol_id: ProtocolId::from("test-protocol-name"),
@@ -989,16 +964,12 @@ impl TestNetFactory for JustificationTestNet {
-> (
BlockImportAdapter<Transaction>,
Option<BoxJustificationImport<Block>>,
Option<BoxFinalityProofImport<Block>>,
Option<BoxFinalityProofRequestBuilder<Block>>,
Self::PeerData,
)
{
(
client.as_block_import(),
Some(Box::new(ForceFinalized(client))),
None,
None,
Default::default(),
)
}
+2 -8
View File
@@ -41,7 +41,7 @@ use futures::{
};
use sc_keystore::LocalKeystore;
use log::{info, warn};
use sc_network::config::{Role, FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder};
use sc_network::config::{Role, OnDemand};
use sc_network::NetworkService;
use sp_runtime::generic::BlockId;
use sp_runtime::traits::{
@@ -830,10 +830,6 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> {
pub block_announce_validator_builder: Option<Box<
dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send
>>,
/// An optional finality proof request builder.
pub finality_proof_request_builder: Option<BoxFinalityProofRequestBuilder<TBl>>,
/// An optional, shared finality proof request provider.
pub finality_proof_provider: Option<Arc<dyn FinalityProofProvider<TBl>>>,
}
/// Build the network service, the network status sinks and an RPC sender.
@@ -858,7 +854,7 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
{
let BuildNetworkParams {
config, client, transaction_pool, spawn_handle, import_queue, on_demand,
block_announce_validator_builder, finality_proof_request_builder, finality_proof_provider,
block_announce_validator_builder,
} = params;
let transaction_pool_adapter = Arc::new(TransactionPoolAdapter {
@@ -896,8 +892,6 @@ pub fn build_network<TBl, TExPool, TImpQu, TCl>(
},
network_config: config.network.clone(),
chain: client.clone(),
finality_proof_provider,
finality_proof_request_builder,
on_demand: on_demand,
transaction_pool: transaction_pool_adapter as _,
import_queue: Box::new(import_queue),
+1 -1
View File
@@ -73,7 +73,7 @@ pub use sc_executor::NativeExecutionDispatch;
pub use std::{ops::Deref, result::Result, sync::Arc};
#[doc(hidden)]
pub use sc_network::config::{
FinalityProofProvider, OnDemand, BoxFinalityProofRequestBuilder, TransactionImport,
OnDemand, TransactionImport,
TransactionImportFuture,
};
pub use sc_tracing::TracingReceiver;
@@ -26,7 +26,7 @@ use std::sync::Arc;
use std::any::Any;
use crate::Error;
use crate::import_queue::{Verifier, CacheKeyId};
use crate::import_queue::CacheKeyId;
/// Block import result.
#[derive(Debug, PartialEq, Eq)]
@@ -54,8 +54,6 @@ pub struct ImportedAux {
pub needs_justification: bool,
/// Received a bad justification.
pub bad_justification: bool,
/// Request a finality proof for the given block.
pub needs_finality_proof: bool,
/// Whether the block that was imported is the new best block.
pub is_new_best: bool,
}
@@ -63,7 +61,7 @@ pub struct ImportedAux {
impl ImportResult {
/// Returns default value for `ImportResult::Imported` with
/// `clear_justification_requests`, `needs_justification`,
/// `bad_justification` and `needs_finality_proof` set to false.
/// `bad_justification` set to false.
pub fn imported(is_new_best: bool) -> ImportResult {
let mut aux = ImportedAux::default();
aux.is_new_best = is_new_best;
@@ -345,21 +343,3 @@ pub trait JustificationImport<B: BlockT> {
justification: Justification,
) -> Result<(), Self::Error>;
}
/// Finality proof import trait.
pub trait FinalityProofImport<B: BlockT> {
type Error: std::error::Error + Send + 'static;
/// Called by the import queue when it is started. Returns a list of finality proofs to request
/// from the network.
fn on_start(&mut self) -> Vec<(B::Hash, NumberFor<B>)> { Vec::new() }
/// Import a Block justification and finalize the given block. Returns finalized block or error.
fn import_finality_proof(
&mut self,
hash: B::Hash,
number: NumberFor<B>,
finality_proof: Vec<u8>,
verifier: &mut dyn Verifier<B>,
) -> Result<(B::Hash, NumberFor<B>), Self::Error>;
}
@@ -34,7 +34,7 @@ use crate::{
error::Error as ConsensusError,
block_import::{
BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult,
BlockCheckParams, FinalityProofImport,
BlockCheckParams,
},
metrics::Metrics,
};
@@ -56,11 +56,6 @@ pub type BoxBlockImport<B, Transaction> = Box<
/// Shared justification import struct used by the queue.
pub type BoxJustificationImport<B> = Box<dyn JustificationImport<B, Error=ConsensusError> + Send + Sync>;
/// Shared finality proof import struct used by the queue.
pub type BoxFinalityProofImport<B> = Box<
dyn FinalityProofImport<B, Error = ConsensusError> + Send + Sync
>;
/// Maps to the Origin used by the network.
pub type Origin = libp2p::PeerId;
@@ -115,15 +110,6 @@ pub trait ImportQueue<B: BlockT>: Send {
number: NumberFor<B>,
justification: Justification
);
/// Import block finality proof.
fn import_finality_proof(
&mut self,
who: Origin,
hash: B::Hash,
number: NumberFor<B>,
finality_proof: Vec<u8>
);
/// Polls for actions to perform on the network.
///
/// This method should behave in a way similar to `Future::poll`. It can register the current
@@ -146,19 +132,6 @@ pub trait Link<B: BlockT>: Send {
fn justification_imported(&mut self, _who: Origin, _hash: &B::Hash, _number: NumberFor<B>, _success: bool) {}
/// Request a justification for the given block.
fn request_justification(&mut self, _hash: &B::Hash, _number: NumberFor<B>) {}
/// Finality proof import result.
///
/// Even though we have asked for finality proof of block A, provider could return proof of
/// some earlier block B, if the proof for A was too large. The sync module should continue
/// asking for proof of A in this case.
fn finality_proof_imported(
&mut self,
_who: Origin,
_request_block: (B::Hash, NumberFor<B>),
_finalization_result: Result<(B::Hash, NumberFor<B>), ()>,
) {}
/// Request a finality proof for the given block.
fn request_finality_proof(&mut self, _hash: &B::Hash, _number: NumberFor<B>) {}
}
/// Block import successful result.
@@ -25,7 +25,7 @@ use prometheus_endpoint::Registry;
use crate::{
block_import::BlockOrigin,
import_queue::{
BlockImportResult, BlockImportError, Verifier, BoxBlockImport, BoxFinalityProofImport,
BlockImportResult, BlockImportError, Verifier, BoxBlockImport,
BoxJustificationImport, ImportQueue, Link, Origin,
IncomingBlock, import_single_block_metered,
buffered_link::{self, BufferedLinkSender, BufferedLinkReceiver},
@@ -36,8 +36,8 @@ use crate::{
/// Interface to a basic block import queue that is importing blocks sequentially in a separate
/// task, with plugable verification.
pub struct BasicQueue<B: BlockT, Transaction> {
/// Channel to send finality work messages to the background task.
finality_sender: TracingUnboundedSender<worker_messages::Finality<B>>,
/// Channel to send justifcation import messages to the background task.
justification_sender: TracingUnboundedSender<worker_messages::ImportJustification<B>>,
/// Channel to send block import messages to the background task.
block_import_sender: TracingUnboundedSender<worker_messages::ImportBlocks<B>>,
/// Results coming from the worker task.
@@ -48,7 +48,7 @@ pub struct BasicQueue<B: BlockT, Transaction> {
impl<B: BlockT, Transaction> Drop for BasicQueue<B, Transaction> {
fn drop(&mut self) {
// Flush the queue and close the receiver to terminate the future.
self.finality_sender.close_channel();
self.justification_sender.close_channel();
self.block_import_sender.close_channel();
self.result_port.close();
}
@@ -57,13 +57,11 @@ impl<B: BlockT, Transaction> Drop for BasicQueue<B, Transaction> {
impl<B: BlockT, Transaction: Send + 'static> BasicQueue<B, Transaction> {
/// Instantiate a new basic queue, with given verifier.
///
/// This creates a background task, and calls `on_start` on the justification importer and
/// finality proof importer.
/// This creates a background task, and calls `on_start` on the justification importer.
pub fn new<V: 'static + Verifier<B>>(
verifier: V,
block_import: BoxBlockImport<B, Transaction>,
justification_import: Option<BoxJustificationImport<B>>,
finality_proof_import: Option<BoxFinalityProofImport<B>>,
spawner: &impl sp_core::traits::SpawnNamed,
prometheus_registry: Option<&Registry>,
) -> Self {
@@ -77,19 +75,18 @@ impl<B: BlockT, Transaction: Send + 'static> BasicQueue<B, Transaction> {
.ok()
});
let (future, finality_sender, block_import_sender) = BlockImportWorker::new(
let (future, justification_sender, block_import_sender) = BlockImportWorker::new(
result_sender,
verifier,
block_import,
justification_import,
finality_proof_import,
metrics,
);
spawner.spawn_blocking("basic-block-import-worker", future.boxed());
Self {
finality_sender,
justification_sender,
block_import_sender,
result_port,
_phantom: PhantomData,
@@ -122,8 +119,8 @@ impl<B: BlockT, Transaction: Send> ImportQueue<B> for BasicQueue<B, Transaction>
number: NumberFor<B>,
justification: Justification,
) {
let res = self.finality_sender.unbounded_send(
worker_messages::Finality::ImportJustification(who, hash, number, justification),
let res = self.justification_sender.unbounded_send(
worker_messages::ImportJustification(who, hash, number, justification),
);
if res.is_err() {
@@ -134,26 +131,6 @@ impl<B: BlockT, Transaction: Send> ImportQueue<B> for BasicQueue<B, Transaction>
}
}
fn import_finality_proof(
&mut self,
who: Origin,
hash: B::Hash,
number: NumberFor<B>,
finality_proof: Vec<u8>,
) {
trace!(target: "sync", "Scheduling finality proof of {}/{} for import", number, hash);
let res = self.finality_sender.unbounded_send(
worker_messages::Finality::ImportFinalityProof(who, hash, number, finality_proof),
);
if res.is_err() {
log::error!(
target: "sync",
"import_finality_proof: Background import task is no longer alive"
);
}
}
fn poll_actions(&mut self, cx: &mut Context, link: &mut dyn Link<B>) {
if self.result_port.poll_actions(cx, link).is_err() {
log::error!(target: "sync", "poll_actions: Background import task is no longer alive");
@@ -166,17 +143,12 @@ mod worker_messages {
use super::*;
pub struct ImportBlocks<B: BlockT>(pub BlockOrigin, pub Vec<IncomingBlock<B>>);
pub enum Finality<B: BlockT> {
ImportJustification(Origin, B::Hash, NumberFor<B>, Justification),
ImportFinalityProof(Origin, B::Hash, NumberFor<B>, Vec<u8>),
}
pub struct ImportJustification<B: BlockT>(pub Origin, pub B::Hash, pub NumberFor<B>, pub Justification);
}
struct BlockImportWorker<B: BlockT, Transaction> {
result_sender: BufferedLinkSender<B>,
justification_import: Option<BoxJustificationImport<B>>,
finality_proof_import: Option<BoxFinalityProofImport<B>>,
delay_between_blocks: Duration,
metrics: Option<Metrics>,
_phantom: PhantomData<Transaction>,
@@ -188,17 +160,16 @@ impl<B: BlockT, Transaction: Send> BlockImportWorker<B, Transaction> {
verifier: V,
block_import: BoxBlockImport<B, Transaction>,
justification_import: Option<BoxJustificationImport<B>>,
finality_proof_import: Option<BoxFinalityProofImport<B>>,
metrics: Option<Metrics>,
) -> (
impl Future<Output = ()> + Send,
TracingUnboundedSender<worker_messages::Finality<B>>,
TracingUnboundedSender<worker_messages::ImportJustification<B>>,
TracingUnboundedSender<worker_messages::ImportBlocks<B>>,
) {
use worker_messages::*;
let (finality_sender, mut finality_port) =
tracing_unbounded("mpsc_import_queue_worker_finality");
let (justification_sender, mut justification_port) =
tracing_unbounded("mpsc_import_queue_worker_justification");
let (block_import_sender, mut block_import_port) =
tracing_unbounded("mpsc_import_queue_worker_blocks");
@@ -206,23 +177,17 @@ impl<B: BlockT, Transaction: Send> BlockImportWorker<B, Transaction> {
let mut worker = BlockImportWorker {
result_sender,
justification_import,
finality_proof_import,
delay_between_blocks: Duration::new(0, 0),
metrics,
_phantom: PhantomData,
};
// Let's initialize `justification_import` and `finality_proof_import`.
// Let's initialize `justification_import`
if let Some(justification_import) = worker.justification_import.as_mut() {
for (hash, number) in justification_import.on_start() {
worker.result_sender.request_justification(&hash, number);
}
}
if let Some(finality_proof_import) = worker.finality_proof_import.as_mut() {
for (hash, number) in finality_proof_import.on_start() {
worker.result_sender.request_finality_proof(&hash, number);
}
}
// The future below has two possible states:
//
@@ -230,7 +195,7 @@ impl<B: BlockT, Transaction: Send> BlockImportWorker<B, Transaction> {
// `Future`, and `block_import` is `None`.
// - Something else, in which case `block_import` is `Some` and `importing` is None.
//
// Additionally, the task will prioritize processing of finality work messages over
// Additionally, the task will prioritize processing of justification import messages over
// block import messages, hence why two distinct channels are used.
let mut block_import_verifier = Some((block_import, verifier));
let mut importing = None;
@@ -243,28 +208,15 @@ impl<B: BlockT, Transaction: Send> BlockImportWorker<B, Transaction> {
return Poll::Ready(())
}
// Grab the next finality action request sent to the import queue.
let finality_work = match Stream::poll_next(Pin::new(&mut finality_port), cx) {
Poll::Ready(Some(msg)) => Some(msg),
Poll::Ready(None) => return Poll::Ready(()),
Poll::Pending => None,
};
match finality_work {
Some(Finality::ImportFinalityProof(who, hash, number, proof)) => {
let (_, verif) = block_import_verifier
.as_mut()
.expect("block_import_verifier is always Some; qed");
worker.import_finality_proof(verif, who, hash, number, proof);
continue;
}
Some(Finality::ImportJustification(who, hash, number, justification)) => {
// Grab the next justification import request sent to the import queue.
match Stream::poll_next(Pin::new(&mut justification_port), cx) {
Poll::Ready(Some(ImportJustification(who, hash, number, justification))) => {
worker.import_justification(who, hash, number, justification);
continue;
}
None => {}
}
},
Poll::Ready(None) => return Poll::Ready(()),
Poll::Pending => {},
};
// If we are in the process of importing a bunch of blocks, let's resume this
// process before doing anything more.
@@ -299,7 +251,7 @@ impl<B: BlockT, Transaction: Send> BlockImportWorker<B, Transaction> {
}
});
(future, finality_sender, block_import_sender)
(future, justification_sender, block_import_sender)
}
/// Returns a `Future` that imports the given blocks and sends the results on
@@ -324,36 +276,6 @@ impl<B: BlockT, Transaction: Send> BlockImportWorker<B, Transaction> {
})
}
fn import_finality_proof<V: 'static + Verifier<B>>(
&mut self,
verifier: &mut V,
who: Origin,
hash: B::Hash,
number: NumberFor<B>,
finality_proof: Vec<u8>
) {
let started = wasm_timer::Instant::now();
let result = self.finality_proof_import.as_mut().map(|finality_proof_import| {
finality_proof_import.import_finality_proof(hash, number, finality_proof, verifier)
.map_err(|e| {
debug!(
"Finality proof import failed with {:?} for hash: {:?} number: {:?} coming from node: {:?}",
e,
hash,
number,
who,
);
})
}).unwrap_or(Err(()));
if let Some(metrics) = self.metrics.as_ref() {
metrics.finality_proof_import_time.observe(started.elapsed().as_secs_f64());
}
trace!(target: "sync", "Imported finality proof for {}/{}", number, hash);
self.result_sender.finality_proof_imported(who, (hash, number), result);
}
fn import_justification(
&mut self,
who: Origin,
@@ -596,7 +518,7 @@ mod tests {
let (result_sender, mut result_port) = buffered_link::buffered_link();
let (mut worker, mut finality_sender, mut block_import_sender) =
BlockImportWorker::new(result_sender, (), Box::new(()), Some(Box::new(())), None, None);
BlockImportWorker::new(result_sender, (), Box::new(()), Some(Box::new(())), None);
let mut import_block = |n| {
let header = Header {
@@ -629,7 +551,7 @@ mod tests {
let mut import_justification = || {
let hash = Hash::random();
block_on(finality_sender.send(worker_messages::Finality::ImportJustification(
block_on(finality_sender.send(worker_messages::ImportJustification(
libp2p::PeerId::random(),
hash,
1,
@@ -81,8 +81,6 @@ enum BlockImportWorkerMsg<B: BlockT> {
BlocksProcessed(usize, usize, Vec<(Result<BlockImportResult<NumberFor<B>>, BlockImportError>, B::Hash)>),
JustificationImported(Origin, B::Hash, NumberFor<B>, bool),
RequestJustification(B::Hash, NumberFor<B>),
FinalityProofImported(Origin, (B::Hash, NumberFor<B>), Result<(B::Hash, NumberFor<B>), ()>),
RequestFinalityProof(B::Hash, NumberFor<B>),
}
impl<B: BlockT> Link<B> for BufferedLinkSender<B> {
@@ -109,20 +107,6 @@ impl<B: BlockT> Link<B> for BufferedLinkSender<B> {
fn request_justification(&mut self, hash: &B::Hash, number: NumberFor<B>) {
let _ = self.tx.unbounded_send(BlockImportWorkerMsg::RequestJustification(hash.clone(), number));
}
fn finality_proof_imported(
&mut self,
who: Origin,
request_block: (B::Hash, NumberFor<B>),
finalization_result: Result<(B::Hash, NumberFor<B>), ()>,
) {
let msg = BlockImportWorkerMsg::FinalityProofImported(who, request_block, finalization_result);
let _ = self.tx.unbounded_send(msg);
}
fn request_finality_proof(&mut self, hash: &B::Hash, number: NumberFor<B>) {
let _ = self.tx.unbounded_send(BlockImportWorkerMsg::RequestFinalityProof(hash.clone(), number));
}
}
/// See [`buffered_link`].
@@ -154,10 +138,6 @@ impl<B: BlockT> BufferedLinkReceiver<B> {
link.justification_imported(who, &hash, number, success),
BlockImportWorkerMsg::RequestJustification(hash, number) =>
link.request_justification(&hash, number),
BlockImportWorkerMsg::FinalityProofImported(who, block, result) =>
link.finality_proof_imported(who, block, result),
BlockImportWorkerMsg::RequestFinalityProof(hash, number) =>
link.request_finality_proof(&hash, number),
}
}
}
@@ -49,7 +49,7 @@ mod metrics;
pub use self::error::Error;
pub use block_import::{
BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams,
ImportResult, JustificationImport, FinalityProofImport,
ImportResult, JustificationImport,
};
pub use select_chain::SelectChain;
pub use sp_state_machine::Backend as StateBackend;
@@ -30,7 +30,6 @@ pub(crate) struct Metrics {
pub import_queue_processed: CounterVec<U64>,
pub block_verification_time: HistogramVec,
pub block_verification_and_import_time: Histogram,
pub finality_proof_import_time: Histogram,
pub justification_import_time: Histogram,
}
@@ -63,15 +62,6 @@ impl Metrics {
)?,
registry,
)?,
finality_proof_import_time: register(
Histogram::with_opts(
HistogramOpts::new(
"finality_proof_import_time",
"Time taken to import finality proofs",
),
)?,
registry,
)?,
justification_import_time: register(
Histogram::with_opts(
HistogramOpts::new(