Fix slasher tests (#5906)

* Fix electra tests

* Add electra attestations to double vote tests
This commit is contained in:
Pawan Dhananjay
2024-06-13 19:27:36 -07:00
committed by GitHub
parent b21b1086f1
commit 35e07eb0a9
3 changed files with 201 additions and 111 deletions

View File

@@ -60,49 +60,46 @@ impl<E: EthSpec> AttesterSlashingStatus<E> {
Ok(match self { Ok(match self {
NotSlashable => None, NotSlashable => None,
AlreadyDoubleVoted => None, AlreadyDoubleVoted => None,
DoubleVote(existing) | SurroundedByExisting(existing) => match *existing { DoubleVote(existing) | SurroundedByExisting(existing) => {
IndexedAttestation::Base(existing_att) => { match (&*existing, new_attestation) {
Some(AttesterSlashing::Base(AttesterSlashingBase { (IndexedAttestation::Base(existing_att), IndexedAttestation::Base(new)) => {
attestation_1: existing_att, Some(AttesterSlashing::Base(AttesterSlashingBase {
attestation_2: new_attestation attestation_1: existing_att.clone(),
.as_base() attestation_2: new.clone(),
.map_err(|e| format!("{e:?}"))? }))
.clone(), }
})) // A slashing involving an electra attestation type must return an `AttesterSlashingElectra` type
} (_, _) => Some(AttesterSlashing::Electra(AttesterSlashingElectra {
IndexedAttestation::Electra(existing_att) => { attestation_1: existing
Some(AttesterSlashing::Electra(AttesterSlashingElectra { .clone()
attestation_1: existing_att, .to_electra()
// A double vote should never convert, a surround vote where the surrounding .map_err(|e| format!("{e:?}"))?,
// vote is electra may convert.
attestation_2: new_attestation attestation_2: new_attestation
.clone() .clone()
.to_electra() .to_electra()
.map_err(|e| format!("{e:?}"))?, .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:?}"))?,
})),
},
}) })
} }
} }

View File

@@ -63,7 +63,6 @@ pub fn att_slashing(
attestation_1: &IndexedAttestation<E>, attestation_1: &IndexedAttestation<E>,
attestation_2: &IndexedAttestation<E>, attestation_2: &IndexedAttestation<E>,
) -> AttesterSlashing<E> { ) -> AttesterSlashing<E> {
// TODO(electra): fix this one we superstruct IndexedAttestation (return the correct type)
match (attestation_1, attestation_2) { match (attestation_1, attestation_2) {
(IndexedAttestation::Base(att1), IndexedAttestation::Base(att2)) => { (IndexedAttestation::Base(att1), IndexedAttestation::Base(att2)) => {
AttesterSlashing::Base(AttesterSlashingBase { AttesterSlashing::Base(AttesterSlashingBase {
@@ -71,13 +70,11 @@ pub fn att_slashing(
attestation_2: att2.clone(), attestation_2: att2.clone(),
}) })
} }
(IndexedAttestation::Electra(att1), IndexedAttestation::Electra(att2)) => { // A slashing involving an electra attestation type must return an electra AttesterSlashing type
AttesterSlashing::Electra(AttesterSlashingElectra { (_, _) => AttesterSlashing::Electra(AttesterSlashingElectra {
attestation_1: att1.clone(), attestation_1: attestation_1.clone().to_electra().unwrap(),
attestation_2: att2.clone(), attestation_2: attestation_2.clone().to_electra().unwrap(),
}) }),
}
_ => panic!("attestations must be of the same type"),
} }
} }

View File

@@ -5,7 +5,9 @@ use maplit::hashset;
use rayon::prelude::*; use rayon::prelude::*;
use slasher::{ use slasher::{
config::DEFAULT_CHUNK_SIZE, 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, Config, Slasher,
}; };
use std::collections::HashSet; use std::collections::HashSet;
@@ -15,23 +17,35 @@ use types::{AttesterSlashing, Epoch, IndexedAttestation};
#[test] #[test]
fn double_vote_single_val() { fn double_vote_single_val() {
let v = vec![99]; let v = vec![99];
let att1 = indexed_att(&v, 0, 1, 0); for (att1, att2) in [
let att2 = indexed_att(&v, 0, 1, 1); (indexed_att(&v, 0, 1, 0), indexed_att(&v, 0, 1, 1)),
let slashings = hashset![att_slashing(&att1, &att2)]; (
let attestations = vec![att1, att2]; indexed_att_electra(&v, 0, 1, 0),
slasher_test_indiv(&attestations, &slashings, 1); indexed_att_electra(&v, 0, 1, 1),
slasher_test_indiv(&attestations, &slashings, 1000); ),
] {
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] #[test]
fn double_vote_multi_vals() { fn double_vote_multi_vals() {
let v = vec![0, 1, 2]; let v = vec![0, 1, 2];
let att1 = indexed_att(&v, 0, 1, 0); for (att1, att2) in [
let att2 = indexed_att(&v, 0, 1, 1); (indexed_att(&v, 0, 1, 0), indexed_att(&v, 0, 1, 1)),
let slashings = hashset![att_slashing(&att1, &att2)]; (
let attestations = vec![att1, att2]; indexed_att_electra(&v, 0, 1, 0),
slasher_test_indiv(&attestations, &slashings, 1); indexed_att_electra(&v, 0, 1, 1),
slasher_test_indiv(&attestations, &slashings, 1000); ),
] {
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. // A subset of validators double vote.
@@ -39,12 +53,18 @@ fn double_vote_multi_vals() {
fn double_vote_some_vals() { fn double_vote_some_vals() {
let v1 = vec![0, 1, 2, 3, 4, 5, 6]; let v1 = vec![0, 1, 2, 3, 4, 5, 6];
let v2 = vec![0, 2, 4, 6]; let v2 = vec![0, 2, 4, 6];
let att1 = indexed_att(v1, 0, 1, 0); for (att1, att2) in [
let att2 = indexed_att(v2, 0, 1, 1); (indexed_att(&v1, 0, 1, 0), indexed_att(&v2, 0, 1, 1)),
let slashings = hashset![att_slashing(&att1, &att2)]; (
let attestations = vec![att1, att2]; indexed_att_electra(&v1, 0, 1, 0),
slasher_test_indiv(&attestations, &slashings, 1); indexed_att_electra(&v2, 0, 1, 1),
slasher_test_indiv(&attestations, &slashings, 1000); ),
] {
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. // 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 v1 = vec![0, 1, 2, 3, 4, 5, 6];
let v2 = vec![0, 2, 4, 6]; let v2 = vec![0, 2, 4, 6];
let v3 = vec![1, 3, 5]; let v3 = vec![1, 3, 5];
let att1 = indexed_att(v1, 0, 1, 0); for (att1, att2, att3) in [
let att2 = indexed_att(v2, 0, 1, 1); (
let att3 = indexed_att(v3, 0, 1, 0); indexed_att(&v1, 0, 1, 0),
let slashings = hashset![att_slashing(&att1, &att2)]; indexed_att(&v2, 0, 1, 1),
let attestations = vec![att1, att2, att3]; indexed_att(&v3, 0, 1, 0),
slasher_test_indiv(&attestations, &slashings, 1); ),
slasher_test_indiv(&attestations, &slashings, 1000); (
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. // Nobody double votes, nobody gets slashed.
@@ -67,11 +97,17 @@ fn double_vote_some_vals_repeat() {
fn no_double_vote_same_target() { fn no_double_vote_same_target() {
let v1 = vec![0, 1, 2, 3, 4, 5, 6]; let v1 = vec![0, 1, 2, 3, 4, 5, 6];
let v2 = vec![0, 1, 2, 3, 4, 5, 7, 8]; let v2 = vec![0, 1, 2, 3, 4, 5, 7, 8];
let att1 = indexed_att(v1, 0, 1, 0); for (att1, att2) in [
let att2 = indexed_att(v2, 0, 1, 0); (indexed_att(&v1, 0, 1, 0), indexed_att(&v2, 0, 1, 0)),
let attestations = vec![att1, att2]; (
slasher_test_indiv(&attestations, &hashset! {}, 1); indexed_att_electra(&v1, 0, 1, 0),
slasher_test_indiv(&attestations, &hashset! {}, 1000); 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. // Two groups votes for different things, no slashings.
@@ -79,73 +115,133 @@ fn no_double_vote_same_target() {
fn no_double_vote_distinct_vals() { fn no_double_vote_distinct_vals() {
let v1 = vec![0, 1, 2, 3]; let v1 = vec![0, 1, 2, 3];
let v2 = vec![4, 5, 6, 7]; let v2 = vec![4, 5, 6, 7];
let att1 = indexed_att(v1, 0, 1, 0); for (att1, att2) in [
let att2 = indexed_att(v2, 0, 1, 1); (indexed_att(&v1, 0, 1, 0), indexed_att(&v2, 0, 1, 0)),
let attestations = vec![att1, att2]; (
slasher_test_indiv(&attestations, &hashset! {}, 1); indexed_att_electra(&v1, 0, 1, 0),
slasher_test_indiv(&attestations, &hashset! {}, 1000); 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] #[test]
fn no_double_vote_repeated() { fn no_double_vote_repeated() {
let v = vec![0, 1, 2, 3, 4]; let v = vec![0, 1, 2, 3, 4];
let att1 = indexed_att(v, 0, 1, 0); for att1 in [indexed_att(&v, 0, 1, 0), indexed_att_electra(&v, 0, 1, 0)] {
let att2 = att1.clone(); let att2 = att1.clone();
let attestations = vec![att1, att2]; let attestations = vec![att1, att2];
slasher_test_indiv(&attestations, &hashset! {}, 1); slasher_test_indiv(&attestations, &hashset! {}, 1);
slasher_test_batch(&attestations, &hashset! {}, 1); slasher_test_batch(&attestations, &hashset! {}, 1);
parallel_slasher_test(&attestations, hashset! {}, 1); parallel_slasher_test(&attestations, hashset! {}, 1);
}
} }
#[test] #[test]
fn surrounds_existing_single_val_single_chunk() { fn surrounds_existing_single_val_single_chunk() {
let v = vec![0]; let v = vec![0];
let att1 = indexed_att(&v, 1, 2, 0); for (att1, att2) in [
let att2 = indexed_att(&v, 0, 3, 0); (indexed_att(&v, 1, 2, 0), indexed_att(&v, 0, 3, 0)),
let slashings = hashset![att_slashing(&att2, &att1)]; (indexed_att(&v, 1, 2, 0), indexed_att_electra(&v, 0, 3, 0)),
slasher_test_indiv(&[att1, att2], &slashings, 3); (
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] #[test]
fn surrounds_existing_multi_vals_single_chunk() { fn surrounds_existing_multi_vals_single_chunk() {
let validators = vec![0, 16, 1024, 300_000, 300_001]; let validators = vec![0, 16, 1024, 300_000, 300_001];
let att1 = indexed_att(validators.clone(), 1, 2, 0); for (att1, att2) in [
let att2 = indexed_att(validators, 0, 3, 0); (
let slashings = hashset![att_slashing(&att2, &att1)]; indexed_att(&validators, 1, 2, 0),
slasher_test_indiv(&[att1, att2], &slashings, 3); 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] #[test]
fn surrounds_existing_many_chunks() { fn surrounds_existing_many_chunks() {
let v = vec![0]; let v = vec![0];
let chunk_size = DEFAULT_CHUNK_SIZE as u64; let chunk_size = DEFAULT_CHUNK_SIZE as u64;
let att1 = indexed_att(&v, 3 * chunk_size, 3 * chunk_size + 1, 0); for (att1, att2) in [
let att2 = indexed_att(&v, 0, 3 * chunk_size + 2, 0); (
let slashings = hashset![att_slashing(&att2, &att1)]; indexed_att(&v, 3 * chunk_size, 3 * chunk_size + 1, 0),
let attestations = vec![att1, att2]; indexed_att(&v, 0, 3 * chunk_size + 2, 0),
slasher_test_indiv(&attestations, &slashings, 4 * chunk_size); ),
(
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] #[test]
fn surrounded_by_single_val_single_chunk() { fn surrounded_by_single_val_single_chunk() {
let v = vec![0]; let v = vec![0];
let att1 = indexed_att(&v, 0, 15, 0); for (att1, att2) in [
let att2 = indexed_att(&v, 1, 14, 0); (indexed_att(&v, 0, 15, 0), indexed_att(&v, 1, 14, 0)),
let slashings = hashset![att_slashing(&att1, &att2)]; (indexed_att(&v, 0, 15, 0), indexed_att_electra(&v, 1, 14, 0)),
let attestations = vec![att1, att2]; (
slasher_test_indiv(&attestations, &slashings, 15); 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] #[test]
fn surrounded_by_single_val_multi_chunk() { fn surrounded_by_single_val_multi_chunk() {
let v = vec![0]; let v = vec![0];
let chunk_size = DEFAULT_CHUNK_SIZE as u64; let chunk_size = DEFAULT_CHUNK_SIZE as u64;
let att1 = indexed_att(&v, 0, 3 * chunk_size, 0); for (att1, att2) in [
let att2 = indexed_att(&v, chunk_size, chunk_size + 1, 0); (
let slashings = hashset![att_slashing(&att1, &att2)]; indexed_att(&v, 0, 3 * chunk_size, 0),
let attestations = vec![att1, att2]; indexed_att(&v, chunk_size, chunk_size + 1, 0),
slasher_test_indiv(&attestations, &slashings, 3 * chunk_size); ),
slasher_test_indiv(&attestations, &slashings, 4 * chunk_size); (
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. // Process each attestation individually, and confirm that the slashings produced are as expected.