mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 10:31:03 +00:00
grandpa: update to finality-grandpa v0.12.0 (#5853)
* grandpa: update to v0.12.0 * grandpa: fix tests * grandpa: better validation of authority set invariants * grandpa: avoid duplicating invalid authority list check * grandpa: add missing doc * grandpa: better validation of expect proofs * grandpa: fix test compilation * grandpa: fix tests * grandpa: add test for AuthoritySet invariants * grandpa: bump finality-grandpa to v0.12.0
This commit is contained in:
Generated
+4
-2
@@ -1346,10 +1346,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "finality-grandpa"
|
name = "finality-grandpa"
|
||||||
version = "0.11.2"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "024517816630be5204eba201e8d1d405042b1255a5e0e3f298b054fc24d59e1d"
|
checksum = "9d7907cc24468e29b5d3ea2097e78104492b6650c55f96af1f14e7915dc155ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"either",
|
||||||
"futures 0.3.4",
|
"futures 0.3.4",
|
||||||
"futures-timer 2.0.2",
|
"futures-timer 2.0.2",
|
||||||
"log",
|
"log",
|
||||||
@@ -6344,6 +6345,7 @@ name = "sc-finality-grandpa"
|
|||||||
version = "0.8.0-dev"
|
version = "0.8.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_matches",
|
"assert_matches",
|
||||||
|
"derive_more",
|
||||||
"env_logger 0.7.1",
|
"env_logger 0.7.1",
|
||||||
"finality-grandpa",
|
"finality-grandpa",
|
||||||
"fork-tree",
|
"fork-tree",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
|
|||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
derive_more = "0.99.2"
|
||||||
fork-tree = { version = "2.0.0-dev", path = "../../utils/fork-tree" }
|
fork-tree = { version = "2.0.0-dev", path = "../../utils/fork-tree" }
|
||||||
futures = "0.3.4"
|
futures = "0.3.4"
|
||||||
futures-timer = "3.0.1"
|
futures-timer = "3.0.1"
|
||||||
@@ -41,11 +42,11 @@ sp-finality-tracker = { version = "2.0.0-dev", path = "../../primitives/finality
|
|||||||
sp-finality-grandpa = { version = "2.0.0-dev", path = "../../primitives/finality-grandpa" }
|
sp-finality-grandpa = { version = "2.0.0-dev", path = "../../primitives/finality-grandpa" }
|
||||||
prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-dev"}
|
prometheus-endpoint = { package = "substrate-prometheus-endpoint", path = "../../utils/prometheus", version = "0.8.0-dev"}
|
||||||
sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" }
|
sc-block-builder = { version = "0.8.0-dev", path = "../block-builder" }
|
||||||
finality-grandpa = { version = "0.11.2", features = ["derive-codec"] }
|
finality-grandpa = { version = "0.12.0", features = ["derive-codec"] }
|
||||||
pin-project = "0.4.6"
|
pin-project = "0.4.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
finality-grandpa = { version = "0.11.2", features = ["derive-codec", "test-helpers"] }
|
finality-grandpa = { version = "0.12.0", features = ["derive-codec", "test-helpers"] }
|
||||||
sc-network = { version = "0.8.0-dev", path = "../network" }
|
sc-network = { version = "0.8.0-dev", path = "../network" }
|
||||||
sc-network-test = { version = "0.8.0-dev", path = "../network/test" }
|
sc-network-test = { version = "0.8.0-dev", path = "../network/test" }
|
||||||
sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" }
|
sp-keyring = { version = "2.0.0-dev", path = "../../primitives/keyring" }
|
||||||
|
|||||||
@@ -29,6 +29,15 @@ use std::fmt::Debug;
|
|||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Error type returned on operations on the `AuthoritySet`.
|
||||||
|
#[derive(Debug, derive_more::Display, derive_more::From)]
|
||||||
|
pub enum Error<E> {
|
||||||
|
#[display("Invalid authority set, either empty or with an authority weight set to 0.")]
|
||||||
|
InvalidAuthoritySet,
|
||||||
|
#[display(fmt = "Invalid operation in the pending changes tree: {}", _0)]
|
||||||
|
ForkTree(fork_tree::Error<E>),
|
||||||
|
}
|
||||||
|
|
||||||
/// A shared authority set.
|
/// A shared authority set.
|
||||||
pub(crate) struct SharedAuthoritySet<H, N> {
|
pub(crate) struct SharedAuthoritySet<H, N> {
|
||||||
inner: Arc<RwLock<AuthoritySet<H, N>>>,
|
inner: Arc<RwLock<AuthoritySet<H, N>>>,
|
||||||
@@ -64,7 +73,11 @@ where N: Add<Output=N> + Ord + Clone + Debug,
|
|||||||
|
|
||||||
/// Get the current authorities and their weights (for the current set ID).
|
/// Get the current authorities and their weights (for the current set ID).
|
||||||
pub(crate) fn current_authorities(&self) -> VoterSet<AuthorityId> {
|
pub(crate) fn current_authorities(&self) -> VoterSet<AuthorityId> {
|
||||||
self.inner.read().current_authorities.iter().cloned().collect()
|
VoterSet::new(self.inner.read().current_authorities.iter().cloned()).expect(
|
||||||
|
"current_authorities is non-empty and weights are non-zero; \
|
||||||
|
constructor and all mutating operations on `AuthoritySet` ensure this; \
|
||||||
|
qed.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +101,7 @@ pub(crate) struct Status<H, N> {
|
|||||||
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
|
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
|
||||||
pub(crate) struct AuthoritySet<H, N> {
|
pub(crate) struct AuthoritySet<H, N> {
|
||||||
pub(crate) current_authorities: AuthorityList,
|
pub(crate) current_authorities: AuthorityList,
|
||||||
pub(crate) set_id: u64,
|
set_id: u64,
|
||||||
// Tree of pending standard changes across forks. Standard changes are
|
// Tree of pending standard changes across forks. Standard changes are
|
||||||
// enacted on finality and must be enacted (i.e. finalized) in-order across
|
// enacted on finality and must be enacted (i.e. finalized) in-order across
|
||||||
// a given branch
|
// a given branch
|
||||||
@@ -96,21 +109,49 @@ pub(crate) struct AuthoritySet<H, N> {
|
|||||||
// Pending forced changes across different forks (at most one per fork).
|
// Pending forced changes across different forks (at most one per fork).
|
||||||
// Forced changes are enacted on block depth (not finality), for this reason
|
// Forced changes are enacted on block depth (not finality), for this reason
|
||||||
// only one forced change should exist per fork.
|
// only one forced change should exist per fork.
|
||||||
pub(crate) pending_forced_changes: Vec<PendingChange<H, N>>,
|
pending_forced_changes: Vec<PendingChange<H, N>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, N> AuthoritySet<H, N>
|
impl<H, N> AuthoritySet<H, N>
|
||||||
where H: PartialEq,
|
where H: PartialEq,
|
||||||
N: Ord,
|
N: Ord,
|
||||||
{
|
{
|
||||||
|
// authority sets must be non-empty and all weights must be greater than 0
|
||||||
|
fn invalid_authority_list(authorities: &AuthorityList) -> bool {
|
||||||
|
authorities.is_empty() || authorities.iter().any(|(_, w)| *w == 0)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a genesis set with given authorities.
|
/// Get a genesis set with given authorities.
|
||||||
pub(crate) fn genesis(initial: AuthorityList) -> Self {
|
pub(crate) fn genesis(initial: AuthorityList) -> Option<Self> {
|
||||||
AuthoritySet {
|
if Self::invalid_authority_list(&initial) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(AuthoritySet {
|
||||||
current_authorities: initial,
|
current_authorities: initial,
|
||||||
set_id: 0,
|
set_id: 0,
|
||||||
pending_standard_changes: ForkTree::new(),
|
pending_standard_changes: ForkTree::new(),
|
||||||
pending_forced_changes: Vec::new(),
|
pending_forced_changes: Vec::new(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new authority set.
|
||||||
|
pub(crate) fn new(
|
||||||
|
authorities: AuthorityList,
|
||||||
|
set_id: u64,
|
||||||
|
pending_standard_changes: ForkTree<H, N, PendingChange<H, N>>,
|
||||||
|
pending_forced_changes: Vec<PendingChange<H, N>>,
|
||||||
|
) -> Option<Self> {
|
||||||
|
if Self::invalid_authority_list(&authorities) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(AuthoritySet {
|
||||||
|
current_authorities: authorities,
|
||||||
|
set_id,
|
||||||
|
pending_standard_changes,
|
||||||
|
pending_forced_changes,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current set id and a reference to the current authority set.
|
/// Get the current set id and a reference to the current authority set.
|
||||||
@@ -128,7 +169,7 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
pending: PendingChange<H, N>,
|
pending: PendingChange<H, N>,
|
||||||
is_descendent_of: &F,
|
is_descendent_of: &F,
|
||||||
) -> Result<(), fork_tree::Error<E>> where
|
) -> Result<(), Error<E>> where
|
||||||
F: Fn(&H, &H) -> Result<bool, E>,
|
F: Fn(&H, &H) -> Result<bool, E>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
{
|
{
|
||||||
@@ -159,15 +200,16 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
pending: PendingChange<H, N>,
|
pending: PendingChange<H, N>,
|
||||||
is_descendent_of: &F,
|
is_descendent_of: &F,
|
||||||
) -> Result<(), fork_tree::Error<E>> where
|
) -> Result<(), Error<E>> where
|
||||||
F: Fn(&H, &H) -> Result<bool, E>,
|
F: Fn(&H, &H) -> Result<bool, E>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
{
|
{
|
||||||
for change in self.pending_forced_changes.iter() {
|
for change in self.pending_forced_changes.iter() {
|
||||||
if change.canon_hash == pending.canon_hash ||
|
if change.canon_hash == pending.canon_hash ||
|
||||||
is_descendent_of(&change.canon_hash, &pending.canon_hash)?
|
is_descendent_of(&change.canon_hash, &pending.canon_hash)
|
||||||
|
.map_err(fork_tree::Error::Client)?
|
||||||
{
|
{
|
||||||
return Err(fork_tree::Error::UnfinalizedAncestor);
|
return Err(fork_tree::Error::UnfinalizedAncestor.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,10 +243,14 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
pending: PendingChange<H, N>,
|
pending: PendingChange<H, N>,
|
||||||
is_descendent_of: &F,
|
is_descendent_of: &F,
|
||||||
) -> Result<(), fork_tree::Error<E>> where
|
) -> Result<(), Error<E>> where
|
||||||
F: Fn(&H, &H) -> Result<bool, E>,
|
F: Fn(&H, &H) -> Result<bool, E>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
{
|
{
|
||||||
|
if Self::invalid_authority_list(&pending.next_authorities) {
|
||||||
|
return Err(Error::InvalidAuthoritySet);
|
||||||
|
}
|
||||||
|
|
||||||
match pending.delay_kind {
|
match pending.delay_kind {
|
||||||
DelayKind::Best { .. } => {
|
DelayKind::Best { .. } => {
|
||||||
self.add_forced_change(pending, is_descendent_of)
|
self.add_forced_change(pending, is_descendent_of)
|
||||||
@@ -309,8 +355,8 @@ where
|
|||||||
finalized_number: N,
|
finalized_number: N,
|
||||||
is_descendent_of: &F,
|
is_descendent_of: &F,
|
||||||
initial_sync: bool,
|
initial_sync: bool,
|
||||||
) -> Result<Status<H, N>, fork_tree::Error<E>>
|
) -> Result<Status<H, N>, Error<E>> where
|
||||||
where F: Fn(&H, &H) -> Result<bool, E>,
|
F: Fn(&H, &H) -> Result<bool, E>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
{
|
{
|
||||||
let mut status = Status {
|
let mut status = Status {
|
||||||
@@ -370,8 +416,8 @@ where
|
|||||||
finalized_hash: H,
|
finalized_hash: H,
|
||||||
finalized_number: N,
|
finalized_number: N,
|
||||||
is_descendent_of: &F,
|
is_descendent_of: &F,
|
||||||
) -> Result<Option<bool>, fork_tree::Error<E>>
|
) -> Result<Option<bool>, Error<E>> where
|
||||||
where F: Fn(&H, &H) -> Result<bool, E>,
|
F: Fn(&H, &H) -> Result<bool, E>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
{
|
{
|
||||||
self.pending_standard_changes.finalizes_any_with_descendent_if(
|
self.pending_standard_changes.finalizes_any_with_descendent_if(
|
||||||
@@ -379,7 +425,7 @@ where
|
|||||||
finalized_number.clone(),
|
finalized_number.clone(),
|
||||||
is_descendent_of,
|
is_descendent_of,
|
||||||
|change| change.effective_number() == finalized_number
|
|change| change.effective_number() == finalized_number
|
||||||
)
|
).map_err(Error::ForkTree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,8 +503,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn current_limit_filters_min() {
|
fn current_limit_filters_min() {
|
||||||
|
let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)];
|
||||||
|
|
||||||
let mut authorities = AuthoritySet {
|
let mut authorities = AuthoritySet {
|
||||||
current_authorities: Vec::new(),
|
current_authorities: current_authorities.clone(),
|
||||||
set_id: 0,
|
set_id: 0,
|
||||||
pending_standard_changes: ForkTree::new(),
|
pending_standard_changes: ForkTree::new(),
|
||||||
pending_forced_changes: Vec::new(),
|
pending_forced_changes: Vec::new(),
|
||||||
@@ -466,7 +514,7 @@ mod tests {
|
|||||||
|
|
||||||
let change = |height| {
|
let change = |height| {
|
||||||
PendingChange {
|
PendingChange {
|
||||||
next_authorities: Vec::new(),
|
next_authorities: current_authorities.clone(),
|
||||||
delay: 0,
|
delay: 0,
|
||||||
canon_height: height,
|
canon_height: height,
|
||||||
canon_hash: height.to_string(),
|
canon_hash: height.to_string(),
|
||||||
@@ -502,15 +550,17 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn changes_iterated_in_pre_order() {
|
fn changes_iterated_in_pre_order() {
|
||||||
|
let current_authorities = vec![(AuthorityId::from_slice(&[1; 32]), 1)];
|
||||||
|
|
||||||
let mut authorities = AuthoritySet {
|
let mut authorities = AuthoritySet {
|
||||||
current_authorities: Vec::new(),
|
current_authorities: current_authorities.clone(),
|
||||||
set_id: 0,
|
set_id: 0,
|
||||||
pending_standard_changes: ForkTree::new(),
|
pending_standard_changes: ForkTree::new(),
|
||||||
pending_forced_changes: Vec::new(),
|
pending_forced_changes: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let change_a = PendingChange {
|
let change_a = PendingChange {
|
||||||
next_authorities: Vec::new(),
|
next_authorities: current_authorities.clone(),
|
||||||
delay: 10,
|
delay: 10,
|
||||||
canon_height: 5,
|
canon_height: 5,
|
||||||
canon_hash: "hash_a",
|
canon_hash: "hash_a",
|
||||||
@@ -518,7 +568,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let change_b = PendingChange {
|
let change_b = PendingChange {
|
||||||
next_authorities: Vec::new(),
|
next_authorities: current_authorities.clone(),
|
||||||
delay: 0,
|
delay: 0,
|
||||||
canon_height: 5,
|
canon_height: 5,
|
||||||
canon_hash: "hash_b",
|
canon_hash: "hash_b",
|
||||||
@@ -526,7 +576,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let change_c = PendingChange {
|
let change_c = PendingChange {
|
||||||
next_authorities: Vec::new(),
|
next_authorities: current_authorities.clone(),
|
||||||
delay: 5,
|
delay: 5,
|
||||||
canon_height: 10,
|
canon_height: 10,
|
||||||
canon_hash: "hash_c",
|
canon_hash: "hash_c",
|
||||||
@@ -543,7 +593,7 @@ mod tests {
|
|||||||
|
|
||||||
// forced changes are iterated last
|
// forced changes are iterated last
|
||||||
let change_d = PendingChange {
|
let change_d = PendingChange {
|
||||||
next_authorities: Vec::new(),
|
next_authorities: current_authorities.clone(),
|
||||||
delay: 2,
|
delay: 2,
|
||||||
canon_height: 1,
|
canon_height: 1,
|
||||||
canon_hash: "hash_d",
|
canon_hash: "hash_d",
|
||||||
@@ -551,7 +601,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let change_e = PendingChange {
|
let change_e = PendingChange {
|
||||||
next_authorities: Vec::new(),
|
next_authorities: current_authorities.clone(),
|
||||||
delay: 2,
|
delay: 2,
|
||||||
canon_height: 0,
|
canon_height: 0,
|
||||||
canon_hash: "hash_e",
|
canon_hash: "hash_e",
|
||||||
@@ -689,7 +739,7 @@ mod tests {
|
|||||||
// trying to finalize past `change_c` without finalizing `change_a` first
|
// trying to finalize past `change_c` without finalizing `change_a` first
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
authorities.apply_standard_changes("hash_d", 40, &is_descendent_of, false),
|
authorities.apply_standard_changes("hash_d", 40, &is_descendent_of, false),
|
||||||
Err(fork_tree::Error::UnfinalizedAncestor)
|
Err(Error::ForkTree(fork_tree::Error::UnfinalizedAncestor))
|
||||||
));
|
));
|
||||||
|
|
||||||
let status = authorities.apply_standard_changes(
|
let status = authorities.apply_standard_changes(
|
||||||
@@ -871,4 +921,74 @@ mod tests {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn maintains_authority_list_invariants() {
|
||||||
|
// empty authority lists are invalid
|
||||||
|
assert_eq!(AuthoritySet::<(), ()>::genesis(vec![]), None);
|
||||||
|
assert_eq!(
|
||||||
|
AuthoritySet::<(), ()>::new(vec![], 0, ForkTree::new(), Vec::new()),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let invalid_authorities_weight = vec![
|
||||||
|
(AuthorityId::from_slice(&[1; 32]), 5),
|
||||||
|
(AuthorityId::from_slice(&[2; 32]), 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
// authority weight of zero is invalid
|
||||||
|
assert_eq!(
|
||||||
|
AuthoritySet::<(), ()>::genesis(invalid_authorities_weight.clone()),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
AuthoritySet::<(), ()>::new(
|
||||||
|
invalid_authorities_weight.clone(),
|
||||||
|
0,
|
||||||
|
ForkTree::new(),
|
||||||
|
Vec::new()
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut authority_set =
|
||||||
|
AuthoritySet::<(), u64>::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 5)]).unwrap();
|
||||||
|
|
||||||
|
let invalid_change_empty_authorities = PendingChange {
|
||||||
|
next_authorities: vec![],
|
||||||
|
delay: 10,
|
||||||
|
canon_height: 5,
|
||||||
|
canon_hash: (),
|
||||||
|
delay_kind: DelayKind::Finalized,
|
||||||
|
};
|
||||||
|
|
||||||
|
// pending change contains an empty authority set
|
||||||
|
assert!(matches!(
|
||||||
|
authority_set.add_pending_change(
|
||||||
|
invalid_change_empty_authorities.clone(),
|
||||||
|
&static_is_descendent_of(false)
|
||||||
|
),
|
||||||
|
Err(Error::InvalidAuthoritySet)
|
||||||
|
));
|
||||||
|
|
||||||
|
let invalid_change_authorities_weight = PendingChange {
|
||||||
|
next_authorities: invalid_authorities_weight,
|
||||||
|
delay: 10,
|
||||||
|
canon_height: 5,
|
||||||
|
canon_hash: (),
|
||||||
|
delay_kind: DelayKind::Best {
|
||||||
|
median_last_finalized: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// pending change contains an an authority set
|
||||||
|
// where one authority has weight of 0
|
||||||
|
assert!(matches!(
|
||||||
|
authority_set.add_pending_change(
|
||||||
|
invalid_change_authorities_weight,
|
||||||
|
&static_is_descendent_of(false)
|
||||||
|
),
|
||||||
|
Err(Error::InvalidAuthoritySet)
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,12 +97,14 @@ where H: Clone + Debug + PartialEq,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthoritySet {
|
let authority_set = AuthoritySet::new(
|
||||||
current_authorities: self.current_authorities,
|
self.current_authorities,
|
||||||
set_id: self.set_id,
|
self.set_id,
|
||||||
pending_forced_changes: Vec::new(),
|
pending_standard_changes,
|
||||||
pending_standard_changes
|
Vec::new(),
|
||||||
}
|
);
|
||||||
|
|
||||||
|
authority_set.expect("current_authorities is non-empty and weights are non-zero; qed.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +336,8 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
|
|||||||
from genesis on what appears to be first startup.");
|
from genesis on what appears to be first startup.");
|
||||||
|
|
||||||
let genesis_authorities = genesis_authorities()?;
|
let genesis_authorities = genesis_authorities()?;
|
||||||
let genesis_set = AuthoritySet::genesis(genesis_authorities.clone());
|
let genesis_set = AuthoritySet::genesis(genesis_authorities.clone())
|
||||||
|
.expect("genesis authorities is non-empty; all weights are non-zero; qed.");
|
||||||
let state = make_genesis_round();
|
let state = make_genesis_round();
|
||||||
let base = state.prevote_ghost
|
let base = state.prevote_ghost
|
||||||
.expect("state is for completed round; completed rounds must have a prevote ghost; qed.");
|
.expect("state is for completed round; completed rounds must have a prevote ghost; qed.");
|
||||||
@@ -503,12 +506,12 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*authority_set.inner().read(),
|
*authority_set.inner().read(),
|
||||||
AuthoritySet {
|
AuthoritySet::new(
|
||||||
current_authorities: authorities.clone(),
|
authorities.clone(),
|
||||||
pending_standard_changes: ForkTree::new(),
|
|
||||||
pending_forced_changes: Vec::new(),
|
|
||||||
set_id,
|
set_id,
|
||||||
},
|
ForkTree::new(),
|
||||||
|
Vec::new(),
|
||||||
|
).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut current_rounds = CurrentRounds::new();
|
let mut current_rounds = CurrentRounds::new();
|
||||||
@@ -547,12 +550,12 @@ mod test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let authority_set = AuthoritySet::<H256, u64> {
|
let authority_set = AuthoritySet::<H256, u64>::new(
|
||||||
current_authorities: authorities.clone(),
|
authorities.clone(),
|
||||||
pending_standard_changes: ForkTree::new(),
|
|
||||||
pending_forced_changes: Vec::new(),
|
|
||||||
set_id,
|
set_id,
|
||||||
};
|
ForkTree::new(),
|
||||||
|
Vec::new(),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
let voter_set_state = V1VoterSetState::Live(round_number, round_state.clone());
|
let voter_set_state = V1VoterSetState::Live(round_number, round_state.clone());
|
||||||
|
|
||||||
@@ -593,12 +596,12 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*authority_set.inner().read(),
|
*authority_set.inner().read(),
|
||||||
AuthoritySet {
|
AuthoritySet::new(
|
||||||
current_authorities: authorities.clone(),
|
authorities.clone(),
|
||||||
pending_standard_changes: ForkTree::new(),
|
|
||||||
pending_forced_changes: Vec::new(),
|
|
||||||
set_id,
|
set_id,
|
||||||
},
|
ForkTree::new(),
|
||||||
|
Vec::new(),
|
||||||
|
).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut current_rounds = CurrentRounds::new();
|
let mut current_rounds = CurrentRounds::new();
|
||||||
|
|||||||
@@ -1618,7 +1618,10 @@ mod tests {
|
|||||||
use crate::environment::VoterSetState;
|
use crate::environment::VoterSetState;
|
||||||
|
|
||||||
let base = (H256::zero(), 0);
|
let base = (H256::zero(), 0);
|
||||||
let voters = AuthoritySet::genesis(Vec::new());
|
|
||||||
|
let voters = vec![(AuthorityId::from_slice(&[1; 32]), 1)];
|
||||||
|
let voters = AuthoritySet::genesis(voters).unwrap();
|
||||||
|
|
||||||
let set_state = VoterSetState::live(
|
let set_state = VoterSetState::live(
|
||||||
0,
|
0,
|
||||||
&voters,
|
&voters,
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
|
|||||||
// is a no-op if currently in that set.
|
// is a no-op if currently in that set.
|
||||||
self.validator.note_set(
|
self.validator.note_set(
|
||||||
set_id,
|
set_id,
|
||||||
voters.voters().iter().map(|(v, _)| v.clone()).collect(),
|
voters.iter().map(|(v, _)| v.clone()).collect(),
|
||||||
|to, neighbor| self.neighbor_sender.send(to, neighbor),
|
|to, neighbor| self.neighbor_sender.send(to, neighbor),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -289,7 +289,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
|
|||||||
|
|
||||||
let locals = local_key.and_then(|pair| {
|
let locals = local_key.and_then(|pair| {
|
||||||
let id = pair.public();
|
let id = pair.public();
|
||||||
if voters.contains_key(&id) {
|
if voters.contains(&id) {
|
||||||
Some((pair, id))
|
Some((pair, id))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -308,12 +308,12 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
|
|||||||
}
|
}
|
||||||
Ok(GossipMessage::Vote(msg)) => {
|
Ok(GossipMessage::Vote(msg)) => {
|
||||||
// check signature.
|
// check signature.
|
||||||
if !voters.contains_key(&msg.message.id) {
|
if !voters.contains(&msg.message.id) {
|
||||||
debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id);
|
debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id);
|
||||||
return future::ready(None);
|
return future::ready(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if voters.len() <= TELEMETRY_VOTERS_LIMIT {
|
if voters.len().get() <= TELEMETRY_VOTERS_LIMIT {
|
||||||
match &msg.message.message {
|
match &msg.message.message {
|
||||||
PrimaryPropose(propose) => {
|
PrimaryPropose(propose) => {
|
||||||
telemetry!(CONSENSUS_INFO; "afg.received_propose";
|
telemetry!(CONSENSUS_INFO; "afg.received_propose";
|
||||||
@@ -378,7 +378,7 @@ impl<B: BlockT, N: Network<B>> NetworkBridge<B, N> {
|
|||||||
) {
|
) {
|
||||||
self.validator.note_set(
|
self.validator.note_set(
|
||||||
set_id,
|
set_id,
|
||||||
voters.voters().iter().map(|(v, _)| v.clone()).collect(),
|
voters.iter().map(|(v, _)| v.clone()).collect(),
|
||||||
|to, neighbor| self.neighbor_sender.send(to, neighbor),
|
|to, neighbor| self.neighbor_sender.send(to, neighbor),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -476,7 +476,7 @@ fn incoming_global<B: BlockT>(
|
|||||||
gossip_validator: &Arc<GossipValidator<B>>,
|
gossip_validator: &Arc<GossipValidator<B>>,
|
||||||
voters: &VoterSet<AuthorityId>,
|
voters: &VoterSet<AuthorityId>,
|
||||||
| {
|
| {
|
||||||
if voters.len() <= TELEMETRY_VOTERS_LIMIT {
|
if voters.len().get() <= TELEMETRY_VOTERS_LIMIT {
|
||||||
let precommits_signed_by: Vec<String> =
|
let precommits_signed_by: Vec<String> =
|
||||||
msg.message.auth_data.iter().map(move |(_, a)| {
|
msg.message.auth_data.iter().map(move |(_, a)| {
|
||||||
format!("{}", a)
|
format!("{}", a)
|
||||||
@@ -799,13 +799,13 @@ fn check_compact_commit<Block: BlockT>(
|
|||||||
) -> Result<(), ReputationChange> {
|
) -> Result<(), ReputationChange> {
|
||||||
// 4f + 1 = equivocations from f voters.
|
// 4f + 1 = equivocations from f voters.
|
||||||
let f = voters.total_weight() - voters.threshold();
|
let f = voters.total_weight() - voters.threshold();
|
||||||
let full_threshold = voters.total_weight() + f;
|
let full_threshold = (f + voters.total_weight()).0;
|
||||||
|
|
||||||
// check total weight is not out of range.
|
// check total weight is not out of range.
|
||||||
let mut total_weight = 0;
|
let mut total_weight = 0;
|
||||||
for (_, ref id) in &msg.auth_data {
|
for (_, ref id) in &msg.auth_data {
|
||||||
if let Some(weight) = voters.info(id).map(|info| info.weight()) {
|
if let Some(weight) = voters.get(id).map(|info| info.weight()) {
|
||||||
total_weight += weight;
|
total_weight += weight.get();
|
||||||
if total_weight > full_threshold {
|
if total_weight > full_threshold {
|
||||||
return Err(cost::MALFORMED_COMMIT);
|
return Err(cost::MALFORMED_COMMIT);
|
||||||
}
|
}
|
||||||
@@ -815,7 +815,7 @@ fn check_compact_commit<Block: BlockT>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if total_weight < voters.threshold() {
|
if total_weight < voters.threshold().get() {
|
||||||
return Err(cost::MALFORMED_COMMIT);
|
return Err(cost::MALFORMED_COMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,7 +860,7 @@ fn check_catch_up<Block: BlockT>(
|
|||||||
) -> Result<(), ReputationChange> {
|
) -> Result<(), ReputationChange> {
|
||||||
// 4f + 1 = equivocations from f voters.
|
// 4f + 1 = equivocations from f voters.
|
||||||
let f = voters.total_weight() - voters.threshold();
|
let f = voters.total_weight() - voters.threshold();
|
||||||
let full_threshold = voters.total_weight() + f;
|
let full_threshold = (f + voters.total_weight()).0;
|
||||||
|
|
||||||
// check total weight is not out of range for a set of votes.
|
// check total weight is not out of range for a set of votes.
|
||||||
fn check_weight<'a>(
|
fn check_weight<'a>(
|
||||||
@@ -871,8 +871,8 @@ fn check_catch_up<Block: BlockT>(
|
|||||||
let mut total_weight = 0;
|
let mut total_weight = 0;
|
||||||
|
|
||||||
for id in votes {
|
for id in votes {
|
||||||
if let Some(weight) = voters.info(&id).map(|info| info.weight()) {
|
if let Some(weight) = voters.get(&id).map(|info| info.weight()) {
|
||||||
total_weight += weight;
|
total_weight += weight.get();
|
||||||
if total_weight > full_threshold {
|
if total_weight > full_threshold {
|
||||||
return Err(cost::MALFORMED_CATCH_UP);
|
return Err(cost::MALFORMED_CATCH_UP);
|
||||||
}
|
}
|
||||||
@@ -882,7 +882,7 @@ fn check_catch_up<Block: BlockT>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if total_weight < voters.threshold() {
|
if total_weight < voters.threshold().get() {
|
||||||
return Err(cost::MALFORMED_CATCH_UP);
|
return Err(cost::MALFORMED_CATCH_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ use std::{borrow::Cow, pin::Pin, task::{Context, Poll}};
|
|||||||
use crate::environment::SharedVoterSetState;
|
use crate::environment::SharedVoterSetState;
|
||||||
use sp_finality_grandpa::{AuthorityList, GRANDPA_ENGINE_ID};
|
use sp_finality_grandpa::{AuthorityList, GRANDPA_ENGINE_ID};
|
||||||
use super::gossip::{self, GossipValidator};
|
use super::gossip::{self, GossipValidator};
|
||||||
use super::{AuthorityId, VoterSet, Round, SetId};
|
use super::{VoterSet, Round, SetId};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum Event {
|
pub(crate) enum Event {
|
||||||
@@ -142,11 +142,15 @@ fn voter_set_state() -> SharedVoterSetState<Block> {
|
|||||||
use crate::authorities::AuthoritySet;
|
use crate::authorities::AuthoritySet;
|
||||||
use crate::environment::VoterSetState;
|
use crate::environment::VoterSetState;
|
||||||
use finality_grandpa::round::State as RoundState;
|
use finality_grandpa::round::State as RoundState;
|
||||||
use sp_core::H256;
|
use sp_core::{crypto::Public, H256};
|
||||||
|
use sp_finality_grandpa::AuthorityId;
|
||||||
|
|
||||||
let state = RoundState::genesis((H256::zero(), 0));
|
let state = RoundState::genesis((H256::zero(), 0));
|
||||||
let base = state.prevote_ghost.unwrap();
|
let base = state.prevote_ghost.unwrap();
|
||||||
let voters = AuthoritySet::genesis(Vec::new());
|
|
||||||
|
let voters = vec![(AuthorityId::from_slice(&[1; 32]), 1)];
|
||||||
|
let voters = AuthoritySet::genesis(voters).unwrap();
|
||||||
|
|
||||||
let set_state = VoterSetState::live(
|
let set_state = VoterSetState::live(
|
||||||
0,
|
0,
|
||||||
&voters,
|
&voters,
|
||||||
@@ -212,7 +216,7 @@ impl sc_network_gossip::ValidatorContext<Block> for NoopContext {
|
|||||||
fn good_commit_leads_to_relay() {
|
fn good_commit_leads_to_relay() {
|
||||||
let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||||
let public = make_ids(&private[..]);
|
let public = make_ids(&private[..]);
|
||||||
let voter_set = Arc::new(public.iter().cloned().collect::<VoterSet<AuthorityId>>());
|
let voter_set = Arc::new(VoterSet::new(public.iter().cloned()).unwrap());
|
||||||
|
|
||||||
let round = 1;
|
let round = 1;
|
||||||
let set_id = 1;
|
let set_id = 1;
|
||||||
@@ -360,7 +364,7 @@ fn bad_commit_leads_to_report() {
|
|||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
let private = [Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie];
|
||||||
let public = make_ids(&private[..]);
|
let public = make_ids(&private[..]);
|
||||||
let voter_set = Arc::new(public.iter().cloned().collect::<VoterSet<AuthorityId>>());
|
let voter_set = Arc::new(VoterSet::new(public.iter().cloned()).unwrap());
|
||||||
|
|
||||||
let round = 1;
|
let round = 1;
|
||||||
let set_id = 1;
|
let set_id = 1;
|
||||||
|
|||||||
@@ -579,23 +579,23 @@ where
|
|||||||
Block: 'static,
|
Block: 'static,
|
||||||
B: Backend<Block>,
|
B: Backend<Block>,
|
||||||
C: crate::ClientForGrandpa<Block, B> + 'static,
|
C: crate::ClientForGrandpa<Block, B> + 'static,
|
||||||
N: NetworkT<Block> + 'static + Send,
|
N: NetworkT<Block> + 'static + Send + Sync,
|
||||||
SC: SelectChain<Block> + 'static,
|
SC: SelectChain<Block> + 'static,
|
||||||
VR: VotingRule<Block, C>,
|
VR: VotingRule<Block, C>,
|
||||||
NumberFor<Block>: BlockNumberOps,
|
NumberFor<Block>: BlockNumberOps,
|
||||||
{
|
{
|
||||||
type Timer = Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send>>;
|
type Timer = Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + Sync>>;
|
||||||
type Id = AuthorityId;
|
type Id = AuthorityId;
|
||||||
type Signature = AuthoritySignature;
|
type Signature = AuthoritySignature;
|
||||||
|
|
||||||
// regular round message streams
|
// regular round message streams
|
||||||
type In = Pin<Box<dyn Stream<
|
type In = Pin<Box<dyn Stream<
|
||||||
Item = Result<::finality_grandpa::SignedMessage<Block::Hash, NumberFor<Block>, Self::Signature, Self::Id>, Self::Error>
|
Item = Result<::finality_grandpa::SignedMessage<Block::Hash, NumberFor<Block>, Self::Signature, Self::Id>, Self::Error>
|
||||||
> + Send>>;
|
> + Send + Sync>>;
|
||||||
type Out = Pin<Box<dyn Sink<
|
type Out = Pin<Box<dyn Sink<
|
||||||
::finality_grandpa::Message<Block::Hash, NumberFor<Block>>,
|
::finality_grandpa::Message<Block::Hash, NumberFor<Block>>,
|
||||||
Error = Self::Error,
|
Error = Self::Error,
|
||||||
> + Send>>;
|
> + Send + Sync>>;
|
||||||
|
|
||||||
type Error = CommandOrError<Block::Hash, NumberFor<Block>>;
|
type Error = CommandOrError<Block::Hash, NumberFor<Block>>;
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ use sc_telemetry::{telemetry, CONSENSUS_INFO};
|
|||||||
use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY};
|
use sp_finality_grandpa::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY};
|
||||||
|
|
||||||
use crate::justification::GrandpaJustification;
|
use crate::justification::GrandpaJustification;
|
||||||
|
use crate::VoterSet;
|
||||||
|
|
||||||
/// Maximum number of fragments that we want to return in a single prove_finality call.
|
/// Maximum number of fragments that we want to return in a single prove_finality call.
|
||||||
const MAX_FRAGMENTS_IN_PROOF: usize = 8;
|
const MAX_FRAGMENTS_IN_PROOF: usize = 8;
|
||||||
@@ -588,7 +589,11 @@ impl<Block: BlockT> ProvableJustification<Block::Header> for GrandpaJustificatio
|
|||||||
NumberFor<Block>: BlockNumberOps,
|
NumberFor<Block>: BlockNumberOps,
|
||||||
{
|
{
|
||||||
fn verify(&self, set_id: u64, authorities: &[(AuthorityId, u64)]) -> ClientResult<()> {
|
fn verify(&self, set_id: u64, authorities: &[(AuthorityId, u64)]) -> ClientResult<()> {
|
||||||
GrandpaJustification::verify(self, set_id, &authorities.iter().cloned().collect())
|
let authorities = VoterSet::new(authorities.iter().cloned()).ok_or(
|
||||||
|
ClientError::Consensus(sp_consensus::Error::InvalidAuthoritiesSet),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
GrandpaJustification::verify(self, set_id, &authorities)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ pub fn run_grandpa_voter<Block: BlockT, BE: 'static, C, N, SC, VR>(
|
|||||||
let events = telemetry_on_connect
|
let events = telemetry_on_connect
|
||||||
.for_each(move |_| {
|
.for_each(move |_| {
|
||||||
let curr = authorities.current_authorities();
|
let curr = authorities.current_authorities();
|
||||||
let mut auths = curr.voters().into_iter().map(|(p, _)| p);
|
let mut auths = curr.iter().map(|(p, _)| p);
|
||||||
let maybe_authority_id = authority_id(&mut auths, &conf.keystore)
|
let maybe_authority_id = authority_id(&mut auths, &conf.keystore)
|
||||||
.unwrap_or(Default::default());
|
.unwrap_or(Default::default());
|
||||||
|
|
||||||
@@ -682,8 +682,8 @@ pub fn run_grandpa_voter<Block: BlockT, BE: 'static, C, N, SC, VR>(
|
|||||||
"authority_id" => maybe_authority_id.to_string(),
|
"authority_id" => maybe_authority_id.to_string(),
|
||||||
"authority_set_id" => ?authorities.set_id(),
|
"authority_set_id" => ?authorities.set_id(),
|
||||||
"authorities" => {
|
"authorities" => {
|
||||||
let authorities: Vec<String> = curr.voters()
|
let authorities: Vec<String> = curr.iter()
|
||||||
.iter().map(|(id, _)| id.to_string()).collect();
|
.map(|(id, _)| id.to_string()).collect();
|
||||||
serde_json::to_string(&authorities)
|
serde_json::to_string(&authorities)
|
||||||
.expect("authorities is always at least an empty vector; elements are always of type string")
|
.expect("authorities is always at least an empty vector; elements are always of type string")
|
||||||
}
|
}
|
||||||
@@ -823,7 +823,7 @@ where
|
|||||||
"authority_id" => authority_id.to_string(),
|
"authority_id" => authority_id.to_string(),
|
||||||
"authority_set_id" => ?self.env.set_id,
|
"authority_set_id" => ?self.env.set_id,
|
||||||
"authorities" => {
|
"authorities" => {
|
||||||
let authorities: Vec<String> = self.env.voters.voters()
|
let authorities: Vec<String> = self.env.voters
|
||||||
.iter().map(|(id, _)| id.to_string()).collect();
|
.iter().map(|(id, _)| id.to_string()).collect();
|
||||||
serde_json::to_string(&authorities)
|
serde_json::to_string(&authorities)
|
||||||
.expect("authorities is always at least an empty vector; elements are always of type string")
|
.expect("authorities is always at least an empty vector; elements are always of type string")
|
||||||
@@ -894,8 +894,16 @@ where
|
|||||||
Ok(Some(set_state))
|
Ok(Some(set_state))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
let voters = Arc::new(VoterSet::new(new.authorities.into_iter())
|
||||||
|
.expect("new authorities come from pending change; \
|
||||||
|
pending change comes from `AuthoritySet`; \
|
||||||
|
`AuthoritySet` validates authorities is non-empty and weights are non-zero; \
|
||||||
|
qed."
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
self.env = Arc::new(Environment {
|
self.env = Arc::new(Environment {
|
||||||
voters: Arc::new(new.authorities.into_iter().collect()),
|
voters,
|
||||||
set_id: new.set_id,
|
set_id: new.set_id,
|
||||||
voter_set_state: self.env.voter_set_state.clone(),
|
voter_set_state: self.env.voter_set_state.clone(),
|
||||||
// Fields below are simply transferred and not updated.
|
// Fields below are simply transferred and not updated.
|
||||||
@@ -1017,7 +1025,8 @@ fn is_voter(
|
|||||||
keystore: &Option<KeyStorePtr>,
|
keystore: &Option<KeyStorePtr>,
|
||||||
) -> Option<AuthorityPair> {
|
) -> Option<AuthorityPair> {
|
||||||
match keystore {
|
match keystore {
|
||||||
Some(keystore) => voters.voters().iter()
|
Some(keystore) => voters
|
||||||
|
.iter()
|
||||||
.find_map(|(p, _)| keystore.read().key_pair::<AuthorityPair>(&p).ok()),
|
.find_map(|(p, _)| keystore.read().key_pair::<AuthorityPair>(&p).ok()),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,11 +409,13 @@ mod tests {
|
|||||||
(Arc::new(client), backend)
|
(Arc::new(client), backend)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let voters = vec![(sp_keyring::Ed25519Keyring::Alice.public().into(), 1)];
|
||||||
|
|
||||||
let persistent_data = aux_schema::load_persistent(
|
let persistent_data = aux_schema::load_persistent(
|
||||||
&*backend,
|
&*backend,
|
||||||
client.info().genesis_hash,
|
client.info().genesis_hash,
|
||||||
0,
|
0,
|
||||||
|| Ok(vec![]),
|
|| Ok(voters),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let (_tx, voter_command_rx) = tracing_unbounded("");
|
let (_tx, voter_command_rx) = tracing_unbounded("");
|
||||||
|
|||||||
@@ -990,7 +990,6 @@ fn test_bad_justification() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn voter_persists_its_votes() {
|
fn voter_persists_its_votes() {
|
||||||
use std::iter::FromIterator;
|
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use futures::future;
|
use futures::future;
|
||||||
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver};
|
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver};
|
||||||
@@ -1145,7 +1144,7 @@ fn voter_persists_its_votes() {
|
|||||||
let (round_rx, round_tx) = network.round_communication(
|
let (round_rx, round_tx) = network.round_communication(
|
||||||
communication::Round(1),
|
communication::Round(1),
|
||||||
communication::SetId(0),
|
communication::SetId(0),
|
||||||
Arc::new(VoterSet::from_iter(voters)),
|
Arc::new(VoterSet::new(voters).unwrap()),
|
||||||
Some(peers[1].pair().into()),
|
Some(peers[1].pair().into()),
|
||||||
HasVoted::No,
|
HasVoted::No,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ pub(crate) struct UntilImported<Block: BlockT, BlockStatus, BlockSyncRequester,
|
|||||||
inner: Fuse<I>,
|
inner: Fuse<I>,
|
||||||
ready: VecDeque<M::Blocked>,
|
ready: VecDeque<M::Blocked>,
|
||||||
/// Interval at which to check status of each awaited block.
|
/// Interval at which to check status of each awaited block.
|
||||||
check_pending: Pin<Box<dyn Stream<Item = Result<(), std::io::Error>> + Send>>,
|
check_pending: Pin<Box<dyn Stream<Item = Result<(), std::io::Error>> + Send + Sync>>,
|
||||||
/// Mapping block hashes to their block number, the point in time it was
|
/// Mapping block hashes to their block number, the point in time it was
|
||||||
/// first encountered (Instant) and a list of GRANDPA messages referencing
|
/// first encountered (Instant) and a list of GRANDPA messages referencing
|
||||||
/// the block hash.
|
/// the block hash.
|
||||||
|
|||||||
Reference in New Issue
Block a user