Punish offline validators, aura-style (#1216)

* make offline-reporting infrastructure more generic

* add a listener-trait for watching when the timestamp has been set

* prevent inclusion of empty offline reports

* add test for exclusion

* generate aura-offline reports

* ability to slash many times for being offline "multiple" times

* Logic for punishing validators for missing aura steps

* stub tests

* pave way for verification of timestamp vs slot

* alter aura import queue to wait for timestamp

* check timestamp matches seal

* do inherent check properly

* service compiles

* all tests compile

* test srml-aura logic

* aura tests pass

* everything builds

* some more final tweaks to block authorship for aura

* switch to manual delays before step

* restore substrate-consensus-aura to always std and address grumbles

* update some state roots in executor tests

* node-executor tests pass

* get most tests passing

* address grumbles
This commit is contained in:
Robert Habermeier
2018-12-10 18:37:08 +01:00
committed by GitHub
parent dcc38fe45a
commit 6299b42a4d
41 changed files with 1344 additions and 379 deletions
-2
View File
@@ -12,7 +12,6 @@ futures = "0.1"
exit-future = "0.1"
substrate-cli = { path = "../../core/cli" }
parity-codec = { version = "2.1" }
parking_lot = "0.4"
slog = "^2"
sr-io = { path = "../../core/sr-io" }
substrate-client = { path = "../../core/client" }
@@ -24,7 +23,6 @@ substrate-service = { path = "../../core/service" }
substrate-transaction-pool = { path = "../../core/transaction-pool" }
substrate-network = { path = "../../core/network" }
substrate-consensus-aura = { path = "../../core/consensus/aura" }
substrate-consensus-common = { path = "../../core/consensus/common" }
substrate-finality-grandpa = { path = "../../core/finality-grandpa" }
sr-primitives = { path = "../../core/sr-primitives" }
node-executor = { path = "../executor" }
+3 -3
View File
@@ -50,7 +50,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
const CENTS: u128 = 1_000 * MILLICENTS; // assume this is worth about a cent.
const DOLLARS: u128 = 100 * CENTS;
const SECS_PER_BLOCK: u64 = 4;
const SECS_PER_BLOCK: u64 = 6;
const MINUTES: u64 = 60 / SECS_PER_BLOCK;
const HOURS: u64 = MINUTES * 60;
const DAYS: u64 = HOURS * 24;
@@ -111,7 +111,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
enact_delay_period: 0,
}),
timestamp: Some(TimestampConfig {
period: SECS_PER_BLOCK,
period: SECS_PER_BLOCK / 2, // due to the nature of aura the slots are 2*period
}),
treasury: Some(TreasuryConfig {
proposal_bond: Permill::from_percent(5),
@@ -234,7 +234,7 @@ pub fn testnet_genesis(
enact_delay_period: 0,
}),
timestamp: Some(TimestampConfig {
period: 5, // 5 second block time.
period: 2, // 2*2=4 second block time.
}),
treasury: Some(TreasuryConfig {
proposal_bond: Permill::from_percent(5),
-2
View File
@@ -33,7 +33,6 @@ extern crate substrate_transaction_pool as transaction_pool;
#[macro_use]
extern crate substrate_network as network;
extern crate substrate_consensus_aura as consensus;
extern crate substrate_consensus_common as consensus_common;
extern crate substrate_client as client;
extern crate substrate_finality_grandpa as grandpa;
extern crate node_primitives;
@@ -45,7 +44,6 @@ extern crate substrate_keystore;
#[macro_use]
extern crate log;
extern crate structopt;
extern crate parking_lot;
pub use cli::error;
pub mod chain_spec;
+29 -29
View File
@@ -21,22 +21,18 @@
use std::sync::Arc;
use transaction_pool::{self, txpool::{Pool as TransactionPool}};
use node_runtime::{GenesisConfig, RuntimeApi};
use node_primitives::Block;
use node_primitives::{Block, InherentData};
use substrate_service::{
FactoryFullConfiguration, LightComponents, FullComponents, FullBackend,
FullClient, LightClient, LightBackend, FullExecutor, LightExecutor, TaskExecutor
};
use node_executor;
use consensus::{import_queue, start_aura, Config as AuraConfig, AuraImportQueue, NothingExtra};
use consensus_common::offline_tracker::OfflineTracker;
use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra};
use primitives::ed25519::Pair;
use client;
use std::time::Duration;
use parking_lot::RwLock;
use grandpa;
const AURA_SLOT_DURATION: u64 = 6;
construct_simple_protocol! {
/// Demo protocol attachment for substrate.
pub struct NodeProtocol where Block = Block { }
@@ -105,15 +101,13 @@ construct_service_factory! {
let proposer = Arc::new(substrate_service::ProposerFactory {
client: service.client(),
transaction_pool: service.transaction_pool(),
offline: Arc::new(RwLock::new(OfflineTracker::new())),
force_delay: 0 // FIXME: allow this to be configured https://github.com/paritytech/substrate/issues/1170
});
let client = service.client();
executor.spawn(start_aura(
AuraConfig {
local_key: Some(key),
slot_duration: AURA_SLOT_DURATION,
},
service.client(),
SlotDuration::get_or_compute(&*client)?,
key,
client,
block_import.clone(),
proposer,
service.network(),
@@ -124,31 +118,39 @@ construct_service_factory! {
},
LightService = LightComponents<Self>
{ |config, executor| <LightComponents<Factory>>::new(config, executor) },
FullImportQueue = AuraImportQueue<Self::Block, grandpa::BlockImportForService<Self>, NothingExtra>
FullImportQueue = AuraImportQueue<
Self::Block,
grandpa::BlockImportForService<Self>,
NothingExtra,
::consensus::InherentProducingFn<InherentData>,
>
{ |config: &mut FactoryFullConfiguration<Self> , client: Arc<FullClient<Self>>| {
let slot_duration = SlotDuration::get_or_compute(&*client)?;
let (block_import, link_half) = grandpa::block_import::<_, _, _, RuntimeApi, FullClient<Self>>(client.clone(), client)?;
let block_import = Arc::new(block_import);
config.custom.grandpa_import_setup = Some((block_import.clone(), link_half));
Ok(import_queue(
AuraConfig {
local_key: None,
slot_duration: 5
},
slot_duration,
block_import,
NothingExtra,
::consensus::make_basic_inherent as _,
))
}},
LightImportQueue = AuraImportQueue<Self::Block, LightClient<Self>, NothingExtra>
{ |ref mut config, client| Ok(
import_queue(AuraConfig {
local_key: None,
slot_duration: 5
},
client,
NothingExtra,
))
LightImportQueue = AuraImportQueue<
Self::Block,
LightClient<Self>,
NothingExtra,
::consensus::InherentProducingFn<InherentData>,
>
{ |ref mut config, client: Arc<LightClient<Self>>|
Ok(import_queue(
SlotDuration::get_or_compute(&*client)?,
client,
NothingExtra,
::consensus::make_basic_inherent as _,
))
},
}
}
@@ -165,7 +167,6 @@ mod tests {
let bob: Arc<ed25519::Pair> = Arc::new(Keyring::Bob.into());
let validators = vec![alice.public().0.into(), bob.public().0.into()];
let keys: Vec<&ed25519::Pair> = vec![&*alice, &*bob];
let offline = Arc::new(RwLock::new(OfflineTracker::new()));
let dummy_runtime = ::tokio::runtime::Runtime::new().unwrap();
let block_factory = |service: &<Factory as service::ServiceFactory>::FullService| {
let block_id = BlockId::number(service.client().info().unwrap().chain.best_number);
@@ -175,7 +176,6 @@ mod tests {
client: service.client().clone(),
transaction_pool: service.transaction_pool().clone(),
network: consensus_net,
offline: offline.clone(),
force_delay: 0,
handle: dummy_runtime.executor(),
};