babe: report equivocations (#6362)

* slots: create primitives crate for consensus slots

* offences: add method to check if an offence is unknown

* babe: initial equivocation reporting implementation

* babe: organize imports

* babe: working equivocation reporting

* babe: add slot number to equivocation proof

* session: move duplicate traits to session primitives

* babe: move equivocation stuff to its own file

* offences: fix test

* session: don't have primitives depend on frame_support

* babe: use opaque type for key owner proof

* babe: cleanup client equivocation reporting

* babe: cleanup equivocation code in pallet

* babe: allow sending signed equivocation reports

* node: fix compilation

* fix test compilation

* babe: return bool on check_equivocation_proof

* babe: add test for equivocation reporting

* babe: add more tests

* babe: add test for validate unsigned

* babe: take slot number in generate_key_ownership_proof API

* babe: add benchmark for equivocation proof checking

* session: add benchmark for membership proof checking

* offences: fix babe benchmark

* babe: add weights based on benchmark results

* babe: adjust weights after benchmarking on reference hardware

* babe: reorder checks in check_and_report_equivocation
This commit is contained in:
André Silva
2020-07-04 11:18:13 +01:00
committed by GitHub
parent 61635e75c1
commit a9c21b8b84
34 changed files with 2031 additions and 275 deletions
@@ -19,6 +19,7 @@
use codec::{Encode, Decode};
use sc_client_api::backend::AuxStore;
use sp_blockchain::{Result as ClientResult, Error as ClientError};
use sp_consensus_slots::EquivocationProof;
use sp_runtime::traits::Header;
const SLOT_HEADER_MAP_KEY: &[u8] = b"slot_header_map";
@@ -44,31 +45,6 @@ fn load_decode<C, T>(backend: &C, key: &[u8]) -> ClientResult<Option<T>>
}
}
/// Represents an equivocation proof.
#[derive(Debug, Clone)]
pub struct EquivocationProof<H> {
slot: u64,
fst_header: H,
snd_header: H,
}
impl<H> EquivocationProof<H> {
/// Get the slot number where the equivocation happened.
pub fn slot(&self) -> u64 {
self.slot
}
/// Get the first header involved in the equivocation.
pub fn fst_header(&self) -> &H {
&self.fst_header
}
/// Get the second header involved in the equivocation.
pub fn snd_header(&self) -> &H {
&self.snd_header
}
}
/// Checks if the header is an equivocation and returns the proof in that case.
///
/// Note: it detects equivocations only when slot_now - slot <= MAX_SLOT_CAPACITY.
@@ -78,7 +54,7 @@ pub fn check_equivocation<C, H, P>(
slot: u64,
header: &H,
signer: &P,
) -> ClientResult<Option<EquivocationProof<H>>>
) -> ClientResult<Option<EquivocationProof<H, P>>>
where
H: Header,
C: AuxStore,
@@ -114,9 +90,10 @@ pub fn check_equivocation<C, H, P>(
// 2) with different hash
if header.hash() != prev_header.hash() {
return Ok(Some(EquivocationProof {
slot, // 3) and mentioning the same slot.
fst_header: prev_header.clone(),
snd_header: header.clone(),
slot_number: slot,
offender: signer.clone(),
first_header: prev_header.clone(),
second_header: header.clone(),
}));
} else {
// We don't need to continue in case of duplicated header,