From e1bc8dcb8aa9ce387881d1f9d6193235d890f0ca Mon Sep 17 00:00:00 2001 From: phink Date: Fri, 9 Feb 2024 08:29:06 +0100 Subject: [PATCH 1/7] Proto/Alpha: hoist get_slashing_history_for_stored_requests --- .../lib_protocol/unstake_requests_storage.ml | 144 +++++++++--------- 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml index ec1e78f7fdf9..f00f99b4d833 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml @@ -164,85 +164,91 @@ let add ctxt ~contract ~delegate cycle amount = return ctxt module For_RPC = struct - let apply_slash_to_unstaked_unfinalizable ctxt {requests; delegate} = + let get_slashing_history_for_stored_requests ctxt delegate = let open Lwt_result_syntax in let current_level = Raw_context.current_level ctxt in let cycle_eras = Raw_context.cycle_eras ctxt in let is_last_of_cycle = Level_repr.last_of_cycle ~cycle_eras current_level in - let slashable_deposits_period = - Constants_storage.slashable_deposits_period ctxt - in let* slashing_history_opt = Storage.Contract.Slashed_deposits.find ctxt (Contract_repr.Implicit delegate) in - let slashing_history = Option.value slashing_history_opt ~default:[] in + match slashing_history_opt with + | None -> return [] + | Some slashing_history -> + if not (Constants_storage.adaptive_issuance_ns_enable ctxt) then + (* Remove slashes that haven't been applied yet *) + let slashing_history = + if not is_last_of_cycle then + List.filter + (fun (cycle, _) -> Cycle_repr.(cycle < current_level.cycle)) + slashing_history + else slashing_history + in + (* We get the current cycle's denunciations for events in the previous cycle, + and remove them from the slashing events (since they haven't been applied yet). + Another solution would be to add the slashing cycle in Storage.Contract.Slashed_deposits, + but since it's only used for this specific RPC, let's not. *) + let* denunciations_opt = + Storage.Pending_denunciations.find ctxt delegate + in + let denunciations = Option.value denunciations_opt ~default:[] in + let not_yet_slashed_pct = + if is_last_of_cycle then Percentage.p0 + else + List.fold_left + (fun acc Denunciations_repr.{misbehaviour; _} -> + let misbehaviour_cycle = + (Level_repr.level_from_raw + ~cycle_eras:(Raw_context.cycle_eras ctxt) + misbehaviour.level) + .cycle + in + if Cycle_repr.(misbehaviour_cycle = current_level.cycle) then + acc + else + match misbehaviour.kind with + | Double_baking -> + Percentage.add_bounded + acc + (Constants_storage + .percentage_of_frozen_deposits_slashed_per_double_baking + ctxt) + | Double_attesting -> + Percentage.add_bounded + acc + (Constants_storage + .percentage_of_frozen_deposits_slashed_per_double_attestation + ctxt)) + Percentage.p0 + denunciations + in + return + @@ List.map + (fun (cycle, pct) -> + if Cycle_repr.(succ cycle = current_level.cycle) then + (cycle, Percentage.(sub_bounded pct not_yet_slashed_pct)) + else (cycle, pct)) + slashing_history + else if not is_last_of_cycle then + return + @@ List.filter + (fun (cycle, _) -> Cycle_repr.(succ cycle < current_level.cycle)) + slashing_history + else + return + @@ List.filter + (fun (cycle, _) -> Cycle_repr.(cycle < current_level.cycle)) + slashing_history + + let apply_slash_to_unstaked_unfinalizable ctxt {requests; delegate} = + let open Lwt_result_syntax in + let slashable_deposits_period = + Constants_storage.slashable_deposits_period ctxt + in let* slashing_history = - if not (Constants_storage.adaptive_issuance_ns_enable ctxt) then - (* Remove slashes that haven't been applied yet *) - let slashing_history = - if not is_last_of_cycle then - List.filter - (fun (cycle, _) -> Cycle_repr.(cycle < current_level.cycle)) - slashing_history - else slashing_history - in - (* We get the current cycle's denunciations for events in the previous cycle, - and remove them from the slashing events (since they haven't been applied yet). - Another solution would be to add the slashing cycle in Storage.Contract.Slashed_deposits, - but since it's only used for this specific RPC, let's not. *) - let* denunciations_opt = - Storage.Pending_denunciations.find ctxt delegate - in - let denunciations = Option.value denunciations_opt ~default:[] in - let not_yet_slashed_pct = - if is_last_of_cycle then Percentage.p0 - else - List.fold_left - (fun acc Denunciations_repr.{misbehaviour; _} -> - let misbehaviour_cycle = - (Level_repr.level_from_raw - ~cycle_eras:(Raw_context.cycle_eras ctxt) - misbehaviour.level) - .cycle - in - if Cycle_repr.(misbehaviour_cycle = current_level.cycle) then - acc - else - match misbehaviour.kind with - | Double_baking -> - Percentage.add_bounded - acc - (Constants_storage - .percentage_of_frozen_deposits_slashed_per_double_baking - ctxt) - | Double_attesting -> - Percentage.add_bounded - acc - (Constants_storage - .percentage_of_frozen_deposits_slashed_per_double_attestation - ctxt)) - Percentage.p0 - denunciations - in - return - @@ List.map - (fun (cycle, pct) -> - if Cycle_repr.(succ cycle = current_level.cycle) then - (cycle, Percentage.(sub_bounded pct not_yet_slashed_pct)) - else (cycle, pct)) - slashing_history - else if not is_last_of_cycle then - return - @@ List.filter - (fun (cycle, _) -> Cycle_repr.(succ cycle < current_level.cycle)) - slashing_history - else - return - @@ List.filter - (fun (cycle, _) -> Cycle_repr.(cycle < current_level.cycle)) - slashing_history + get_slashing_history_for_stored_requests ctxt delegate in List.map_es (fun (request_cycle, request_amount) -> -- GitLab From 7cd0a26e66055ec599f471f8eb7c4b762c02d10b Mon Sep 17 00:00:00 2001 From: phink Date: Fri, 9 Feb 2024 08:33:30 +0100 Subject: [PATCH 2/7] Proto/Alpha: Unstake_requests_storage.For_RPC.unstake_requests with pending slash flag --- .../lib_protocol/unstake_requests_storage.ml | 240 ++++++++++++++++++ .../lib_protocol/unstake_requests_storage.mli | 36 +++ 2 files changed, 276 insertions(+) diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml index f00f99b4d833..d6d893389d5f 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml @@ -261,4 +261,244 @@ module For_RPC = struct in return (request_cycle, new_amount)) requests + + type finalizable_request_wps = { + fr_delegate : Signature.Public_key_hash.t; + fr_cycle : Cycle_repr.t; + fr_amount : Tez_repr.t; + fr_pending_slash : bool; + } + + type finalizable_requests_wps = finalizable_request_wps list + + type unfinalizable_request_wps = { + ur_cycle : Cycle_repr.t; + ur_amount : Tez_repr.t; + ur_pending_slash : bool; + } + + type unfinalizable_requests_wps = { + delegate : Signature.Public_key_hash.t; + u_requests : unfinalizable_request_wps list; + } + + let finalizable_request_wps_encoding : finalizable_request_wps Data_encoding.t + = + let open Data_encoding in + conv + (fun {fr_delegate; fr_cycle; fr_amount; fr_pending_slash} -> + (fr_delegate, fr_cycle, fr_amount, fr_pending_slash)) + (fun (fr_delegate, fr_cycle, fr_amount, fr_pending_slash) -> + {fr_delegate; fr_cycle; fr_amount; fr_pending_slash}) + (obj4 + (req "delegate" Signature.Public_key_hash.encoding) + (req "cycle" Cycle_repr.encoding) + (req "amount" Tez_repr.encoding) + (req "pending_slash" bool)) + + let unfinalizable_request_wps_encoding : + unfinalizable_request_wps Data_encoding.t = + let open Data_encoding in + let encoding = + obj3 + (req "cycle" Cycle_repr.encoding) + (req "amount" Tez_repr.encoding) + (req "pending_slash" bool) + in + conv + (fun {ur_cycle; ur_amount; ur_pending_slash} -> + (ur_cycle, ur_amount, ur_pending_slash)) + (fun (ur_cycle, ur_amount, ur_pending_slash) -> + {ur_cycle; ur_amount; ur_pending_slash}) + encoding + + let finalizable_requests_wps_encoding : + finalizable_requests_wps Data_encoding.t = + Data_encoding.list finalizable_request_wps_encoding + + let unfinalizable_requests_wps_encoding : + unfinalizable_requests_wps Data_encoding.t = + let open Data_encoding in + conv + (fun {delegate; u_requests} -> (delegate, u_requests)) + (fun (delegate, u_requests) -> {delegate; u_requests}) + (obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "requests" (list unfinalizable_request_wps_encoding))) + + type unstake_requests = { + finalizable_requests_wps : finalizable_requests_wps; + unfinalizable_requests_wps : unfinalizable_requests_wps; + } + + let unstake_requests_encoding : unstake_requests Data_encoding.t = + let open Data_encoding in + conv + (fun {finalizable_requests_wps; unfinalizable_requests_wps} -> + (finalizable_requests_wps, unfinalizable_requests_wps)) + (fun (finalizable_requests_wps, unfinalizable_requests_wps) -> + {finalizable_requests_wps; unfinalizable_requests_wps}) + (obj2 + (req "finalizable_requests" finalizable_requests_wps_encoding) + (req "unfinalizable_requests" unfinalizable_requests_wps_encoding)) + + (* Prepare for RPCs. *) + + let exists_pending_slash ~preserved_cycles slashing_history ~from_cycle = + let first_cycle_to_apply_slash = from_cycle in + let last_cycle_to_apply_slash = + Cycle_repr.add from_cycle preserved_cycles + in + List.exists + (fun (slashing_cycle, _) -> + Cycle_repr.( + slashing_cycle >= first_cycle_to_apply_slash + && slashing_cycle <= last_cycle_to_apply_slash)) + slashing_history + + let get_finalizable_requests ctxt contract = + let open Lwt_result_syntax in + let preserved_cycles = Constants_storage.preserved_cycles ctxt in + let max_slashing_period = Constants_repr.max_slashing_period in + let preserved_plus_slashing = preserved_cycles + max_slashing_period in + let current_cycle = (Raw_context.current_level ctxt).cycle in + let* requests_opt = Storage.Contract.Unstake_requests.find ctxt contract in + match requests_opt with + | None | Some {delegate = _; requests = []} -> return_none + | Some {delegate; requests} -> ( + match Cycle_repr.sub current_cycle preserved_plus_slashing with + | None (* no finalizable cycle *) -> + return_some ([], {delegate; requests}) + | Some greatest_finalizable_cycle -> + let* slashing_history_opt = + Storage.Contract.Slashed_deposits.find + ctxt + (Contract_repr.Implicit delegate) + in + let is_finalizable_pending_slash request_cycle = + Option.fold + ~none:false + ~some:(fun slashing_history -> + exists_pending_slash + ~preserved_cycles + slashing_history + ~from_cycle:request_cycle) + slashing_history_opt + in + let prepared_finalizable_requests, unfinalizable_requests = + List.partition_map + (fun ((cycle, amount) as request) -> + if Cycle_repr.(cycle <= greatest_finalizable_cycle) then + let fr_pending_slash = is_finalizable_pending_slash cycle in + Left + { + fr_delegate = delegate; + fr_amount = amount; + fr_cycle = cycle; + fr_pending_slash; + } + else Right request) + requests + in + let unfinalizable_requests = + Storage.Unstake_request. + {delegate; requests = unfinalizable_requests} + in + return_some (prepared_finalizable_requests, unfinalizable_requests)) + + let is_stored_request_pending_slash ~preserved_cycles slashing_history + ~from_cycle = + let first_cycle_to_apply_slash = from_cycle in + let last_cycle_to_apply_slash = + Cycle_repr.add from_cycle preserved_cycles + in + List.exists + (fun (slashing_cycle, slashing_percentage) -> + Cycle_repr.( + slashing_cycle >= first_cycle_to_apply_slash + && slashing_cycle <= last_cycle_to_apply_slash) + && Percentage.Compare.(slashing_percentage >= Percentage.p0)) + slashing_history + + let extend_stored_requests_with_pending_slash ctxt ~delegate ~requests = + let open Lwt_result_syntax in + let preserved_cycles = Constants_storage.preserved_cycles ctxt in + let* slashing_history = + get_slashing_history_for_stored_requests ctxt delegate + in + match slashing_history with + | [] -> + let u_requests = + List.map + (fun (ur_cycle, ur_amount) -> + {ur_cycle; ur_amount; ur_pending_slash = false}) + requests + in + return {delegate; u_requests} + | slashing_history -> + let* u_requests = + List.map_es + (fun (ur_cycle, ur_amount) -> + let ur_pending_slash = + is_stored_request_pending_slash + ~preserved_cycles + slashing_history + ~from_cycle:ur_cycle + in + return {ur_cycle; ur_amount; ur_pending_slash}) + requests + in + return {delegate; u_requests} + + let get_unstake_requests_opt ctxt contract = + let open Lwt_result_syntax in + let* result = get_finalizable_requests ctxt contract in + match result with + | None -> return_none + | Some (finalizable_requests_wps, unfinalizable_requests) -> + let* unfinalizable_requests_wps = + extend_stored_requests_with_pending_slash + ctxt + ~delegate:unfinalizable_requests.delegate + ~requests:unfinalizable_requests.requests + in + return_some {finalizable_requests_wps; unfinalizable_requests_wps} + + type unstake_requests_sum = { + unfinalizable_pending_slash : bool; + unfinalizable_requests_sum : Tez_repr.t; + finalizable_pending_slash : bool; + finalizable_requests_sum : Tez_repr.t; + } + + let sum_of_unstake_requests unstake_requests = + let open Lwt_result_syntax in + let sum a p xs = + List.fold_left_e + (fun (pending_slash, total) req -> + let open Result_syntax in + let+ total = Tez_repr.(total +? a req) in + (pending_slash || p req, total)) + (false, Tez_repr.zero) + xs + in + let*? unfinalizable_pending_slash, unfinalizable_requests_sum = + sum + (fun r -> r.ur_amount) + (fun r -> r.ur_pending_slash) + unstake_requests.unfinalizable_requests_wps.u_requests + in + let*? finalizable_pending_slash, finalizable_requests_sum = + sum + (fun r -> r.fr_amount) + (fun r -> r.fr_pending_slash) + unstake_requests.finalizable_requests_wps + in + return + { + unfinalizable_pending_slash; + unfinalizable_requests_sum; + finalizable_pending_slash; + finalizable_requests_sum; + } end diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.mli b/src/proto_alpha/lib_protocol/unstake_requests_storage.mli index 6b4a7eb8b639..ab35b99c6bec 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.mli +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.mli @@ -94,4 +94,40 @@ module For_RPC : sig Raw_context.t -> stored_requests -> (Cycle_repr.t * Tez_repr.t) list tzresult Lwt.t + + type finalizable_requests_wps + + type unfinalizable_requests_wps + + val finalizable_requests_wps_encoding : + finalizable_requests_wps Data_encoding.t + + val unfinalizable_requests_wps_encoding : + unfinalizable_requests_wps Data_encoding.t + + type unstake_requests = { + finalizable_requests_wps : finalizable_requests_wps; + unfinalizable_requests_wps : unfinalizable_requests_wps; + } + + val extend_stored_requests_with_pending_slash : + Raw_context.t -> + delegate:Signature.public_key_hash -> + requests:(Cycle_repr.t * Tez_repr.t) list -> + unfinalizable_requests_wps tzresult Lwt.t + + val unstake_requests_encoding : unstake_requests Data_encoding.t + + val get_unstake_requests_opt : + Raw_context.t -> Contract_repr.t -> unstake_requests option tzresult Lwt.t + + type unstake_requests_sum = { + unfinalizable_pending_slash : bool; + unfinalizable_requests_sum : Tez_repr.t; + finalizable_pending_slash : bool; + finalizable_requests_sum : Tez_repr.t; + } + + val sum_of_unstake_requests : + unstake_requests -> unstake_requests_sum tzresult Lwt.t end -- GitLab From a86980facbde291555c6163f99882c975c92bfa4 Mon Sep 17 00:00:00 2001 From: phink Date: Fri, 9 Feb 2024 08:36:35 +0100 Subject: [PATCH 3/7] Proto/Alpha_context: include Unstake_requests_storage.For_RPC --- src/proto_alpha/lib_protocol/alpha_context.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 5d1a46e276f4..381ce638afc2 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -728,6 +728,8 @@ module Unstake_requests = struct {delegate; requests} in return {delegate; requests} + + include Unstake_requests_storage.For_RPC end end -- GitLab From 13b2f84cef6749770d782df79ea52457c17dbb83 Mon Sep 17 00:00:00 2001 From: phink Date: Fri, 9 Feb 2024 08:42:03 +0100 Subject: [PATCH 4/7] Proto/Alpha_context: Unstake_requests.For_RPC.unstake_requests with pending slash --- .../lib_protocol/alpha_context.mli | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 409b938cdf17..9f266e52499e 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -5287,6 +5287,42 @@ module Unstake_requests : sig val apply_slash_to_unstaked_unfinalizable_stored_requests : context -> stored_requests -> stored_requests tzresult Lwt.t + + type finalizable_requests_wps + + type unfinalizable_requests_wps + + val finalizable_requests_wps_encoding : + finalizable_requests_wps Data_encoding.t + + val unfinalizable_requests_wps_encoding : + unfinalizable_requests_wps Data_encoding.t + + val extend_stored_requests_with_pending_slash : + t -> + delegate:public_key_hash -> + requests:(Cycle.t * Tez.t) list -> + unfinalizable_requests_wps tzresult Lwt.t + + type unstake_requests = { + finalizable_requests_wps : finalizable_requests_wps; + unfinalizable_requests_wps : unfinalizable_requests_wps; + } + + val unstake_requests_encoding : unstake_requests Data_encoding.t + + val get_unstake_requests_opt : + t -> Contract.t -> unstake_requests option tzresult Lwt.t + + type unstake_requests_sum = { + unfinalizable_pending_slash : bool; + unfinalizable_requests_sum : Tez.t; + finalizable_pending_slash : bool; + finalizable_requests_sum : Tez.t; + } + + val sum_of_unstake_requests : + unstake_requests -> unstake_requests_sum tzresult Lwt.t end end -- GitLab From 7cbdb7a6d79558b822d7a1ef51cefd44f4bcbad7 Mon Sep 17 00:00:00 2001 From: phink Date: Fri, 9 Feb 2024 08:46:12 +0100 Subject: [PATCH 5/7] Proto/AI: remove slashing application to returned balances --- .../lib_protocol/alpha_context.mli | 4 +- .../lib_protocol/contract_services.ml | 22 ++++----- .../lib_protocol/contract_services.mli | 6 +-- .../lib_protocol/contract_storage.ml | 46 ++++++++----------- .../lib_protocol/contract_storage.mli | 8 +++- .../lib_protocol/delegate_services.ml | 26 +++-------- .../lib_protocol/delegate_services.mli | 6 +-- .../lib_protocol/delegate_storage.ml | 35 ++++---------- .../test/helpers/adaptive_issuance_helpers.ml | 10 ++-- .../lib_protocol/test/helpers/context.mli | 5 +- 10 files changed, 64 insertions(+), 104 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9f266e52499e..8a3a8eb42706 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1860,10 +1860,10 @@ module Contract : sig val get_staked_balance : context -> t -> Tez.t option tzresult Lwt.t val get_unstaked_frozen_balance : - context -> t -> Tez.t option tzresult Lwt.t + context -> t -> (Tez.t * bool) option tzresult Lwt.t val get_unstaked_finalizable_balance : - context -> t -> Tez.t option tzresult Lwt.t + context -> t -> (Tez.t * bool) option tzresult Lwt.t val get_full_balance : context -> t -> Tez.t tzresult Lwt.t end diff --git a/src/proto_alpha/lib_protocol/contract_services.ml b/src/proto_alpha/lib_protocol/contract_services.ml index 308535694aab..7cd27b4d3c0f 100644 --- a/src/proto_alpha/lib_protocol/contract_services.ml +++ b/src/proto_alpha/lib_protocol/contract_services.ml @@ -54,6 +54,10 @@ let info_encoding = (opt "script" Script.encoding) (opt "counter" Manager_counter.encoding_for_RPCs) +let pending_slash_balance_encoding = + let open Data_encoding in + obj2 (req "balance" Tez.encoding) (req "pending_slash" bool) + let legacy = Script_ir_translator_config.make ~legacy:true () module S = struct @@ -109,7 +113,7 @@ module S = struct operation, but is still frozen for the duration of the slashing \ period. Returns None if the contract is originated." ~query:RPC_query.empty - ~output:(option Tez.encoding) + ~output:(option pending_slash_balance_encoding) RPC_path.(custom_root /: Contract.rpc_arg / "unstaked_frozen_balance") let unstaked_finalizable_balance = @@ -121,7 +125,7 @@ module S = struct stake/unstake/finalize_unstake operation. Returns None if the \ contract is originated." ~query:RPC_query.empty - ~output:(option Tez.encoding) + ~output:(option pending_slash_balance_encoding) RPC_path.( custom_root /: Contract.rpc_arg / "unstaked_finalizable_balance") @@ -134,7 +138,7 @@ module S = struct spendable balance with a [finalize_unstake] operation call. Returns \ None if there is no unstake request pending." ~query:RPC_query.empty - ~output:(option Unstake_requests.prepared_finalize_unstake_encoding) + ~output:(option Unstake_requests.For_RPC.unstake_requests_encoding) RPC_path.(custom_root /: Contract.rpc_arg / "unstake_requests") let full_balance = @@ -494,17 +498,7 @@ let register () = Contract.For_RPC.get_unstaked_finalizable_balance ; register_field ~chunked:false S.full_balance Contract.For_RPC.get_full_balance ; register1 ~chunked:false S.unstake_requests (fun ctxt contract () () -> - let* result = Unstake_requests.prepare_finalize_unstake ctxt contract in - match result with - | None -> return_none - | Some {finalizable; unfinalizable} -> - let* unfinalizable = - Unstake_requests.For_RPC - .apply_slash_to_unstaked_unfinalizable_stored_requests - ctxt - unfinalizable - in - return_some Unstake_requests.{finalizable; unfinalizable}) ; + Unstake_requests.For_RPC.get_unstake_requests_opt ctxt contract) ; opt_register1 ~chunked:false S.manager_key (fun ctxt contract () () -> match contract with | Originated _ -> return_none diff --git a/src/proto_alpha/lib_protocol/contract_services.mli b/src/proto_alpha/lib_protocol/contract_services.mli index 51d8ee862186..4d3962dacffd 100644 --- a/src/proto_alpha/lib_protocol/contract_services.mli +++ b/src/proto_alpha/lib_protocol/contract_services.mli @@ -73,19 +73,19 @@ val unstaked_frozen_balance : 'a #RPC_context.simple -> 'a -> Contract.t -> - Tez.t option shell_tzresult Lwt.t + (Tez.t * bool) option shell_tzresult Lwt.t val unstaked_finalizable_balance : 'a #RPC_context.simple -> 'a -> Contract.t -> - Tez.t option shell_tzresult Lwt.t + (Tez.t * bool) option shell_tzresult Lwt.t val unstake_requests : 'a #RPC_context.simple -> 'a -> Contract.t -> - Unstake_requests.prepared_finalize_unstake option shell_tzresult Lwt.t + Unstake_requests.For_RPC.unstake_requests option shell_tzresult Lwt.t val full_balance : 'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/contract_storage.ml b/src/proto_alpha/lib_protocol/contract_storage.ml index e5a1a2f78d25..fbcce1c88f3b 100644 --- a/src/proto_alpha/lib_protocol/contract_storage.ml +++ b/src/proto_alpha/lib_protocol/contract_storage.ml @@ -879,48 +879,35 @@ module For_RPC = struct function | Contract_repr.Originated _ -> return_none | Implicit _ as contract -> ( - let* result = - Unstake_requests_storage.prepare_finalize_unstake + let* unstake_requests_opt = + Unstake_requests_storage.For_RPC.get_unstake_requests_opt ctxt - ~for_next_cycle_use_only_after_slashing:false contract in - match result with - | None -> return_some (Tez_repr.zero, Tez_repr.zero) - | Some {finalizable; unfinalizable} -> - let* unfinalizable_requests = - Unstake_requests_storage.For_RPC - .apply_slash_to_unstaked_unfinalizable - ctxt - unfinalizable - in - let*? sum_unfinalizable = - List.fold_left_e - (fun acc (_cycle, tz) -> Tez_repr.(acc +? tz)) - Tez_repr.zero - unfinalizable_requests - in - let*? sum_finalizable = - List.fold_left_e - (fun acc (_, _cycle, tz) -> Tez_repr.(acc +? tz)) - Tez_repr.zero - finalizable + match unstake_requests_opt with + | None -> return_none + | Some unstake_requests -> + let* x = + Unstake_requests_storage.For_RPC.sum_of_unstake_requests + unstake_requests in - return_some (sum_unfinalizable, sum_finalizable)) + return_some x) let get_unstaked_frozen_balance ctxt contract = let open Lwt_result_syntax in let* balance_opt = get_unstaked_balance ctxt contract in match balance_opt with | None -> return_none - | Some (amount, _) -> return_some amount + | Some {unfinalizable_requests_sum; unfinalizable_pending_slash; _} -> + return_some (unfinalizable_requests_sum, unfinalizable_pending_slash) let get_unstaked_finalizable_balance ctxt contract = let open Lwt_result_syntax in let* balance_opt = get_unstaked_balance ctxt contract in match balance_opt with | None -> return_none - | Some (_, amount) -> return_some amount + | Some {finalizable_requests_sum; finalizable_pending_slash; _} -> + return_some (finalizable_requests_sum, finalizable_pending_slash) let get_full_balance ctxt contract = let open Lwt_result_syntax in @@ -929,7 +916,12 @@ module For_RPC = struct let staked = Option.value ~default:Tez_repr.zero s in let* us = get_unstaked_balance ctxt contract in let u_frozen, u_final = - Option.value ~default:(Tez_repr.zero, Tez_repr.zero) us + Option.fold + ~none:(Tez_repr.zero, Tez_repr.zero) + ~some:(fun us -> + let open Unstake_requests_storage.For_RPC in + (us.unfinalizable_requests_sum, us.finalizable_requests_sum)) + us in Tez_repr.( let*? x = balance_n_frozen +? staked in diff --git a/src/proto_alpha/lib_protocol/contract_storage.mli b/src/proto_alpha/lib_protocol/contract_storage.mli index 9635021e1739..dea19d0271bf 100644 --- a/src/proto_alpha/lib_protocol/contract_storage.mli +++ b/src/proto_alpha/lib_protocol/contract_storage.mli @@ -333,10 +333,14 @@ module For_RPC : sig Raw_context.t -> Contract_repr.t -> Tez_repr.t option tzresult Lwt.t val get_unstaked_frozen_balance : - Raw_context.t -> Contract_repr.t -> Tez_repr.t option tzresult Lwt.t + Raw_context.t -> + Contract_repr.t -> + (Tez_repr.t * bool) option tzresult Lwt.t val get_unstaked_finalizable_balance : - Raw_context.t -> Contract_repr.t -> Tez_repr.t option tzresult Lwt.t + Raw_context.t -> + Contract_repr.t -> + (Tez_repr.t * bool) option tzresult Lwt.t val get_full_balance : Raw_context.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index ad13cc74a005..c4f0038a0e6a 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -249,15 +249,6 @@ let participation_info_encoding = (req "remaining_allowed_missed_slots" int31) (req "expected_attesting_rewards" Tez.encoding)) -type deposit_per_cycle = {cycle : Cycle.t; deposit : Tez.t} - -let deposit_per_cycle_encoding : deposit_per_cycle Data_encoding.t = - let open Data_encoding in - conv - (fun {cycle; deposit} -> (cycle, deposit)) - (fun (cycle, deposit) -> {cycle; deposit}) - (obj2 (req "cycle" Cycle.encoding) (req "deposit" Tez.encoding)) - type pending_staking_parameters = Cycle.t * Staking_parameters_repr.t let pending_staking_parameters_encoding : @@ -348,7 +339,7 @@ module S = struct this cycle. Cycles go from the last unslashable cycle to the current \ cycle." ~query:RPC_query.empty - ~output:(Data_encoding.list deposit_per_cycle_encoding) + ~output:Unstake_requests.For_RPC.unfinalizable_requests_wps_encoding RPC_path.(path / "unstaked_frozen_deposits") let staking_balance = @@ -644,16 +635,11 @@ let register () = return (cycle, deposit)) cycles in - let* slashed_requests = - Alpha_context.Unstake_requests.For_RPC - .apply_slash_to_unstaked_unfinalizable - ctxt - ~delegate:pkh - ~requests - in - List.map_es - (fun (cycle, deposit) -> return {cycle; deposit}) - slashed_requests) ; + Alpha_context.Unstake_requests.For_RPC + .extend_stored_requests_with_pending_slash + ctxt + ~delegate:pkh + ~requests) ; register1 ~chunked:false S.staking_balance (fun ctxt pkh () () -> let* () = check_delegate_registered ctxt pkh in Delegate.For_RPC.staking_balance ctxt pkh) ; diff --git a/src/proto_alpha/lib_protocol/delegate_services.mli b/src/proto_alpha/lib_protocol/delegate_services.mli index 17cb85ed0b55..871aeee0751a 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.mli +++ b/src/proto_alpha/lib_protocol/delegate_services.mli @@ -70,10 +70,6 @@ type info = { pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; } -type deposit_per_cycle = {cycle : Cycle.t; deposit : Tez.t} - -val deposit_per_cycle_encoding : deposit_per_cycle Data_encoding.t - val info_encoding : info Data_encoding.t val info : @@ -104,7 +100,7 @@ val unstaked_frozen_deposits : 'a #RPC_context.simple -> 'a -> Signature.Public_key_hash.t -> - deposit_per_cycle list shell_tzresult Lwt.t + Unstake_requests.For_RPC.unfinalizable_requests_wps shell_tzresult Lwt.t val staking_balance : 'a #RPC_context.simple -> diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index b58808258454..87dbe3f66345 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -348,34 +348,19 @@ module For_RPC = struct ~contract:(Contract_repr.Implicit delegate) in let* unstaked_frozen = - let* result = - Unstake_requests_storage.prepare_finalize_unstake - ctxt - ~for_next_cycle_use_only_after_slashing:false - (Contract_repr.Implicit delegate) + let open Unstake_requests_storage.For_RPC in + let* unstake_requests_opt = + get_unstake_requests_opt ctxt (Contract_repr.Implicit delegate) in - match result with + match unstake_requests_opt with | None -> return Tez_repr.zero - | Some {finalizable; unfinalizable} -> - let* unfinalizable_requests = - Unstake_requests_storage.For_RPC - .apply_slash_to_unstaked_unfinalizable - ctxt - unfinalizable + | Some unstake_requests -> + let* sum = sum_of_unstake_requests unstake_requests in + let*? res = + Tez_repr.( + sum.unfinalizable_requests_sum +? sum.finalizable_requests_sum) in - let*? sum_unfinalizable = - List.fold_left_e - (fun acc (_cycle, tz) -> Tez_repr.(acc +? tz)) - Tez_repr.zero - unfinalizable_requests - in - let*? sum = - List.fold_left_e - (fun acc (_, _cycle, tz) -> Tez_repr.(acc +? tz)) - sum_unfinalizable - finalizable - in - return sum + return res in let*? all_frozen = Tez_repr.(own_frozen_deposits +? unstaked_frozen) in let delegate_contract = Contract_repr.Implicit delegate in diff --git a/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml index e3e9c17c5aca..c22732093765 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/adaptive_issuance_helpers.ml @@ -1147,12 +1147,14 @@ let get_balance_from_context ctxt contract = let* unstaked_frozen_b = Context.Contract.unstaked_frozen_balance ctxt contract in - let unstaked_frozen_b = Option.value ~default:Tez.zero unstaked_frozen_b in + let unstaked_frozen_b = + Option.value ~default:(Tez.zero, false) unstaked_frozen_b + in let* unstaked_finalizable_b = Context.Contract.unstaked_finalizable_balance ctxt contract in let unstaked_finalizable_b = - Option.value ~default:Tez.zero unstaked_finalizable_b + Option.value ~default:(Tez.zero, false) unstaked_finalizable_b in let* total_balance = Context.Contract.full_balance ctxt contract in let* staking_delegator_numerator_b = @@ -1173,8 +1175,8 @@ let get_balance_from_context ctxt contract = liquid_b; bonds_b; staked_b; - unstaked_frozen_b; - unstaked_finalizable_b; + unstaked_frozen_b = fst unstaked_frozen_b; + unstaked_finalizable_b = fst unstaked_finalizable_b; staking_delegator_numerator_b; staking_delegate_denominator_b; } diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli index 50311775faf0..85c11d5d96ea 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli @@ -215,10 +215,11 @@ module Contract : sig val staked_balance : t -> Contract.t -> Tez.t option tzresult Lwt.t - val unstaked_frozen_balance : t -> Contract.t -> Tez.t option tzresult Lwt.t + val unstaked_frozen_balance : + t -> Contract.t -> (Tez.t * bool) option tzresult Lwt.t val unstaked_finalizable_balance : - t -> Contract.t -> Tez.t option tzresult Lwt.t + t -> Contract.t -> (Tez.t * bool) option tzresult Lwt.t val full_balance : t -> Contract.t -> Tez.t tzresult Lwt.t -- GitLab From e7a829c71ee3384c0f98454b7b5875afb3b27717 Mon Sep 17 00:00:00 2001 From: phink Date: Fri, 9 Feb 2024 08:51:08 +0100 Subject: [PATCH 6/7] Proto/AI: remove dead code --- src/proto_alpha/lib_protocol/alpha_context.ml | 18 ------- .../lib_protocol/alpha_context.mli | 15 ------ .../lib_protocol/unstake_requests_storage.ml | 52 ------------------- .../lib_protocol/unstake_requests_storage.mli | 12 ----- 4 files changed, 97 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 381ce638afc2..a42642b2d954 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -710,25 +710,7 @@ module Cache = Cache_repr module Unstake_requests = struct include Unstake_requests_storage - let prepare_finalize_unstake = - prepare_finalize_unstake ~for_next_cycle_use_only_after_slashing:false - module For_RPC = struct - let apply_slash_to_unstaked_unfinalizable ctxt ~delegate ~requests = - Unstake_requests_storage.For_RPC.apply_slash_to_unstaked_unfinalizable - ctxt - {delegate; requests} - - let apply_slash_to_unstaked_unfinalizable_stored_requests ctxt - {delegate; requests} = - let open Lwt_result_syntax in - let* requests = - Unstake_requests_storage.For_RPC.apply_slash_to_unstaked_unfinalizable - ctxt - {delegate; requests} - in - return {delegate; requests} - include Unstake_requests_storage.For_RPC end end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 8a3a8eb42706..a45e90dbbeb5 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -5272,22 +5272,7 @@ module Unstake_requests : sig unfinalizable : stored_requests; } - val prepared_finalize_unstake_encoding : - prepared_finalize_unstake Data_encoding.encoding - - val prepare_finalize_unstake : - context -> Contract.t -> prepared_finalize_unstake option tzresult Lwt.t - module For_RPC : sig - val apply_slash_to_unstaked_unfinalizable : - context -> - delegate:public_key_hash -> - requests:(Cycle.t * Tez.t) list -> - (Cycle.t * Tez.t) list tzresult Lwt.t - - val apply_slash_to_unstaked_unfinalizable_stored_requests : - context -> stored_requests -> stored_requests tzresult Lwt.t - type finalizable_requests_wps type unfinalizable_requests_wps diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml index d6d893389d5f..680236e579bc 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml @@ -26,48 +26,16 @@ type finalizable = (Signature.Public_key_hash.t * Cycle_repr.t * Tez_repr.t) list -let finalizable_encoding = - let open Data_encoding in - let elt_encoding = - obj3 - (req "delegate" Signature.Public_key_hash.encoding) - (req "cycle" Cycle_repr.encoding) - (req "amount" Tez_repr.encoding) - in - list elt_encoding - type stored_requests = Storage.Unstake_request.t = { delegate : Signature.Public_key_hash.t; requests : (Cycle_repr.t * Tez_repr.t) list; } -let stored_requests_encoding = - let open Data_encoding in - let request_encoding = - obj2 (req "cycle" Cycle_repr.encoding) (req "amount" Tez_repr.encoding) - in - conv - (fun {delegate; requests} -> (delegate, requests)) - (fun (delegate, requests) -> {delegate; requests}) - (obj2 - (req "delegate" Signature.Public_key_hash.encoding) - (req "requests" (list request_encoding))) - type prepared_finalize_unstake = { finalizable : finalizable; unfinalizable : stored_requests; } -let prepared_finalize_unstake_encoding : - prepared_finalize_unstake Data_encoding.t = - let open Data_encoding in - conv - (fun {finalizable; unfinalizable} -> (finalizable, unfinalizable)) - (fun (finalizable, unfinalizable) -> {finalizable; unfinalizable}) - (obj2 - (req "finalizable" finalizable_encoding) - (req "unfinalizable" stored_requests_encoding)) - let apply_slashes ~slashable_deposits_period slashing_history ~from_cycle amount = let first_cycle_to_apply_slash = from_cycle in @@ -242,26 +210,6 @@ module For_RPC = struct (fun (cycle, _) -> Cycle_repr.(cycle < current_level.cycle)) slashing_history - let apply_slash_to_unstaked_unfinalizable ctxt {requests; delegate} = - let open Lwt_result_syntax in - let slashable_deposits_period = - Constants_storage.slashable_deposits_period ctxt - in - let* slashing_history = - get_slashing_history_for_stored_requests ctxt delegate - in - List.map_es - (fun (request_cycle, request_amount) -> - let new_amount = - apply_slashes - ~slashable_deposits_period - slashing_history - ~from_cycle:request_cycle - request_amount - in - return (request_cycle, new_amount)) - requests - type finalizable_request_wps = { fr_delegate : Signature.Public_key_hash.t; fr_cycle : Cycle_repr.t; diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.mli b/src/proto_alpha/lib_protocol/unstake_requests_storage.mli index ab35b99c6bec..6bdd62977166 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.mli +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.mli @@ -41,9 +41,6 @@ type prepared_finalize_unstake = { unfinalizable : stored_requests; } -val prepared_finalize_unstake_encoding : - prepared_finalize_unstake Data_encoding.encoding - (** [prepare_finalize_unstake ctxt ~for_next_cycle_use_only_after_slashing contract] preprocesses a [finalize_unstake] for [contract]. It returns a list of transfers [(d, c, a)] to do from delegate's [d] unstaked frozen @@ -86,15 +83,6 @@ val add : (** Slow functions only used for RPCs *) module For_RPC : sig - (** Apply current slash history to unfinalizable unstake requests. - [prepare_finalize_unstake] does not compute this value because it is never - used internally. However, we need to apply slashes anyways when trying to - compute the accurate balance of a staker *) - val apply_slash_to_unstaked_unfinalizable : - Raw_context.t -> - stored_requests -> - (Cycle_repr.t * Tez_repr.t) list tzresult Lwt.t - type finalizable_requests_wps type unfinalizable_requests_wps -- GitLab From 2eaa5df8d7c09d1971bd8a2701162c9afe2ff35c Mon Sep 17 00:00:00 2001 From: phink Date: Fri, 9 Feb 2024 09:15:43 +0100 Subject: [PATCH 7/7] Proto/AI: Unstake_requests_storage renaming --- .../lib_protocol/unstake_requests_storage.ml | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml index 680236e579bc..ea7c3d8442a7 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml @@ -292,7 +292,8 @@ module For_RPC = struct (* Prepare for RPCs. *) - let exists_pending_slash ~preserved_cycles slashing_history ~from_cycle = + let is_finalizable_request_cycle_pending_slash ~preserved_cycles + slashing_history ~from_cycle = let first_cycle_to_apply_slash = from_cycle in let last_cycle_to_apply_slash = Cycle_repr.add from_cycle preserved_cycles @@ -327,7 +328,7 @@ module For_RPC = struct Option.fold ~none:false ~some:(fun slashing_history -> - exists_pending_slash + is_finalizable_request_cycle_pending_slash ~preserved_cycles slashing_history ~from_cycle:request_cycle) @@ -354,7 +355,7 @@ module For_RPC = struct in return_some (prepared_finalizable_requests, unfinalizable_requests)) - let is_stored_request_pending_slash ~preserved_cycles slashing_history + let is_stored_request_cycle_pending_slash ~preserved_cycles slashing_history ~from_cycle = let first_cycle_to_apply_slash = from_cycle in let last_cycle_to_apply_slash = @@ -370,7 +371,6 @@ module For_RPC = struct let extend_stored_requests_with_pending_slash ctxt ~delegate ~requests = let open Lwt_result_syntax in - let preserved_cycles = Constants_storage.preserved_cycles ctxt in let* slashing_history = get_slashing_history_for_stored_requests ctxt delegate in @@ -384,15 +384,17 @@ module For_RPC = struct in return {delegate; u_requests} | slashing_history -> + let preserved_cycles = Constants_storage.preserved_cycles ctxt in + let is_stored_request_pending_slash from_cycle = + is_stored_request_cycle_pending_slash + ~preserved_cycles + slashing_history + ~from_cycle + in let* u_requests = List.map_es (fun (ur_cycle, ur_amount) -> - let ur_pending_slash = - is_stored_request_pending_slash - ~preserved_cycles - slashing_history - ~from_cycle:ur_cycle - in + let ur_pending_slash = is_stored_request_pending_slash ur_cycle in return {ur_cycle; ur_amount; ur_pending_slash}) requests in -- GitLab