@@ -53,7 +53,7 @@ use storage::{
5353 bonds_for_source_prefix, bonds_prefix, consensus_keys_key,
5454 decimal_mult_amount, get_validator_address_from_bond, into_tm_voting_power,
5555 is_bond_key, is_unbond_key, is_validator_slashes_key,
56- last_block_proposer_key, mult_change_to_amount , params_key, slashes_prefix,
56+ last_block_proposer_key, params_key, slashes_prefix,
5757 unbonds_for_source_prefix, unbonds_prefix, validator_address_raw_hash_key,
5858 validator_last_slash_key, validator_max_commission_rate_change_key,
5959 BondDetails , BondsAndUnbondsDetail , BondsAndUnbondsDetails ,
@@ -2584,6 +2584,7 @@ where
25842584 let validator = bond_id. validator . clone ( ) ;
25852585 let ( bonds, _unbonds) = bonds_and_unbonds. entry ( bond_id) . or_default ( ) ;
25862586 bonds. push ( make_bond_details (
2587+ params,
25872588 & validator,
25882589 change,
25892590 start,
@@ -2647,6 +2648,7 @@ where
26472648 . filter ( |( _start, change) | * change > token:: Change :: default ( ) )
26482649 . map ( |( start, change) | {
26492650 make_bond_details (
2651+ params,
26502652 & validator,
26512653 change,
26522654 start,
@@ -2679,8 +2681,8 @@ where
26792681 Ok ( HashMap :: from_iter ( [ ( bond_id, details) ] ) )
26802682}
26812683
2682- // TODO: check carefully for validity
26832684fn make_bond_details (
2685+ params : & PosParams ,
26842686 validator : & Address ,
26852687 change : token:: Change ,
26862688 start : Epoch ,
@@ -2693,36 +2695,37 @@ fn make_bond_details(
26932695 . cloned ( )
26942696 . unwrap_or_default ( ) ;
26952697 let amount = token:: Amount :: from_change ( change) ;
2696- let slashed_amount =
2697- slashes
2698- . iter ( )
2699- . fold ( None , |acc : Option < token:: Amount > , slash| {
2700- if slash. epoch >= start {
2701- let validator_slashes =
2702- applied_slashes. entry ( validator. clone ( ) ) . or_default ( ) ;
2703- if !prev_applied_slashes
2704- . iter ( )
2705- . any ( |s| s. clone ( ) == slash. clone ( ) )
2706- {
2707- validator_slashes. push ( slash. clone ( ) ) ;
2708- }
2709- return Some (
2710- acc. unwrap_or_default ( )
2711- + mult_change_to_amount ( slash. rate , change) ,
2712- ) ;
2713- }
2714- acc
2715- } ) ;
2716- let slashed_amount =
2717- slashed_amount. map ( |slashed| cmp:: min ( amount, slashed) ) ;
2698+ let mut slash_rates_by_epoch = BTreeMap :: < Epoch , Decimal > :: new ( ) ;
2699+
2700+ let validator_slashes =
2701+ applied_slashes. entry ( validator. clone ( ) ) . or_default ( ) ;
2702+ for slash in slashes {
2703+ if slash. epoch >= start {
2704+ let cur_rate = slash_rates_by_epoch. entry ( slash. epoch ) . or_default ( ) ;
2705+ * cur_rate = cmp:: min ( Decimal :: ONE , * cur_rate + slash. rate ) ;
2706+
2707+ if !prev_applied_slashes. iter ( ) . any ( |s| s == slash) {
2708+ validator_slashes. push ( slash. clone ( ) ) ;
2709+ }
2710+ }
2711+ }
2712+
2713+ let slashed_amount = if slash_rates_by_epoch. is_empty ( ) {
2714+ None
2715+ } else {
2716+ let amount_after_slashing = token:: Amount :: from_change (
2717+ get_slashed_amount ( params, amount, & slash_rates_by_epoch) . unwrap ( ) ,
2718+ ) ;
2719+ Some ( amount - amount_after_slashing)
2720+ } ;
2721+
27182722 BondDetails {
27192723 start,
27202724 amount,
27212725 slashed_amount,
27222726 }
27232727}
27242728
2725- // TODO: check carefully for validity
27262729fn make_unbond_details (
27272730 params : & PosParams ,
27282731 validator : & Address ,
@@ -2736,37 +2739,38 @@ fn make_unbond_details(
27362739 . get ( validator)
27372740 . cloned ( )
27382741 . unwrap_or_default ( ) ;
2739- // TODO: checks bounds for considering valid unbond with slash!
2740- let slashed_amount =
2741- slashes
2742- . iter ( )
2743- . fold ( None , |acc : Option < token:: Amount > , slash| {
2744- if slash. epoch >= start
2745- && slash. epoch
2746- < withdraw
2747- . checked_sub ( Epoch (
2748- params. unbonding_len
2749- + params. cubic_slashing_window_length ,
2750- ) )
2751- . unwrap_or_default ( )
2752- {
2753- let validator_slashes =
2754- applied_slashes. entry ( validator. clone ( ) ) . or_default ( ) ;
2755- if !prev_applied_slashes
2756- . iter ( )
2757- . any ( |s| s. clone ( ) == slash. clone ( ) )
2758- {
2759- validator_slashes. push ( slash. clone ( ) ) ;
2760- }
2761- return Some (
2762- acc. unwrap_or_default ( )
2763- + decimal_mult_amount ( slash. rate , amount) ,
2764- ) ;
2765- }
2766- acc
2767- } ) ;
2768- let slashed_amount =
2769- slashed_amount. map ( |slashed| cmp:: min ( amount, slashed) ) ;
2742+ let mut slash_rates_by_epoch = BTreeMap :: < Epoch , Decimal > :: new ( ) ;
2743+
2744+ let validator_slashes =
2745+ applied_slashes. entry ( validator. clone ( ) ) . or_default ( ) ;
2746+ for slash in slashes {
2747+ if slash. epoch >= start
2748+ && slash. epoch
2749+ < withdraw
2750+ . checked_sub ( Epoch (
2751+ params. unbonding_len
2752+ + params. cubic_slashing_window_length ,
2753+ ) )
2754+ . unwrap_or_default ( )
2755+ {
2756+ let cur_rate = slash_rates_by_epoch. entry ( slash. epoch ) . or_default ( ) ;
2757+ * cur_rate = cmp:: min ( Decimal :: ONE , * cur_rate + slash. rate ) ;
2758+
2759+ if !prev_applied_slashes. iter ( ) . any ( |s| s == slash) {
2760+ validator_slashes. push ( slash. clone ( ) ) ;
2761+ }
2762+ }
2763+ }
2764+
2765+ let slashed_amount = if slash_rates_by_epoch. is_empty ( ) {
2766+ None
2767+ } else {
2768+ let amount_after_slashing = token:: Amount :: from_change (
2769+ get_slashed_amount ( params, amount, & slash_rates_by_epoch) . unwrap ( ) ,
2770+ ) ;
2771+ Some ( amount - amount_after_slashing)
2772+ } ;
2773+
27702774 UnbondDetails {
27712775 start,
27722776 withdraw,
0 commit comments