mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 05:11:02 +00:00
localize messages to set-index and add pending changes
This commit is contained in:
Generated
+1
@@ -3027,6 +3027,7 @@ 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)",
|
||||||
"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)",
|
||||||
|
"parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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",
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.1.17"
|
futures = "0.1.17"
|
||||||
parity-codec = "2.1"
|
parity-codec = "2.1"
|
||||||
|
parity-codec-derive = "2.0"
|
||||||
sr-primitives = { path = "../sr-primitives" }
|
sr-primitives = { path = "../sr-primitives" }
|
||||||
substrate-primitives = { path = "../primitives" }
|
substrate-primitives = { path = "../primitives" }
|
||||||
substrate-client = { path = "../client" }
|
substrate-client = { path = "../client" }
|
||||||
|
substrate-network = { path = "../network" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
tokio = "0.1.7"
|
tokio = "0.1.7"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2018 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/>.
|
||||||
|
|
||||||
|
//! Utilities for dealing with authorities, authority sets, and handoffs.
|
||||||
|
|
||||||
|
use substrate_primitives::AuthorityId;
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
/// A shared authority set.
|
||||||
|
pub(crate) struct SharedAuthoritySet<H, N> {
|
||||||
|
inner: RwLock<AuthoritySet<H, N>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, N> SharedAuthoritySet<H, N> {
|
||||||
|
/// The genesis authority set.
|
||||||
|
pub(crate) fn genesis(initial: Vec<(AuthorityId, usize)>) -> Self {
|
||||||
|
SharedAuthoritySet {
|
||||||
|
inner: RwLock::new(AuthoritySet {
|
||||||
|
current_authorities: initial,
|
||||||
|
set_id: 0,
|
||||||
|
pending_changes: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Execute some work using the inner authority set.
|
||||||
|
pub(crate) fn with<F, U>(&self, f: F) -> U
|
||||||
|
where F: FnOnce(&AuthoritySet<H, N>) -> U
|
||||||
|
{
|
||||||
|
f(&*self.inner.read())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, N: Add + Clone> SharedAuthoritySet<H, N> {
|
||||||
|
/// Note an upcoming pending transition.
|
||||||
|
pub(crate) fn add_pending_change(&self, pending: PendingChange<H, N>) {
|
||||||
|
let idx = self.pending_changes
|
||||||
|
.binary_search_by_key(|change| change.effective_number())
|
||||||
|
.unwrap_or_else(|i| i);
|
||||||
|
|
||||||
|
self.pending_changes.insert(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the earliest limit-block number, if any.
|
||||||
|
pub(crate) fn current_limit(&self) -> Option<&N> {
|
||||||
|
self.pending_changes.get(0).map(|change| &change.effective_number());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, N> From<AuthoritySet<H, N>> for SharedAuthoritySet<H, N> {
|
||||||
|
fn from(set: AuthoritySet<H, N>) -> Self {
|
||||||
|
SharedAuthoritySet { inner: RwLock::new(set) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A set of authorities.
|
||||||
|
#[derive(Encode, Decode)]
|
||||||
|
pub(crate) struct AuthoritySet<H, N> {
|
||||||
|
current_authorities: Vec<(AuthorityId, usize)>,
|
||||||
|
set_id: u64,
|
||||||
|
pending_changes: Vec<PendingChange<H, N>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A pending change to the authority set.
|
||||||
|
///
|
||||||
|
/// This will be applied when the announcing block is at some depth within
|
||||||
|
/// the finalized chain.
|
||||||
|
#[derive(Encode, Decode)]
|
||||||
|
pub(crate) struct PendingChange<H, N> {
|
||||||
|
/// The new authorities and weights to apply.
|
||||||
|
pub(crate) next_authorities: Vec<(AuthorityId, usize)>,
|
||||||
|
/// How deep in the finalized chain the announcing block must be
|
||||||
|
/// before the change is applied.
|
||||||
|
pub(crate) finalization_depth: N,
|
||||||
|
/// The announcing block's height.
|
||||||
|
pub(crate) canon_height: N,
|
||||||
|
/// The announcing block's hash.
|
||||||
|
pub(crate) canon_hash: H,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, N: Add + Clone> PendingChange<H, N> {
|
||||||
|
/// Returns the effective number.
|
||||||
|
fn effective_number(&self) -> N {
|
||||||
|
self.canon_height + self.finalization_depth
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ 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_primitives;
|
extern crate substrate_primitives;
|
||||||
|
extern crate substrate_network as network;
|
||||||
extern crate tokio;
|
extern crate tokio;
|
||||||
extern crate parity_codec as codec;
|
extern crate parity_codec as codec;
|
||||||
|
|
||||||
@@ -38,6 +39,9 @@ extern crate parking_lot;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate substrate_keyring as keyring;
|
extern crate substrate_keyring as keyring;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate parity_codec_derive;
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use futures::stream::Fuse;
|
use futures::stream::Fuse;
|
||||||
use futures::sync::mpsc;
|
use futures::sync::mpsc;
|
||||||
@@ -57,7 +61,13 @@ use std::collections::{VecDeque, HashMap};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
|
mod authorities;
|
||||||
|
|
||||||
const LAST_COMPLETED_KEY: &[u8] = b"grandpa_completed_round";
|
const LAST_COMPLETED_KEY: &[u8] = b"grandpa_completed_round";
|
||||||
|
const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters";
|
||||||
|
|
||||||
|
/// round-number, round-state, set indicator
|
||||||
|
type LastCompleted<H> = (u64, RoundState<H>, u64);
|
||||||
|
|
||||||
/// A GRANDPA message for a substrate chain.
|
/// A GRANDPA message for a substrate chain.
|
||||||
pub type Message<Block> = grandpa::Message<<Block as BlockT>::Hash>;
|
pub type Message<Block> = grandpa::Message<<Block as BlockT>::Hash>;
|
||||||
@@ -69,8 +79,7 @@ pub struct Config {
|
|||||||
/// The expected duration for a message to be gossiped across the network.
|
/// The expected duration for a message to be gossiped across the network.
|
||||||
pub gossip_duration: Duration,
|
pub gossip_duration: Duration,
|
||||||
/// The voters.
|
/// The voters.
|
||||||
// TODO: make dynamic
|
pub genesis_voters: Vec<AuthorityId>,
|
||||||
pub voters: Vec<AuthorityId>,
|
|
||||||
/// The local signing key.
|
/// The local signing key.
|
||||||
pub local_key: Option<Arc<ed25519::Pair>>,
|
pub local_key: Option<Arc<ed25519::Pair>>,
|
||||||
}
|
}
|
||||||
@@ -298,15 +307,23 @@ impl<I, N: Network> Drop for ClearOnDrop<I, N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round_localized_payload<E: Encode>(round: u64, message: &E) -> Vec<u8> {
|
fn localized_payload<E: Encode>(round: u64, set_id: u64, message: &E) -> Vec<u8> {
|
||||||
let mut v = message.encode();
|
let mut v = message.encode();
|
||||||
|
|
||||||
round.using_encoded(|s| v.extend(s));
|
round.using_encoded(|s| v.extend(s));
|
||||||
|
set_id.using_encoded(|s| v.extend(s));
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
// converts a message stream into a stream of signed messages.
|
// converts a message stream into a stream of signed messages.
|
||||||
// the output stream checks signatures also.
|
// the output stream checks signatures also.
|
||||||
fn checked_message_stream<Block: BlockT, S>(inner: S, round: u64, voters: Vec<AuthorityId>)
|
fn checked_message_stream<Block: BlockT, S>(
|
||||||
|
round: u64,
|
||||||
|
set_id: u64,
|
||||||
|
inner: S,
|
||||||
|
voters: Vec<AuthorityId>,
|
||||||
|
)
|
||||||
-> impl Stream<Item=SignedMessage<Block>,Error=Error> where
|
-> impl Stream<Item=SignedMessage<Block>,Error=Error> where
|
||||||
S: Stream<Item=Vec<u8>,Error=()>
|
S: Stream<Item=Vec<u8>,Error=()>
|
||||||
{
|
{
|
||||||
@@ -326,7 +343,7 @@ fn checked_message_stream<Block: BlockT, S>(inner: S, round: u64, voters: Vec<Au
|
|||||||
}
|
}
|
||||||
|
|
||||||
let as_public = ::ed25519::Public::from_raw(msg.id.0);
|
let as_public = ::ed25519::Public::from_raw(msg.id.0);
|
||||||
let encoded_raw = round_localized_payload(round, &msg.message);
|
let encoded_raw = localized_payload(round, set_id, &msg.message);
|
||||||
if ::ed25519::verify_strong(&msg.signature, &encoded_raw, as_public) {
|
if ::ed25519::verify_strong(&msg.signature, &encoded_raw, as_public) {
|
||||||
Ok(Some(msg))
|
Ok(Some(msg))
|
||||||
} else {
|
} else {
|
||||||
@@ -339,9 +356,10 @@ fn checked_message_stream<Block: BlockT, S>(inner: S, round: u64, voters: Vec<Au
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn outgoing_messages<Block: BlockT, N: Network>(
|
fn outgoing_messages<Block: BlockT, N: Network>(
|
||||||
|
round: u64,
|
||||||
|
set_id: u64,
|
||||||
local_key: Option<Arc<ed25519::Pair>>,
|
local_key: Option<Arc<ed25519::Pair>>,
|
||||||
voters: Vec<AuthorityId>,
|
voters: Vec<AuthorityId>,
|
||||||
round: u64,
|
|
||||||
network: N,
|
network: N,
|
||||||
) -> (
|
) -> (
|
||||||
impl Stream<Item=SignedMessage<Block>,Error=Error>,
|
impl Stream<Item=SignedMessage<Block>,Error=Error>,
|
||||||
@@ -357,7 +375,7 @@ fn outgoing_messages<Block: BlockT, N: Network>(
|
|||||||
.map(move |msg: Message<Block>| {
|
.map(move |msg: Message<Block>| {
|
||||||
// when locals exist, sign messages on import
|
// when locals exist, sign messages on import
|
||||||
if let Some((ref pair, local_id)) = locals {
|
if let Some((ref pair, local_id)) = locals {
|
||||||
let encoded = round_localized_payload(round, &msg);
|
let encoded = localized_payload(round, set_id, &msg);
|
||||||
let signature = pair.sign(&encoded[..]);
|
let signature = pair.sign(&encoded[..]);
|
||||||
let signed = SignedMessage::<Block> {
|
let signed = SignedMessage::<Block> {
|
||||||
message: msg,
|
message: msg,
|
||||||
@@ -480,17 +498,20 @@ 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);
|
||||||
|
|
||||||
|
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, _>(
|
||||||
self.network.messages_for(round),
|
|
||||||
round,
|
round,
|
||||||
self.config.voters.clone(),
|
set_id,
|
||||||
|
self.network.messages_for(round),
|
||||||
|
self.config.genesis_voters.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (out_rx, outgoing) = outgoing_messages::<Block, _>(
|
let (out_rx, outgoing) = outgoing_messages::<Block, _>(
|
||||||
|
round,
|
||||||
|
set_id,
|
||||||
self.config.local_key.clone(),
|
self.config.local_key.clone(),
|
||||||
self.config.voters.clone(),
|
self.config.voters.clone(),
|
||||||
round,
|
|
||||||
self.network.clone(),
|
self.network.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user