@@ -62,6 +62,7 @@ use sp_runtime::{
6262 traits:: { Saturating , Zero } ,
6363 DispatchResult , Perbill , RuntimeDebug ,
6464} ;
65+ use sp_staking:: offence:: DisableStrategy ;
6566use sp_std:: {
6667 ops:: { Add , AddAssign , Sub } ,
6768 prelude:: * ,
@@ -298,6 +299,8 @@ pub struct SlashParams<'a, T: 'a + Config> {
298299 /// The maximum percentage of a slash that ever gets paid out.
299300 /// This is f_inf in the paper.
300301 pub reward_proportion : Perbill ,
302+ /// When to disable offenders.
303+ pub disable_strategy : DisableStrategy ,
301304}
302305
303306/// Computes a slash of a validator and nominators. It returns an unapplied
@@ -309,30 +312,33 @@ pub struct SlashParams<'a, T: 'a + Config> {
309312pub fn compute_slash < T : Config > (
310313 params : SlashParams < T > ,
311314) -> Option < UnappliedSlash < T :: AccountId , RingBalance < T > , KtonBalance < T > > > {
312- let SlashParams { stash, slash, exposure, slash_era, window_start, now, reward_proportion } =
313- params. clone ( ) ;
314-
315315 let mut reward_payout = Zero :: zero ( ) ;
316316 let mut val_slashed = Zero :: zero ( ) ;
317317
318318 // is the slash amount here a maximum for the era?
319- let own_slash =
320- RK { r : slash * exposure. own_ring_balance , k : slash * exposure. own_kton_balance } ;
321- if ( slash * exposure. total_power ) . is_zero ( ) {
319+ let own_slash = RK {
320+ r : params. slash * params. exposure . own_ring_balance ,
321+ k : params. slash * params. exposure . own_kton_balance ,
322+ } ;
323+ if ( params. slash * params. exposure . total_power ) . is_zero ( ) {
322324 // kick out the validator even if they won't be slashed,
323325 // as long as the misbehavior is from their most recent slashing span.
324326 kick_out_if_recent :: < T > ( params) ;
325327 return None ;
326328 }
327329
328330 let ( prior_slash_p, _era_slash) =
329- <Pallet < T > as Store >:: ValidatorSlashInEra :: get ( & slash_era, stash)
331+ <Pallet < T > as Store >:: ValidatorSlashInEra :: get ( & params . slash_era , params . stash )
330332 . unwrap_or ( ( Perbill :: zero ( ) , Zero :: zero ( ) ) ) ;
331333
332334 // compare slash proportions rather than slash values to avoid issues due to rounding
333335 // error.
334- if slash. deconstruct ( ) > prior_slash_p. deconstruct ( ) {
335- <Pallet < T > as Store >:: ValidatorSlashInEra :: insert ( & slash_era, stash, & ( slash, own_slash) ) ;
336+ if params. slash . deconstruct ( ) > prior_slash_p. deconstruct ( ) {
337+ <Pallet < T > as Store >:: ValidatorSlashInEra :: insert (
338+ & params. slash_era ,
339+ params. stash ,
340+ & ( params. slash , own_slash) ,
341+ ) ;
336342 } else {
337343 // we slash based on the max in era - this new event is not the max,
338344 // so neither the validator or any nominators will need an update.
@@ -347,35 +353,34 @@ pub fn compute_slash<T: Config>(
347353 // apply slash to validator.
348354 {
349355 let mut spans = fetch_spans :: < T > (
350- stash,
351- window_start,
356+ params . stash ,
357+ params . window_start ,
352358 & mut reward_payout,
353359 & mut val_slashed,
354- reward_proportion,
360+ params . reward_proportion ,
355361 ) ;
356362
357- let target_span = spans. compare_and_update_span_slash ( slash_era, own_slash) ;
363+ let target_span = spans. compare_and_update_span_slash ( params . slash_era , own_slash) ;
358364
359365 if target_span == Some ( spans. span_index ( ) ) {
360366 // misbehavior occurred within the current slashing span - take appropriate
361367 // actions.
362368
363369 // chill the validator - it misbehaved in the current span and should
364370 // not continue in the next election. also end the slashing span.
365- spans. end_span ( now) ;
366- <Pallet < T > >:: chill_stash ( stash) ;
371+ spans. end_span ( params . now ) ;
372+ <Pallet < T > >:: chill_stash ( params . stash ) ;
367373 }
368374 }
369375
370- // add the validator to the offenders list and make sure it is disabled for
371- // the duration of the era
372- add_offending_validator :: < T > ( params. stash , true ) ;
376+ let disable_when_slashed = params. disable_strategy != DisableStrategy :: Never ;
377+ add_offending_validator :: < T > ( params. stash , disable_when_slashed) ;
373378
374379 let mut nominators_slashed = vec ! [ ] ;
375- reward_payout += slash_nominators :: < T > ( params, prior_slash_p, & mut nominators_slashed) ;
380+ reward_payout += slash_nominators :: < T > ( params. clone ( ) , prior_slash_p, & mut nominators_slashed) ;
376381
377382 Some ( UnappliedSlash {
378- validator : stash. clone ( ) ,
383+ validator : params . stash . clone ( ) ,
379384 own : val_slashed,
380385 others : nominators_slashed,
381386 reporters : vec ! [ ] ,
@@ -402,9 +407,8 @@ fn kick_out_if_recent<T: Config>(params: SlashParams<T>) {
402407 <Pallet < T > >:: chill_stash ( params. stash ) ;
403408 }
404409
405- // add the validator to the offenders list but since there's no slash being
406- // applied there's no need to disable the validator
407- add_offending_validator :: < T > ( params. stash , false ) ;
410+ let disable_without_slash = params. disable_strategy == DisableStrategy :: Always ;
411+ add_offending_validator :: < T > ( params. stash , disable_without_slash) ;
408412}
409413
410414/// Add the given validator to the offenders list and optionally disable it.
@@ -457,13 +461,10 @@ fn slash_nominators<T: Config>(
457461 prior_slash_p : Perbill ,
458462 nominators_slashed : & mut Vec < ( T :: AccountId , RKT < T > ) > ,
459463) -> RKT < T > {
460- let SlashParams { stash : _, slash, exposure, slash_era, window_start, now, reward_proportion } =
461- params;
462-
463464 let mut reward_payout = Zero :: zero ( ) ;
464465
465- nominators_slashed. reserve ( exposure. others . len ( ) ) ;
466- for nominator in & exposure. others {
466+ nominators_slashed. reserve ( params . exposure . others . len ( ) ) ;
467+ for nominator in & params . exposure . others {
467468 let stash = & nominator. who ;
468469 let mut nom_slashed = Zero :: zero ( ) ;
469470
@@ -474,16 +475,19 @@ fn slash_nominators<T: Config>(
474475 r : prior_slash_p * nominator. ring_balance ,
475476 k : prior_slash_p * nominator. kton_balance ,
476477 } ;
477- let own_slash_by_validator =
478- RK { r : slash * nominator. ring_balance , k : slash * nominator. kton_balance } ;
478+ let own_slash_by_validator = RK {
479+ r : params. slash * nominator. ring_balance ,
480+ k : params. slash * nominator. kton_balance ,
481+ } ;
479482 let own_slash_difference = own_slash_by_validator. saturating_sub ( own_slash_prior) ;
480483
481- let mut era_slash = <Pallet < T > as Store >:: NominatorSlashInEra :: get ( & slash_era, stash)
482- . unwrap_or_else ( || Zero :: zero ( ) ) ;
484+ let mut era_slash =
485+ <Pallet < T > as Store >:: NominatorSlashInEra :: get ( & params. slash_era , stash)
486+ . unwrap_or_else ( || Zero :: zero ( ) ) ;
483487
484488 era_slash += own_slash_difference;
485489
486- <Pallet < T > as Store >:: NominatorSlashInEra :: insert ( & slash_era, stash, & era_slash) ;
490+ <Pallet < T > as Store >:: NominatorSlashInEra :: insert ( & params . slash_era , stash, & era_slash) ;
487491
488492 era_slash
489493 } ;
@@ -492,18 +496,18 @@ fn slash_nominators<T: Config>(
492496 {
493497 let mut spans = fetch_spans :: < T > (
494498 stash,
495- window_start,
499+ params . window_start ,
496500 & mut reward_payout,
497501 & mut nom_slashed,
498- reward_proportion,
502+ params . reward_proportion ,
499503 ) ;
500504
501- let target_span = spans. compare_and_update_span_slash ( slash_era, era_slash) ;
505+ let target_span = spans. compare_and_update_span_slash ( params . slash_era , era_slash) ;
502506
503507 if target_span == Some ( spans. span_index ( ) ) {
504508 // End the span, but don't chill the nominator. its nomination
505509 // on this validator will be ignored in the future.
506- spans. end_span ( now) ;
510+ spans. end_span ( params . now ) ;
507511 }
508512 }
509513
0 commit comments