diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 14ca813b7c46a1dd1bc5dc739b712d58cb6aa99d..9b52ee10f0f20dbfb6fe7330e031e5672a66aff5 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -645,6 +645,16 @@ module Unstake_requests = struct 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} end end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 3ee73cfd2d6928e18d7d79543f9eb879dab017d8..d5771589aa47f595ba2976b153cbf1649be05aa1 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4908,6 +4908,9 @@ 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 @@ -4928,6 +4931,9 @@ module Unstake_requests : sig 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 end end diff --git a/src/proto_alpha/lib_protocol/contract_services.ml b/src/proto_alpha/lib_protocol/contract_services.ml index 678dcc192f755c22a50d2e9c2253224ac6287bd5..4de6133cfe79b5abc421a79019788a4283be761e 100644 --- a/src/proto_alpha/lib_protocol/contract_services.ml +++ b/src/proto_alpha/lib_protocol/contract_services.ml @@ -116,6 +116,18 @@ module S = struct RPC_path.( custom_root /: Contract.rpc_arg / "unstaked_finalizable_balance") + let unstake_requests = + RPC_service.get_service + ~description: + "Access the unstake requests of the contract. The requests that appear \ + in the finalizable field can be finalized, which means that the \ + contract can transfer these (no longer frozen) funds to their \ + 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) + RPC_path.(custom_root /: Contract.rpc_arg / "unstake_requests") + let full_balance = RPC_service.get_service ~description: @@ -446,6 +458,16 @@ let register () = S.unstaked_finalizable_balance 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 () () -> + Unstake_requests.prepare_finalize_unstake ctxt contract >>=? function + | None -> return_none + | Some {finalizable; unfinalizable} -> + Unstake_requests.For_RPC + .apply_slash_to_unstaked_unfinalizable_stored_requests + ctxt + unfinalizable + >>=? fun unfinalizable -> + return_some Unstake_requests.{finalizable; unfinalizable}) ; opt_register1 ~chunked:false S.manager_key (fun ctxt contract () () -> match contract with | Originated _ -> return_none @@ -659,6 +681,9 @@ let unstaked_finalizable_balance ctxt block contract = () () +let unstake_requests ctxt block contract = + RPC_context.make_call1 S.unstake_requests ctxt block contract () () + let full_balance ctxt block contract = RPC_context.make_call1 S.full_balance ctxt block contract () () diff --git a/src/proto_alpha/lib_protocol/contract_services.mli b/src/proto_alpha/lib_protocol/contract_services.mli index aa1c199a347228ea50e251a05ec9b41aff96a085..02be39258942223299feab9f18abe883b47cb8bd 100644 --- a/src/proto_alpha/lib_protocol/contract_services.mli +++ b/src/proto_alpha/lib_protocol/contract_services.mli @@ -75,6 +75,12 @@ val unstaked_finalizable_balance : Contract.t -> Tez.t 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 + val full_balance : 'a #RPC_context.simple -> 'a -> Contract.t -> Tez.t shell_tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml index 1ec8f4143bd45e3ddcb2ee97ce209bd19300f4db..7f2a1e41e2e630c25ee3ae37d51bd02970a5247d 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.ml +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.ml @@ -26,16 +26,48 @@ 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 z100 = Z.of_int 100 let apply_slashes ~preserved_plus_slashing slashing_history ~from_cycle amount = diff --git a/src/proto_alpha/lib_protocol/unstake_requests_storage.mli b/src/proto_alpha/lib_protocol/unstake_requests_storage.mli index 9c859ad10f49aaa51f2599e9b9907b8535bb878c..5d75ee4a97f4b9faf95d04b0e271c01f9d3ecf64 100644 --- a/src/proto_alpha/lib_protocol/unstake_requests_storage.mli +++ b/src/proto_alpha/lib_protocol/unstake_requests_storage.mli @@ -41,6 +41,9 @@ type prepared_finalize_unstake = { unfinalizable : stored_requests; } +val prepared_finalize_unstake_encoding : + prepared_finalize_unstake Data_encoding.encoding + (** [prepare_finalize_unstake ctxt contract] preprocesses a [finalize_unstake] for [contract]. It returns a list of transfers [(d, c, a)] to do from delegate's [d] unstaked frozen deposits for cycle [c] of amount [a] in