diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index 8ec6fd5d5e0e62276cbee746918e86130ce8a901..722dda9b60ec493262d8eedf0fc907ede2f7df4d 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -33,6 +33,10 @@ Breaking Changes RPC Changes ----------- +- The new ``current_voting_power`` RPC computes the voting power of a + delegate based on its current stake (as opposed to reading it from + the vote listings as the ``voting_power`` does) (MR :gl:`!9329`) + Operation receipts ------------------ diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 520cb27cc3fad10d4da7bf4be8e78b911a9f8b3a..7344f52bdc07f9c66cbd8caca88a87906df157cb 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2373,6 +2373,9 @@ module Vote : sig val get_voting_power : context -> public_key_hash -> (context * int64) tzresult Lwt.t + val get_current_voting_power_free : + context -> public_key_hash -> int64 tzresult Lwt.t + val get_total_voting_power_free : context -> int64 tzresult Lwt.t val get_total_voting_power : context -> (context * int64) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index 3689d8540f20ddb982a91e4639f97180223a4afa..ebd5605f73239c72599585c50440bfdf9783137d 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -371,6 +371,15 @@ module S = struct ~output:Cycle.encoding RPC_path.(path / "grace_period") + let current_voting_power = + RPC_service.get_service + ~description: + "The voting power of a given delegate, as computed from its current \ + stake." + ~query:RPC_query.empty + ~output:Data_encoding.int64 + RPC_path.(path / "current_voting_power") + let voting_power = RPC_service.get_service ~description:"The voting power in the vote listings for a given delegate." @@ -528,6 +537,9 @@ let register () = register1 ~chunked:false S.grace_period (fun ctxt pkh () () -> check_delegate_registered ctxt pkh >>=? fun () -> Delegate.last_cycle_before_deactivation ctxt pkh) ; + register1 ~chunked:false S.current_voting_power (fun ctxt pkh () () -> + check_delegate_registered ctxt pkh >>=? fun () -> + Vote.get_current_voting_power_free ctxt pkh) ; register1 ~chunked:false S.voting_power (fun ctxt pkh () () -> check_delegate_registered ctxt pkh >>=? fun () -> Vote.get_voting_power_free ctxt pkh) ; @@ -594,6 +606,9 @@ let grace_period ctxt block pkh = let voting_power ctxt block pkh = RPC_context.make_call1 S.voting_power ctxt block pkh () () +let current_voting_power ctxt block pkh = + RPC_context.make_call1 S.current_voting_power ctxt block pkh () () + let voting_info ctxt block pkh = RPC_context.make_call1 S.voting_info ctxt block pkh () () diff --git a/src/proto_alpha/lib_protocol/delegate_services.mli b/src/proto_alpha/lib_protocol/delegate_services.mli index c78efbb728c39f780066c53b2d2d160db38b9d3e..4d0de3b058c2c2f276ee36f8a6d71ce9ad56b950 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.mli +++ b/src/proto_alpha/lib_protocol/delegate_services.mli @@ -131,6 +131,9 @@ val grace_period : Signature.Public_key_hash.t -> Cycle.t shell_tzresult Lwt.t +val current_voting_power : + 'a #RPC_context.simple -> 'a -> public_key_hash -> int64 shell_tzresult Lwt.t + val voting_power : 'a #RPC_context.simple -> 'a -> public_key_hash -> int64 shell_tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index ac10aaf70ec98c13881fad65dea69488b944a43a..c1630418a695728f31e4c44b1b2c29bbb1db15ab 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -168,10 +168,7 @@ let fold ctxt ~f ~order init = ctxt ~order ~init:(Ok init) - ~f:(fun delegate () acc -> - acc >>?= fun acc -> - get_staking_balance ctxt delegate >>=? fun stake -> - f (delegate, stake) acc) + ~f:(fun delegate () acc -> acc >>?= fun acc -> f delegate acc) let fold_snapshot ctxt ~index ~f ~init = Storage.Stake.Active_delegates_with_minimal_stake.fold_snapshot diff --git a/src/proto_alpha/lib_protocol/stake_storage.mli b/src/proto_alpha/lib_protocol/stake_storage.mli index 326e0463c407f1d8f3d7cc73f0aa8c6f2a5f6bed..18521072de20ea4b02f2ad0da7d0102813870cf2 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.mli +++ b/src/proto_alpha/lib_protocol/stake_storage.mli @@ -59,11 +59,10 @@ val snapshot : Raw_context.t -> Raw_context.t tzresult Lwt.t (** [fold ctxt ~f ~order init] folds [f] on the list of active delegates having the minimal required stake. The folding process starts with [init]. Each element of the - list is a pair [pkh, stake], where [pkh] is the public key hash of the - delegate and [stake] is the staking balance of the delegate. *) + list is the public key hash of a delegate. *) val fold : Raw_context.t -> - f:(Signature.Public_key_hash.t * Tez_repr.t -> 'a -> 'a tzresult Lwt.t) -> + f:(Signature.Public_key_hash.t -> 'a -> 'a tzresult Lwt.t) -> order:[`Sorted | `Undefined] -> 'a -> 'a tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.ml b/src/proto_alpha/lib_protocol/test/helpers/context.ml index 65eb5847af2423b6d4f95ca7c8e861a480e74007..ab17cd2a43ed11ec3771017708e654b149b6bd38 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -168,6 +168,8 @@ let get_cumulated_endorsing_power_for_delegate ctxt ~levels pkh = 0 levels +let get_current_voting_power = Delegate_services.current_voting_power rpc_ctxt + let get_voting_power = Delegate_services.voting_power rpc_ctxt let get_total_voting_power = Alpha_services.Voting.total_voting_power rpc_ctxt diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli index 32f9b2fc6e1e99e3d509f17327aae794b3d4e8b4..c4c76d85962a92bbe05401f3c050641b3a7c32eb 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli @@ -71,6 +71,9 @@ val get_endorsing_power_for_delegate : val get_cumulated_endorsing_power_for_delegate : t -> levels:Raw_level.t list -> public_key_hash -> int tzresult Lwt.t +val get_current_voting_power : + t -> public_key_hash -> int64 Environment.Error_monad.shell_tzresult Lwt.t + val get_voting_power : t -> public_key_hash -> int64 Environment.Error_monad.shell_tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/vote_storage.ml b/src/proto_alpha/lib_protocol/vote_storage.ml index 87cbc6c0464c8150b6648b350b33f89c186b9372..86d6d35135ca5b21528edb2802266c049bce41f9 100644 --- a/src/proto_alpha/lib_protocol/vote_storage.ml +++ b/src/proto_alpha/lib_protocol/vote_storage.ml @@ -104,6 +104,20 @@ let listings_encoding = (req "pkh" Signature.Public_key_hash.encoding) (req "voting_power" int64))) +let get_current_voting_power_free ctxt delegate = + let open Lwt_result_syntax in + let* stake = Stake_storage.get_staking_balance ctxt delegate in + let delegate_contract = Contract_repr.Implicit delegate in + let* deposits = Frozen_deposits_storage.get ctxt delegate_contract in + let frozen = deposits.current_amount in + let frozen = Tez_repr.min stake frozen in + (* Cannot fail: + frozen = min stake _ ⇒ frozen <= stake ⇒ stake - frozen >= 0. *) + let*? delegated = Tez_repr.(stake -? frozen) in + let stake = Stake_repr.make ~frozen ~delegated in + let weight = Stake_context.staking_weight ctxt stake in + return weight + let update_listings ctxt = let open Lwt_result_syntax in let*! ctxt = Storage.Vote.Listings.clear ctxt in @@ -112,18 +126,10 @@ let update_listings ctxt = ctxt (ctxt, 0L) ~order:`Sorted - ~f:(fun (delegate, stake) (ctxt, total) -> - let delegate_contract = Contract_repr.Implicit delegate in - let* deposits = Frozen_deposits_storage.get ctxt delegate_contract in - let frozen = deposits.current_amount in - let frozen = Tez_repr.min stake frozen in - (* Cannot fail: - frozen = min stake _ ⇒ frozen <= stake ⇒ stake - frozen >= 0. *) - let*? delegated = Tez_repr.(stake -? frozen) in - let stake = Stake_repr.make ~frozen ~delegated in - let weight = Stake_context.staking_weight ctxt stake in - Storage.Vote.Listings.init ctxt delegate weight >>=? fun ctxt -> - return (ctxt, Int64.add total weight)) + ~f:(fun delegate (ctxt, total) -> + let* weight = get_current_voting_power_free ctxt delegate in + let+ ctxt = Storage.Vote.Listings.init ctxt delegate weight in + (ctxt, Int64.add total weight)) in let*! ctxt = Storage.Vote.Voting_power_in_listings.add ctxt total in return ctxt diff --git a/src/proto_alpha/lib_protocol/vote_storage.mli b/src/proto_alpha/lib_protocol/vote_storage.mli index 41e5d65227fed85a51bf2ccca084c1f1c341c770..29a03caf5f7648375b758ce605fcc69128e95610 100644 --- a/src/proto_alpha/lib_protocol/vote_storage.mli +++ b/src/proto_alpha/lib_protocol/vote_storage.mli @@ -130,14 +130,23 @@ val delegate_info_encoding : delegate_info Data_encoding.t val get_delegate_info : Raw_context.t -> Signature.public_key_hash -> delegate_info tzresult Lwt.t +(** Returns the voting power of a delegate from the voting power + listings. This function does not account for gas cost. *) val get_voting_power_free : Raw_context.t -> Signature.public_key_hash -> int64 tzresult Lwt.t +(** Same as [get_voting_power_free] but consumes gas. *) val get_voting_power : Raw_context.t -> Signature.public_key_hash -> (Raw_context.t * int64) tzresult Lwt.t +(** Same as [get_voting_power_free] but computes the voting power + based on the current stake of the delegate instead of reading it + from the vote listings. *) +val get_current_voting_power_free : + Raw_context.t -> Signature.public_key_hash -> int64 tzresult Lwt.t + (** Returns the sum of all voting power in the listings, without accounting for gas cost. *) val get_total_voting_power_free : Raw_context.t -> int64 tzresult Lwt.t