Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
add some naive equivocation defenses
Browse files Browse the repository at this point in the history
  • Loading branch information
rphmeier committed Jun 7, 2023
1 parent a6a0f80 commit 3afbfe7
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/consensus/aura/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ async-trait = "0.1.68"
codec = { package = "parity-scale-codec", version = "3.0.0", features = [ "derive" ] }
futures = "0.3.28"
tracing = "0.1.37"
lru = "0.10.0"

# Substrate
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
Expand Down
4 changes: 2 additions & 2 deletions client/consensus/aura/src/collators/lookahead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub async fn run<Block, P, BI, CIDP, Client, Backend, RClient, SO, Proposer, CS>
// This is an arbitrary value which is likely guaranteed to exceed any reasonable
// limit, as it would correspond to 10 non-included blocks.
//
// Since we only search for parent blocks which have already been included,
// Since we only search for parent blocks which have already been imported,
// we can guarantee that all imported blocks respect the unincluded segment
// rules specified by the parachain's runtime and thus will never be too deep.
const PARENT_SEARCH_DEPTH: usize = 10;
Expand Down Expand Up @@ -344,6 +344,6 @@ async fn max_ancestry_lookback(
//
// For now, just provide the conservative value of '2'.
// Overestimating can cause problems, as we'd be building on forks of the
// chain that never get included. Underestimating is less of an issue.
// chain that can never get included. Underestimating is less of an issue.
2
}
43 changes: 41 additions & 2 deletions client/consensus/aura/src/equivocation_import_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/// should be thrown out and which ones should be kept.
use codec::{Decode, Encode};
use lru::LruCache;
use cumulus_client_consensus_common::ParachainBlockImportMarker;

use sc_consensus::{
Expand All @@ -36,12 +37,41 @@ use sp_consensus_aura::{AuraApi, Slot, SlotDuration};
use sp_core::crypto::Pair;
use sp_inherents::{CreateInherentDataProviders, InherentDataProvider};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use std::{fmt::Debug, sync::Arc};
use std::{fmt::Debug, num::NonZeroUsize, sync::Arc};

const LRU_WINDOW: usize = 256;
const EQUIVOCATION_LIMIT: usize = 16;

struct NaiveEquivocationDefender {
cache: LruCache<u64, usize>,
}

impl Default for NaiveEquivocationDefender {
fn default() -> Self {
NaiveEquivocationDefender {
cache: LruCache::new(NonZeroUsize::new(LRU_WINDOW).expect("window > 0; qed")),
}
}
}

impl NaiveEquivocationDefender {
// return `true` if equivocation is beyond the limit.
fn insert_and_check(&mut self, slot: Slot) -> bool {
let val = self.cache.get_or_insert_mut(*slot, || 0);
if *val == EQUIVOCATION_LIMIT {
true
} else {
*val += 1;
false
}
}
}

struct Verifier<P, Client, Block, CIDP> {
client: Arc<Client>,
create_inherent_data_providers: CIDP,
slot_duration: SlotDuration,
defender: NaiveEquivocationDefender,
telemetry: Option<TelemetryHandle>,
_marker: std::marker::PhantomData<(Block, P)>,
}
Expand Down Expand Up @@ -88,7 +118,7 @@ where
);

match res {
Ok((pre_header, _slot, seal_digest)) => {
Ok((pre_header, slot, seal_digest)) => {
telemetry!(
self.telemetry;
CONSENSUS_TRACE;
Expand All @@ -100,6 +130,14 @@ where
block_params.post_digests.push(seal_digest);
block_params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
block_params.post_hash = Some(post_hash);

// Check for and reject egregious amounts of equivocations.
if self.defender.insert_and_check(slot) {
return Err(format!(
"Rejecting block {:?} due to excessive equivocations at slot",
post_hash,
));
}
},
Err(aura_internal::SealVerificationError::Deferred(hdr, slot)) => {
telemetry!(
Expand Down Expand Up @@ -207,6 +245,7 @@ where
let verifier = Verifier::<P, _, _, _> {
client,
create_inherent_data_providers,
defender: NaiveEquivocationDefender::default(),
slot_duration,
telemetry,
_marker: std::marker::PhantomData,
Expand Down

0 comments on commit 3afbfe7

Please sign in to comment.