Skip to content

Commit bba7a11

Browse files
committed
Self review changes
1 parent 8621eb9 commit bba7a11

File tree

6 files changed

+47
-22
lines changed

6 files changed

+47
-22
lines changed

common/task_executor/src/rayon_pool_provider.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub struct RayonPoolProvider {
1515
/// By default ~25% of CPUs or a minimum of 1 thread.
1616
low_priority_thread_pool: Arc<ThreadPool>,
1717
/// Larger rayon thread pool for high-priority, compute-intensive tasks.
18-
/// By default ~80% of CPUs or a minimum of 1 thread. Citical/highest
18+
/// By default ~80% of CPUs or a minimum of 1 thread. Critical/highest
1919
/// priority tasks should use the global pool instead.
2020
high_priority_thread_pool: Arc<ThreadPool>,
2121
}

validator_client/http_api/src/tests/keystores.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,8 @@ async fn generic_migration_test(
11091109
assert_eq!(safe_attestations.len(), 1);
11101110
// Compare data only, ignoring signatures which are added during signing.
11111111
assert_eq!(safe_attestations[0].data(), attestation.data());
1112+
// Check that the signature is non-zero.
1113+
assert!(!safe_attestations[0].signature().is_infinity());
11121114
}
11131115

11141116
// Delete the selected keys from VC1.
@@ -1192,6 +1194,8 @@ async fn generic_migration_test(
11921194
// Compare data only, ignoring signatures which are added during signing.
11931195
assert_eq!(safe_attestations.len(), 1);
11941196
assert_eq!(safe_attestations[0].data(), attestation.data());
1197+
// Check that the signature is non-zero.
1198+
assert!(!safe_attestations[0].signature().is_infinity());
11951199
} else {
11961200
assert!(safe_attestations.is_empty());
11971201
}

validator_client/lighthouse_validator_store/src/lib.rs

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,14 @@ impl<T: SlotClock + 'static, E: EthSpec> LighthouseValidatorStore<T, E> {
558558
})
559559
}
560560

561-
#[instrument(skip_all)]
562-
async fn sign_attestation_no_checks(
561+
/// Sign an attestation without performing any slashing protection checks.
562+
///
563+
/// THIS METHOD IS DANGEROUS AND SHOULD ONLY BE USED INTERNALLY IMMEDIATELY PRIOR TO A
564+
/// SLASHING PROTECTION CHECK. See `slashing_protect_attestations`.
565+
///
566+
/// This method DOES perform doppelganger protection checks.
567+
#[instrument(level = "debug", skip_all)]
568+
async fn sign_attestation_no_slashing_protection(
563569
&self,
564570
validator_pubkey: PublicKeyBytes,
565571
validator_committee_position: usize,
@@ -587,20 +593,27 @@ impl<T: SlotClock + 'static, E: EthSpec> LighthouseValidatorStore<T, E> {
587593
Ok(())
588594
}
589595

590-
#[instrument(
591-
name = "store_check_and_insert_attestations",
592-
level = "debug",
593-
skip_all
594-
)]
595-
fn check_and_insert_attestations(
596+
/// Provide slashing protection for `attestations`, safely updating the slashing protection DB.
597+
///
598+
/// Return a vec of safe attestations which have passed slashing protection. Unsafe attestations
599+
/// will be dropped and result in warning logs.
600+
///
601+
/// This method SKIPS slashing protection for web3signer validators that have slashing
602+
/// protection disabled at the Lighthouse layer. It is up to the user to ensure slashing
603+
/// protection is enabled in web3signer instead.
604+
#[instrument(level = "debug", skip_all)]
605+
fn slashing_protect_attestations(
596606
&self,
597607
attestations: Vec<(Attestation<E>, PublicKeyBytes)>,
598-
) -> Result<Vec<(Attestation<E>, PublicKeyBytes)>, Error> {
599-
let mut safe_attestations = vec![];
600-
let mut attestations_to_check = vec![];
608+
) -> Result<Vec<Attestation<E>>, Error> {
609+
let mut safe_attestations = Vec::with_capacity(attestations.len());
610+
let mut attestations_to_check = Vec::with_capacity(attestations.len());
601611

602612
// Split attestations into de-facto safe attestations (checked by web3signer's slashing
603613
// protection) and ones requiring checking against the slashing protection DB.
614+
//
615+
// All attestations are added to `attestation_to_check`, with skipped attestations having
616+
// `CheckSlashability::No`.
604617
for (attestation, validator_pubkey) in &attestations {
605618
let signing_method = self.doppelganger_checked_signing_method(*validator_pubkey)?;
606619
let signing_epoch = attestation.data().target.epoch;
@@ -636,7 +649,7 @@ impl<T: SlotClock + 'static, E: EthSpec> LighthouseValidatorStore<T, E> {
636649
{
637650
match slashing_status {
638651
Ok(Safe::Valid) => {
639-
safe_attestations.push((attestation, validator_pubkey));
652+
safe_attestations.push(attestation);
640653
validator_metrics::inc_counter_vec(
641654
&validator_metrics::SIGNED_ATTESTATIONS_TOTAL,
642655
&[validator_metrics::SUCCESS],
@@ -881,25 +894,24 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore for LighthouseValidatorS
881894
let pubkey = *pubkey;
882895
let validator_committee_index = *validator_committee_index;
883896
async move {
884-
self.sign_attestation_no_checks(
897+
self.sign_attestation_no_slashing_protection(
885898
pubkey,
886899
validator_committee_index,
887900
attestation,
888901
)
889902
.await
890-
.map(|_| pubkey)
891903
}
892904
});
893905

894906
// Execute all signing in parallel.
895907
let results: Vec<_> = join_all(signing_futures).await;
896908

897909
// Collect successfully signed attestations and log errors.
898-
let mut signed_attestations = Vec::new();
910+
let mut signed_attestations = Vec::with_capacity(attestations.len());
899911
for (result, (pubkey, _, attestation)) in results.into_iter().zip(attestations.into_iter())
900912
{
901913
match result {
902-
Ok(_) => {
914+
Ok(()) => {
903915
signed_attestations.push((attestation, pubkey));
904916
}
905917
Err(ValidatorStoreError::UnknownPubkey(pubkey)) => {
@@ -919,12 +931,12 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore for LighthouseValidatorS
919931
}
920932

921933
if signed_attestations.is_empty() {
922-
return Ok(Vec::new());
934+
return Ok(vec![]);
923935
}
924936

925937
// Check slashing protection and insert into database.
926-
let safe_attestations = self.check_and_insert_attestations(signed_attestations)?;
927-
Ok(safe_attestations.into_iter().map(|(a, _)| a).collect())
938+
let safe_attestations = self.slashing_protect_attestations(signed_attestations)?;
939+
Ok(safe_attestations)
928940
}
929941

930942
async fn sign_validator_registration_data(

validator_client/signing_method/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ impl SigningMethod {
181181
let voting_keypair = voting_keypair.clone();
182182
// Spawn a blocking task to produce the signature. This avoids blocking the core
183183
// tokio executor.
184+
//
185+
// We are using the Rayon high-priority pool which uses up to 80% of available
186+
// threads. In future we could consider using 90-100% in the VC, seeing as we have
187+
// very little other work to do aside from signing.
184188
let signature = executor
185189
.spawn_blocking_with_rayon_async(RayonPoolType::HighPriority, move || {
186190
voting_keypair.sk.sign(signing_root)

validator_client/slashing_protection/src/slashing_database.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,9 @@ impl SlashingDatabase {
194194
U: From<NotSafe>,
195195
{
196196
let mut conn = self.conn_pool.get().map_err(NotSafe::from)?;
197-
let txn = conn.transaction().map_err(NotSafe::from)?;
197+
let txn = conn
198+
.transaction_with_behavior(TransactionBehavior::Exclusive)
199+
.map_err(NotSafe::from)?;
198200
let value = f(&txn)?;
199201
txn.commit().map_err(NotSafe::from)?;
200202
Ok(value)
@@ -659,7 +661,7 @@ impl SlashingDatabase {
659661
let mut conn = self.conn_pool.get()?;
660662
let txn = conn.transaction_with_behavior(TransactionBehavior::Exclusive)?;
661663

662-
let mut results = vec![];
664+
let mut results = Vec::with_capacity(attestations.len());
663665
for (attestation, validator_pubkey, domain, check_slashability) in attestations {
664666
match check_slashability {
665667
CheckSlashability::No => {

validator_client/validator_store/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ pub trait ValidatorStore: Send + Sync {
103103
current_slot: Slot,
104104
) -> impl Future<Output = Result<SignedBlock<Self::E>, Error<Self::Error>>> + Send;
105105

106+
/// Sign a batch of `attestations` and apply slashing protection to them.
107+
///
108+
/// Only successfully signed attestations that pass slashing protection are returned.
106109
#[allow(clippy::type_complexity)]
107110
fn sign_attestations(
108111
&self,

0 commit comments

Comments
 (0)