mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 13:24:44 +00:00
Fix slasher tests (#5906)
* Fix electra tests * Add electra attestations to double vote tests
This commit is contained in:
@@ -60,49 +60,46 @@ impl<E: EthSpec> AttesterSlashingStatus<E> {
|
||||
Ok(match self {
|
||||
NotSlashable => None,
|
||||
AlreadyDoubleVoted => None,
|
||||
DoubleVote(existing) | SurroundedByExisting(existing) => match *existing {
|
||||
IndexedAttestation::Base(existing_att) => {
|
||||
Some(AttesterSlashing::Base(AttesterSlashingBase {
|
||||
attestation_1: existing_att,
|
||||
attestation_2: new_attestation
|
||||
.as_base()
|
||||
.map_err(|e| format!("{e:?}"))?
|
||||
.clone(),
|
||||
}))
|
||||
}
|
||||
IndexedAttestation::Electra(existing_att) => {
|
||||
Some(AttesterSlashing::Electra(AttesterSlashingElectra {
|
||||
attestation_1: existing_att,
|
||||
// A double vote should never convert, a surround vote where the surrounding
|
||||
// vote is electra may convert.
|
||||
DoubleVote(existing) | SurroundedByExisting(existing) => {
|
||||
match (&*existing, new_attestation) {
|
||||
(IndexedAttestation::Base(existing_att), IndexedAttestation::Base(new)) => {
|
||||
Some(AttesterSlashing::Base(AttesterSlashingBase {
|
||||
attestation_1: existing_att.clone(),
|
||||
attestation_2: new.clone(),
|
||||
}))
|
||||
}
|
||||
// A slashing involving an electra attestation type must return an `AttesterSlashingElectra` type
|
||||
(_, _) => Some(AttesterSlashing::Electra(AttesterSlashingElectra {
|
||||
attestation_1: existing
|
||||
.clone()
|
||||
.to_electra()
|
||||
.map_err(|e| format!("{e:?}"))?,
|
||||
attestation_2: new_attestation
|
||||
.clone()
|
||||
.to_electra()
|
||||
.map_err(|e| format!("{e:?}"))?,
|
||||
}))
|
||||
}
|
||||
},
|
||||
SurroundsExisting(existing) => {
|
||||
match new_attestation {
|
||||
IndexedAttestation::Base(new_attestation) => {
|
||||
Some(AttesterSlashing::Base(AttesterSlashingBase {
|
||||
attestation_1: existing
|
||||
.as_base()
|
||||
.map_err(|e| format!("{e:?}"))?
|
||||
.clone(),
|
||||
attestation_2: new_attestation.clone(),
|
||||
}))
|
||||
}
|
||||
IndexedAttestation::Electra(new_attestation) => {
|
||||
Some(AttesterSlashing::Electra(AttesterSlashingElectra {
|
||||
attestation_1: existing.to_electra().map_err(|e| format!("{e:?}"))?,
|
||||
// A double vote should never convert, a surround vote where the surrounding
|
||||
// vote is electra may convert.
|
||||
attestation_2: new_attestation.clone(),
|
||||
}))
|
||||
}
|
||||
})),
|
||||
}
|
||||
}
|
||||
SurroundsExisting(existing) => match (&*existing, new_attestation) {
|
||||
(IndexedAttestation::Base(existing_att), IndexedAttestation::Base(new)) => {
|
||||
Some(AttesterSlashing::Base(AttesterSlashingBase {
|
||||
attestation_1: new.clone(),
|
||||
attestation_2: existing_att.clone(),
|
||||
}))
|
||||
}
|
||||
// A slashing involving an electra attestation type must return an `AttesterSlashingElectra` type
|
||||
(_, _) => Some(AttesterSlashing::Electra(AttesterSlashingElectra {
|
||||
attestation_1: new_attestation
|
||||
.clone()
|
||||
.to_electra()
|
||||
.map_err(|e| format!("{e:?}"))?,
|
||||
attestation_2: existing
|
||||
.clone()
|
||||
.to_electra()
|
||||
.map_err(|e| format!("{e:?}"))?,
|
||||
})),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ pub fn att_slashing(
|
||||
attestation_1: &IndexedAttestation<E>,
|
||||
attestation_2: &IndexedAttestation<E>,
|
||||
) -> AttesterSlashing<E> {
|
||||
// TODO(electra): fix this one we superstruct IndexedAttestation (return the correct type)
|
||||
match (attestation_1, attestation_2) {
|
||||
(IndexedAttestation::Base(att1), IndexedAttestation::Base(att2)) => {
|
||||
AttesterSlashing::Base(AttesterSlashingBase {
|
||||
@@ -71,13 +70,11 @@ pub fn att_slashing(
|
||||
attestation_2: att2.clone(),
|
||||
})
|
||||
}
|
||||
(IndexedAttestation::Electra(att1), IndexedAttestation::Electra(att2)) => {
|
||||
AttesterSlashing::Electra(AttesterSlashingElectra {
|
||||
attestation_1: att1.clone(),
|
||||
attestation_2: att2.clone(),
|
||||
})
|
||||
}
|
||||
_ => panic!("attestations must be of the same type"),
|
||||
// A slashing involving an electra attestation type must return an electra AttesterSlashing type
|
||||
(_, _) => AttesterSlashing::Electra(AttesterSlashingElectra {
|
||||
attestation_1: attestation_1.clone().to_electra().unwrap(),
|
||||
attestation_2: attestation_2.clone().to_electra().unwrap(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ use maplit::hashset;
|
||||
use rayon::prelude::*;
|
||||
use slasher::{
|
||||
config::DEFAULT_CHUNK_SIZE,
|
||||
test_utils::{att_slashing, indexed_att, slashed_validators_from_slashings, E},
|
||||
test_utils::{
|
||||
att_slashing, indexed_att, indexed_att_electra, slashed_validators_from_slashings, E,
|
||||
},
|
||||
Config, Slasher,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
@@ -15,23 +17,35 @@ use types::{AttesterSlashing, Epoch, IndexedAttestation};
|
||||
#[test]
|
||||
fn double_vote_single_val() {
|
||||
let v = vec![99];
|
||||
let att1 = indexed_att(&v, 0, 1, 0);
|
||||
let att2 = indexed_att(&v, 0, 1, 1);
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
for (att1, att2) in [
|
||||
(indexed_att(&v, 0, 1, 0), indexed_att(&v, 0, 1, 1)),
|
||||
(
|
||||
indexed_att_electra(&v, 0, 1, 0),
|
||||
indexed_att_electra(&v, 0, 1, 1),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_vote_multi_vals() {
|
||||
let v = vec![0, 1, 2];
|
||||
let att1 = indexed_att(&v, 0, 1, 0);
|
||||
let att2 = indexed_att(&v, 0, 1, 1);
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
for (att1, att2) in [
|
||||
(indexed_att(&v, 0, 1, 0), indexed_att(&v, 0, 1, 1)),
|
||||
(
|
||||
indexed_att_electra(&v, 0, 1, 0),
|
||||
indexed_att_electra(&v, 0, 1, 1),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// A subset of validators double vote.
|
||||
@@ -39,12 +53,18 @@ fn double_vote_multi_vals() {
|
||||
fn double_vote_some_vals() {
|
||||
let v1 = vec![0, 1, 2, 3, 4, 5, 6];
|
||||
let v2 = vec![0, 2, 4, 6];
|
||||
let att1 = indexed_att(v1, 0, 1, 0);
|
||||
let att2 = indexed_att(v2, 0, 1, 1);
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
for (att1, att2) in [
|
||||
(indexed_att(&v1, 0, 1, 0), indexed_att(&v2, 0, 1, 1)),
|
||||
(
|
||||
indexed_att_electra(&v1, 0, 1, 0),
|
||||
indexed_att_electra(&v2, 0, 1, 1),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// A subset of validators double vote, others vote twice for the same thing.
|
||||
@@ -53,13 +73,23 @@ fn double_vote_some_vals_repeat() {
|
||||
let v1 = vec![0, 1, 2, 3, 4, 5, 6];
|
||||
let v2 = vec![0, 2, 4, 6];
|
||||
let v3 = vec![1, 3, 5];
|
||||
let att1 = indexed_att(v1, 0, 1, 0);
|
||||
let att2 = indexed_att(v2, 0, 1, 1);
|
||||
let att3 = indexed_att(v3, 0, 1, 0);
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2, att3];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
for (att1, att2, att3) in [
|
||||
(
|
||||
indexed_att(&v1, 0, 1, 0),
|
||||
indexed_att(&v2, 0, 1, 1),
|
||||
indexed_att(&v3, 0, 1, 0),
|
||||
),
|
||||
(
|
||||
indexed_att_electra(&v1, 0, 1, 0),
|
||||
indexed_att_electra(&v2, 0, 1, 1),
|
||||
indexed_att_electra(&v3, 0, 1, 0),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2, att3];
|
||||
slasher_test_indiv(&attestations, &slashings, 1);
|
||||
slasher_test_indiv(&attestations, &slashings, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Nobody double votes, nobody gets slashed.
|
||||
@@ -67,11 +97,17 @@ fn double_vote_some_vals_repeat() {
|
||||
fn no_double_vote_same_target() {
|
||||
let v1 = vec![0, 1, 2, 3, 4, 5, 6];
|
||||
let v2 = vec![0, 1, 2, 3, 4, 5, 7, 8];
|
||||
let att1 = indexed_att(v1, 0, 1, 0);
|
||||
let att2 = indexed_att(v2, 0, 1, 0);
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1);
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1000);
|
||||
for (att1, att2) in [
|
||||
(indexed_att(&v1, 0, 1, 0), indexed_att(&v2, 0, 1, 0)),
|
||||
(
|
||||
indexed_att_electra(&v1, 0, 1, 0),
|
||||
indexed_att_electra(&v2, 0, 1, 0),
|
||||
),
|
||||
] {
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1);
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Two groups votes for different things, no slashings.
|
||||
@@ -79,73 +115,133 @@ fn no_double_vote_same_target() {
|
||||
fn no_double_vote_distinct_vals() {
|
||||
let v1 = vec![0, 1, 2, 3];
|
||||
let v2 = vec![4, 5, 6, 7];
|
||||
let att1 = indexed_att(v1, 0, 1, 0);
|
||||
let att2 = indexed_att(v2, 0, 1, 1);
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1);
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1000);
|
||||
for (att1, att2) in [
|
||||
(indexed_att(&v1, 0, 1, 0), indexed_att(&v2, 0, 1, 0)),
|
||||
(
|
||||
indexed_att_electra(&v1, 0, 1, 0),
|
||||
indexed_att_electra(&v2, 0, 1, 1),
|
||||
),
|
||||
] {
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1);
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_double_vote_repeated() {
|
||||
let v = vec![0, 1, 2, 3, 4];
|
||||
let att1 = indexed_att(v, 0, 1, 0);
|
||||
let att2 = att1.clone();
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1);
|
||||
slasher_test_batch(&attestations, &hashset! {}, 1);
|
||||
parallel_slasher_test(&attestations, hashset! {}, 1);
|
||||
for att1 in [indexed_att(&v, 0, 1, 0), indexed_att_electra(&v, 0, 1, 0)] {
|
||||
let att2 = att1.clone();
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &hashset! {}, 1);
|
||||
slasher_test_batch(&attestations, &hashset! {}, 1);
|
||||
parallel_slasher_test(&attestations, hashset! {}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn surrounds_existing_single_val_single_chunk() {
|
||||
let v = vec![0];
|
||||
let att1 = indexed_att(&v, 1, 2, 0);
|
||||
let att2 = indexed_att(&v, 0, 3, 0);
|
||||
let slashings = hashset![att_slashing(&att2, &att1)];
|
||||
slasher_test_indiv(&[att1, att2], &slashings, 3);
|
||||
for (att1, att2) in [
|
||||
(indexed_att(&v, 1, 2, 0), indexed_att(&v, 0, 3, 0)),
|
||||
(indexed_att(&v, 1, 2, 0), indexed_att_electra(&v, 0, 3, 0)),
|
||||
(
|
||||
indexed_att_electra(&v, 1, 2, 0),
|
||||
indexed_att_electra(&v, 0, 3, 0),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att2, &att1)];
|
||||
slasher_test_indiv(&[att1, att2], &slashings, 3);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn surrounds_existing_multi_vals_single_chunk() {
|
||||
let validators = vec![0, 16, 1024, 300_000, 300_001];
|
||||
let att1 = indexed_att(validators.clone(), 1, 2, 0);
|
||||
let att2 = indexed_att(validators, 0, 3, 0);
|
||||
let slashings = hashset![att_slashing(&att2, &att1)];
|
||||
slasher_test_indiv(&[att1, att2], &slashings, 3);
|
||||
for (att1, att2) in [
|
||||
(
|
||||
indexed_att(&validators, 1, 2, 0),
|
||||
indexed_att(&validators, 0, 3, 0),
|
||||
),
|
||||
(
|
||||
indexed_att(&validators, 1, 2, 0),
|
||||
indexed_att_electra(&validators, 0, 3, 0),
|
||||
),
|
||||
(
|
||||
indexed_att_electra(&validators, 1, 2, 0),
|
||||
indexed_att_electra(&validators, 0, 3, 0),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att2, &att1)];
|
||||
slasher_test_indiv(&[att1, att2], &slashings, 3);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn surrounds_existing_many_chunks() {
|
||||
let v = vec![0];
|
||||
let chunk_size = DEFAULT_CHUNK_SIZE as u64;
|
||||
let att1 = indexed_att(&v, 3 * chunk_size, 3 * chunk_size + 1, 0);
|
||||
let att2 = indexed_att(&v, 0, 3 * chunk_size + 2, 0);
|
||||
let slashings = hashset![att_slashing(&att2, &att1)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 4 * chunk_size);
|
||||
for (att1, att2) in [
|
||||
(
|
||||
indexed_att(&v, 3 * chunk_size, 3 * chunk_size + 1, 0),
|
||||
indexed_att(&v, 0, 3 * chunk_size + 2, 0),
|
||||
),
|
||||
(
|
||||
indexed_att(&v, 3 * chunk_size, 3 * chunk_size + 1, 0),
|
||||
indexed_att_electra(&v, 0, 3 * chunk_size + 2, 0),
|
||||
),
|
||||
(
|
||||
indexed_att_electra(&v, 3 * chunk_size, 3 * chunk_size + 1, 0),
|
||||
indexed_att_electra(&v, 0, 3 * chunk_size + 2, 0),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att2, &att1)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 4 * chunk_size);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn surrounded_by_single_val_single_chunk() {
|
||||
let v = vec![0];
|
||||
let att1 = indexed_att(&v, 0, 15, 0);
|
||||
let att2 = indexed_att(&v, 1, 14, 0);
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 15);
|
||||
for (att1, att2) in [
|
||||
(indexed_att(&v, 0, 15, 0), indexed_att(&v, 1, 14, 0)),
|
||||
(indexed_att(&v, 0, 15, 0), indexed_att_electra(&v, 1, 14, 0)),
|
||||
(
|
||||
indexed_att_electra(&v, 0, 15, 0),
|
||||
indexed_att_electra(&v, 1, 14, 0),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 15);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn surrounded_by_single_val_multi_chunk() {
|
||||
let v = vec![0];
|
||||
let chunk_size = DEFAULT_CHUNK_SIZE as u64;
|
||||
let att1 = indexed_att(&v, 0, 3 * chunk_size, 0);
|
||||
let att2 = indexed_att(&v, chunk_size, chunk_size + 1, 0);
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 3 * chunk_size);
|
||||
slasher_test_indiv(&attestations, &slashings, 4 * chunk_size);
|
||||
for (att1, att2) in [
|
||||
(
|
||||
indexed_att(&v, 0, 3 * chunk_size, 0),
|
||||
indexed_att(&v, chunk_size, chunk_size + 1, 0),
|
||||
),
|
||||
(
|
||||
indexed_att(&v, 0, 3 * chunk_size, 0),
|
||||
indexed_att_electra(&v, chunk_size, chunk_size + 1, 0),
|
||||
),
|
||||
(
|
||||
indexed_att_electra(&v, 0, 3 * chunk_size, 0),
|
||||
indexed_att_electra(&v, chunk_size, chunk_size + 1, 0),
|
||||
),
|
||||
] {
|
||||
let slashings = hashset![att_slashing(&att1, &att2)];
|
||||
let attestations = vec![att1, att2];
|
||||
slasher_test_indiv(&attestations, &slashings, 3 * chunk_size);
|
||||
slasher_test_indiv(&attestations, &slashings, 4 * chunk_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Process each attestation individually, and confirm that the slashings produced are as expected.
|
||||
|
||||
Reference in New Issue
Block a user