From 8b94a9c34d8fd240674581d3b6fec54cd569851f Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Fri, 10 Jan 2025 18:48:43 +0100 Subject: [PATCH 1/2] Alpha: refactor apply_block_denounciations --- .../delegate_slashed_deposits_storage.ml | 191 +++++++++--------- 1 file changed, 95 insertions(+), 96 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml index 9d6deb9d05e7..785f1b62b1f0 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -189,6 +189,93 @@ let get_applicable_and_remaining_denunciations ctxt current_cycle = in Lwt.return (new_block_map, new_remaining_denunciations)) +(* This function only considers the baker's current stake (his own and that of + its stakers), it does not consider the unstake requests. *) +let init_to_burn_and_reward ctxt global_limit_of_staking_over_baking delegate + punishing_amount = + let open Lwt_result_syntax in + let* {baker_part; stakers_part = _} = + Shared_stake.share ~rounding:`Towards_baker ctxt delegate punishing_amount + (* Ensures: + + - [baker_part + stakers_part = punishing_amount] + + - [baker_part / punishing_amount = own_frozen / (own_frozen + allowed_staked_frozen)] + + where [allowed_staked_frozen] is [staked_frozen] + capped by the delegate's [limit_of_staking_over_baking], + which notably means that [allowed_staked_frozen <= staked_frozen] + i.e. [own_frozen + allowed_staked_frozen <= own_frozen + staked_frozen = current_amount] + + Combining all of the above: + + [baker_part / punishing_amount >= own_frozen / current_amount] + + [(punishing_amount - stakers_part) / punishing_amount >= (current_amount - staked_frozen) / current_amount] + + [1 - (stakers_part / punishing_amount) >= 1 - (staked_frozen / current_amount)] + + [stakers_part / punishing_amount <= staked_frozen / current_amount] + + [stakers_part <= staked_frozen * punishing_amount / current_amount] + + Moreover, we know from above that [punishing_amount <= current_amount] so: + + [stakers_part <= staked_frozen] + *) + in + let* full_staking_balance = + Stake_storage.get_full_staking_balance ctxt delegate + in + let own_frozen = Full_staking_balance_repr.own_frozen full_staking_balance in + let actual_baker_part = Tez_repr.min baker_part own_frozen in + let*? actual_stakers_part = + Tez_repr.(punishing_amount -? actual_baker_part) + in + (* To avoid underflows, we need to guarantee that: + - [actual_baker_part <= own_frozen] and + - [actual_stakers_part <= staked_frozen] + + The [min] ensures that [actual_baker_part <= own_frozen]. + + For [actual_stakers_part], let's examine two cases + based on the [min]: + + - Case 1: [actual_baker_part = baker_part] + + [actual_stakers_part = punishing_amount - actual_baker_part + = punishing_amount - baker_part + = stakers_part + <= staked_frozen] as proven above + + - Case 2: [actual_baker_part = own_frozen] + + [actual_stakers_part = punishing_amount - actual_baker_part + = punishing_amount - own_frozen + <= current_amount - own_frozen + = own_frozen + staked_frozen - own_frozen + = staked_frozen] + *) + let*? {amount_to_burn = to_burn_baker; reward = to_reward_baker} = + split_reward_and_burn actual_baker_part global_limit_of_staking_over_baking + in + let*? {amount_to_burn = to_burn_stakers; reward = to_reward_stakers} = + split_reward_and_burn + actual_stakers_part + global_limit_of_staking_over_baking + in + let giver_baker = `Frozen_deposits (Frozen_staker_repr.baker delegate) in + let giver_stakers = + `Frozen_deposits (Frozen_staker_repr.shared_between_stakers ~delegate) + in + let init_to_burn = + [(giver_baker, to_burn_baker); (giver_stakers, to_burn_stakers)] + in + let init_to_reward = + [(giver_baker, to_reward_baker); (giver_stakers, to_reward_stakers)] + in + return (init_to_burn, init_to_reward) + let apply_block_denunciations ctxt current_cycle block_denunciations_map = let slashable_deposits_period = Constants_storage.slashable_deposits_period ctxt @@ -302,109 +389,21 @@ let apply_block_denunciations ctxt current_cycle block_denunciations_map = = own_frozen + staked_frozen] *) in - let* {baker_part; stakers_part = _} = - Shared_stake.share - ~rounding:`Towards_baker + let* init_to_burn, init_to_reward = + init_to_burn_and_reward ctxt + global_limit_of_staking_over_baking delegate punishing_amount - (* Ensures: - - - [baker_part + stakers_part = punishing_amount] - - - [baker_part / punishing_amount = own_frozen / (own_frozen + allowed_staked_frozen)] - - where [allowed_staked_frozen] is [staked_frozen] - capped by the delegate's [limit_of_staking_over_baking], - which notably means that [allowed_staked_frozen <= staked_frozen] - i.e. [own_frozen + allowed_staked_frozen <= own_frozen + staked_frozen = current_amount] - - Combining all of the above: - - [baker_part / punishing_amount >= own_frozen / current_amount] - - [(punishing_amount - stakers_part) / punishing_amount >= (current_amount - staked_frozen) / current_amount] - - [1 - (stakers_part / punishing_amount) >= 1 - (staked_frozen / current_amount)] - - [stakers_part / punishing_amount <= staked_frozen / current_amount] - - [stakers_part <= staked_frozen * punishing_amount / current_amount] - - Moreover, we know from above that [punishing_amount <= current_amount] so: - - [stakers_part <= staked_frozen] - *) - in - let* full_staking_balance = - Stake_storage.get_full_staking_balance ctxt delegate - in - let own_frozen = - Full_staking_balance_repr.own_frozen full_staking_balance - in - let actual_baker_part = Tez_repr.min baker_part own_frozen in - let*? actual_stakers_part = - Tez_repr.(punishing_amount -? actual_baker_part) in - (* To avoid underflows, we need to guarantee that: - - [actual_baker_part <= own_frozen] and - - [actual_stakers_part <= staked_frozen] - - The [min] ensures that [actual_baker_part <= own_frozen]. - - For [actual_stakers_part], let's examine two cases - based on the [min]: - - - Case 1: [actual_baker_part = baker_part] - - [actual_stakers_part = punishing_amount - actual_baker_part - = punishing_amount - baker_part - = stakers_part - <= staked_frozen] as proven above - - - Case 2: [actual_baker_part = own_frozen] - - [actual_stakers_part = punishing_amount - actual_baker_part - = punishing_amount - own_frozen - <= current_amount - own_frozen - = own_frozen + staked_frozen - own_frozen - = staked_frozen] - *) - let*? {amount_to_burn = to_burn_baker; reward = to_reward_baker} = - split_reward_and_burn - actual_baker_part - global_limit_of_staking_over_baking + let oldest_slashable_cycle = + Cycle_repr.sub misbehaviour_cycle slashable_deposits_period + |> Option.value ~default:Cycle_repr.root in - let*? {amount_to_burn = to_burn_stakers; reward = to_reward_stakers} - = - split_reward_and_burn - actual_stakers_part - global_limit_of_staking_over_baking - in - let giver_baker = - `Frozen_deposits (Frozen_staker_repr.baker delegate) - in - let giver_stakers = - `Frozen_deposits - (Frozen_staker_repr.shared_between_stakers ~delegate) - in - let init_to_burn = - [(giver_baker, to_burn_baker); (giver_stakers, to_burn_stakers)] - in - let init_to_reward = - [ - (giver_baker, to_reward_baker); - (giver_stakers, to_reward_stakers); - ] + let slashable_cycles = + Cycle_repr.(oldest_slashable_cycle ---> misbehaviour_cycle) in let* to_burn, to_reward = - let oldest_slashable_cycle = - Cycle_repr.sub misbehaviour_cycle slashable_deposits_period - |> Option.value ~default:Cycle_repr.root - in - let slashable_cycles = - Cycle_repr.(oldest_slashable_cycle ---> misbehaviour_cycle) - in List.fold_left_es (fun (to_burn, to_reward) cycle -> let* frozen_deposits = -- GitLab From 8026226705ed910ef6399a1e5f80b6ad942014cb Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 14 Jan 2025 07:24:39 +0100 Subject: [PATCH 2/2] Alpha: rename `apply_block_denunciations` to `apply_cycle_denunciations` Rename this function in `Delegate_slashed_deposits_storage`, because it applies (at the end of a cycle) pending denunciations accumulated during the cycle. --- .../lib_protocol/delegate_slashed_deposits_storage.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml index 785f1b62b1f0..069a1a4f5da0 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -276,7 +276,7 @@ let init_to_burn_and_reward ctxt global_limit_of_staking_over_baking delegate in return (init_to_burn, init_to_reward) -let apply_block_denunciations ctxt current_cycle block_denunciations_map = +let apply_cycle_denunciations ctxt current_cycle block_denunciations_map = let slashable_deposits_period = Constants_storage.slashable_deposits_period ctxt in @@ -453,7 +453,7 @@ let apply_denunciations ctxt = get_applicable_and_remaining_denunciations ctxt current_cycle in let* ctxt, balance_updates = - apply_block_denunciations ctxt current_cycle applicable_denunciations_map + apply_cycle_denunciations ctxt current_cycle applicable_denunciations_map in return (ctxt, balance_updates, remaining_denunciations) -- GitLab