mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-19 22:45:40 +00:00
grandpa: support for hard forking any pending standard changes (#5306)
* grandpa: support for hard forking any pending standard changes * grandpa: expose authority_set_hard_forks in block import constructor * grandpa: don't break the public api
This commit is contained in:
@@ -30,7 +30,7 @@ use sp_consensus::{
|
|||||||
BlockCheckParams, BlockImportParams, ImportResult, JustificationImport,
|
BlockCheckParams, BlockImportParams, ImportResult, JustificationImport,
|
||||||
SelectChain,
|
SelectChain,
|
||||||
};
|
};
|
||||||
use sp_finality_grandpa::{GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog};
|
use sp_finality_grandpa::{ConsensusLog, ScheduledChange, SetId, GRANDPA_ENGINE_ID};
|
||||||
use sp_runtime::Justification;
|
use sp_runtime::Justification;
|
||||||
use sp_runtime::generic::{BlockId, OpaqueDigestItemId};
|
use sp_runtime::generic::{BlockId, OpaqueDigestItemId};
|
||||||
use sp_runtime::traits::{
|
use sp_runtime::traits::{
|
||||||
@@ -59,6 +59,7 @@ pub struct GrandpaBlockImport<Backend, Block: BlockT, Client, SC> {
|
|||||||
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
||||||
send_voter_commands: mpsc::UnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
|
send_voter_commands: mpsc::UnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
|
||||||
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
|
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
|
||||||
|
authority_set_hard_forks: HashMap<Block::Hash, PendingChange<Block::Hash, NumberFor<Block>>>,
|
||||||
_phantom: PhantomData<Backend>,
|
_phantom: PhantomData<Backend>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ impl<Backend, Block: BlockT, Client, SC: Clone> Clone for
|
|||||||
authority_set: self.authority_set.clone(),
|
authority_set: self.authority_set.clone(),
|
||||||
send_voter_commands: self.send_voter_commands.clone(),
|
send_voter_commands: self.send_voter_commands.clone(),
|
||||||
consensus_changes: self.consensus_changes.clone(),
|
consensus_changes: self.consensus_changes.clone(),
|
||||||
|
authority_set_hard_forks: self.authority_set_hard_forks.clone(),
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,9 +214,16 @@ where
|
|||||||
Client: crate::ClientForGrandpa<Block, BE>,
|
Client: crate::ClientForGrandpa<Block, BE>,
|
||||||
{
|
{
|
||||||
// check for a new authority set change.
|
// check for a new authority set change.
|
||||||
fn check_new_change(&self, header: &Block::Header, hash: Block::Hash)
|
fn check_new_change(
|
||||||
-> Option<PendingChange<Block::Hash, NumberFor<Block>>>
|
&self,
|
||||||
{
|
header: &Block::Header,
|
||||||
|
hash: Block::Hash,
|
||||||
|
) -> Option<PendingChange<Block::Hash, NumberFor<Block>>> {
|
||||||
|
// check for forced authority set hard forks
|
||||||
|
if let Some(change) = self.authority_set_hard_forks.get(&hash) {
|
||||||
|
return Some(change.clone());
|
||||||
|
}
|
||||||
|
|
||||||
// check for forced change.
|
// check for forced change.
|
||||||
if let Some((median_last_finalized, change)) = find_forced_change::<Block>(header) {
|
if let Some((median_last_finalized, change)) = find_forced_change::<Block>(header) {
|
||||||
return Some(PendingChange {
|
return Some(PendingChange {
|
||||||
@@ -529,13 +538,50 @@ impl<Backend, Block: BlockT, Client, SC> GrandpaBlockImport<Backend, Block, Clie
|
|||||||
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
||||||
send_voter_commands: mpsc::UnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
|
send_voter_commands: mpsc::UnboundedSender<VoterCommand<Block::Hash, NumberFor<Block>>>,
|
||||||
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
|
consensus_changes: SharedConsensusChanges<Block::Hash, NumberFor<Block>>,
|
||||||
|
authority_set_hard_forks: Vec<(SetId, PendingChange<Block::Hash, NumberFor<Block>>)>,
|
||||||
) -> GrandpaBlockImport<Backend, Block, Client, SC> {
|
) -> GrandpaBlockImport<Backend, Block, Client, SC> {
|
||||||
|
// check for and apply any forced authority set hard fork that applies
|
||||||
|
// to the *current* authority set.
|
||||||
|
if let Some((_, change)) = authority_set_hard_forks
|
||||||
|
.iter()
|
||||||
|
.find(|(set_id, _)| *set_id == authority_set.set_id())
|
||||||
|
{
|
||||||
|
let mut authority_set = authority_set.inner().write();
|
||||||
|
authority_set.current_authorities = change.next_authorities.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// index authority set hard forks by block hash so that they can be used
|
||||||
|
// by any node syncing the chain and importing a block hard fork
|
||||||
|
// authority set changes.
|
||||||
|
let authority_set_hard_forks = authority_set_hard_forks
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, change)| (change.canon_hash, change))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
// check for and apply any forced authority set hard fork that apply to
|
||||||
|
// any *pending* standard changes, checking by the block hash at which
|
||||||
|
// they were announced.
|
||||||
|
{
|
||||||
|
let mut authority_set = authority_set.inner().write();
|
||||||
|
|
||||||
|
authority_set.pending_standard_changes = authority_set
|
||||||
|
.pending_standard_changes
|
||||||
|
.clone()
|
||||||
|
.map(&mut |hash, _, original| {
|
||||||
|
authority_set_hard_forks
|
||||||
|
.get(&hash)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(original)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
GrandpaBlockImport {
|
GrandpaBlockImport {
|
||||||
inner,
|
inner,
|
||||||
select_chain,
|
select_chain,
|
||||||
authority_set,
|
authority_set,
|
||||||
send_voter_commands,
|
send_voter_commands,
|
||||||
consensus_changes,
|
consensus_changes,
|
||||||
|
authority_set_hard_forks,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -417,10 +417,43 @@ pub fn block_import<BE, Block: BlockT, Client, SC>(
|
|||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
|
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
|
||||||
select_chain: SC,
|
select_chain: SC,
|
||||||
) -> Result<(
|
) -> Result<
|
||||||
|
(
|
||||||
GrandpaBlockImport<BE, Block, Client, SC>,
|
GrandpaBlockImport<BE, Block, Client, SC>,
|
||||||
LinkHalf<Block, Client, SC>,
|
LinkHalf<Block, Client, SC>,
|
||||||
), ClientError>
|
),
|
||||||
|
ClientError,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
SC: SelectChain<Block>,
|
||||||
|
BE: Backend<Block> + 'static,
|
||||||
|
Client: ClientForGrandpa<Block, BE> + 'static,
|
||||||
|
{
|
||||||
|
block_import_with_authority_set_hard_forks(
|
||||||
|
client,
|
||||||
|
genesis_authorities_provider,
|
||||||
|
select_chain,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make block importer and link half necessary to tie the background voter to
|
||||||
|
/// it. A vector of authority set hard forks can be passed, any authority set
|
||||||
|
/// change signaled at the given block (either already signalled or in a further
|
||||||
|
/// block when importing it) will be replaced by a standard change with the
|
||||||
|
/// given static authorities.
|
||||||
|
pub fn block_import_with_authority_set_hard_forks<BE, Block: BlockT, Client, SC>(
|
||||||
|
client: Arc<Client>,
|
||||||
|
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
|
||||||
|
select_chain: SC,
|
||||||
|
authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor<Block>), AuthorityList)>,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
GrandpaBlockImport<BE, Block, Client, SC>,
|
||||||
|
LinkHalf<Block, Client, SC>,
|
||||||
|
),
|
||||||
|
ClientError,
|
||||||
|
>
|
||||||
where
|
where
|
||||||
SC: SelectChain<Block>,
|
SC: SelectChain<Block>,
|
||||||
BE: Backend<Block> + 'static,
|
BE: Backend<Block> + 'static,
|
||||||
@@ -444,6 +477,24 @@ where
|
|||||||
|
|
||||||
let (voter_commands_tx, voter_commands_rx) = mpsc::unbounded();
|
let (voter_commands_tx, voter_commands_rx) = mpsc::unbounded();
|
||||||
|
|
||||||
|
// create pending change objects with 0 delay and enacted on finality
|
||||||
|
// (i.e. standard changes) for each authority set hard fork.
|
||||||
|
let authority_set_hard_forks = authority_set_hard_forks
|
||||||
|
.into_iter()
|
||||||
|
.map(|(set_id, (hash, number), authorities)| {
|
||||||
|
(
|
||||||
|
set_id,
|
||||||
|
authorities::PendingChange {
|
||||||
|
next_authorities: authorities,
|
||||||
|
delay: Zero::zero(),
|
||||||
|
canon_hash: hash,
|
||||||
|
canon_height: number,
|
||||||
|
delay_kind: authorities::DelayKind::Finalized,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
GrandpaBlockImport::new(
|
GrandpaBlockImport::new(
|
||||||
client.clone(),
|
client.clone(),
|
||||||
@@ -451,6 +502,7 @@ where
|
|||||||
persistent_data.authority_set.clone(),
|
persistent_data.authority_set.clone(),
|
||||||
voter_commands_tx,
|
voter_commands_tx,
|
||||||
persistent_data.consensus_changes.clone(),
|
persistent_data.consensus_changes.clone(),
|
||||||
|
authority_set_hard_forks,
|
||||||
),
|
),
|
||||||
LinkHalf {
|
LinkHalf {
|
||||||
client,
|
client,
|
||||||
|
|||||||
Reference in New Issue
Block a user