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
+22 -9
View File
@@ -505,9 +505,8 @@ impl<B, E, Block: BlockT<Hash=H256>, N, RA> voter::Environment<Block::Hash, Numb
);
let encoded_state = (round, state).encode();
if let Err(e) = self.inner.backend()
.insert_aux(&[(LAST_COMPLETED_KEY, &encoded_state[..])], &[])
{
let res = Backend::insert_aux(&**self.inner.backend(), &[(LAST_COMPLETED_KEY, &encoded_state[..])], &[]);
if let Err(e) = res {
warn!(target: "afg", "Shutting down voter due to error bookkeeping last completed round in DB: {:?}", e);
Err(Error::Client(e).into())
} else {
@@ -737,7 +736,8 @@ fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
let last_completed: LastCompleted<_, _> = (0, round_state);
let encoded = last_completed.encode();
client.backend().insert_aux(
Backend::insert_aux(
&**client.backend(),
&[
(AUTHORITY_SET_KEY, &encoded_set[..]),
(LAST_COMPLETED_KEY, &encoded[..]),
@@ -745,7 +745,7 @@ fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
&[]
)
} else {
client.backend().insert_aux(&[(AUTHORITY_SET_KEY, &encoded_set[..])], &[])
Backend::insert_aux(&**client.backend(), &[(AUTHORITY_SET_KEY, &encoded_set[..])], &[])
};
if let Err(e) = write_result {
@@ -954,7 +954,7 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, PRA> BlockImport<Block>
)?;
let encoded = authorities.encode();
self.inner.backend().insert_aux(&[(AUTHORITY_SET_KEY, &encoded[..])], &[])?;
Backend::insert_aux(&**self.inner.backend(), &[(AUTHORITY_SET_KEY, &encoded[..])], &[])?;
};
let enacts_change = self.authority_set.inner().read().enacts_change(number, |canon_number| {
@@ -1066,6 +1066,19 @@ where
}
}
impl<B, E, Block: BlockT<Hash=H256>, RA, PRA> ProvideRuntimeApi for GrandpaBlockImport<B, E, Block, RA, PRA>
where
B: Backend<Block, Blake2Hasher> + 'static,
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
PRA: ProvideRuntimeApi,
{
type Api = PRA::Api;
fn runtime_api<'a>(&'a self) -> ::runtime_primitives::traits::ApiRef<'a, Self::Api> {
self.api.runtime_api()
}
}
/// Half of a link between a block-import worker and a the background voter.
// This should remain non-clone.
pub struct LinkHalf<B, E, Block: BlockT<Hash=H256>, RA> {
@@ -1131,7 +1144,7 @@ pub fn block_import<B, E, Block: BlockT<Hash=H256>, RA, PRA>(
PRA::Api: GrandpaApi<Block>
{
use runtime_primitives::traits::Zero;
let authority_set = match client.backend().get_aux(AUTHORITY_SET_KEY)? {
let authority_set = match Backend::get_aux(&**client.backend(), AUTHORITY_SET_KEY)? {
None => {
info!(target: "afg", "Loading GRANDPA authorities \
from genesis on what appears to be first startup.");
@@ -1144,7 +1157,7 @@ pub fn block_import<B, E, Block: BlockT<Hash=H256>, RA, PRA>(
let authority_set = SharedAuthoritySet::genesis(genesis_authorities);
let encoded = authority_set.inner().read().encode();
client.backend().insert_aux(&[(AUTHORITY_SET_KEY, &encoded[..])], &[])?;
Backend::insert_aux(&**client.backend(), &[(AUTHORITY_SET_KEY, &encoded[..])], &[])?;
authority_set
}
@@ -1261,7 +1274,7 @@ pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA>(
let chain_info = client.info()?;
let genesis_hash = chain_info.chain.genesis_hash;
let (last_round_number, last_state) = match client.backend().get_aux(LAST_COMPLETED_KEY)? {
let (last_round_number, last_state) = match Backend::get_aux(&**client.backend(), LAST_COMPLETED_KEY)? {
None => (0, RoundState::genesis((genesis_hash, <NumberFor<Block>>::zero()))),
Some(raw) => LastCompleted::decode(&mut &raw[..])
.ok_or_else(|| ::client::error::ErrorKind::Backend(