Skip to content

Commit 5815681

Browse files
Expose functions to do preliminary slashing checks (#7783)
Co-Authored-By: Daniel Knopik <[email protected]> Co-Authored-By: Michael Sproul <[email protected]>
1 parent a080bb5 commit 5815681

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ perf.data*
99
*.tar.gz
1010
/bin
1111
genesis.ssz
12-
/clippy.toml
1312
/.cargo
1413

1514
# IntelliJ

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ lint:
249249
-D clippy::fn_to_numeric_cast_any \
250250
-D clippy::manual_let_else \
251251
-D clippy::large_stack_frames \
252+
-D clippy::disallowed_methods \
252253
-D warnings \
253254
-A clippy::derive_partial_eq_without_eq \
254255
-A clippy::upper-case-acronyms \

clippy.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Disallow preliminary slashing checks,
2+
disallowed-methods = [
3+
{ path = "slashing_protection::slashing_database::SlashingDatabase::preliminary_check_block_proposal", reason = "not safe for slashing checks", replacement = "slashing_protection::slashing_database::SlashingDatabase::check_and_insert_block_proposal" },
4+
{ path = "slashing_protection::slashing_database::SlashingDatabase::preliminary_check_block_signing_root", reason = "not safe for slashing checks", replacement = "slashing_protection::slashing_database::SlashingDatabase::check_and_insert_block_signing_root" },
5+
{ path = "slashing_protection::slashing_database::SlashingDatabase::preliminary_check_attestation", reason = "not safe for slashing checks", replacement = "slashing_protection::slashing_database::SlashingDatabase::check_and_insert_attestation" },
6+
{ path = "slashing_protection::slashing_database::SlashingDatabase::preliminary_check_attestation_signing_root", reason = "not safe for slashing checks", replacement = "slashing_protection::slashing_database::SlashingDatabase::check_and_insert_attestation_signing_root" },
7+
]

validator_client/slashing_protection/src/slashing_database.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,40 @@ impl SlashingDatabase {
599599
Ok(safe)
600600
}
601601

602+
/// Check whether a block would be safe to sign if we were to sign it now.
603+
///
604+
/// The database is not modified, and therefore multiple threads reading the database might get
605+
/// the same result. Therefore:
606+
///
607+
/// DO NOT USE THIS FUNCTION TO DECIDE IF A BLOCK IS SAFE TO SIGN!
608+
pub fn preliminary_check_block_proposal(
609+
&self,
610+
validator_pubkey: &PublicKeyBytes,
611+
block_header: &BeaconBlockHeader,
612+
domain: Hash256,
613+
) -> Result<Safe, NotSafe> {
614+
#[allow(clippy::disallowed_methods)]
615+
self.preliminary_check_block_signing_root(
616+
validator_pubkey,
617+
block_header.slot,
618+
block_header.signing_root(domain).into(),
619+
)
620+
}
621+
622+
/// As for `preliminary_check_block_proposal` but without requiring the whole `BeaconBlockHeader`.
623+
///
624+
/// DO NOT USE THIS FUNCTION TO DECIDE IF A BLOCK IS SAFE TO SIGN!
625+
pub fn preliminary_check_block_signing_root(
626+
&self,
627+
validator_pubkey: &PublicKeyBytes,
628+
slot: Slot,
629+
signing_root: SigningRoot,
630+
) -> Result<Safe, NotSafe> {
631+
let mut conn = self.conn_pool.get()?;
632+
let txn = conn.transaction_with_behavior(TransactionBehavior::Exclusive)?;
633+
self.check_block_proposal(&txn, validator_pubkey, slot, signing_root)
634+
}
635+
602636
/// Check an attestation for slash safety, and if it is safe, record it in the database.
603637
///
604638
/// The checking and inserting happen atomically and exclusively. We enforce exclusivity
@@ -670,6 +704,49 @@ impl SlashingDatabase {
670704
Ok(safe)
671705
}
672706

707+
/// Check whether an attestation would be safe to sign if we were to sign it now.
708+
///
709+
/// The database is not modified, and therefore multiple threads reading the database might get
710+
/// the same result. Therefore:
711+
///
712+
/// DO NOT USE THIS FUNCTION TO DECIDE IF AN ATTESTATION IS SAFE TO SIGN!
713+
pub fn preliminary_check_attestation(
714+
&self,
715+
validator_pubkey: &PublicKeyBytes,
716+
attestation: &AttestationData,
717+
domain: Hash256,
718+
) -> Result<Safe, NotSafe> {
719+
let attestation_signing_root = attestation.signing_root(domain).into();
720+
#[allow(clippy::disallowed_methods)]
721+
self.preliminary_check_attestation_signing_root(
722+
validator_pubkey,
723+
attestation.source.epoch,
724+
attestation.target.epoch,
725+
attestation_signing_root,
726+
)
727+
}
728+
729+
/// As for `preliminary_check_attestation` but without requiring the whole `AttestationData`.
730+
///
731+
/// DO NOT USE THIS FUNCTION TO DECIDE IF AN ATTESTATION IS SAFE TO SIGN!
732+
pub fn preliminary_check_attestation_signing_root(
733+
&self,
734+
validator_pubkey: &PublicKeyBytes,
735+
att_source_epoch: Epoch,
736+
att_target_epoch: Epoch,
737+
att_signing_root: SigningRoot,
738+
) -> Result<Safe, NotSafe> {
739+
let mut conn = self.conn_pool.get()?;
740+
let txn = conn.transaction_with_behavior(TransactionBehavior::Exclusive)?;
741+
self.check_attestation(
742+
&txn,
743+
validator_pubkey,
744+
att_source_epoch,
745+
att_target_epoch,
746+
att_signing_root,
747+
)
748+
}
749+
673750
/// Import slashing protection from another client in the interchange format.
674751
///
675752
/// This function will atomically import the entire interchange, failing if *any*

0 commit comments

Comments
 (0)