mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 22:21:07 +00:00
Generalize the Consensus Infrastructure (#883)
* Split out Consensus * Supply ImportQueue through network-service - simplify ImportQueue.import_blocks - remove Deadlock on import_block - Adding Verifier-Trait - Implement import_queue provisioning in service; allow cli to import * Allow to actually customize import queue * Consensus Gossip: Cache Message hash per Topic
This commit is contained in:
committed by
GitHub
parent
a24e61cb29
commit
ac4bcf879f
@@ -0,0 +1,94 @@
|
||||
// Copyright 2017-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/>.
|
||||
|
||||
//! Error types in the BFT service.
|
||||
use runtime_version::RuntimeVersion;
|
||||
|
||||
error_chain! {
|
||||
errors {
|
||||
/// Missing state at block with given descriptor.
|
||||
StateUnavailable(b: String) {
|
||||
description("State missing at given block."),
|
||||
display("State unavailable at block {}", b),
|
||||
}
|
||||
|
||||
/// I/O terminated unexpectedly
|
||||
IoTerminated {
|
||||
description("I/O terminated unexpectedly."),
|
||||
display("I/O terminated unexpectedly."),
|
||||
}
|
||||
|
||||
/// Unable to schedule wakeup.
|
||||
FaultyTimer(e: ::tokio::timer::Error) {
|
||||
description("Timer error"),
|
||||
display("Timer error: {}", e),
|
||||
}
|
||||
|
||||
/// Unable to propose a block.
|
||||
CannotPropose {
|
||||
description("Unable to create block proposal."),
|
||||
display("Unable to create block proposal."),
|
||||
}
|
||||
|
||||
/// Error checking signature
|
||||
InvalidSignature(s: ::primitives::ed25519::Signature, a: ::primitives::AuthorityId) {
|
||||
description("Message signature is invalid"),
|
||||
display("Message signature {:?} by {:?} is invalid.", s, a),
|
||||
}
|
||||
|
||||
/// Account is not an authority.
|
||||
InvalidAuthority(a: ::primitives::AuthorityId) {
|
||||
description("Message sender is not a valid authority"),
|
||||
display("Message sender {:?} is not a valid authority.", a),
|
||||
}
|
||||
|
||||
/// Authoring interface does not match the runtime.
|
||||
IncompatibleAuthoringRuntime(native: RuntimeVersion, on_chain: RuntimeVersion) {
|
||||
description("Authoring for current runtime is not supported"),
|
||||
display("Authoring for current runtime is not supported. Native ({}) cannot author for on-chain ({}).", native, on_chain),
|
||||
}
|
||||
|
||||
/// Authoring interface does not match the runtime.
|
||||
RuntimeVersionMissing {
|
||||
description("Current runtime has no version"),
|
||||
display("Authoring for current runtime is not supported since it has no version."),
|
||||
}
|
||||
|
||||
/// Authoring interface does not match the runtime.
|
||||
NativeRuntimeMissing {
|
||||
description("This build has no native runtime"),
|
||||
display("Authoring in current build is not supported since it has no runtime."),
|
||||
}
|
||||
|
||||
/// Justification requirements not met.
|
||||
InvalidJustification {
|
||||
description("Invalid justification"),
|
||||
display("Invalid justification."),
|
||||
}
|
||||
|
||||
/// Some other error.
|
||||
Other(e: Box<::std::error::Error + Send>) {
|
||||
description("Other error")
|
||||
display("Other error: {}", e.description())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::rhododendron::InputStreamConcluded> for Error {
|
||||
fn from(_: ::rhododendron::InputStreamConcluded) -> Error {
|
||||
ErrorKind::IoTerminated.into()
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,192 @@
|
||||
// Copyright 2017-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/>.
|
||||
|
||||
//! Utility for substrate-based runtimes that want to check misbehavior reports.
|
||||
|
||||
use codec::{Codec, Encode};
|
||||
use primitives::{AuthorityId, Signature};
|
||||
|
||||
use rhododendron::messages::{Action, Message, MisbehaviorKind};
|
||||
use runtime_io;
|
||||
|
||||
// check a message signature. returns true if signed by that authority.
|
||||
fn check_message_sig<B: Codec, H: Codec>(
|
||||
message: Message<B, H>,
|
||||
signature: &Signature,
|
||||
from: &AuthorityId
|
||||
) -> bool {
|
||||
let msg: Vec<u8> = message.encode();
|
||||
runtime_io::ed25519_verify(&signature.0, &msg, from)
|
||||
}
|
||||
|
||||
fn prepare<B, H>(parent: H, round_number: u32, hash: H) -> Message<B, H> {
|
||||
Message {
|
||||
parent,
|
||||
action: Action::Prepare(round_number, hash),
|
||||
}
|
||||
}
|
||||
|
||||
fn commit<B, H>(parent: H, round_number: u32, hash: H) -> Message<B, H> {
|
||||
Message {
|
||||
parent,
|
||||
action: Action::Commit(round_number, hash),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate misbehavior.
|
||||
///
|
||||
/// Doesn't check that the header hash in question is
|
||||
/// valid or whether the misbehaving authority was part of
|
||||
/// the set at that block.
|
||||
pub fn evaluate_misbehavior<B: Codec, H: Codec + Copy>(
|
||||
misbehaved: &AuthorityId,
|
||||
parent_hash: H,
|
||||
kind: &MisbehaviorKind<H>,
|
||||
) -> bool {
|
||||
match *kind {
|
||||
MisbehaviorKind::BftDoublePrepare(round, (h_1, ref s_1), (h_2, ref s_2)) => {
|
||||
s_1 != s_2 &&
|
||||
check_message_sig::<B, H>(prepare::<B, H>(parent_hash, round, h_1), s_1, misbehaved) &&
|
||||
check_message_sig::<B, H>(prepare::<B, H>(parent_hash, round, h_2), s_2, misbehaved)
|
||||
}
|
||||
MisbehaviorKind::BftDoubleCommit(round, (h_1, ref s_1), (h_2, ref s_2)) => {
|
||||
s_1 != s_2 &&
|
||||
check_message_sig::<B, H>(commit::<B, H>(parent_hash, round, h_1), s_1, misbehaved) &&
|
||||
check_message_sig::<B, H>(commit::<B, H>(parent_hash, round, h_2), s_2, misbehaved)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use keyring::ed25519;
|
||||
use keyring::Keyring;
|
||||
use rhododendron;
|
||||
|
||||
use runtime_primitives::testing::{H256, Block as RawBlock};
|
||||
|
||||
type Block = RawBlock<u64>;
|
||||
|
||||
fn sign_prepare(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) {
|
||||
let msg = ::sign_message::<Block>(
|
||||
rhododendron::Message::Vote(rhododendron::Vote::Prepare(round as _, hash)),
|
||||
key,
|
||||
parent_hash
|
||||
);
|
||||
|
||||
match msg {
|
||||
rhododendron::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature),
|
||||
_ => panic!("signing vote leads to signed vote"),
|
||||
}
|
||||
}
|
||||
|
||||
fn sign_commit(key: &ed25519::Pair, round: u32, hash: H256, parent_hash: H256) -> (H256, Signature) {
|
||||
let msg = ::sign_message::<Block>(
|
||||
rhododendron::Message::Vote(rhododendron::Vote::Commit(round as _, hash)),
|
||||
key,
|
||||
parent_hash
|
||||
);
|
||||
|
||||
match msg {
|
||||
rhododendron::LocalizedMessage::Vote(vote) => (hash, vote.signature.signature),
|
||||
_ => panic!("signing vote leads to signed vote"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluates_double_prepare() {
|
||||
let key: ed25519::Pair = Keyring::One.into();
|
||||
let parent_hash = [0xff; 32].into();
|
||||
let hash_1 = [0; 32].into();
|
||||
let hash_2 = [1; 32].into();
|
||||
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().into(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoublePrepare(
|
||||
1,
|
||||
sign_prepare(&key, 1, hash_1, parent_hash),
|
||||
sign_prepare(&key, 1, hash_2, parent_hash)
|
||||
)
|
||||
));
|
||||
|
||||
// same signature twice is not misbehavior.
|
||||
let signed = sign_prepare(&key, 1, hash_1, parent_hash);
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().into(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoublePrepare(
|
||||
1,
|
||||
signed,
|
||||
signed,
|
||||
)
|
||||
) == false);
|
||||
|
||||
// misbehavior has wrong target.
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&Keyring::Two.to_raw_public().into(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoublePrepare(
|
||||
1,
|
||||
sign_prepare(&key, 1, hash_1, parent_hash),
|
||||
sign_prepare(&key, 1, hash_2, parent_hash),
|
||||
)
|
||||
) == false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluates_double_commit() {
|
||||
let key: ed25519::Pair = Keyring::One.into();
|
||||
let parent_hash = [0xff; 32].into();
|
||||
let hash_1 = [0; 32].into();
|
||||
let hash_2 = [1; 32].into();
|
||||
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().into(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoubleCommit(
|
||||
1,
|
||||
sign_commit(&key, 1, hash_1, parent_hash),
|
||||
sign_commit(&key, 1, hash_2, parent_hash)
|
||||
)
|
||||
));
|
||||
|
||||
// same signature twice is not misbehavior.
|
||||
let signed = sign_commit(&key, 1, hash_1, parent_hash);
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&key.public().into(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoubleCommit(
|
||||
1,
|
||||
signed,
|
||||
signed,
|
||||
)
|
||||
) == false);
|
||||
|
||||
// misbehavior has wrong target.
|
||||
assert!(evaluate_misbehavior::<Block, H256>(
|
||||
&Keyring::Two.to_raw_public().into(),
|
||||
parent_hash,
|
||||
&MisbehaviorKind::BftDoubleCommit(
|
||||
1,
|
||||
sign_commit(&key, 1, hash_1, parent_hash),
|
||||
sign_commit(&key, 1, hash_2, parent_hash),
|
||||
)
|
||||
) == false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user