mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 06:21:02 +00:00
note future changes when importing block
This commit is contained in:
Generated
+6
-4
@@ -580,8 +580,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "finality-grandpa"
|
name = "finality-grandpa"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/paritytech/finality-grandpa#fffce2dc450e72ff8b3f43818f8aceb5cfacc2d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -2965,6 +2965,7 @@ dependencies = [
|
|||||||
name = "substrate-consensus-common"
|
name = "substrate-consensus-common"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"sr-primitives 0.1.0",
|
||||||
"substrate-primitives 0.1.0",
|
"substrate-primitives 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3019,7 +3020,7 @@ dependencies = [
|
|||||||
name = "substrate-finality-grandpa"
|
name = "substrate-finality-grandpa"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"finality-grandpa 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"finality-grandpa 0.3.0 (git+https://github.com/paritytech/finality-grandpa)",
|
||||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -3027,6 +3028,7 @@ dependencies = [
|
|||||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sr-primitives 0.1.0",
|
"sr-primitives 0.1.0",
|
||||||
"substrate-client 0.1.0",
|
"substrate-client 0.1.0",
|
||||||
|
"substrate-consensus-common 0.1.0",
|
||||||
"substrate-keyring 0.1.0",
|
"substrate-keyring 0.1.0",
|
||||||
"substrate-network 0.1.0",
|
"substrate-network 0.1.0",
|
||||||
"substrate-primitives 0.1.0",
|
"substrate-primitives 0.1.0",
|
||||||
@@ -4179,7 +4181,7 @@ dependencies = [
|
|||||||
"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
|
"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
|
||||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
|
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
|
||||||
"checksum finality-grandpa 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d8cf871510f0d57630e75f9e65f87cba29581ccab1f78666d8b2e422d0baa6"
|
"checksum finality-grandpa 0.3.0 (git+https://github.com/paritytech/finality-grandpa)" = "<none>"
|
||||||
"checksum fixed-hash 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5ec8112f00ea8a483e04748a85522184418fd1cf02890b626d8fc28683f7de"
|
"checksum fixed-hash 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5ec8112f00ea8a483e04748a85522184418fd1cf02890b626d8fc28683f7de"
|
||||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ version = "0.1.0"
|
|||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
description = "Common utilities for substrate consensus"
|
description = "Common utilities for substrate consensus"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dependencies]
|
||||||
substrate-primitives = { path= "../../primitives"}
|
substrate-primitives = { path = "../../primitives"}
|
||||||
|
sr-primitives = { path = "../../sr-primitives" }
|
||||||
|
|||||||
@@ -17,12 +17,13 @@
|
|||||||
//! Tracks offline validators.
|
//! Tracks offline validators.
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
#![cfg(feature="rhd")]
|
|
||||||
|
|
||||||
extern crate substrate_primitives as primitives;
|
extern crate substrate_primitives as primitives;
|
||||||
|
extern crate sr_primitives;
|
||||||
|
|
||||||
use primitives::{generic::BlockId, Justification};
|
use sr_primitives::{generic::BlockId};
|
||||||
use primitives::traits::{Block, Header};
|
use sr_primitives::traits::{Block, Header};
|
||||||
|
use sr_primitives::Justification;
|
||||||
|
use primitives::AuthorityId;
|
||||||
|
|
||||||
/// Block import trait.
|
/// Block import trait.
|
||||||
pub trait BlockImport<B: Block> {
|
pub trait BlockImport<B: Block> {
|
||||||
@@ -30,4 +31,4 @@ pub trait BlockImport<B: Block> {
|
|||||||
fn import_block(&self, block: B, justification: Justification, authorities: &[AuthorityId]) -> bool;
|
fn import_block(&self, block: B, justification: Justification, authorities: &[AuthorityId]) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod offline_tracker;
|
pub mod offline_tracker;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//! Tracks offline validators.
|
//! Tracks offline validators.
|
||||||
|
|
||||||
use node_primitives::AccountId;
|
use primitives::AuthorityId;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
@@ -56,7 +56,7 @@ impl Observed {
|
|||||||
|
|
||||||
/// Tracks offline validators and can issue a report for those offline.
|
/// Tracks offline validators and can issue a report for those offline.
|
||||||
pub struct OfflineTracker {
|
pub struct OfflineTracker {
|
||||||
observed: HashMap<AccountId, Observed>,
|
observed: HashMap<AuthorityId, Observed>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OfflineTracker {
|
impl OfflineTracker {
|
||||||
@@ -66,7 +66,7 @@ impl OfflineTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Note new consensus is starting with the given set of validators.
|
/// Note new consensus is starting with the given set of validators.
|
||||||
pub fn note_new_block(&mut self, validators: &[AccountId]) {
|
pub fn note_new_block(&mut self, validators: &[AuthorityId]) {
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
let set: HashSet<_> = validators.iter().cloned().collect();
|
let set: HashSet<_> = validators.iter().cloned().collect();
|
||||||
@@ -74,14 +74,14 @@ impl OfflineTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Note that a round has ended.
|
/// Note that a round has ended.
|
||||||
pub fn note_round_end(&mut self, validator: AccountId, was_online: bool) {
|
pub fn note_round_end(&mut self, validator: AuthorityId, was_online: bool) {
|
||||||
self.observed.entry(validator)
|
self.observed.entry(validator)
|
||||||
.or_insert_with(Observed::new)
|
.or_insert_with(Observed::new)
|
||||||
.note_round_end(was_online);
|
.note_round_end(was_online);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a vector of indices for offline account IDs.
|
/// Generate a vector of indices for offline account IDs.
|
||||||
pub fn reports(&self, validators: &[AccountId]) -> Vec<u32> {
|
pub fn reports(&self, validators: &[AuthorityId]) -> Vec<u32> {
|
||||||
validators.iter()
|
validators.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, v)| if self.is_online(v) {
|
.filter_map(|(i, v)| if self.is_online(v) {
|
||||||
@@ -93,7 +93,7 @@ impl OfflineTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Whether reports on a validator set are consistent with our view of things.
|
/// Whether reports on a validator set are consistent with our view of things.
|
||||||
pub fn check_consistency(&self, validators: &[AccountId], reports: &[u32]) -> bool {
|
pub fn check_consistency(&self, validators: &[AuthorityId], reports: &[u32]) -> bool {
|
||||||
reports.iter().cloned().all(|r| {
|
reports.iter().cloned().all(|r| {
|
||||||
let v = match validators.get(r as usize) {
|
let v = match validators.get(r as usize) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@@ -106,7 +106,7 @@ impl OfflineTracker {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_online(&self, v: &AccountId) -> bool {
|
fn is_online(&self, v: &AuthorityId) -> bool {
|
||||||
self.observed.get(v).map(Observed::is_active).unwrap_or(true)
|
self.observed.get(v).map(Observed::is_active).unwrap_or(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,17 @@ futures = "0.1.17"
|
|||||||
parity-codec = "2.1"
|
parity-codec = "2.1"
|
||||||
parity-codec-derive = "2.0"
|
parity-codec-derive = "2.0"
|
||||||
sr-primitives = { path = "../sr-primitives" }
|
sr-primitives = { path = "../sr-primitives" }
|
||||||
|
substrate-consensus-common = { path = "../consensus/common" }
|
||||||
substrate-primitives = { path = "../primitives" }
|
substrate-primitives = { path = "../primitives" }
|
||||||
substrate-client = { path = "../client" }
|
substrate-client = { path = "../client" }
|
||||||
substrate-network = { path = "../network" }
|
substrate-network = { path = "../network" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
parking_lot = "0.4"
|
||||||
tokio = "0.1.7"
|
tokio = "0.1.7"
|
||||||
|
|
||||||
[dependencies.finality-grandpa]
|
[dependencies.finality-grandpa]
|
||||||
version = "0.2.0"
|
#version = "0.3.0"
|
||||||
|
git = "https://github.com/paritytech/finality-grandpa"
|
||||||
features = ["derive-codec"]
|
features = ["derive-codec"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -16,23 +16,33 @@
|
|||||||
|
|
||||||
//! Utilities for dealing with authorities, authority sets, and handoffs.
|
//! Utilities for dealing with authorities, authority sets, and handoffs.
|
||||||
|
|
||||||
|
use parking_lot::RwLock;
|
||||||
use substrate_primitives::AuthorityId;
|
use substrate_primitives::AuthorityId;
|
||||||
|
|
||||||
|
use std::cmp::Ord;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// A shared authority set.
|
/// A shared authority set.
|
||||||
pub(crate) struct SharedAuthoritySet<H, N> {
|
pub(crate) struct SharedAuthoritySet<H, N> {
|
||||||
inner: RwLock<AuthoritySet<H, N>>,
|
inner: Arc<RwLock<AuthoritySet<H, N>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, N> Clone for SharedAuthoritySet<H, N> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
SharedAuthoritySet { inner: self.inner.clone() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, N> SharedAuthoritySet<H, N> {
|
impl<H, N> SharedAuthoritySet<H, N> {
|
||||||
/// The genesis authority set.
|
/// The genesis authority set.
|
||||||
pub(crate) fn genesis(initial: Vec<(AuthorityId, usize)>) -> Self {
|
pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
|
||||||
SharedAuthoritySet {
|
SharedAuthoritySet {
|
||||||
inner: RwLock::new(AuthoritySet {
|
inner: Arc::new(RwLock::new(AuthoritySet {
|
||||||
current_authorities: initial,
|
current_authorities: initial,
|
||||||
set_id: 0,
|
set_id: 0,
|
||||||
pending_changes: Vec::new(),
|
pending_changes: Vec::new(),
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,33 +52,35 @@ impl<H, N> SharedAuthoritySet<H, N> {
|
|||||||
{
|
{
|
||||||
f(&*self.inner.read())
|
f(&*self.inner.read())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<H, N: Add + Clone> SharedAuthoritySet<H, N> {
|
impl<H, N: Add<Output=N> + Ord + Clone> SharedAuthoritySet<H, N> {
|
||||||
/// Note an upcoming pending transition.
|
/// Note an upcoming pending transition.
|
||||||
pub(crate) fn add_pending_change(&self, pending: PendingChange<H, N>) {
|
pub(crate) fn add_pending_change(&self, pending: PendingChange<H, N>) {
|
||||||
let idx = self.pending_changes
|
let mut inner = self.inner.write();
|
||||||
.binary_search_by_key(|change| change.effective_number())
|
let idx = inner.pending_changes
|
||||||
|
.binary_search_by_key(&pending.effective_number(), |change| change.effective_number())
|
||||||
.unwrap_or_else(|i| i);
|
.unwrap_or_else(|i| i);
|
||||||
|
|
||||||
self.pending_changes.insert(idx);
|
inner.pending_changes.insert(idx, pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the earliest limit-block number, if any.
|
/// Get the earliest limit-block number, if any.
|
||||||
pub(crate) fn current_limit(&self) -> Option<&N> {
|
pub(crate) fn current_limit(&self) -> Option<N> {
|
||||||
self.pending_changes.get(0).map(|change| &change.effective_number());
|
self.inner.read().pending_changes.get(0).map(|change| change.effective_number().clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, N> From<AuthoritySet<H, N>> for SharedAuthoritySet<H, N> {
|
impl<H, N> From<AuthoritySet<H, N>> for SharedAuthoritySet<H, N> {
|
||||||
fn from(set: AuthoritySet<H, N>) -> Self {
|
fn from(set: AuthoritySet<H, N>) -> Self {
|
||||||
SharedAuthoritySet { inner: RwLock::new(set) }
|
SharedAuthoritySet { inner: Arc::new(RwLock::new(set)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of authorities.
|
/// A set of authorities.
|
||||||
#[derive(Encode, Decode)]
|
#[derive(Encode, Decode)]
|
||||||
pub(crate) struct AuthoritySet<H, N> {
|
pub(crate) struct AuthoritySet<H, N> {
|
||||||
current_authorities: Vec<(AuthorityId, usize)>,
|
current_authorities: Vec<(AuthorityId, u64)>,
|
||||||
set_id: u64,
|
set_id: u64,
|
||||||
pending_changes: Vec<PendingChange<H, N>>,
|
pending_changes: Vec<PendingChange<H, N>>,
|
||||||
}
|
}
|
||||||
@@ -80,7 +92,7 @@ pub(crate) struct AuthoritySet<H, N> {
|
|||||||
#[derive(Encode, Decode)]
|
#[derive(Encode, Decode)]
|
||||||
pub(crate) struct PendingChange<H, N> {
|
pub(crate) struct PendingChange<H, N> {
|
||||||
/// The new authorities and weights to apply.
|
/// The new authorities and weights to apply.
|
||||||
pub(crate) next_authorities: Vec<(AuthorityId, usize)>,
|
pub(crate) next_authorities: Vec<(AuthorityId, u64)>,
|
||||||
/// How deep in the finalized chain the announcing block must be
|
/// How deep in the finalized chain the announcing block must be
|
||||||
/// before the change is applied.
|
/// before the change is applied.
|
||||||
pub(crate) finalization_depth: N,
|
pub(crate) finalization_depth: N,
|
||||||
@@ -90,9 +102,9 @@ pub(crate) struct PendingChange<H, N> {
|
|||||||
pub(crate) canon_hash: H,
|
pub(crate) canon_hash: H,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, N: Add + Clone> PendingChange<H, N> {
|
impl<H, N: Add<Output=N> + Clone> PendingChange<H, N> {
|
||||||
/// Returns the effective number.
|
/// Returns the effective number.
|
||||||
fn effective_number(&self) -> N {
|
fn effective_number(&self) -> N {
|
||||||
self.canon_height + self.finalization_depth
|
self.canon_height.clone() + self.finalization_depth.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,11 @@ extern crate finality_grandpa as grandpa;
|
|||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate substrate_client as client;
|
extern crate substrate_client as client;
|
||||||
extern crate sr_primitives as runtime_primitives;
|
extern crate sr_primitives as runtime_primitives;
|
||||||
|
extern crate substrate_consensus_common as consensus_common;
|
||||||
extern crate substrate_primitives;
|
extern crate substrate_primitives;
|
||||||
extern crate substrate_network as network;
|
extern crate substrate_network as network;
|
||||||
extern crate tokio;
|
extern crate tokio;
|
||||||
|
extern crate parking_lot;
|
||||||
extern crate parity_codec as codec;
|
extern crate parity_codec as codec;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -47,10 +49,11 @@ use futures::stream::Fuse;
|
|||||||
use futures::sync::mpsc;
|
use futures::sync::mpsc;
|
||||||
use client::{Client, ImportNotifications, backend::Backend, CallExecutor};
|
use client::{Client, ImportNotifications, backend::Backend, CallExecutor};
|
||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
|
use consensus_common::BlockImport;
|
||||||
use runtime_primitives::traits::{
|
use runtime_primitives::traits::{
|
||||||
As, NumberFor, Block as BlockT, Header as HeaderT, DigestItemFor,
|
As, NumberFor, Block as BlockT, Header as HeaderT, DigestItemFor,
|
||||||
};
|
};
|
||||||
use runtime_primitives::generic::BlockId;
|
use runtime_primitives::{generic::BlockId, Justification};
|
||||||
use substrate_primitives::{ed25519, AuthorityId, Blake2Hasher};
|
use substrate_primitives::{ed25519, AuthorityId, Blake2Hasher};
|
||||||
use tokio::timer::Interval;
|
use tokio::timer::Interval;
|
||||||
|
|
||||||
@@ -61,6 +64,8 @@ use std::collections::{VecDeque, HashMap};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
|
use authorities::SharedAuthoritySet;
|
||||||
|
|
||||||
mod authorities;
|
mod authorities;
|
||||||
|
|
||||||
const LAST_COMPLETED_KEY: &[u8] = b"grandpa_completed_round";
|
const LAST_COMPLETED_KEY: &[u8] = b"grandpa_completed_round";
|
||||||
@@ -404,8 +409,9 @@ fn outgoing_messages<Block: BlockT, N: Network>(
|
|||||||
/// The environment we run GRANDPA in.
|
/// The environment we run GRANDPA in.
|
||||||
pub struct Environment<B, E, Block: BlockT, N: Network> {
|
pub struct Environment<B, E, Block: BlockT, N: Network> {
|
||||||
inner: Arc<Client<B, E, Block>>,
|
inner: Arc<Client<B, E, Block>>,
|
||||||
voters: HashMap<AuthorityId, usize>,
|
voters: HashMap<AuthorityId, u64>,
|
||||||
config: Config,
|
config: Config,
|
||||||
|
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
||||||
network: N,
|
network: N,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,14 +467,23 @@ impl<Block: BlockT, B, E, N> grandpa::Chain<Block::Hash> for Environment<B, E, B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A scheduled change of authority set.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct ScheduledChange<N> {
|
||||||
|
/// The new authorities after the change, along with their respective weights.
|
||||||
|
pub next_authorities: Vec<(AuthorityId, u64)>,
|
||||||
|
/// The number of blocks to delay.
|
||||||
|
pub delay: N,
|
||||||
|
}
|
||||||
|
|
||||||
/// A GRANDPA-compatible DigestItem. This can describe when GRANDPA set changes
|
/// A GRANDPA-compatible DigestItem. This can describe when GRANDPA set changes
|
||||||
/// are scheduled.
|
/// are scheduled.
|
||||||
// TODO: with specialization, do a blanket implementation so this trait
|
// TODO: with specialization, do a blanket implementation so this trait
|
||||||
// doesn't have to be implemented by users.
|
// doesn't have to be implemented by users.
|
||||||
pub trait CompatibleDigestItem<N> {
|
pub trait CompatibleDigestItem<N> {
|
||||||
/// If this digest item notes a GRANDPA set change, return the number of
|
/// If this digest item notes a GRANDPA set change, return information about
|
||||||
/// blocks the change should occur after.
|
/// the scheduled change.
|
||||||
fn scheduled_change_in(&self) -> Option<N> { None }
|
fn scheduled_change(&self) -> Option<ScheduledChange<N>> { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B, E, Block, N> where
|
impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B, E, Block, N> where
|
||||||
@@ -487,6 +502,7 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
|
|||||||
type Out = Box<Sink<SinkItem = ::grandpa::Message<Block::Hash>, SinkError = Self::Error>>;
|
type Out = Box<Sink<SinkItem = ::grandpa::Message<Block::Hash>, SinkError = Self::Error>>;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
#[allow(unreachable_code)]
|
||||||
fn round_data(
|
fn round_data(
|
||||||
&self,
|
&self,
|
||||||
round: u64
|
round: u64
|
||||||
@@ -498,7 +514,9 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
|
|||||||
let prevote_timer = Delay::new(now + self.config.gossip_duration * 2);
|
let prevote_timer = Delay::new(now + self.config.gossip_duration * 2);
|
||||||
let precommit_timer = Delay::new(now + self.config.gossip_duration * 4);
|
let precommit_timer = Delay::new(now + self.config.gossip_duration * 4);
|
||||||
|
|
||||||
|
// TODO [now]: Get from shared authority set.
|
||||||
let set_id = unimplemented!();
|
let set_id = unimplemented!();
|
||||||
|
|
||||||
// TODO: dispatch this with `mpsc::spawn`.
|
// TODO: dispatch this with `mpsc::spawn`.
|
||||||
let incoming = checked_message_stream::<Block, _>(
|
let incoming = checked_message_stream::<Block, _>(
|
||||||
round,
|
round,
|
||||||
@@ -511,7 +529,7 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
|
|||||||
round,
|
round,
|
||||||
set_id,
|
set_id,
|
||||||
self.config.local_key.clone(),
|
self.config.local_key.clone(),
|
||||||
self.config.voters.clone(),
|
self.config.genesis_voters.clone(),
|
||||||
self.network.clone(),
|
self.network.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -584,13 +602,57 @@ impl<B, E, Block: BlockT, N> voter::Environment<Block::Hash> for Environment<B,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a GRANDPA voter as a task. The returned future should be executed in a tokio runtime.
|
/// A block-import handler for GRANDPA.
|
||||||
|
///
|
||||||
|
/// This scans each imported block for signals of changing authority set.
|
||||||
|
/// When using GRANDPA, the block import worker should be using this block import
|
||||||
|
/// object.
|
||||||
|
pub struct GrandpaBlockImport<B, E, Block: BlockT> {
|
||||||
|
inner: Arc<Client<B, E, Block>>,
|
||||||
|
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E, Block: BlockT> BlockImport<Block> for GrandpaBlockImport<B, E, Block> where
|
||||||
|
B: Backend<Block, Blake2Hasher> + 'static,
|
||||||
|
E: CallExecutor<Block, Blake2Hasher> + 'static,
|
||||||
|
DigestItemFor<Block>: CompatibleDigestItem<NumberFor<Block>>,
|
||||||
|
{
|
||||||
|
fn import_block(&self, block: Block, _justification: Justification, _authorities: &[AuthorityId]) -> bool {
|
||||||
|
use runtime_primitives::traits::Digest;
|
||||||
|
use authorities::PendingChange;
|
||||||
|
|
||||||
|
let maybe_event = block.header().digest().logs().iter()
|
||||||
|
.filter_map(|log| log.scheduled_change())
|
||||||
|
.next()
|
||||||
|
.map(|change| (block.header().hash(), *block.header().number(), change));
|
||||||
|
|
||||||
|
// TODO [now]: use import-block trait for client when implemented
|
||||||
|
let result = self.inner.import_block(unimplemented!(), unimplemented!()).is_ok();
|
||||||
|
if let (true, Some((hash, number, change))) = (result, maybe_event) {
|
||||||
|
self.authority_set.add_pending_change(PendingChange {
|
||||||
|
next_authorities: change.next_authorities,
|
||||||
|
finalization_depth: number + change.delay,
|
||||||
|
canon_height: number,
|
||||||
|
canon_hash: hash,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO [now]: write to DB, and what to do on failure?
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run a GRANDPA voter as a task. This returns two pieces of data: a task to run,
|
||||||
|
/// and a `BlockImport` implementation.
|
||||||
pub fn run_grandpa<B, E, Block: BlockT, N>(
|
pub fn run_grandpa<B, E, Block: BlockT, N>(
|
||||||
config: Config,
|
config: Config,
|
||||||
client: Arc<Client<B, E, Block>>,
|
client: Arc<Client<B, E, Block>>,
|
||||||
voters: HashMap<AuthorityId, usize>,
|
voters: HashMap<AuthorityId, u64>,
|
||||||
network: N,
|
network: N,
|
||||||
) -> Result<impl Future<Item=(),Error=()>,client::error::Error> where
|
) -> ::client::error::Result<(
|
||||||
|
impl Future<Item=(),Error=()>,
|
||||||
|
GrandpaBlockImport<B, E, Block>,
|
||||||
|
)> where
|
||||||
Block::Hash: Ord,
|
Block::Hash: Ord,
|
||||||
B: Backend<Block, Blake2Hasher> + 'static,
|
B: Backend<Block, Blake2Hasher> + 'static,
|
||||||
E: CallExecutor<Block, Blake2Hasher> + 'static,
|
E: CallExecutor<Block, Blake2Hasher> + 'static,
|
||||||
@@ -614,11 +676,22 @@ pub fn run_grandpa<B, E, Block: BlockT, N>(
|
|||||||
))?
|
))?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: attempt to load from disk.
|
||||||
|
let authority_set = SharedAuthoritySet::genesis(
|
||||||
|
voters.iter().map(|(&id, &weight)| (id, weight)).collect(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let block_import = GrandpaBlockImport {
|
||||||
|
inner: client.clone(),
|
||||||
|
authority_set: authority_set.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let environment = Arc::new(Environment {
|
let environment = Arc::new(Environment {
|
||||||
inner: client,
|
inner: client,
|
||||||
config,
|
config,
|
||||||
voters,
|
voters,
|
||||||
network,
|
network,
|
||||||
|
authority_set,
|
||||||
});
|
});
|
||||||
|
|
||||||
let voter = voter::Voter::new(
|
let voter = voter::Voter::new(
|
||||||
@@ -628,7 +701,9 @@ pub fn run_grandpa<B, E, Block: BlockT, N>(
|
|||||||
last_finalized,
|
last_finalized,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(voter.map_err(|e| warn!("GRANDPA Voter failed: {:?}", e)))
|
let work = voter.map_err(|e| warn!("GRANDPA Voter failed: {:?}", e));
|
||||||
|
|
||||||
|
Ok((work, block_import))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Reference in New Issue
Block a user