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