From 0ddacafd351964df06c5a5e00b49b34d4a1e9397 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 14 Apr 2022 23:37:43 +0200 Subject: [PATCH 01/42] Proto: split `Delegate_storage` in multiple files --- .../test/tenderbrute/lib/tenderbrute.ml | 2 +- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 4 + src/proto_alpha/lib_protocol/alpha_context.ml | 15 +- .../lib_protocol/alpha_context.mli | 10 +- src/proto_alpha/lib_protocol/apply.ml | 11 +- .../lib_protocol/delegate_cycles.ml | 225 +++++ .../lib_protocol/delegate_cycles.mli | 52 ++ .../delegate_missed_endorsements_storage.ml | 266 ++++++ .../delegate_missed_endorsements_storage.mli | 86 ++ .../lib_protocol/delegate_sampler.ml | 242 +++++ .../lib_protocol/delegate_sampler.mli | 65 ++ .../delegate_slashed_deposits_storage.ml | 118 +++ .../delegate_slashed_deposits_storage.mli | 61 ++ .../lib_protocol/delegate_storage.ml | 840 ++---------------- .../lib_protocol/delegate_storage.mli | 209 +---- src/proto_alpha/lib_protocol/dune | 24 + src/proto_alpha/lib_protocol/init_storage.ml | 4 +- 17 files changed, 1250 insertions(+), 984 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/delegate_cycles.ml create mode 100644 src/proto_alpha/lib_protocol/delegate_cycles.mli create mode 100644 src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml create mode 100644 src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli create mode 100644 src/proto_alpha/lib_protocol/delegate_sampler.ml create mode 100644 src/proto_alpha/lib_protocol/delegate_sampler.mli create mode 100644 src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml create mode 100644 src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli diff --git a/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml b/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml index a27b9381426c..fa99d708a0a1 100644 --- a/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml +++ b/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml @@ -100,7 +100,7 @@ let check ctxt ~selection = (fun () -> LevelRoundMap.fold_es (fun (level, round) delegate ctxt -> - Delegate_storage.baking_rights_owner ctxt level ~round + Delegate_sampler.baking_rights_owner ctxt level ~round >|= Environment.wrap_tzresult >>=? fun (ctxt, _, (_, pkh)) -> if not (Signature.Public_key_hash.equal delegate pkh) then raise Exit diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index f0e49e3602fb..5126b741fe92 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -124,6 +124,10 @@ "Contract_storage", "Token", "Delegate_storage", + "Delegate_missed_endorsements_storage", + "Delegate_slashed_deposits_storage", + "Delegate_sampler", + "Delegate_cycles", "Bootstrap_storage", "Vote_storage", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index f1e852c2f6ee..f9a62d1d2c25 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -431,6 +431,11 @@ module Receipt = Receipt_repr module Delegate = struct include Delegate_storage + include Delegate_missed_endorsements_storage + include Delegate_slashed_deposits_storage + include Delegate_cycles + + let deactivated = Delegate_activation_storage.is_inactive type deposits = Storage.deposits = { initial_amount : Tez.t; @@ -452,15 +457,15 @@ end module Stake_distribution = struct let snapshot = Stake_storage.snapshot - let compute_snapshot_index = Delegate_storage.compute_snapshot_index + let compute_snapshot_index = Delegate_sampler.compute_snapshot_index - let baking_rights_owner = Delegate.baking_rights_owner + let baking_rights_owner = Delegate_sampler.baking_rights_owner - let slot_owner = Delegate.slot_owner + let slot_owner = Delegate_sampler.slot_owner - let delegate_pubkey = Delegate.pubkey + let delegate_pubkey = Delegate_storage.pubkey - let get_staking_balance = Delegate.staking_balance + let get_staking_balance = Delegate_storage.staking_balance end module Nonce = Nonce_storage diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index e246db86a4fd..aed01ea9e6db 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2287,22 +2287,20 @@ module Delegate : sig tzresult Lwt.t - val already_slashed_for_double_endorsing : - context -> public_key_hash -> Level.t -> bool tzresult Lwt.t + val check_and_record_already_slashed_for_double_endorsing : + context -> public_key_hash -> Level.t -> (context * bool) tzresult Lwt.t - val already_slashed_for_double_baking : - context -> public_key_hash -> Level.t -> bool tzresult Lwt.t + val check_and_record_already_slashed_for_double_baking : + context -> public_key_hash -> Level.t -> (context * bool) tzresult Lwt.t val punish_double_endorsing : context -> public_key_hash -> - Level.t -> (context * Tez.t * Receipt.balance_updates) tzresult Lwt.t val punish_double_baking : context -> public_key_hash -> - Level.t -> (context * Tez.t * Receipt.balance_updates) tzresult Lwt.t val full_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index bd65117ab13d..9e2d82a9193f 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2860,18 +2860,19 @@ let check_denunciation_age ctxt kind given_level = {kind; level = given_level; last_cycle = last_slashable_cycle}) let punish_delegate ctxt delegate level mistake mk_result ~payload_producer = - let already_slashed, punish = + let check_and_record_already_slashed, punish = match mistake with | `Double_baking -> - ( Delegate.already_slashed_for_double_baking, + ( Delegate.check_and_record_already_slashed_for_double_baking, Delegate.punish_double_baking ) | `Double_endorsing -> - ( Delegate.already_slashed_for_double_endorsing, + ( Delegate.check_and_record_already_slashed_for_double_endorsing, Delegate.punish_double_endorsing ) in - already_slashed ctxt delegate level >>=? fun slashed -> + check_and_record_already_slashed ctxt delegate level + >>=? fun (ctxt, slashed) -> fail_when slashed Unrequired_denunciation >>=? fun () -> - punish ctxt delegate level >>=? fun (ctxt, burned, punish_balance_updates) -> + punish ctxt delegate >>=? fun (ctxt, burned, punish_balance_updates) -> (match Tez.(burned /? 2L) with | Ok reward -> Token.transfer diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml new file mode 100644 index 000000000000..a866f2727f6d --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -0,0 +1,225 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let update_activity ctxt last_cycle = + let preserved = Constants_storage.preserved_cycles ctxt in + match Cycle_repr.sub last_cycle preserved with + | None -> return (ctxt, []) + | Some _unfrozen_cycle -> + Stake_storage.fold_on_active_delegates_with_rolls + ctxt + ~order:`Sorted + ~init:(Ok (ctxt, [])) + ~f:(fun delegate () acc -> + acc >>?= fun (ctxt, deactivated) -> + Delegate_activation_storage.last_cycle_before_deactivation + ctxt + delegate + >>=? fun cycle -> + if Cycle_repr.(cycle <= last_cycle) then + Delegate_storage.set_inactive ctxt delegate >>=? fun ctxt -> + return (ctxt, delegate :: deactivated) + else return (ctxt, deactivated)) + >|=? fun (ctxt, deactivated) -> (ctxt, deactivated) + +(* Return a map from delegates (with active stake at some cycle + in the cycle window [from_cycle, to_cycle]) to the maximum + of the stake to be deposited for each such cycle (which is just the + [frozen_deposits_percentage] of the active stake at that cycle). Also + return the delegates that have fallen out of the sliding window. *) +let max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle = + let frozen_deposits_percentage = + Constants_storage.frozen_deposits_percentage ctxt + in + let cycles = Cycle_repr.(from_cycle ---> to_cycle) in + (match Cycle_repr.pred from_cycle with + | None -> return Signature.Public_key_hash.Set.empty + | Some cleared_cycle -> ( + Stake_storage.find_selected_distribution ctxt cleared_cycle + >|=? fun cleared_cycle_delegates -> + match cleared_cycle_delegates with + | None -> Signature.Public_key_hash.Set.empty + | Some delegates -> + List.fold_left + (fun set (d, _) -> Signature.Public_key_hash.Set.add d set) + Signature.Public_key_hash.Set.empty + delegates)) + >>=? fun cleared_cycle_delegates -> + List.fold_left_es + (fun (maxima, delegates_to_remove) (cycle : Cycle_repr.t) -> + Stake_storage.get_selected_distribution ctxt cycle + >|=? fun active_stakes -> + List.fold_left + (fun (maxima, delegates_to_remove) (delegate, stake) -> + let stake_to_be_deposited = + Tez_repr.(div_exn (mul_exn stake frozen_deposits_percentage) 100) + in + let maxima = + Signature.Public_key_hash.Map.update + delegate + (function + | None -> Some stake_to_be_deposited + | Some maximum -> + Some (Tez_repr.max maximum stake_to_be_deposited)) + maxima + in + let delegates_to_remove = + Signature.Public_key_hash.Set.remove delegate delegates_to_remove + in + (maxima, delegates_to_remove)) + (maxima, delegates_to_remove) + active_stakes) + (Signature.Public_key_hash.Map.empty, cleared_cycle_delegates) + cycles + +let freeze_deposits ?(origin = Receipt_repr.Block_application) ctxt ~new_cycle + ~balance_updates = + let max_slashable_period = Constants_storage.max_slashing_period ctxt in + (* We want to be able to slash for at most [max_slashable_period] *) + (match Cycle_repr.(sub new_cycle (max_slashable_period - 1)) with + | None -> + Storage.Tenderbake.First_level_of_protocol.get ctxt + >>=? fun first_level_of_protocol -> + let cycle_eras = Raw_context.cycle_eras ctxt in + let level = + Level_repr.level_from_raw ~cycle_eras first_level_of_protocol + in + return level.cycle + | Some cycle -> return cycle) + >>=? fun from_cycle -> + let preserved_cycles = Constants_storage.preserved_cycles ctxt in + let to_cycle = Cycle_repr.(add new_cycle preserved_cycles) in + max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle + >>=? fun (maxima, delegates_to_remove) -> + Signature.Public_key_hash.Map.fold_es + (fun delegate maximum_stake_to_be_deposited (ctxt, balance_updates) -> + (* Here we make sure to preserve the following invariant : + maximum_stake_to_be_deposited <= frozen_deposits + balance + See select_distribution_for_cycle *) + let delegate_contract = Contract_repr.Implicit delegate in + Frozen_deposits_storage.update_initial_amount + ctxt + delegate_contract + maximum_stake_to_be_deposited + >>=? fun ctxt -> + Frozen_deposits_storage.get ctxt delegate_contract >>=? fun deposits -> + let current_amount = deposits.current_amount in + if Tez_repr.(current_amount > maximum_stake_to_be_deposited) then + Tez_repr.(current_amount -? maximum_stake_to_be_deposited) + >>?= fun to_reimburse -> + Token.transfer + ~origin + ctxt + (`Frozen_deposits delegate) + (`Delegate_balance delegate) + to_reimburse + >|=? fun (ctxt, bupds) -> (ctxt, bupds @ balance_updates) + else if Tez_repr.(current_amount < maximum_stake_to_be_deposited) then + Tez_repr.(maximum_stake_to_be_deposited -? current_amount) + >>?= fun desired_to_freeze -> + Contract_storage.get_balance ctxt delegate_contract >>=? fun balance -> + (* In case the delegate hasn't been slashed in this cycle, + the following invariant holds: + maximum_stake_to_be_deposited <= frozen_deposits + balance + See select_distribution_for_cycle + + If the delegate has been slashed during the cycle, the invariant + above doesn't necessarily hold. In this case, we freeze the max + we can for the delegate. *) + let to_freeze = Tez_repr.(min balance desired_to_freeze) in + Token.transfer + ~origin + ctxt + (`Delegate_balance delegate) + (`Frozen_deposits delegate) + to_freeze + >|=? fun (ctxt, bupds) -> (ctxt, bupds @ balance_updates) + else return (ctxt, balance_updates)) + maxima + (ctxt, balance_updates) + >>=? fun (ctxt, balance_updates) -> + (* Unfreeze deposits (that is, set them to zero) for delegates that + were previously in the relevant window (and therefore had some + frozen deposits) but are not in the new window; because that means + that such a delegate had no active stake in the relevant cycles, + and therefore it should have no frozen deposits. *) + Signature.Public_key_hash.Set.fold_es + (fun delegate (ctxt, balance_updates) -> + let delegate_contract = Contract_repr.Implicit delegate in + Frozen_deposits_storage.update_initial_amount + ctxt + delegate_contract + Tez_repr.zero + >>=? fun ctxt -> + Frozen_deposits_storage.get ctxt delegate_contract + >>=? fun frozen_deposits -> + if Tez_repr.(frozen_deposits.current_amount > zero) then + Token.transfer + ~origin + ctxt + (`Frozen_deposits delegate) + (`Delegate_balance delegate) + frozen_deposits.current_amount + >|=? fun (ctxt, bupds) -> (ctxt, bupds @ balance_updates) + else return (ctxt, balance_updates)) + delegates_to_remove + (ctxt, balance_updates) + +let freeze_deposits_do_not_call_except_for_migration = + freeze_deposits ~origin:Protocol_migration + +let cycle_end ctxt last_cycle unrevealed_nonces = + let new_cycle = Cycle_repr.add last_cycle 1 in + Delegate_sampler.select_new_distribution_at_cycle_end ctxt ~new_cycle + >>=? fun ctxt -> + Delegate_slashed_deposits_storage.clear_outdated_slashed_deposits + ctxt + ~new_cycle + >>= fun ctxt -> + Delegate_missed_endorsements_storage.distribute_endorsing_rewards + ctxt + last_cycle + unrevealed_nonces + >>=? fun (ctxt, balance_updates) -> + freeze_deposits ctxt ~new_cycle ~balance_updates + >>=? fun (ctxt, balance_updates) -> + Stake_storage.clear_at_cycle_end ctxt ~new_cycle >>=? fun ctxt -> + Delegate_sampler.clear_outdated_sampling_data ctxt ~new_cycle >>=? fun ctxt -> + update_activity ctxt last_cycle >>=? fun (ctxt, deactivated_delagates) -> + return (ctxt, balance_updates, deactivated_delagates) + +let init_first_cycles ctxt = + let preserved = Constants_storage.preserved_cycles ctxt in + List.fold_left_es + (fun ctxt c -> + let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in + Stake_storage.snapshot ctxt >>=? fun ctxt -> + (* NB: we need to take several snapshots because + select_distribution_for_cycle deletes the snapshots *) + Delegate_sampler.select_distribution_for_cycle ctxt cycle) + ctxt + Misc.(0 --> preserved) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.mli b/src/proto_alpha/lib_protocol/delegate_cycles.mli new file mode 100644 index 000000000000..f45fd05bed59 --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_cycles.mli @@ -0,0 +1,52 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Trigger the context maintenance at the end of cycle 'n', i.e.: + unfreeze the endorsing rewards, potentially deactivate delegates. + Return the corresponding balances updates and the list of + deactivated delegates. *) +val cycle_end : + Raw_context.t -> + Cycle_repr.t -> + Storage.Seed.unrevealed_nonce list -> + (Raw_context.t + * Receipt_repr.balance_updates + * Signature.Public_key_hash.t list) + tzresult + Lwt.t + +(** [init_first_cycles ctxt] computes and records the distribution of the total + active stake among active delegates. This concerns the total active stake + involved in the calculation of baking rights for all cycles in the range + [0, preserved_cycles]. *) +val init_first_cycles : Raw_context.t -> Raw_context.t tzresult Lwt.t + +val freeze_deposits_do_not_call_except_for_migration : + Raw_context.t -> + new_cycle:Cycle_repr.t -> + balance_updates:Receipt_repr.balance_updates -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml new file mode 100644 index 000000000000..b776c0eb8171 --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -0,0 +1,266 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let expected_slots_for_given_active_stake ctxt ~total_active_stake ~active_stake + = + let blocks_per_cycle = + Int32.to_int (Constants_storage.blocks_per_cycle ctxt) + in + let consensus_committee_size = + Constants_storage.consensus_committee_size ctxt + in + let number_of_endorsements_per_cycle = + blocks_per_cycle * consensus_committee_size + in + Result.return + (Z.to_int + (Z.div + (Z.mul + (Z.of_int64 (Tez_repr.to_mutez active_stake)) + (Z.of_int number_of_endorsements_per_cycle)) + (Z.of_int64 (Tez_repr.to_mutez total_active_stake)))) + +type level_participation = Participated | Didn't_participate + +(* Note that the participation for the last block of a cycle is + recorded in the next cycle. *) +let record_endorsing_participation ctxt ~delegate ~participation + ~endorsing_power = + match participation with + | Participated -> Delegate_storage.set_active ctxt delegate + | Didn't_participate -> ( + let contract = Contract_repr.Implicit delegate in + Storage.Contract.Missed_endorsements.find ctxt contract >>=? function + | Some {remaining_slots; missed_levels} -> + let remaining_slots = remaining_slots - endorsing_power in + Storage.Contract.Missed_endorsements.update + ctxt + contract + {remaining_slots; missed_levels = missed_levels + 1} + | None -> ( + let level = Level_storage.current ctxt in + Raw_context.stake_distribution_for_current_cycle ctxt + >>?= fun stake_distribution -> + match + Signature.Public_key_hash.Map.find delegate stake_distribution + with + | None -> + (* This happens when the block is the first one in a + cycle, and therefore the endorsements are for the last + block of the previous cycle, and when the delegate does + not have an active stake at the current cycle; in this + case its participation is simply ignored. *) + assert (Compare.Int32.(level.cycle_position = 0l)) ; + return ctxt + | Some active_stake -> + Stake_storage.get_total_active_stake ctxt level.cycle + >>=? fun total_active_stake -> + expected_slots_for_given_active_stake + ctxt + ~total_active_stake + ~active_stake + >>?= fun expected_slots -> + let Ratio_repr.{numerator; denominator} = + Constants_storage.minimal_participation_ratio ctxt + in + let minimal_activity = expected_slots * numerator / denominator in + let maximal_inactivity = expected_slots - minimal_activity in + let remaining_slots = maximal_inactivity - endorsing_power in + Storage.Contract.Missed_endorsements.init + ctxt + contract + {remaining_slots; missed_levels = 1})) + +let record_baking_activity_and_pay_rewards_and_fees ctxt ~payload_producer + ~block_producer ~baking_reward ~reward_bonus = + Delegate_storage.set_active ctxt payload_producer >>=? fun ctxt -> + (if not (Signature.Public_key_hash.equal payload_producer block_producer) then + Delegate_storage.set_active ctxt block_producer + else return ctxt) + >>=? fun ctxt -> + let pay_payload_producer ctxt delegate = + let contract = Contract_repr.Implicit delegate in + Token.balance ctxt `Block_fees >>=? fun (ctxt, block_fees) -> + Token.transfer_n + ctxt + [(`Block_fees, block_fees); (`Baking_rewards, baking_reward)] + (`Contract contract) + in + let pay_block_producer ctxt delegate bonus = + let contract = Contract_repr.Implicit delegate in + Token.transfer ctxt `Baking_bonuses (`Contract contract) bonus + in + pay_payload_producer ctxt payload_producer + >>=? fun (ctxt, balance_updates_payload_producer) -> + (match reward_bonus with + | Some bonus -> pay_block_producer ctxt block_producer bonus + | None -> return (ctxt, [])) + >>=? fun (ctxt, balance_updates_block_producer) -> + return + (ctxt, balance_updates_payload_producer @ balance_updates_block_producer) + +type participation_info = { + expected_cycle_activity : int; + minimal_cycle_activity : int; + missed_slots : int; + missed_levels : int; + remaining_allowed_missed_slots : int; + expected_endorsing_rewards : Tez_repr.t; +} + +(* Inefficient, only for RPC *) +let delegate_participation_info ctxt delegate = + let level = Level_storage.current ctxt in + Stake_storage.get_selected_distribution ctxt level.cycle + >>=? fun stake_distribution -> + match + List.assoc_opt + ~equal:Signature.Public_key_hash.equal + delegate + stake_distribution + with + | None -> + (* delegate does not have an active stake at the current cycle *) + return + { + expected_cycle_activity = 0; + minimal_cycle_activity = 0; + missed_slots = 0; + missed_levels = 0; + remaining_allowed_missed_slots = 0; + expected_endorsing_rewards = Tez_repr.zero; + } + | Some active_stake -> + Stake_storage.get_total_active_stake ctxt level.cycle + >>=? fun total_active_stake -> + expected_slots_for_given_active_stake + ctxt + ~total_active_stake + ~active_stake + >>?= fun expected_cycle_activity -> + let Ratio_repr.{numerator; denominator} = + Constants_storage.minimal_participation_ratio ctxt + in + let endorsing_reward_per_slot = + Constants_storage.endorsing_reward_per_slot ctxt + in + let minimal_cycle_activity = + expected_cycle_activity * numerator / denominator + in + let maximal_cycle_inactivity = + expected_cycle_activity - minimal_cycle_activity + in + let expected_endorsing_rewards = + Tez_repr.mul_exn endorsing_reward_per_slot expected_cycle_activity + in + let contract = Contract_repr.Implicit delegate in + Storage.Contract.Missed_endorsements.find ctxt contract + >>=? fun missed_endorsements -> + let missed_slots, missed_levels, remaining_allowed_missed_slots = + match missed_endorsements with + | None -> (0, 0, maximal_cycle_inactivity) + | Some {remaining_slots; missed_levels} -> + ( maximal_cycle_inactivity - remaining_slots, + missed_levels, + Compare.Int.max 0 remaining_slots ) + in + let expected_endorsing_rewards = + match missed_endorsements with + | Some r when Compare.Int.(r.remaining_slots < 0) -> Tez_repr.zero + | _ -> expected_endorsing_rewards + in + return + { + expected_cycle_activity; + minimal_cycle_activity; + missed_slots; + missed_levels; + remaining_allowed_missed_slots; + expected_endorsing_rewards; + } + +let delegate_participated_enough ctxt delegate = + Storage.Contract.Missed_endorsements.find ctxt delegate >>=? function + | None -> return_true + | Some missed_endorsements -> + return Compare.Int.(missed_endorsements.remaining_slots >= 0) + +let delegate_has_revealed_nonces delegate unrevelead_nonces_set = + not (Signature.Public_key_hash.Set.mem delegate unrevelead_nonces_set) + +let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = + let endorsing_reward_per_slot = + Constants_storage.endorsing_reward_per_slot ctxt + in + let unrevealed_nonces_set = + List.fold_left + (fun set {Storage.Seed.nonce_hash = _; delegate} -> + Signature.Public_key_hash.Set.add delegate set) + Signature.Public_key_hash.Set.empty + unrevealed_nonces + in + Stake_storage.get_total_active_stake ctxt last_cycle + >>=? fun total_active_stake -> + Stake_storage.get_selected_distribution ctxt last_cycle >>=? fun delegates -> + List.fold_left_es + (fun (ctxt, balance_updates) (delegate, active_stake) -> + let delegate_contract = Contract_repr.Implicit delegate in + delegate_participated_enough ctxt delegate_contract + >>=? fun sufficient_participation -> + let has_revealed_nonces = + delegate_has_revealed_nonces delegate unrevealed_nonces_set + in + expected_slots_for_given_active_stake + ctxt + ~total_active_stake + ~active_stake + >>?= fun expected_slots -> + let rewards = Tez_repr.mul_exn endorsing_reward_per_slot expected_slots in + (if sufficient_participation && has_revealed_nonces then + (* Sufficient participation: we pay the rewards *) + Token.transfer + ctxt + `Endorsing_rewards + (`Contract delegate_contract) + rewards + >|=? fun (ctxt, payed_rewards_receipts) -> + (ctxt, payed_rewards_receipts @ balance_updates) + else + (* Insufficient participation or unrevealed nonce: no rewards *) + Token.transfer + ctxt + `Endorsing_rewards + (`Lost_endorsing_rewards + (delegate, not sufficient_participation, not has_revealed_nonces)) + rewards + >|=? fun (ctxt, payed_rewards_receipts) -> + (ctxt, payed_rewards_receipts @ balance_updates)) + >>=? fun (ctxt, balance_updates) -> + Storage.Contract.Missed_endorsements.remove ctxt delegate_contract + >>= fun ctxt -> return (ctxt, balance_updates)) + (ctxt, []) + delegates diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli new file mode 100644 index 000000000000..3ac64a03ae96 --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli @@ -0,0 +1,86 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type level_participation = Participated | Didn't_participate + +(** Record the participation of a delegate as a validator. *) +val record_endorsing_participation : + Raw_context.t -> + delegate:Signature.Public_key_hash.t -> + participation:level_participation -> + endorsing_power:int -> + Raw_context.t tzresult Lwt.t + +(** Participation information. We denote by: + - "static" information that does not change during the cycle + - "dynamic" information that may change during the cycle *) +type participation_info = { + expected_cycle_activity : int; + (** The total expected slots to be endorsed in the cycle. (static) *) + minimal_cycle_activity : int; + (** The minimal endorsing slots in the cycle to get endorsing + rewards. (static) *) + missed_slots : int; + (** The number of missed endorsing slots in the cycle. (dynamic) *) + missed_levels : int; + (** The number of missed endorsing levels in the cycle. (dynamic) *) + remaining_allowed_missed_slots : int; + (** Remaining amount of endorsing slots that can be missed in the + cycle before forfeiting the rewards. (dynamic) *) + expected_endorsing_rewards : Tez_repr.t; + (** Endorsing rewards that will be distributed at the end of the + cycle if activity at that point will be greater than the minimal + required. If the activity is already known to be below the + required minimum, then the rewards are zero. (dynamic) *) +} + +(** Only use this function for RPC: this is expensive. + + [delegate_participation_info] and [!val:check_delegate] forms the + implementation of RPC call "/context/delegates//participation". + *) +val delegate_participation_info : + Raw_context.t -> + Signature.Public_key_hash.t -> + participation_info tzresult Lwt.t + +(** Sets the payload and block producer as active. Pays the baking + reward and the fees to the payload producer and the reward bonus to + the payload producer (if the reward_bonus is not None).*) +val record_baking_activity_and_pay_rewards_and_fees : + Raw_context.t -> + payload_producer:Signature.Public_key_hash.t -> + block_producer:Signature.Public_key_hash.t -> + baking_reward:Tez_repr.t -> + reward_bonus:Tez_repr.t option -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +val distribute_endorsing_rewards : + Raw_context.t -> + Cycle_repr.t -> + Storage.Seed.unrevealed_nonce list -> + (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml new file mode 100644 index 000000000000..71b837b7ef60 --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -0,0 +1,242 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Delegate_sampler_state = struct + module Cache_client = struct + type cached_value = + (Signature.public_key * Signature.public_key_hash) Sampler.t + + let namespace = Cache_repr.create_namespace "sampler_state" + + let cache_index = 2 + + let value_of_identifier ctxt identifier = + let cycle = Cycle_repr.of_string_exn identifier in + Storage.Delegate_sampler_state.get ctxt cycle + end + + module Cache = (val Cache_repr.register_exn (module Cache_client)) + + let identifier_of_cycle cycle = Format.asprintf "%a" Cycle_repr.pp cycle + + let init ctxt cycle sampler_state = + let id = identifier_of_cycle cycle in + Storage.Delegate_sampler_state.init ctxt cycle sampler_state + >>=? fun ctxt -> + let size = 1 (* that's symbolic: 1 cycle = 1 entry *) in + Cache.update ctxt id (Some (sampler_state, size)) >>?= fun ctxt -> + return ctxt + + let get ctxt cycle = + let id = identifier_of_cycle cycle in + Cache.find ctxt id >>=? function + | None -> Storage.Delegate_sampler_state.get ctxt cycle + | Some v -> return v + + let remove_existing ctxt cycle = + let id = identifier_of_cycle cycle in + Cache.update ctxt id None >>?= fun ctxt -> + Storage.Delegate_sampler_state.remove_existing ctxt cycle +end + +module Random = struct + (* [init_random_state] initialize a random sequence drawing state + that's unique for a given (seed, level, index) triple. Elements + from this sequence are drawn using [take_int64], updating the + state for the next draw. The initial state is the Blake2b hash of + the three randomness sources, and an offset set to zero + (indicating that zero bits of randomness have been + consumed). When drawing random elements, bits are extracted from + the state until exhaustion (256 bits), at which point the state + is rehashed and the offset reset to 0. *) + + let init_random_state seed level index = + ( Raw_hashes.blake2b + (Data_encoding.Binary.to_bytes_exn + Data_encoding.(tup3 Seed_repr.seed_encoding int32 int32) + (seed, level.Level_repr.cycle_position, Int32.of_int index)), + 0 ) + + let take_int64 bound state = + let drop_if_over = + (* This function draws random values in [0-(bound-1)] by drawing + in [0-(2^63-1)] (64-bit) and computing the value modulo + [bound]. For the application of [mod bound] to preserve + uniformity, the input space must be of the form + [0-(n*bound-1)]. We enforce this by rejecting 64-bit samples + above this limit (in which case, we draw a new 64-sample from + the sequence and try again). *) + Int64.sub Int64.max_int (Int64.rem Int64.max_int bound) + in + let rec loop (bytes, n) = + let consumed_bytes = 8 in + let state_size = Bytes.length bytes in + if Compare.Int.(n > state_size - consumed_bytes) then + loop (Raw_hashes.blake2b bytes, 0) + else + let r = TzEndian.get_int64 bytes n in + (* The absolute value of min_int is min_int. Also, every + positive integer is represented twice (positive and negative), + but zero is only represented once. We fix both problems at + once. *) + let r = if Compare.Int64.(r = Int64.min_int) then 0L else Int64.abs r in + if Compare.Int64.(r >= drop_if_over) then + loop (bytes, n + consumed_bytes) + else + let v = Int64.rem r bound in + (v, (bytes, n + consumed_bytes)) + in + loop state + + (** [sampler_for_cycle ctxt cycle] reads the sampler for [cycle] from + [ctxt] if it has been previously inited. Otherwise it initializes + the sampler and caches it in [ctxt] with + [Raw_context.set_sampler_for_cycle]. *) + let sampler_for_cycle ctxt cycle = + let read ctxt = + Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> + Delegate_sampler_state.get ctxt cycle >>=? fun state -> + return (seed, state) + in + Raw_context.sampler_for_cycle ~read ctxt cycle + + let owner c (level : Level_repr.t) offset = + let cycle = level.Level_repr.cycle in + sampler_for_cycle c cycle >>=? fun (c, seed, state) -> + let sample ~int_bound ~mass_bound = + let state = init_random_state seed level offset in + let i, state = take_int64 (Int64.of_int int_bound) state in + let elt, _ = take_int64 mass_bound state in + (Int64.to_int i, elt) + in + let pk, pkh = Sampler.sample state sample in + return (c, (pk, pkh)) +end + +let slot_owner c level slot = Random.owner c level (Slot_repr.to_int slot) + +let baking_rights_owner c (level : Level_repr.t) ~round = + Round_repr.to_int round >>?= fun round -> + let consensus_committee_size = Constants_storage.consensus_committee_size c in + Slot_repr.of_int (round mod consensus_committee_size) >>?= fun slot -> + slot_owner c level slot >>=? fun (ctxt, pk) -> return (ctxt, slot, pk) + +let get_stakes_for_selected_index ctxt index = + Stake_storage.fold_snapshot + ctxt + ~index + ~f:(fun (delegate, staking_balance) (acc, total_stake) -> + let delegate_contract = Contract_repr.Implicit delegate in + let open Tez_repr in + let open Lwt_result_syntax in + let* frozen_deposits_limit = + Delegate_storage.frozen_deposits_limit ctxt delegate + in + + let* balance_and_frozen_bonds = + Contract_storage.get_balance_and_frozen_bonds ctxt delegate_contract + in + let* frozen_deposits = + Frozen_deposits_storage.get ctxt delegate_contract + in + let*? total_balance = + balance_and_frozen_bonds +? frozen_deposits.current_amount + in + let* stake_for_cycle = + let frozen_deposits_percentage = + Int64.of_int @@ Constants_storage.frozen_deposits_percentage ctxt + in + let max_mutez = of_mutez_exn Int64.max_int in + let frozen_deposits_limit = + match frozen_deposits_limit with Some fdp -> fdp | None -> max_mutez + in + let aux = min total_balance frozen_deposits_limit in + let*? overflow_bound = max_mutez /? 100L in + if aux <= overflow_bound then + let*? aux = aux *? 100L in + let*? v = aux /? frozen_deposits_percentage in + return (min v staking_balance) + else + let*? sbal = staking_balance /? 100L in + let*? a = aux /? frozen_deposits_percentage in + if sbal <= a then return staking_balance + else + let*? r = max_mutez /? frozen_deposits_percentage in + return r + in + let*? total_stake = Tez_repr.(total_stake +? stake_for_cycle) in + return ((delegate, stake_for_cycle) :: acc, total_stake)) + ~init:([], Tez_repr.zero) + +let compute_snapshot_index_for_seed ~max_snapshot_index seed = + let rd = Seed_repr.initialize_new seed [Bytes.of_string "stake_snapshot"] in + let seq = Seed_repr.sequence rd 0l in + Seed_repr.take_int32 seq (Int32.of_int max_snapshot_index) + |> fst |> Int32.to_int |> return + +let compute_snapshot_index ctxt cycle ~max_snapshot_index = + Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> + compute_snapshot_index_for_seed ~max_snapshot_index seed + +let select_distribution_for_cycle ctxt cycle = + Stake_storage.max_snapshot_index ctxt >>=? fun max_snapshot_index -> + Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> + compute_snapshot_index_for_seed ~max_snapshot_index seed + >>=? fun selected_index -> + get_stakes_for_selected_index ctxt selected_index + >>=? fun (stakes, total_stake) -> + Stake_storage.set_selected_distribution_for_cycle + ctxt + cycle + stakes + total_stake + >>=? fun ctxt -> + List.fold_left_es + (fun acc (pkh, stake) -> + Delegate_storage.pubkey ctxt pkh >|=? fun pk -> + ((pk, pkh), Tez_repr.to_mutez stake) :: acc) + [] + stakes + >>=? fun stakes_pk -> + let state = Sampler.create stakes_pk in + Delegate_sampler_state.init ctxt cycle state >>=? fun ctxt -> + (* pre-allocate the sampler *) + Lwt.return (Raw_context.init_sampler_for_cycle ctxt cycle seed state) + +let select_new_distribution_at_cycle_end ctxt ~new_cycle = + let preserved = Constants_storage.preserved_cycles ctxt in + let for_cycle = Cycle_repr.add new_cycle preserved in + select_distribution_for_cycle ctxt for_cycle + +let clear_outdated_sampling_data ctxt ~new_cycle = + let max_slashing_period = Constants_storage.max_slashing_period ctxt in + match Cycle_repr.sub new_cycle max_slashing_period with + | None -> return ctxt + | Some outdated_cycle -> + Delegate_sampler_state.remove_existing ctxt outdated_cycle + >>=? fun ctxt -> + Storage.Seed.For_cycle.remove_existing ctxt outdated_cycle diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.mli b/src/proto_alpha/lib_protocol/delegate_sampler.mli new file mode 100644 index 000000000000..194c5a50468b --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_sampler.mli @@ -0,0 +1,65 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Participation slots potentially associated to accounts. The + accounts that didn't place a deposit will be excluded from this + list. This function should only be used to compute the deposits to + freeze or initialize the protocol while stitching. RPCs can use this + function to predict an approximation of long term future slot + allocations. It shouldn't be used in the baker. *) +val slot_owner : + Raw_context.t -> + Level_repr.t -> + Slot_repr.t -> + (Raw_context.t * (Signature.public_key * Signature.public_key_hash)) tzresult + Lwt.t + +val baking_rights_owner : + Raw_context.t -> + Level_repr.t -> + round:Round_repr.round -> + (Raw_context.t + * Slot_repr.t + * (Signature.public_key * Signature.public_key_hash)) + tzresult + Lwt.t + +(** [compute_snapshot_index ctxt cycle max_snapshot_index] Returns the index of + the selected snapshot for the [cycle] passed as argument, and for the max + index of snapshots taken so far, [max_snapshot_index] (see + [Stake_storage.max_snapshot_index]. *) +val compute_snapshot_index : + Raw_context.t -> Cycle_repr.t -> max_snapshot_index:int -> int tzresult Lwt.t + +val select_new_distribution_at_cycle_end : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val clear_outdated_sampling_data : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +val select_distribution_for_cycle : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml new file mode 100644 index 000000000000..043f8c117346 --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -0,0 +1,118 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +let check_and_record_already_slashed_for_double_baking ctxt delegate + (level : Level_repr.t) = + let open Lwt_tzresult_syntax in + let* slashed = + Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) + in + let already_slashed, updated_slashed = + match slashed with + | None -> + (false, {Storage.for_double_baking = true; for_double_endorsing = false}) + | Some slashed -> + (slashed.for_double_baking, {slashed with for_double_baking = true}) + in + let*! ctxt = + Storage.Slashed_deposits.add + (ctxt, level.cycle) + (level.level, delegate) + updated_slashed + in + return (ctxt, already_slashed) + +let check_and_record_already_slashed_for_double_endorsing ctxt delegate + (level : Level_repr.t) = + let open Lwt_tzresult_syntax in + let* slashed = + Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) + in + let already_slashed, updated_slashed = + match slashed with + | None -> + (false, {Storage.for_double_endorsing = true; for_double_baking = false}) + | Some slashed -> + ( slashed.for_double_endorsing, + {slashed with for_double_endorsing = true} ) + in + let*! ctxt = + Storage.Slashed_deposits.add + (ctxt, level.cycle) + (level.level, delegate) + updated_slashed + in + return (ctxt, already_slashed) + +let clear_outdated_slashed_deposits ctxt ~new_cycle = + let max_slashable_period = Constants_storage.max_slashing_period ctxt in + match Cycle_repr.(sub new_cycle max_slashable_period) with + | None -> Lwt.return ctxt + | Some outdated_cycle -> Storage.Slashed_deposits.clear (ctxt, outdated_cycle) + +let punish_double_endorsing ctxt delegate = + let delegate_contract = Contract_repr.Implicit delegate in + Frozen_deposits_storage.get ctxt delegate_contract >>=? fun frozen_deposits -> + let slashing_ratio : Ratio_repr.t = + Constants_storage.ratio_of_frozen_deposits_slashed_per_double_endorsement + ctxt + in + let punish_value = + Tez_repr.( + div_exn + (mul_exn frozen_deposits.initial_amount slashing_ratio.numerator) + slashing_ratio.denominator) + in + let amount_to_burn = + Tez_repr.(min frozen_deposits.current_amount punish_value) + in + Token.transfer + ctxt + (`Frozen_deposits delegate) + `Double_signing_punishments + amount_to_burn + >>=? fun (ctxt, balance_updates) -> + Stake_storage.remove_stake ctxt delegate amount_to_burn >>=? fun ctxt -> + return (ctxt, amount_to_burn, balance_updates) + +let punish_double_baking ctxt delegate = + let delegate_contract = Contract_repr.Implicit delegate in + Frozen_deposits_storage.get ctxt delegate_contract >>=? fun frozen_deposits -> + let slashing_for_one_block = + Constants_storage.double_baking_punishment ctxt + in + let amount_to_burn = + Tez_repr.(min frozen_deposits.current_amount slashing_for_one_block) + in + Token.transfer + ctxt + (`Frozen_deposits delegate) + `Double_signing_punishments + amount_to_burn + >>=? fun (ctxt, balance_updates) -> + Stake_storage.remove_stake ctxt delegate amount_to_burn >>=? fun ctxt -> + return (ctxt, amount_to_burn, balance_updates) diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli new file mode 100644 index 000000000000..474456f6c49d --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli @@ -0,0 +1,61 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Burn some frozen deposit for a delegate at a given level. Returns + the burned amount. *) +val punish_double_endorsing : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t + +val punish_double_baking : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t + +(** Returns true if the given delegate has already been slashed + for double baking for the given level, and record in the context + that the given delegate has now been slashed for double baking + for the given level. *) +val check_and_record_already_slashed_for_double_baking : + Raw_context.t -> + Signature.Public_key_hash.t -> + Level_repr.t -> + (Raw_context.t * bool) tzresult Lwt.t + +(** Returns true if the given delegate has already been slashed for + double preendorsing or double endorsing for the given level, and + record in the context that the given delegate has now been slashed + for double preendorsing or double endorsing for the given level. *) +val check_and_record_already_slashed_for_double_endorsing : + Raw_context.t -> + Signature.Public_key_hash.t -> + Level_repr.t -> + (Raw_context.t * bool) tzresult Lwt.t + +val clear_outdated_slashed_deposits : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index d2f0fa7c7656..8d10d9fad5c4 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -170,6 +171,37 @@ let () = (function Not_registered pkh -> Some pkh | _ -> None) (fun pkh -> Not_registered pkh) +(* The fact that this succeeds iff [registered ctxt pkh] returns true is an + invariant of the [set] function. *) +let check_delegate ctxt pkh = + Storage.Delegates.mem ctxt pkh >>= function + | true -> return_unit + | false -> fail (Not_registered pkh) + +let fold = Storage.Delegates.fold + +let list = Storage.Delegates.elements + +let pubkey ctxt pkh = + Contract_manager_storage.get_manager_key + ctxt + pkh + ~error:(Unregistered_delegate pkh) + +let frozen_deposits_limit ctxt delegate = + Storage.Contract.Frozen_deposits_limit.find + ctxt + (Contract_repr.Implicit delegate) + +let set_frozen_deposits_limit ctxt delegate limit = + Storage.Contract.Frozen_deposits_limit.add_or_remove + ctxt + (Contract_repr.Implicit delegate) + limit + +let frozen_deposits ctxt delegate = + Frozen_deposits_storage.get ctxt (Contract_repr.Implicit delegate) + let set_inactive ctxt delegate = Delegate_activation_storage.set_inactive ctxt delegate >>= fun ctxt -> Stake_storage.deactivate_only_call_from_delegate_storage ctxt delegate >|= ok @@ -180,16 +212,30 @@ let set_active ctxt delegate = if not inactive then return ctxt else Stake_storage.activate_only_call_from_delegate_storage ctxt delegate +let balance ctxt delegate = + let contract = Contract_repr.Implicit delegate in + Storage.Contract.Spendable_balance.get ctxt contract + let staking_balance ctxt delegate = Contract_delegate_storage.registered ctxt delegate >>=? fun is_registered -> if is_registered then Stake_storage.get_staking_balance ctxt delegate else return Tez_repr.zero -let pubkey ctxt delegate = - Contract_manager_storage.get_manager_key - ctxt - delegate - ~error:(Unregistered_delegate delegate) +let delegated_balance ctxt delegate = + staking_balance ctxt delegate >>=? fun staking_balance -> + balance ctxt delegate >>=? fun balance -> + frozen_deposits ctxt delegate >>=? fun frozen_deposits -> + Tez_repr.(balance +? frozen_deposits.current_amount) + >>?= fun self_staking_balance -> + Lwt.return Tez_repr.(staking_balance -? self_staking_balance) + +let full_balance ctxt delegate = + frozen_deposits ctxt delegate >>=? fun frozen_deposits -> + let delegate_contract = Contract_repr.Implicit delegate in + Contract_storage.get_balance_and_frozen_bonds ctxt delegate_contract + >>=? fun balance_and_frozen_bonds -> + Lwt.return + Tez_repr.(frozen_deposits.current_amount +? balance_and_frozen_bonds) let init ctxt contract delegate = Contract_manager_storage.is_manager_key_revealed ctxt delegate @@ -254,7 +300,7 @@ let set c contract delegate = else return_unit | Originated _ -> return_unit) >>=? fun () -> - Storage.Contract.Spendable_balance.mem c contract >>= fun exists -> + Contract_storage.allocated c contract >>= fun exists -> error_when (self_delegation && not exists) (Empty_delegate_account delegate) @@ -269,785 +315,3 @@ let set c contract delegate = if self_delegation then Storage.Delegates.add c delegate >>= fun c -> set_active c delegate else return c - -let frozen_deposits_limit ctxt delegate = - Storage.Contract.Frozen_deposits_limit.find - ctxt - (Contract_repr.Implicit delegate) - -let set_frozen_deposits_limit ctxt delegate limit = - Storage.Contract.Frozen_deposits_limit.add_or_remove - ctxt - (Contract_repr.Implicit delegate) - limit - -let update_activity ctxt last_cycle = - let preserved = Constants_storage.preserved_cycles ctxt in - match Cycle_repr.sub last_cycle preserved with - | None -> return (ctxt, []) - | Some _unfrozen_cycle -> - Stake_storage.fold_on_active_delegates_with_rolls - ctxt - ~order:`Sorted - ~init:(Ok (ctxt, [])) - ~f:(fun delegate () acc -> - acc >>?= fun (ctxt, deactivated) -> - Delegate_activation_storage.last_cycle_before_deactivation - ctxt - delegate - >>=? fun cycle -> - if Cycle_repr.(cycle <= last_cycle) then - set_inactive ctxt delegate >|=? fun ctxt -> - (ctxt, delegate :: deactivated) - else return (ctxt, deactivated)) - >|=? fun (ctxt, deactivated) -> (ctxt, deactivated) - -let expected_slots_for_given_active_stake ctxt ~total_active_stake ~active_stake - = - let blocks_per_cycle = - Int32.to_int (Constants_storage.blocks_per_cycle ctxt) - in - let consensus_committee_size = - Constants_storage.consensus_committee_size ctxt - in - let number_of_endorsements_per_cycle = - blocks_per_cycle * consensus_committee_size - in - Result.return - (Z.to_int - (Z.div - (Z.mul - (Z.of_int64 (Tez_repr.to_mutez active_stake)) - (Z.of_int number_of_endorsements_per_cycle)) - (Z.of_int64 (Tez_repr.to_mutez total_active_stake)))) - -let delegate_participated_enough ctxt delegate = - Storage.Contract.Missed_endorsements.find ctxt delegate >>=? function - | None -> return_true - | Some missed_endorsements -> - return Compare.Int.(missed_endorsements.remaining_slots >= 0) - -let delegate_has_revealed_nonces delegate unrevelead_nonces_set = - not (Signature.Public_key_hash.Set.mem delegate unrevelead_nonces_set) - -let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = - let endorsing_reward_per_slot = - Constants_storage.endorsing_reward_per_slot ctxt - in - let unrevealed_nonces_set = - List.fold_left - (fun set {Storage.Seed.nonce_hash = _; delegate} -> - Signature.Public_key_hash.Set.add delegate set) - Signature.Public_key_hash.Set.empty - unrevealed_nonces - in - Stake_storage.get_total_active_stake ctxt last_cycle - >>=? fun total_active_stake -> - Stake_storage.get_selected_distribution ctxt last_cycle >>=? fun delegates -> - List.fold_left_es - (fun (ctxt, balance_updates) (delegate, active_stake) -> - let delegate_contract = Contract_repr.Implicit delegate in - delegate_participated_enough ctxt delegate_contract - >>=? fun sufficient_participation -> - let has_revealed_nonces = - delegate_has_revealed_nonces delegate unrevealed_nonces_set - in - expected_slots_for_given_active_stake - ctxt - ~total_active_stake - ~active_stake - >>?= fun expected_slots -> - let rewards = Tez_repr.mul_exn endorsing_reward_per_slot expected_slots in - (if sufficient_participation && has_revealed_nonces then - (* Sufficient participation: we pay the rewards *) - Token.transfer - ctxt - `Endorsing_rewards - (`Contract delegate_contract) - rewards - >|=? fun (ctxt, payed_rewards_receipts) -> - (ctxt, payed_rewards_receipts @ balance_updates) - else - (* Insufficient participation or unrevealed nonce: no rewards *) - Token.transfer - ctxt - `Endorsing_rewards - (`Lost_endorsing_rewards - (delegate, not sufficient_participation, not has_revealed_nonces)) - rewards - >|=? fun (ctxt, payed_rewards_receipts) -> - (ctxt, payed_rewards_receipts @ balance_updates)) - >>=? fun (ctxt, balance_updates) -> - Storage.Contract.Missed_endorsements.remove ctxt delegate_contract - >>= fun ctxt -> return (ctxt, balance_updates)) - (ctxt, []) - delegates - -let clear_outdated_slashed_deposits ctxt ~new_cycle = - let max_slashable_period = Constants_storage.max_slashing_period ctxt in - match Cycle_repr.(sub new_cycle max_slashable_period) with - | None -> Lwt.return ctxt - | Some outdated_cycle -> Storage.Slashed_deposits.clear (ctxt, outdated_cycle) - -(* Return a map from delegates (with active stake at some cycle - in the cycle window [from_cycle, to_cycle]) to the maximum - of the stake to be deposited for each such cycle (which is just the - [frozen_deposits_percentage] of the active stake at that cycle). Also - return the delegates that have fallen out of the sliding window. *) -let max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle = - let frozen_deposits_percentage = - Constants_storage.frozen_deposits_percentage ctxt - in - let cycles = Cycle_repr.(from_cycle ---> to_cycle) in - (match Cycle_repr.pred from_cycle with - | None -> return Signature.Public_key_hash.Set.empty - | Some cleared_cycle -> ( - Stake_storage.find_selected_distribution ctxt cleared_cycle - >|=? fun cleared_cycle_delegates -> - match cleared_cycle_delegates with - | None -> Signature.Public_key_hash.Set.empty - | Some delegates -> - List.fold_left - (fun set (d, _) -> Signature.Public_key_hash.Set.add d set) - Signature.Public_key_hash.Set.empty - delegates)) - >>=? fun cleared_cycle_delegates -> - List.fold_left_es - (fun (maxima, delegates_to_remove) (cycle : Cycle_repr.t) -> - Stake_storage.get_selected_distribution ctxt cycle - >|=? fun active_stakes -> - List.fold_left - (fun (maxima, delegates_to_remove) (delegate, stake) -> - let stake_to_be_deposited = - Tez_repr.(div_exn (mul_exn stake frozen_deposits_percentage) 100) - in - let maxima = - Signature.Public_key_hash.Map.update - delegate - (function - | None -> Some stake_to_be_deposited - | Some maximum -> - Some (Tez_repr.max maximum stake_to_be_deposited)) - maxima - in - let delegates_to_remove = - Signature.Public_key_hash.Set.remove delegate delegates_to_remove - in - (maxima, delegates_to_remove)) - (maxima, delegates_to_remove) - active_stakes) - (Signature.Public_key_hash.Map.empty, cleared_cycle_delegates) - cycles - -let freeze_deposits ?(origin = Receipt_repr.Block_application) ctxt ~new_cycle - ~balance_updates = - let max_slashable_period = Constants_storage.max_slashing_period ctxt in - (* We want to be able to slash for at most [max_slashable_period] *) - (match Cycle_repr.(sub new_cycle (max_slashable_period - 1)) with - | None -> - Storage.Tenderbake.First_level_of_protocol.get ctxt - >>=? fun first_level_of_protocol -> - let cycle_eras = Raw_context.cycle_eras ctxt in - let level = - Level_repr.level_from_raw ~cycle_eras first_level_of_protocol - in - return level.cycle - | Some cycle -> return cycle) - >>=? fun from_cycle -> - let preserved_cycles = Constants_storage.preserved_cycles ctxt in - let to_cycle = Cycle_repr.(add new_cycle preserved_cycles) in - max_frozen_deposits_and_delegates_to_remove ctxt ~from_cycle ~to_cycle - >>=? fun (maxima, delegates_to_remove) -> - Signature.Public_key_hash.Map.fold_es - (fun delegate maximum_stake_to_be_deposited (ctxt, balance_updates) -> - (* Here we make sure to preserve the following invariant : - maximum_stake_to_be_deposited <= frozen_deposits + balance - See select_distribution_for_cycle *) - let delegate_contract = Contract_repr.Implicit delegate in - Frozen_deposits_storage.update_initial_amount - ctxt - delegate_contract - maximum_stake_to_be_deposited - >>=? fun ctxt -> - Frozen_deposits_storage.get ctxt delegate_contract >>=? fun deposits -> - let current_amount = deposits.current_amount in - if Tez_repr.(current_amount > maximum_stake_to_be_deposited) then - Tez_repr.(current_amount -? maximum_stake_to_be_deposited) - >>?= fun to_reimburse -> - Token.transfer - ~origin - ctxt - (`Frozen_deposits delegate) - (`Delegate_balance delegate) - to_reimburse - >|=? fun (ctxt, bupds) -> (ctxt, bupds @ balance_updates) - else if Tez_repr.(current_amount < maximum_stake_to_be_deposited) then - Tez_repr.(maximum_stake_to_be_deposited -? current_amount) - >>?= fun desired_to_freeze -> - Storage.Contract.Spendable_balance.get ctxt delegate_contract - >>=? fun balance -> - (* In case the delegate hasn't been slashed in this cycle, - the following invariant holds: - maximum_stake_to_be_deposited <= frozen_deposits + balance - See select_distribution_for_cycle - - If the delegate has been slashed during the cycle, the invariant - above doesn't necessarily hold. In this case, we freeze the max - we can for the delegate. *) - let to_freeze = Tez_repr.(min balance desired_to_freeze) in - Token.transfer - ~origin - ctxt - (`Delegate_balance delegate) - (`Frozen_deposits delegate) - to_freeze - >|=? fun (ctxt, bupds) -> (ctxt, bupds @ balance_updates) - else return (ctxt, balance_updates)) - maxima - (ctxt, balance_updates) - >>=? fun (ctxt, balance_updates) -> - (* Unfreeze deposits (that is, set them to zero) for delegates that - were previously in the relevant window (and therefore had some - frozen deposits) but are not in the new window; because that means - that such a delegate had no active stake in the relevant cycles, - and therefore it should have no frozen deposits. *) - Signature.Public_key_hash.Set.fold_es - (fun delegate (ctxt, balance_updates) -> - let delegate_contract = Contract_repr.Implicit delegate in - Frozen_deposits_storage.update_initial_amount - ctxt - delegate_contract - Tez_repr.zero - >>=? fun ctxt -> - Frozen_deposits_storage.get ctxt delegate_contract - >>=? fun frozen_deposits -> - if Tez_repr.(frozen_deposits.current_amount > zero) then - Token.transfer - ~origin - ctxt - (`Frozen_deposits delegate) - (`Delegate_balance delegate) - frozen_deposits.current_amount - >|=? fun (ctxt, bupds) -> (ctxt, bupds @ balance_updates) - else return (ctxt, balance_updates)) - delegates_to_remove - (ctxt, balance_updates) - -let freeze_deposits_do_not_call_except_for_migration = - freeze_deposits ~origin:Protocol_migration - -module Delegate_sampler_state = struct - module Cache_client = struct - type cached_value = - (Signature.Public_key.t * Signature.Public_key_hash.t) Sampler.t - - let namespace = Cache_repr.create_namespace "sampler_state" - - let cache_index = 2 - - let value_of_identifier ctxt identifier = - let cycle = Cycle_repr.of_string_exn identifier in - Storage.Delegate_sampler_state.get ctxt cycle - end - - module Cache = (val Cache_repr.register_exn (module Cache_client)) - - let identifier_of_cycle cycle = Format.asprintf "%a" Cycle_repr.pp cycle - - let init ctxt cycle sampler_state = - let id = identifier_of_cycle cycle in - Storage.Delegate_sampler_state.init ctxt cycle sampler_state - >>=? fun ctxt -> - let size = 1 (* that's symbolic: 1 cycle = 1 entry *) in - Cache.update ctxt id (Some (sampler_state, size)) >>?= fun ctxt -> - return ctxt - - let get ctxt cycle = - let id = identifier_of_cycle cycle in - Cache.find ctxt id >>=? function - | None -> Storage.Delegate_sampler_state.get ctxt cycle - | Some v -> return v - - let remove_existing ctxt cycle = - let id = identifier_of_cycle cycle in - Cache.update ctxt id None >>?= fun ctxt -> - Storage.Delegate_sampler_state.remove_existing ctxt cycle -end - -let get_stakes_for_selected_index ctxt index = - Stake_storage.fold_snapshot - ctxt - ~index - ~f:(fun (delegate, staking_balance) (acc, total_stake) -> - let delegate_contract = Contract_repr.Implicit delegate in - let open Tez_repr in - let open Lwt_result_syntax in - let* frozen_deposits_limit = - Storage.Contract.Frozen_deposits_limit.find ctxt delegate_contract - in - - let* balance_and_frozen_bonds = - Contract_storage.get_balance_and_frozen_bonds ctxt delegate_contract - in - let* frozen_deposits = - Frozen_deposits_storage.get ctxt delegate_contract - in - let*? total_balance = - balance_and_frozen_bonds +? frozen_deposits.current_amount - in - let* stake_for_cycle = - let frozen_deposits_percentage = - Int64.of_int @@ Constants_storage.frozen_deposits_percentage ctxt - in - let max_mutez = of_mutez_exn Int64.max_int in - let frozen_deposits_limit = - match frozen_deposits_limit with Some fdp -> fdp | None -> max_mutez - in - let aux = min total_balance frozen_deposits_limit in - let*? overflow_bound = max_mutez /? 100L in - if aux <= overflow_bound then - let*? aux = aux *? 100L in - let*? v = aux /? frozen_deposits_percentage in - return (min v staking_balance) - else - let*? sbal = staking_balance /? 100L in - let*? a = aux /? frozen_deposits_percentage in - if sbal <= a then return staking_balance - else - let*? r = max_mutez /? frozen_deposits_percentage in - return r - in - let*? total_stake = Tez_repr.(total_stake +? stake_for_cycle) in - return ((delegate, stake_for_cycle) :: acc, total_stake)) - ~init:([], Tez_repr.zero) - -let compute_snapshot_index_for_seed ~max_snapshot_index seed = - let rd = Seed_repr.initialize_new seed [Bytes.of_string "stake_snapshot"] in - let seq = Seed_repr.sequence rd 0l in - Seed_repr.take_int32 seq (Int32.of_int max_snapshot_index) - |> fst |> Int32.to_int |> return - -let compute_snapshot_index ctxt cycle ~max_snapshot_index = - Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> - compute_snapshot_index_for_seed ~max_snapshot_index seed - -let select_distribution_for_cycle ctxt cycle = - Stake_storage.max_snapshot_index ctxt >>=? fun max_snapshot_index -> - Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> - compute_snapshot_index_for_seed ~max_snapshot_index seed - >>=? fun selected_index -> - get_stakes_for_selected_index ctxt selected_index - >>=? fun (stakes, total_stake) -> - Stake_storage.set_selected_distribution_for_cycle - ctxt - cycle - stakes - total_stake - >>=? fun ctxt -> - List.fold_left_es - (fun acc (pkh, stake) -> - pubkey ctxt pkh >|=? fun pk -> ((pk, pkh), Tez_repr.to_mutez stake) :: acc) - [] - stakes - >>=? fun stakes_pk -> - let state = Sampler.create stakes_pk in - Delegate_sampler_state.init ctxt cycle state >>=? fun ctxt -> - (* pre-allocate the sampler *) - Lwt.return (Raw_context.init_sampler_for_cycle ctxt cycle seed state) - -let select_new_distribution_at_cycle_end ctxt ~new_cycle = - let preserved = Constants_storage.preserved_cycles ctxt in - let for_cycle = Cycle_repr.add new_cycle preserved in - select_distribution_for_cycle ctxt for_cycle - -let clear_outdated_sampling_data ctxt ~new_cycle = - let max_slashing_period = Constants_storage.max_slashing_period ctxt in - match Cycle_repr.sub new_cycle max_slashing_period with - | None -> return ctxt - | Some outdated_cycle -> - Delegate_sampler_state.remove_existing ctxt outdated_cycle - >>=? fun ctxt -> - Storage.Seed.For_cycle.remove_existing ctxt outdated_cycle - -let cycle_end ctxt last_cycle unrevealed_nonces = - let new_cycle = Cycle_repr.add last_cycle 1 in - select_new_distribution_at_cycle_end ctxt ~new_cycle >>=? fun ctxt -> - clear_outdated_slashed_deposits ctxt ~new_cycle >>= fun ctxt -> - distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces - >>=? fun (ctxt, balance_updates) -> - freeze_deposits ctxt ~new_cycle ~balance_updates - >>=? fun (ctxt, balance_updates) -> - Stake_storage.clear_at_cycle_end ctxt ~new_cycle >>=? fun ctxt -> - clear_outdated_sampling_data ctxt ~new_cycle >>=? fun ctxt -> - update_activity ctxt last_cycle >>=? fun (ctxt, deactivated_delagates) -> - return (ctxt, balance_updates, deactivated_delagates) - -let balance ctxt delegate = - let contract = Contract_repr.Implicit delegate in - Storage.Contract.Spendable_balance.get ctxt contract - -let frozen_deposits ctxt delegate = - Frozen_deposits_storage.get ctxt (Contract_repr.Implicit delegate) - -let full_balance ctxt delegate = - frozen_deposits ctxt delegate >>=? fun frozen_deposits -> - let delegate_contract = Contract_repr.Implicit delegate in - Contract_storage.get_balance_and_frozen_bonds ctxt delegate_contract - >>=? fun balance_and_frozen_bonds -> - Lwt.return - Tez_repr.(frozen_deposits.current_amount +? balance_and_frozen_bonds) - -let deactivated = Delegate_activation_storage.is_inactive - -let delegated_balance ctxt delegate = - staking_balance ctxt delegate >>=? fun staking_balance -> - balance ctxt delegate >>=? fun balance -> - frozen_deposits ctxt delegate >>=? fun frozen_deposits -> - Tez_repr.(balance +? frozen_deposits.current_amount) - >>?= fun self_staking_balance -> - Lwt.return Tez_repr.(staking_balance -? self_staking_balance) - -let fold = Storage.Delegates.fold - -let list = Storage.Delegates.elements - -(* The fact that this succeeds iff [registered ctxt pkh] returns true is an - invariant of the [set] function. *) -let check_delegate ctxt pkh = - Storage.Delegates.mem ctxt pkh >>= function - | true -> return_unit - | false -> fail (Not_registered pkh) - -module Random = struct - (* [init_random_state] initialize a random sequence drawing state - that's unique for a given (seed, level, index) triple. Elements - from this sequence are drawn using [take_int64], updating the - state for the next draw. The initial state is the Blake2b hash of - the three randomness sources, and an offset set to zero - (indicating that zero bits of randomness have been - consumed). When drawing random elements, bits are extracted from - the state until exhaustion (256 bits), at which point the state - is rehashed and the offset reset to 0. *) - - let init_random_state seed level index = - ( Raw_hashes.blake2b - (Data_encoding.Binary.to_bytes_exn - Data_encoding.(tup3 Seed_repr.seed_encoding int32 int32) - (seed, level.Level_repr.cycle_position, Int32.of_int index)), - 0 ) - - let take_int64 bound state = - let drop_if_over = - (* This function draws random values in [0-(bound-1)] by drawing - in [0-(2^63-1)] (64-bit) and computing the value modulo - [bound]. For the application of [mod bound] to preserve - uniformity, the input space must be of the form - [0-(n*bound-1)]. We enforce this by rejecting 64-bit samples - above this limit (in which case, we draw a new 64-sample from - the sequence and try again). *) - Int64.sub Int64.max_int (Int64.rem Int64.max_int bound) - in - let rec loop (bytes, n) = - let consumed_bytes = 8 in - let state_size = Bytes.length bytes in - if Compare.Int.(n > state_size - consumed_bytes) then - loop (Raw_hashes.blake2b bytes, 0) - else - let r = TzEndian.get_int64 bytes n in - (* The absolute value of min_int is min_int. Also, every - positive integer is represented twice (positive and negative), - but zero is only represented once. We fix both problems at - once. *) - let r = if Compare.Int64.(r = Int64.min_int) then 0L else Int64.abs r in - if Compare.Int64.(r >= drop_if_over) then - loop (bytes, n + consumed_bytes) - else - let v = Int64.rem r bound in - (v, (bytes, n + consumed_bytes)) - in - loop state - - (** [sampler_for_cycle ctxt cycle] reads the sampler for [cycle] from - [ctxt] if it has been previously inited. Otherwise it initializes - the sampler and caches it in [ctxt] with - [Raw_context.set_sampler_for_cycle]. *) - let sampler_for_cycle ctxt cycle = - let read ctxt = - Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> - Delegate_sampler_state.get ctxt cycle >>=? fun state -> - return (seed, state) - in - Raw_context.sampler_for_cycle ~read ctxt cycle - - let owner c (level : Level_repr.t) offset = - let cycle = level.Level_repr.cycle in - sampler_for_cycle c cycle >>=? fun (c, seed, state) -> - let sample ~int_bound ~mass_bound = - let state = init_random_state seed level offset in - let i, state = take_int64 (Int64.of_int int_bound) state in - let elt, _ = take_int64 mass_bound state in - (Int64.to_int i, elt) - in - let pk, pkh = Sampler.sample state sample in - return (c, (pk, pkh)) -end - -let slot_owner c level slot = Random.owner c level (Slot_repr.to_int slot) - -let baking_rights_owner c (level : Level_repr.t) ~round = - Round_repr.to_int round >>?= fun round -> - let consensus_committee_size = Constants_storage.consensus_committee_size c in - Slot_repr.of_int (round mod consensus_committee_size) >>?= fun slot -> - slot_owner c level slot >>=? fun (ctxt, pk) -> return (ctxt, slot, pk) - -let already_slashed_for_double_endorsing ctxt delegate (level : Level_repr.t) = - Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) - >>=? function - | None -> return_false - | Some slashed -> return slashed.for_double_endorsing - -let already_slashed_for_double_baking ctxt delegate (level : Level_repr.t) = - Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) - >>=? function - | None -> return_false - | Some slashed -> return slashed.for_double_baking - -let punish_double_endorsing ctxt delegate (level : Level_repr.t) = - let delegate_contract = Contract_repr.Implicit delegate in - Frozen_deposits_storage.get ctxt delegate_contract >>=? fun frozen_deposits -> - let slashing_ratio : Ratio_repr.t = - Constants_storage.ratio_of_frozen_deposits_slashed_per_double_endorsement - ctxt - in - let punish_value = - Tez_repr.( - div_exn - (mul_exn frozen_deposits.initial_amount slashing_ratio.numerator) - slashing_ratio.denominator) - in - let amount_to_burn = - Tez_repr.(min frozen_deposits.current_amount punish_value) - in - Token.transfer - ctxt - (`Frozen_deposits delegate) - `Double_signing_punishments - amount_to_burn - >>=? fun (ctxt, balance_updates) -> - Stake_storage.remove_stake ctxt delegate amount_to_burn >>=? fun ctxt -> - Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) - >>=? fun slashed -> - let slashed : Storage.slashed_level = - match slashed with - | None -> {for_double_endorsing = true; for_double_baking = false} - | Some slashed -> - assert (Compare.Bool.(slashed.for_double_endorsing = false)) ; - {slashed with for_double_endorsing = true} - in - Storage.Slashed_deposits.add - (ctxt, level.cycle) - (level.level, delegate) - slashed - >>= fun ctxt -> return (ctxt, amount_to_burn, balance_updates) - -let punish_double_baking ctxt delegate (level : Level_repr.t) = - let delegate_contract = Contract_repr.Implicit delegate in - Frozen_deposits_storage.get ctxt delegate_contract >>=? fun frozen_deposits -> - let slashing_for_one_block = - Constants_storage.double_baking_punishment ctxt - in - let amount_to_burn = - Tez_repr.(min frozen_deposits.current_amount slashing_for_one_block) - in - Token.transfer - ctxt - (`Frozen_deposits delegate) - `Double_signing_punishments - amount_to_burn - >>=? fun (ctxt, balance_updates) -> - Stake_storage.remove_stake ctxt delegate amount_to_burn >>=? fun ctxt -> - Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) - >>=? fun slashed -> - let slashed : Storage.slashed_level = - match slashed with - | None -> {for_double_endorsing = false; for_double_baking = true} - | Some slashed -> - assert (Compare.Bool.(slashed.for_double_baking = false)) ; - {slashed with for_double_baking = true} - in - Storage.Slashed_deposits.add - (ctxt, level.cycle) - (level.level, delegate) - slashed - >>= fun ctxt -> return (ctxt, amount_to_burn, balance_updates) - -type level_participation = Participated | Didn't_participate - -(* Note that the participation for the last block of a cycle is - recorded in the next cycle. *) -let record_endorsing_participation ctxt ~delegate ~participation - ~endorsing_power = - match participation with - | Participated -> set_active ctxt delegate - | Didn't_participate -> ( - let contract = Contract_repr.Implicit delegate in - Storage.Contract.Missed_endorsements.find ctxt contract >>=? function - | Some {remaining_slots; missed_levels} -> - let remaining_slots = remaining_slots - endorsing_power in - Storage.Contract.Missed_endorsements.update - ctxt - contract - {remaining_slots; missed_levels = missed_levels + 1} - | None -> ( - let level = Level_storage.current ctxt in - Raw_context.stake_distribution_for_current_cycle ctxt - >>?= fun stake_distribution -> - match - Signature.Public_key_hash.Map.find delegate stake_distribution - with - | None -> - (* This happens when the block is the first one in a - cycle, and therefore the endorsements are for the last - block of the previous cycle, and when the delegate does - not have an active stake at the current cycle; in this - case its participation is simply ignored. *) - assert (Compare.Int32.(level.cycle_position = 0l)) ; - return ctxt - | Some active_stake -> - Stake_storage.get_total_active_stake ctxt level.cycle - >>=? fun total_active_stake -> - expected_slots_for_given_active_stake - ctxt - ~total_active_stake - ~active_stake - >>?= fun expected_slots -> - let Ratio_repr.{numerator; denominator} = - Constants_storage.minimal_participation_ratio ctxt - in - let minimal_activity = expected_slots * numerator / denominator in - let maximal_inactivity = expected_slots - minimal_activity in - let remaining_slots = maximal_inactivity - endorsing_power in - Storage.Contract.Missed_endorsements.init - ctxt - contract - {remaining_slots; missed_levels = 1})) - -let record_baking_activity_and_pay_rewards_and_fees ctxt ~payload_producer - ~block_producer ~baking_reward ~reward_bonus = - set_active ctxt payload_producer >>=? fun ctxt -> - (if not (Signature.Public_key_hash.equal payload_producer block_producer) then - set_active ctxt block_producer - else return ctxt) - >>=? fun ctxt -> - let pay_payload_producer ctxt delegate = - let contract = Contract_repr.Implicit delegate in - Token.balance ctxt `Block_fees >>=? fun (ctxt, block_fees) -> - Token.transfer_n - ctxt - [(`Block_fees, block_fees); (`Baking_rewards, baking_reward)] - (`Contract contract) - in - let pay_block_producer ctxt delegate bonus = - let contract = Contract_repr.Implicit delegate in - Token.transfer ctxt `Baking_bonuses (`Contract contract) bonus - in - pay_payload_producer ctxt payload_producer - >>=? fun (ctxt, balance_updates_payload_producer) -> - (match reward_bonus with - | Some bonus -> pay_block_producer ctxt block_producer bonus - | None -> return (ctxt, [])) - >>=? fun (ctxt, balance_updates_block_producer) -> - return - (ctxt, balance_updates_payload_producer @ balance_updates_block_producer) - -type participation_info = { - expected_cycle_activity : int; - minimal_cycle_activity : int; - missed_slots : int; - missed_levels : int; - remaining_allowed_missed_slots : int; - expected_endorsing_rewards : Tez_repr.t; -} - -(* Inefficient, only for RPC *) -let delegate_participation_info ctxt delegate = - let level = Level_storage.current ctxt in - Stake_storage.get_selected_distribution ctxt level.cycle - >>=? fun stake_distribution -> - match - List.assoc_opt - ~equal:Signature.Public_key_hash.equal - delegate - stake_distribution - with - | None -> - (* delegate does not have an active stake at the current cycle *) - return - { - expected_cycle_activity = 0; - minimal_cycle_activity = 0; - missed_slots = 0; - missed_levels = 0; - remaining_allowed_missed_slots = 0; - expected_endorsing_rewards = Tez_repr.zero; - } - | Some active_stake -> - Stake_storage.get_total_active_stake ctxt level.cycle - >>=? fun total_active_stake -> - expected_slots_for_given_active_stake - ctxt - ~total_active_stake - ~active_stake - >>?= fun expected_cycle_activity -> - let Ratio_repr.{numerator; denominator} = - Constants_storage.minimal_participation_ratio ctxt - in - let endorsing_reward_per_slot = - Constants_storage.endorsing_reward_per_slot ctxt - in - let minimal_cycle_activity = - expected_cycle_activity * numerator / denominator - in - let maximal_cycle_inactivity = - expected_cycle_activity - minimal_cycle_activity - in - let expected_endorsing_rewards = - Tez_repr.mul_exn endorsing_reward_per_slot expected_cycle_activity - in - let contract = Contract_repr.Implicit delegate in - Storage.Contract.Missed_endorsements.find ctxt contract - >>=? fun missed_endorsements -> - let missed_slots, missed_levels, remaining_allowed_missed_slots = - match missed_endorsements with - | None -> (0, 0, maximal_cycle_inactivity) - | Some {remaining_slots; missed_levels} -> - ( maximal_cycle_inactivity - remaining_slots, - missed_levels, - Compare.Int.max 0 remaining_slots ) - in - let expected_endorsing_rewards = - match missed_endorsements with - | Some r when Compare.Int.(r.remaining_slots < 0) -> Tez_repr.zero - | _ -> expected_endorsing_rewards - in - return - { - expected_cycle_activity; - minimal_cycle_activity; - missed_slots; - missed_levels; - remaining_allowed_missed_slots; - expected_endorsing_rewards; - } - -let init_first_cycles ctxt = - let preserved = Constants_storage.preserved_cycles ctxt in - List.fold_left_es - (fun ctxt c -> - let cycle = Cycle_repr.of_int32_exn (Int32.of_int c) in - Stake_storage.snapshot ctxt >>=? fun ctxt -> - (* NB: we need to take several snapshots because - select_distribution_for_cycle deletes the snapshots *) - select_distribution_for_cycle ctxt cycle) - ctxt - Misc.(0 --> preserved) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index cba3a98d9746..ce6f830baf59 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. *) (* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 G.B. Fefe, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -24,41 +25,6 @@ (* *) (*****************************************************************************) -(** Allow to register a delegate when creating an account. *) -val init : - Raw_context.t -> - Contract_repr.t -> - Signature.Public_key_hash.t -> - Raw_context.t tzresult Lwt.t - -val pubkey : - Raw_context.t -> - Signature.Public_key_hash.t -> - Signature.Public_key.t tzresult Lwt.t - -(** Updating the delegate of a contract. - - When calling this function on an "implicit contract" and setting - the delegate to the contract manager registers it as a delegate. One - cannot unregister a delegate for now. The associate contract is now - 'undeletable'. *) -val set : - Raw_context.t -> - Contract_repr.t -> - Signature.Public_key_hash.t option -> - Raw_context.t tzresult Lwt.t - -val frozen_deposits_limit : - Raw_context.t -> - Signature.Public_key_hash.t -> - Tez_repr.t option tzresult Lwt.t - -val set_frozen_deposits_limit : - Raw_context.t -> - Signature.Public_key_hash.t -> - Tez_repr.t option -> - Raw_context.t Lwt.t - type error += | (* `Permanent *) No_deletion of Signature.Public_key_hash.t | (* `Temporary *) Active_delegate @@ -77,39 +43,6 @@ type error += val check_delegate : Raw_context.t -> Signature.Public_key_hash.t -> unit tzresult Lwt.t -(** Participation information. We denote by: - - "static" information that does not change during the cycle - - "dynamic" information that may change during the cycle *) -type participation_info = { - expected_cycle_activity : int; - (** The total expected slots to be endorsed in the cycle. (static) *) - minimal_cycle_activity : int; - (** The minimal endorsing slots in the cycle to get endorsing - rewards. (static) *) - missed_slots : int; - (** The number of missed endorsing slots in the cycle. (dynamic) *) - missed_levels : int; - (** The number of missed endorsing levels in the cycle. (dynamic) *) - remaining_allowed_missed_slots : int; - (** Remaining amount of endorsing slots that can be missed in the - cycle before forfeiting the rewards. (dynamic) *) - expected_endorsing_rewards : Tez_repr.t; - (** Endorsing rewards that will be distributed at the end of the - cycle if activity at that point will be greater than the minimal - required. If the activity is already known to be below the - required minimum, then the rewards are zero. (dynamic) *) -} - -(** Only use this function for RPC: this is expensive. - - [delegate_participation_info] and [!val:check_delegate] forms the - implementation of RPC call "/context/delegates//participation". - *) -val delegate_participation_info : - Raw_context.t -> - Signature.Public_key_hash.t -> - participation_info tzresult Lwt.t - (** Iterate on all registered delegates. *) val fold : Raw_context.t -> @@ -121,85 +54,35 @@ val fold : (** List all registered delegates. *) val list : Raw_context.t -> Signature.Public_key_hash.t list Lwt.t -val balance : - Raw_context.t -> Signature.public_key_hash -> Tez_repr.tez tzresult Lwt.t - -type level_participation = Participated | Didn't_participate - -(** Record the participation of a delegate as a validator. *) -val record_endorsing_participation : - Raw_context.t -> - delegate:Signature.Public_key_hash.t -> - participation:level_participation -> - endorsing_power:int -> - Raw_context.t tzresult Lwt.t - -(** Sets the payload and block producer as active. Pays the baking - reward and the fees to the payload producer and the reward bonus to - the payload producer (if the reward_bonus is not None).*) -val record_baking_activity_and_pay_rewards_and_fees : - Raw_context.t -> - payload_producer:Signature.Public_key_hash.t -> - block_producer:Signature.Public_key_hash.t -> - baking_reward:Tez_repr.t -> - reward_bonus:Tez_repr.t option -> - (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t - -(** Trigger the context maintenance at the end of cycle 'n', i.e.: - unfreeze the endorsing rewards, potentially deactivate delegates. - Return the corresponding balances updates and the list of - deactivated delegates. *) -val cycle_end : - Raw_context.t -> - Cycle_repr.t -> - Storage.Seed.unrevealed_nonce list -> - (Raw_context.t - * Receipt_repr.balance_updates - * Signature.Public_key_hash.t list) - tzresult - Lwt.t - -(** Returns true if the given delegate has already been slashed - for double baking for the given level. *) -val already_slashed_for_double_baking : - Raw_context.t -> - Signature.Public_key_hash.t -> - Level_repr.t -> - bool tzresult Lwt.t - -(** Returns true if the given delegate has already been slashed - for double preendorsing or double endorsing for the given level. *) -val already_slashed_for_double_endorsing : - Raw_context.t -> - Signature.Public_key_hash.t -> - Level_repr.t -> - bool tzresult Lwt.t - -(** Burn some frozen deposit for a delegate at a given level. Returns - the burned amount. *) -val punish_double_endorsing : +val frozen_deposits_limit : Raw_context.t -> Signature.Public_key_hash.t -> - Level_repr.t -> - (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t + Tez_repr.t option tzresult Lwt.t -val punish_double_baking : +val set_frozen_deposits_limit : Raw_context.t -> Signature.Public_key_hash.t -> - Level_repr.t -> - (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t + Tez_repr.t option -> + Raw_context.t Lwt.t (** Returns a delegate's frozen deposits, both the current amount and the initial freezed amount. A delegate's frozen balance is only composed of frozen deposits; - rewards and fees are not frozen, but simply credited at the right - moment. *) + rewards and fees are not frozen, but simply credited at the right + moment. *) val frozen_deposits : Raw_context.t -> Signature.Public_key_hash.t -> Storage.deposits tzresult Lwt.t +val staking_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + +(** Only use this function for RPCs: this is expensive. *) +val delegated_balance : + Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t + (** Returns the full 'balance' of the implicit contract associated to a given key, i.e. the sum of the spendable balance (given by [balance] or [Contract_storage.get_balance]) and of the frozen balance. The frozen @@ -211,55 +94,27 @@ val frozen_deposits : val full_balance : Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t -val staking_balance : - Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t - -(** Only use this function for RPCs: this is expensive. *) -val delegated_balance : - Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t - -val deactivated : - Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t - -(** Participation slots potentially associated to accounts. The - accounts that didn't place a deposit will be excluded from this - list. This function should only be used to compute the deposits to - freeze or initialize the protocol while stitching. RPCs can use this - function to predict an approximation of long term future slot - allocations. It shouldn't be used in the baker. *) -val slot_owner : +(** Allow to register a delegate when creating an account. *) +val init : Raw_context.t -> - Level_repr.t -> - Slot_repr.t -> - (Raw_context.t * (Signature.Public_key.t * Signature.Public_key_hash.t)) - tzresult - Lwt.t + Contract_repr.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t -val baking_rights_owner : +(** Allow to set the delegate of an account. *) +val set : Raw_context.t -> - Level_repr.t -> - round:Round_repr.round -> - (Raw_context.t - * Slot_repr.t - * (Signature.public_key * Signature.public_key_hash)) - tzresult - Lwt.t + Contract_repr.t -> + Signature.Public_key_hash.t option -> + Raw_context.t tzresult Lwt.t -val freeze_deposits_do_not_call_except_for_migration : +val pubkey : Raw_context.t -> - new_cycle:Cycle_repr.t -> - balance_updates:Receipt_repr.balance_updates -> - (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + Signature.Public_key_hash.t -> + Signature.Public_key.t tzresult Lwt.t -(** [init_first_cycles ctxt] computes and records the distribution of the total - active stake among active delegates. This concerns the total active stake - involved in the calculation of baking rights for all cycles in the range - [0, preserved_cycles]. *) -val init_first_cycles : Raw_context.t -> Raw_context.t tzresult Lwt.t +val set_active : + Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t -(** [compute_snapshot_index ctxt cycle max_snapshot_index] Returns the index of - the selected snapshot for the [cycle] passed as argument, and for the max - index of snapshots taken so far, [max_snapshot_index] (see - [Stake_storage.max_snapshot_index]. *) -val compute_snapshot_index : - Raw_context.t -> Cycle_repr.t -> max_snapshot_index:int -> int tzresult Lwt.t +val set_inactive : + Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index ee039990e78f..de1967c75846 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -149,6 +149,10 @@ Contract_storage Token Delegate_storage + Delegate_missed_endorsements_storage + Delegate_slashed_deposits_storage + Delegate_sampler + Delegate_cycles Bootstrap_storage Vote_storage Fees_storage @@ -371,6 +375,11 @@ contract_storage.ml contract_storage.mli token.ml token.mli delegate_storage.ml delegate_storage.mli + delegate_missed_endorsements_storage.ml + delegate_missed_endorsements_storage.mli + delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli + delegate_sampler.ml delegate_sampler.mli + delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli fees_storage.ml fees_storage.mli @@ -579,6 +588,11 @@ contract_storage.ml contract_storage.mli token.ml token.mli delegate_storage.ml delegate_storage.mli + delegate_missed_endorsements_storage.ml + delegate_missed_endorsements_storage.mli + delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli + delegate_sampler.ml delegate_sampler.mli + delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli fees_storage.ml fees_storage.mli @@ -807,6 +821,11 @@ contract_storage.ml contract_storage.mli token.ml token.mli delegate_storage.ml delegate_storage.mli + delegate_missed_endorsements_storage.ml + delegate_missed_endorsements_storage.mli + delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli + delegate_sampler.ml delegate_sampler.mli + delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli fees_storage.ml fees_storage.mli @@ -1031,6 +1050,11 @@ contract_storage.ml contract_storage.mli token.ml token.mli delegate_storage.ml delegate_storage.mli + delegate_missed_endorsements_storage.ml + delegate_missed_endorsements_storage.mli + delegate_slashed_deposits_storage.ml delegate_slashed_deposits_storage.mli + delegate_sampler.ml delegate_sampler.mli + delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli fees_storage.ml fees_storage.mli diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 258702c6e1f0..d5b1b058a73f 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -97,9 +97,9 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = param.bootstrap_accounts param.bootstrap_contracts >>=? fun (ctxt, bootstrap_balance_updates) -> - Delegate_storage.init_first_cycles ctxt >>=? fun ctxt -> + Delegate_cycles.init_first_cycles ctxt >>=? fun ctxt -> let cycle = (Raw_context.current_level ctxt).cycle in - Delegate_storage.freeze_deposits_do_not_call_except_for_migration + Delegate_cycles.freeze_deposits_do_not_call_except_for_migration ~new_cycle:cycle ~balance_updates:[] ctxt -- GitLab From c4299b3d76b294c5bca9491aded97c35f26f0973 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 21 Apr 2022 10:38:31 +0200 Subject: [PATCH 02/42] Proto: move `set_active` into `Stake_storage` --- .../lib_protocol/delegate_cycles.ml | 2 +- .../delegate_missed_endorsements_storage.ml | 6 +++--- .../lib_protocol/delegate_storage.ml | 13 ++---------- .../lib_protocol/delegate_storage.mli | 6 ------ src/proto_alpha/lib_protocol/stake_storage.ml | 21 ++++++++++++------- .../lib_protocol/stake_storage.mli | 4 ++-- 6 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index a866f2727f6d..7d5d6b0b11d3 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -41,7 +41,7 @@ let update_activity ctxt last_cycle = delegate >>=? fun cycle -> if Cycle_repr.(cycle <= last_cycle) then - Delegate_storage.set_inactive ctxt delegate >>=? fun ctxt -> + Stake_storage.set_inactive ctxt delegate >>= fun ctxt -> return (ctxt, delegate :: deactivated) else return (ctxt, deactivated)) >|=? fun (ctxt, deactivated) -> (ctxt, deactivated) diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml index b776c0eb8171..508d2852e8a3 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -51,7 +51,7 @@ type level_participation = Participated | Didn't_participate let record_endorsing_participation ctxt ~delegate ~participation ~endorsing_power = match participation with - | Participated -> Delegate_storage.set_active ctxt delegate + | Participated -> Stake_storage.set_active ctxt delegate | Didn't_participate -> ( let contract = Contract_repr.Implicit delegate in Storage.Contract.Missed_endorsements.find ctxt contract >>=? function @@ -97,9 +97,9 @@ let record_endorsing_participation ctxt ~delegate ~participation let record_baking_activity_and_pay_rewards_and_fees ctxt ~payload_producer ~block_producer ~baking_reward ~reward_bonus = - Delegate_storage.set_active ctxt payload_producer >>=? fun ctxt -> + Stake_storage.set_active ctxt payload_producer >>=? fun ctxt -> (if not (Signature.Public_key_hash.equal payload_producer block_producer) then - Delegate_storage.set_active ctxt block_producer + Stake_storage.set_active ctxt block_producer else return ctxt) >>=? fun ctxt -> let pay_payload_producer ctxt delegate = diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 8d10d9fad5c4..8935aed71ec7 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -202,16 +202,6 @@ let set_frozen_deposits_limit ctxt delegate limit = let frozen_deposits ctxt delegate = Frozen_deposits_storage.get ctxt (Contract_repr.Implicit delegate) -let set_inactive ctxt delegate = - Delegate_activation_storage.set_inactive ctxt delegate >>= fun ctxt -> - Stake_storage.deactivate_only_call_from_delegate_storage ctxt delegate >|= ok - -let set_active ctxt delegate = - Delegate_activation_storage.set_active ctxt delegate - >>=? fun (ctxt, inactive) -> - if not inactive then return ctxt - else Stake_storage.activate_only_call_from_delegate_storage ctxt delegate - let balance ctxt delegate = let contract = Contract_repr.Implicit delegate in Storage.Contract.Spendable_balance.get ctxt contract @@ -313,5 +303,6 @@ let set c contract delegate = Stake_storage.add_stake c delegate balance_and_frozen_bonds >>=? fun c -> if self_delegation then - Storage.Delegates.add c delegate >>= fun c -> set_active c delegate + Storage.Delegates.add c delegate >>= fun c -> + Stake_storage.set_active c delegate else return c diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index ce6f830baf59..089cb829199d 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -112,9 +112,3 @@ val pubkey : Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t tzresult Lwt.t - -val set_active : - Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t - -val set_inactive : - Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index 9c34808d628e..c668430b87bd 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -107,16 +107,21 @@ let add_stake ctxt delegate amount = roll now). *) return ctxt -let deactivate_only_call_from_delegate_storage ctxt delegate = +let set_inactive ctxt delegate = + Delegate_activation_storage.set_inactive ctxt delegate >>= fun ctxt -> Storage.Stake.Active_delegate_with_one_roll.remove ctxt delegate -let activate_only_call_from_delegate_storage ctxt delegate = - get_initialized_stake ctxt delegate >>=? fun (staking_balance, ctxt) -> - let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in - if Tez_repr.(staking_balance >= tokens_per_roll) then - Storage.Stake.Active_delegate_with_one_roll.add ctxt delegate () - >>= fun ctxt -> return ctxt - else return ctxt +let set_active ctxt delegate = + Delegate_activation_storage.set_active ctxt delegate + >>=? fun (ctxt, inactive) -> + if not inactive then return ctxt + else + get_initialized_stake ctxt delegate >>=? fun (staking_balance, ctxt) -> + let tokens_per_roll = Constants_storage.tokens_per_roll ctxt in + if Tez_repr.(staking_balance >= tokens_per_roll) then + Storage.Stake.Active_delegate_with_one_roll.add ctxt delegate () + >>= fun ctxt -> return ctxt + else return ctxt let snapshot ctxt = Storage.Stake.Last_snapshot.get ctxt >>=? fun index -> diff --git a/src/proto_alpha/lib_protocol/stake_storage.mli b/src/proto_alpha/lib_protocol/stake_storage.mli index 894f683cd579..e41693973461 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.mli +++ b/src/proto_alpha/lib_protocol/stake_storage.mli @@ -38,10 +38,10 @@ val add_stake : Tez_repr.t -> Raw_context.t tzresult Lwt.t -val deactivate_only_call_from_delegate_storage : +val set_inactive : Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t Lwt.t -val activate_only_call_from_delegate_storage : +val set_active : Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t val get_staking_balance : -- GitLab From 6e8cb00c7fee6e21effb5f4d179ea23fa3d45daa Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 21 Apr 2022 11:55:00 +0200 Subject: [PATCH 03/42] Proto: Rename `Delegate.check_delegate` into `Delegate.check` --- .../lib_protocol/alpha_context.mli | 2 +- .../lib_protocol/delegate_services.ml | 26 +++++++++---------- .../lib_protocol/delegate_storage.ml | 2 +- .../lib_protocol/delegate_storage.mli | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index aed01ea9e6db..c4c6b62f6952 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2265,7 +2265,7 @@ module Delegate : sig val list : context -> public_key_hash list Lwt.t - val check_delegate : context -> public_key_hash -> unit tzresult Lwt.t + val check_registered : context -> public_key_hash -> unit tzresult Lwt.t type participation_info = { expected_cycle_activity : int; diff --git a/src/proto_alpha/lib_protocol/delegate_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index 6a07486f0c1a..b0c8da4709a4 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -366,7 +366,7 @@ let register () = | {with_minimal_stake = false; without_minimal_stake = false; _} -> return delegates) ; register1 ~chunked:false S.info (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.full_balance ctxt pkh >>=? fun full_balance -> Delegate.frozen_deposits ctxt pkh >>=? fun frozen_deposits -> Delegate.staking_balance ctxt pkh >>=? fun staking_balance -> @@ -389,42 +389,42 @@ let register () = voting_info; }) ; register1 ~chunked:false S.full_balance (fun ctxt pkh () () -> - trace (Balance_rpc_non_delegate pkh) (Delegate.check_delegate ctxt pkh) + trace (Balance_rpc_non_delegate pkh) (Delegate.check_registered ctxt pkh) >>=? fun () -> Delegate.full_balance ctxt pkh) ; register1 ~chunked:false S.current_frozen_deposits (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.frozen_deposits ctxt pkh >>=? fun deposits -> return deposits.current_amount) ; register1 ~chunked:false S.frozen_deposits (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.frozen_deposits ctxt pkh >>=? fun deposits -> return deposits.initial_amount) ; register1 ~chunked:false S.staking_balance (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.staking_balance ctxt pkh) ; register1 ~chunked:false S.frozen_deposits_limit (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.frozen_deposits_limit ctxt pkh) ; register1 ~chunked:true S.delegated_contracts (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.delegated_contracts ctxt pkh >|= ok) ; register1 ~chunked:false S.delegated_balance (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.delegated_balance ctxt pkh) ; register1 ~chunked:false S.deactivated (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.deactivated ctxt pkh) ; register1 ~chunked:false S.grace_period (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.last_cycle_before_deactivation ctxt pkh) ; register1 ~chunked:false S.voting_power (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Vote.get_voting_power_free ctxt pkh) ; register1 ~chunked:false S.voting_info (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Vote.get_delegate_info ctxt pkh) ; register1 ~chunked:false S.participation (fun ctxt pkh () () -> - Delegate.check_delegate ctxt pkh >>=? fun () -> + Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.delegate_participation_info ctxt pkh) let list ctxt block ?(active = true) ?(inactive = false) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 8935aed71ec7..39b2a8050110 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -173,7 +173,7 @@ let () = (* The fact that this succeeds iff [registered ctxt pkh] returns true is an invariant of the [set] function. *) -let check_delegate ctxt pkh = +let check_registered ctxt pkh = Storage.Delegates.mem ctxt pkh >>= function | true -> return_unit | false -> fail (Not_registered pkh) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 089cb829199d..05cda508fdfd 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -40,7 +40,7 @@ type error += | (* `Temporary *) Not_registered of Signature.Public_key_hash.t (** Check that a given implicit account is a registered delegate. *) -val check_delegate : +val check_registered : Raw_context.t -> Signature.Public_key_hash.t -> unit tzresult Lwt.t (** Iterate on all registered delegates. *) -- GitLab From 2d5b8967a368a3a1428267994057b34ccbad67d6 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 16:32:16 +0200 Subject: [PATCH 04/42] Proto: simplify `Delegate.registered` --- src/proto_alpha/lib_protocol/alpha_context.ml | 2 -- src/proto_alpha/lib_protocol/alpha_context.mli | 2 +- src/proto_alpha/lib_protocol/apply.ml | 2 +- .../lib_protocol/contract_delegate_storage.ml | 8 -------- .../lib_protocol/contract_delegate_storage.mli | 5 ----- .../lib_protocol/delegate_storage.ml | 17 ++++++++--------- .../lib_protocol/delegate_storage.mli | 3 +++ 7 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index f9a62d1d2c25..9c9fba5e0a2d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -447,8 +447,6 @@ module Delegate = struct let prepare_stake_distribution = Stake_storage.prepare_stake_distribution - let registered = Contract_delegate_storage.registered - let find = Contract_delegate_storage.find let delegated_contracts = Contract_delegate_storage.delegated_contracts diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index c4c6b62f6952..5a3df6d1f27d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2335,7 +2335,7 @@ module Delegate : sig val delegated_balance : context -> Signature.Public_key_hash.t -> Tez.t tzresult Lwt.t - val registered : context -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + val registered : context -> Signature.public_key_hash -> bool Lwt.t val deactivated : context -> Signature.Public_key_hash.t -> bool tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 9e2d82a9193f..055b7e371d54 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1541,7 +1541,7 @@ let apply_external_manager_operation_content : Tez.(limit > max_limit) (Set_deposits_limit_too_high {limit; max_limit})) >>?= fun () -> - Delegate.registered ctxt source >>=? fun is_registered -> + Delegate.registered ctxt source >>= fun is_registered -> error_unless is_registered (Set_deposits_limit_on_unregistered_delegate source) diff --git a/src/proto_alpha/lib_protocol/contract_delegate_storage.ml b/src/proto_alpha/lib_protocol/contract_delegate_storage.ml index 8dbb1063250d..75efd48243da 100644 --- a/src/proto_alpha/lib_protocol/contract_delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/contract_delegate_storage.ml @@ -25,14 +25,6 @@ let find = Storage.Contract.Delegate.find -(* A delegate is registered if its "implicit account" delegates to itself. *) -let registered c delegate = - Storage.Contract.Delegate.find c (Contract_repr.Implicit delegate) - >|=? function - | Some current_delegate -> - Signature.Public_key_hash.equal delegate current_delegate - | None -> false - let init ctxt contract delegate = Storage.Contract.Delegate.init ctxt contract delegate >>=? fun ctxt -> let delegate_contract = Contract_repr.Implicit delegate in diff --git a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli index 45a05ca408ca..2f9b8e201c4f 100644 --- a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli @@ -30,11 +30,6 @@ val find : Contract_repr.t -> Signature.Public_key_hash.t option tzresult Lwt.t -(** [registered ctxt delegate] returns true iff delegate is an implicit contract - that delegates to itself. *) -val registered : - Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t - (** [init ctxt contract delegate] sets the [delegate] associated to [contract]. This function is undefined if [contract] is not allocated, or if [contract] diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 39b2a8050110..7d5719d1415d 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -171,10 +171,10 @@ let () = (function Not_registered pkh -> Some pkh | _ -> None) (fun pkh -> Not_registered pkh) -(* The fact that this succeeds iff [registered ctxt pkh] returns true is an - invariant of the [set] function. *) +let registered = Storage.Delegates.mem + let check_registered ctxt pkh = - Storage.Delegates.mem ctxt pkh >>= function + registered ctxt pkh >>= function | true -> return_unit | false -> fail (Not_registered pkh) @@ -207,7 +207,7 @@ let balance ctxt delegate = Storage.Contract.Spendable_balance.get ctxt contract let staking_balance ctxt delegate = - Contract_delegate_storage.registered ctxt delegate >>=? fun is_registered -> + registered ctxt delegate >>= fun is_registered -> if is_registered then Stake_storage.get_staking_balance ctxt delegate else return Tez_repr.zero @@ -231,7 +231,7 @@ let init ctxt contract delegate = Contract_manager_storage.is_manager_key_revealed ctxt delegate >>=? fun known_delegate -> error_unless known_delegate (Unregistered_delegate delegate) >>?= fun () -> - Contract_delegate_storage.registered ctxt delegate >>=? fun is_registered -> + registered ctxt delegate >>= fun is_registered -> error_unless is_registered (Unregistered_delegate delegate) >>?= fun () -> Contract_delegate_storage.init ctxt contract delegate >>=? fun ctxt -> Contract_storage.get_balance_and_frozen_bonds ctxt contract @@ -244,7 +244,7 @@ let set c contract delegate = (* check if contract is a registered delegate *) (match contract with | Contract_repr.Implicit pkh -> - Contract_delegate_storage.registered c pkh >>=? fun is_registered -> + registered c pkh >>= fun is_registered -> fail_when is_registered (No_deletion pkh) | Originated _ -> return_unit) >>=? fun () -> @@ -259,8 +259,7 @@ let set c contract delegate = | Some delegate -> Contract_manager_storage.is_manager_key_revealed c delegate >>=? fun known_delegate -> - Contract_delegate_storage.registered c delegate - >>=? fun registered_delegate -> + registered c delegate >>= fun registered_delegate -> let self_delegation = match contract with | Implicit pkh -> Signature.Public_key_hash.equal pkh delegate @@ -283,7 +282,7 @@ let set c contract delegate = (* check if contract is a registered delegate *) (match contract with | Contract_repr.Implicit pkh -> - Contract_delegate_storage.registered c pkh >>=? fun is_registered -> + registered c pkh >>= fun is_registered -> (* allow self-delegation to re-activate *) if (not self_delegation) && is_registered then fail (No_deletion pkh) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 05cda508fdfd..afa43e5df789 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -39,6 +39,9 @@ type error += } | (* `Temporary *) Not_registered of Signature.Public_key_hash.t +(** Has a delegate been registered in the delegate table? *) +val registered : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t + (** Check that a given implicit account is a registered delegate. *) val check_registered : Raw_context.t -> Signature.Public_key_hash.t -> unit tzresult Lwt.t -- GitLab From 97bb10c14d13206324929a459b0967a096113415 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 14 Apr 2022 23:37:43 +0200 Subject: [PATCH 05/42] Proto: remove `freeze_deposits_do_not_call_except_for_migration` --- src/proto_alpha/lib_protocol/delegate_cycles.ml | 8 ++++---- src/proto_alpha/lib_protocol/delegate_cycles.mli | 16 +++++++--------- src/proto_alpha/lib_protocol/init_storage.ml | 7 +------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 7d5d6b0b11d3..57cf944e033a 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -189,9 +189,6 @@ let freeze_deposits ?(origin = Receipt_repr.Block_application) ctxt ~new_cycle delegates_to_remove (ctxt, balance_updates) -let freeze_deposits_do_not_call_except_for_migration = - freeze_deposits ~origin:Protocol_migration - let cycle_end ctxt last_cycle unrevealed_nonces = let new_cycle = Cycle_repr.add last_cycle 1 in Delegate_sampler.select_new_distribution_at_cycle_end ctxt ~new_cycle @@ -212,7 +209,7 @@ let cycle_end ctxt last_cycle unrevealed_nonces = update_activity ctxt last_cycle >>=? fun (ctxt, deactivated_delagates) -> return (ctxt, balance_updates, deactivated_delagates) -let init_first_cycles ctxt = +let init_first_cycles ctxt ~origin = let preserved = Constants_storage.preserved_cycles ctxt in List.fold_left_es (fun ctxt c -> @@ -223,3 +220,6 @@ let init_first_cycles ctxt = Delegate_sampler.select_distribution_for_cycle ctxt cycle) ctxt Misc.(0 --> preserved) + >>=? fun ctxt -> + let cycle = (Raw_context.current_level ctxt).cycle in + freeze_deposits ~origin ~new_cycle:cycle ~balance_updates:[] ctxt diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.mli b/src/proto_alpha/lib_protocol/delegate_cycles.mli index f45fd05bed59..0814d32d45b8 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.mli +++ b/src/proto_alpha/lib_protocol/delegate_cycles.mli @@ -39,14 +39,12 @@ val cycle_end : tzresult Lwt.t -(** [init_first_cycles ctxt] computes and records the distribution of the total - active stake among active delegates. This concerns the total active stake - involved in the calculation of baking rights for all cycles in the range - [0, preserved_cycles]. *) -val init_first_cycles : Raw_context.t -> Raw_context.t tzresult Lwt.t - -val freeze_deposits_do_not_call_except_for_migration : +(** [init_first_cycles ctxt ~origin] computes and records the distribution of + the total active stake among active delegates. This concerns the total + active stake involved in the calculation of baking rights for all cycles + in the range [0, preserved_cycles]. It also freezes the deposits for all + the active delegates. *) +val init_first_cycles : Raw_context.t -> - new_cycle:Cycle_repr.t -> - balance_updates:Receipt_repr.balance_updates -> + origin:Receipt_repr.update_origin -> (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index d5b1b058a73f..e5195fe38233 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -97,12 +97,7 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = param.bootstrap_accounts param.bootstrap_contracts >>=? fun (ctxt, bootstrap_balance_updates) -> - Delegate_cycles.init_first_cycles ctxt >>=? fun ctxt -> - let cycle = (Raw_context.current_level ctxt).cycle in - Delegate_cycles.freeze_deposits_do_not_call_except_for_migration - ~new_cycle:cycle - ~balance_updates:[] - ctxt + Delegate_cycles.init_first_cycles ctxt ~origin:Protocol_migration >>=? fun (ctxt, deposits_balance_updates) -> Vote_storage.init ctxt -- GitLab From f1c3201ab45f60d2dffe57dbcc79c8d7d7ad4c4b Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 13:41:44 +0200 Subject: [PATCH 06/42] Proto: introduce `Alpha_context.Contract.Delegate` --- src/proto_alpha/lib_protocol/alpha_context.ml | 10 ++++++-- .../lib_protocol/alpha_context.mli | 24 ++++++++++--------- src/proto_alpha/lib_protocol/apply.ml | 4 ++-- .../lib_protocol/contract_services.ml | 4 ++-- .../test/integration/test_frozen_bonds.ml | 17 ++++++------- .../test/integration/test_token.ml | 6 ++--- 6 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 9c9fba5e0a2d..f7a7adb729cd 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -271,6 +271,14 @@ module Contract = struct let get_manager_key = Contract_manager_storage.get_manager_key + module Delegate = struct + let find = Contract_delegate_storage.find + + let init = Delegate_storage.init + + let set = Delegate_storage.set + end + module Internal_for_tests = struct include Contract_repr include Contract_storage @@ -447,8 +455,6 @@ module Delegate = struct let prepare_stake_distribution = Stake_storage.prepare_stake_distribution - let find = Contract_delegate_storage.find - let delegated_contracts = Contract_delegate_storage.delegated_contracts end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 5a3df6d1f27d..9a07b260ab13 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1624,6 +1624,19 @@ module Contract : sig script:Script.t * Lazy_storage.diffs option -> context tzresult Lwt.t + module Delegate : sig + val find : context -> t -> Signature.Public_key_hash.t option tzresult Lwt.t + + val init : + context -> t -> Signature.Public_key_hash.t -> context tzresult Lwt.t + + val set : + context -> + t -> + Signature.Public_key_hash.t option -> + context tzresult Lwt.t + end + module Internal_for_tests : sig (** see [Contract_repr.originated_contract] for documentation *) val originated_contract : Origination_nonce.Internal_for_tests.t -> t @@ -2239,17 +2252,6 @@ module Receipt : sig end module Delegate : sig - val init : - context -> - Contract.t -> - Signature.Public_key_hash.t -> - context tzresult Lwt.t - - val find : context -> Contract.t -> public_key_hash option tzresult Lwt.t - - val set : - context -> Contract.t -> public_key_hash option -> context tzresult Lwt.t - val frozen_deposits_limit : context -> Signature.Public_key_hash.t -> Tez.t option tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 055b7e371d54..8c5d7560af35 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -813,7 +813,7 @@ let update_script_storage_and_ticket_balances ctxt ~self storage Ticket_accounting.update_ticket_balances ctxt ~self ~ticket_diffs operations let apply_delegation ~ctxt ~source ~delegate ~before_operation = - Delegate.set ctxt source delegate >|=? fun ctxt -> + Contract.Delegate.set ctxt source delegate >|=? fun ctxt -> (ctxt, Gas.consumed ~since:before_operation ~until:ctxt, []) type execution_arg = @@ -1082,7 +1082,7 @@ let apply_origination ~ctxt ~storage_type ~storage ~unparsed_code let contract = Contract.Originated contract_hash in (match delegate with | None -> return ctxt - | Some delegate -> Delegate.init ctxt contract delegate) + | Some delegate -> Contract.Delegate.init ctxt contract delegate) >>=? fun ctxt -> Token.transfer ctxt (`Contract source) (`Contract contract) credit >>=? fun (ctxt, balance_updates) -> diff --git a/src/proto_alpha/lib_protocol/contract_services.ml b/src/proto_alpha/lib_protocol/contract_services.ml index 451152673e87..b9e2a84bae62 100644 --- a/src/proto_alpha/lib_protocol/contract_services.ml +++ b/src/proto_alpha/lib_protocol/contract_services.ml @@ -398,7 +398,7 @@ let[@coq_axiom_with_reason "gadt"] register () = | false -> return_some None | true -> Contract.get_manager_key ctxt mgr >|=? fun key -> Some (Some key))) ; - register_opt_field ~chunked:false S.delegate Delegate.find ; + register_opt_field ~chunked:false S.delegate Contract.Delegate.find ; opt_register1 ~chunked:false S.counter (fun ctxt contract () () -> match contract with | Originated _ -> return_none @@ -544,7 +544,7 @@ let[@coq_axiom_with_reason "gadt"] register () = S.info (fun ctxt contract {normalize_types} -> Contract.get_balance ctxt contract >>=? fun balance -> - Delegate.find ctxt contract >>=? fun delegate -> + Contract.Delegate.find ctxt contract >>=? fun delegate -> (match contract with | Implicit manager -> Contract.get_counter ctxt manager >>=? fun counter -> diff --git a/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml b/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml index 27f5394c700a..2237adcb1407 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_frozen_bonds.ml @@ -93,7 +93,7 @@ let init_test ~user_is_delegate = (* Configure delegate, as a delegate by self-delegation, for which revealing its manager key is a prerequisite. *) Contract.reveal_manager_key ctxt delegate delegate_pk >>>=? fun ctxt -> - Delegate.set ctxt delegate_contract (Some delegate) >>>=? fun ctxt -> + Contract.Delegate.set ctxt delegate_contract (Some delegate) >>>=? fun ctxt -> return (ctxt, user_contract, user_account, delegate) (** Tested scenario : @@ -111,7 +111,7 @@ let test_delegate_then_freeze_deposit () = (* Fetch user's initial balance before freeze. *) Token.balance ctxt user_account >>>=? fun (ctxt, user_balance) -> (* Let user delegate to "delegate". *) - Delegate.set ctxt user_contract (Some delegate) >>>=? fun ctxt -> + Contract.Delegate.set ctxt user_contract (Some delegate) >>>=? fun ctxt -> (* Fetch staking balance after delegation and before freeze. *) Delegate.staking_balance ctxt delegate >>>=? fun staking_balance -> (* Freeze a tx-rollup deposit. *) @@ -126,7 +126,7 @@ let test_delegate_then_freeze_deposit () = (* Ensure staking balance did not change. *) Assert.equal_tez ~loc:__LOC__ staking_balance' staking_balance >>=? fun () -> (* Remove delegation. *) - Delegate.set ctxt user_contract None >>>=? fun ctxt -> + Contract.Delegate.set ctxt user_contract None >>>=? fun ctxt -> (* Fetch staking balance after delegation removal. *) Delegate.staking_balance ctxt delegate >>>=? fun staking_balance'' -> (* Ensure staking balance decreased by user's initial balance. *) @@ -173,7 +173,7 @@ let test_freeze_deposit_then_delegate () = Now, fetch staking balance before delegation and after freeze. *) Delegate.staking_balance ctxt delegate >>>=? fun staking_balance -> (* Let user delegate to "delegate". *) - Delegate.set ctxt user_contract (Some delegate) >>>=? fun ctxt -> + Contract.Delegate.set ctxt user_contract (Some delegate) >>>=? fun ctxt -> (* Fetch staking balance after delegation. *) Delegate.staking_balance ctxt delegate >>>=? fun staking_balance' -> (* ensure staking balance increased by the user's balance. *) @@ -191,7 +191,7 @@ let test_freeze_deposit_then_delegate () = Assert.equal_tez ~loc:__LOC__ staking_balance'' staking_balance' >>=? fun () -> (* Remove delegation. *) - Delegate.set ctxt user_contract None >>>=? fun ctxt -> + Contract.Delegate.set ctxt user_contract None >>>=? fun ctxt -> (* Fetch staking balance. *) Delegate.staking_balance ctxt delegate >>>=? fun staking_balance''' -> (* Check that staking balance has decreased by the user's initial balance. *) @@ -329,7 +329,8 @@ let test_scenario scenario = (* Configure delegate, as a delegate by self-delegation, for which revealing its manager key is a prerequisite. *) Contract.reveal_manager_key ctxt delegate2 delegate_pk2 >>>=? fun ctxt -> - Delegate.set ctxt delegate_contract2 (Some delegate2) >>>=? fun ctxt -> + Contract.Delegate.set ctxt delegate_contract2 (Some delegate2) + >>>=? fun ctxt -> let tx_rollup1, nonce = mk_tx_rollup () in let tx_rollup2, _ = mk_tx_rollup ~nonce () in let bond_id1 = Bond_id.Tx_rollup_bond_id tx_rollup1 in @@ -344,7 +345,7 @@ let test_scenario scenario = Contract.get_balance_and_frozen_bonds ctxt user_contract >>>=? fun user_balance -> (* Let user delegate to "delegate". *) - Delegate.set ctxt user_contract (Some delegate) >>>=? fun ctxt -> + Contract.Delegate.set ctxt user_contract (Some delegate) >>>=? fun ctxt -> (* Fetch staking balance after delegation *) Delegate.staking_balance ctxt delegate >>>=? fun staking_balance' -> Assert.equal_tez @@ -418,7 +419,7 @@ let test_scenario scenario = (* Fetch user's initial balance before undelegate. *) Token.balance ctxt user_account >>>=? fun (_, user_balance) -> (* Remove delegation. *) - Delegate.set ctxt user_contract None >>>=? fun ctxt -> + Contract.Delegate.set ctxt user_contract None >>>=? fun ctxt -> (* Fetch staking balance after delegation removal. *) Delegate.staking_balance ctxt delegate >>>=? fun staking_balance' -> (* Ensure staking balance decreased by delegation amount *) diff --git a/src/proto_alpha/lib_protocol/test/integration/test_token.ml b/src/proto_alpha/lib_protocol/test/integration/test_token.ml index 4a05fb1a885e..1d3edd5f6c2f 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_token.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_token.ml @@ -516,13 +516,13 @@ let build_test_cases () = (* Configure baker1, and baker2 as delegates by self-delegation, for which revealing their manager key is a prerequisite. *) wrap (Contract.reveal_manager_key ctxt baker1 baker1_pk) >>=? fun ctxt -> - wrap (Delegate.set ctxt (Contract.Implicit baker1) (Some baker1)) + wrap (Contract.Delegate.set ctxt (Contract.Implicit baker1) (Some baker1)) >>=? fun ctxt -> wrap (Contract.reveal_manager_key ctxt baker2 baker2_pk) >>=? fun ctxt -> - wrap (Delegate.set ctxt (Contract.Implicit baker2) (Some baker2)) + wrap (Contract.Delegate.set ctxt (Contract.Implicit baker2) (Some baker2)) (* Let user1 delegate to baker2. *) >>=? fun ctxt -> - wrap (Delegate.set ctxt (Contract.Implicit user1) (Some baker2)) + wrap (Contract.Delegate.set ctxt (Contract.Implicit user1) (Some baker2)) >>=? fun ctxt -> let tx_rollup1 = mk_rollup () in let bond_id1 = Bond_id.Tx_rollup_bond_id tx_rollup1 in -- GitLab From 160627b8eb6b73e0ece263b8a3f31f8b9c8437dd Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 16:39:20 +0200 Subject: [PATCH 07/42] Proto: introduce `Delegate_table_storage.Contract` --- src/proto_alpha/lib_protocol/alpha_context.ml | 4 +- .../lib_protocol/alpha_context.mli | 15 +- .../lib_protocol/bootstrap_storage.ml | 4 +- .../contract_delegate_storage.mli | 8 +- .../lib_protocol/delegate_storage.ml | 147 +++++++++--------- .../lib_protocol/delegate_storage.mli | 39 +++-- 6 files changed, 114 insertions(+), 103 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index f7a7adb729cd..7a6a515ce76c 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -274,9 +274,7 @@ module Contract = struct module Delegate = struct let find = Contract_delegate_storage.find - let init = Delegate_storage.init - - let set = Delegate_storage.set + include Delegate_storage.Contract end module Internal_for_tests = struct diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9a07b260ab13..38171381971d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1624,17 +1624,16 @@ module Contract : sig script:Script.t * Lazy_storage.diffs option -> context tzresult Lwt.t + (** Functions for handling the delegate of a contract.*) module Delegate : sig - val find : context -> t -> Signature.Public_key_hash.t option tzresult Lwt.t + (** see {!Contract_delegate_storage.find} for documentation *) + val init : context -> t -> public_key_hash -> context tzresult Lwt.t - val init : - context -> t -> Signature.Public_key_hash.t -> context tzresult Lwt.t + (** see {!Delegate_table_storage.set} for documentation *) + val set : context -> t -> public_key_hash option -> context tzresult Lwt.t - val set : - context -> - t -> - Signature.Public_key_hash.t option -> - context tzresult Lwt.t + (** see {!Delegate_table_storage.find} for documentation *) + val find : context -> t -> public_key_hash option tzresult Lwt.t end module Internal_for_tests : sig diff --git a/src/proto_alpha/lib_protocol/bootstrap_storage.ml b/src/proto_alpha/lib_protocol/bootstrap_storage.ml index ce7a64777383..d37f5c3c699e 100644 --- a/src/proto_alpha/lib_protocol/bootstrap_storage.ml +++ b/src/proto_alpha/lib_protocol/bootstrap_storage.ml @@ -41,7 +41,7 @@ let init_account (ctxt, balance_updates) public_key_hash public_key >>=? fun ctxt -> - Delegate_storage.set + Delegate_storage.Contract.set ctxt contract (Some (Option.value ~default:public_key_hash delegate_to)) @@ -62,7 +62,7 @@ let init_contract ~typecheck (ctxt, balance_updates) let contract = Contract_repr.Originated contract_hash in (match delegate with | None -> return ctxt - | Some delegate -> Delegate_storage.init ctxt contract delegate) + | Some delegate -> Delegate_storage.Contract.init ctxt contract delegate) >>=? fun ctxt -> let origin = Receipt_repr.Protocol_migration in Token.transfer ~origin ctxt `Bootstrap (`Contract contract) amount diff --git a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli index 2f9b8e201c4f..1bdd5d5d1895 100644 --- a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli @@ -32,8 +32,7 @@ val find : (** [init ctxt contract delegate] sets the [delegate] associated to [contract]. - This function is undefined if [contract] is not allocated, or if [contract] - has already a delegate. *) + This function is undefined if [contract] has already a delegate. *) val init : Raw_context.t -> Contract_repr.t -> @@ -55,10 +54,7 @@ val unlink : Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t This function is undefined if [contract] is not allocated. *) val delete : Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t -(** [set ctxt contract delegate] updates the [delegate] associated to [contract]. - - This function is undefined if [contract] is not allocated, or if [contract] - does not have a delegate. *) +(** [set ctxt contract delegate] updates the [delegate] associated to [contract]. *) val set : Raw_context.t -> Contract_repr.t -> diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 7d5719d1415d..4f9fda6a3b3b 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -227,81 +227,86 @@ let full_balance ctxt delegate = Lwt.return Tez_repr.(frozen_deposits.current_amount +? balance_and_frozen_bonds) -let init ctxt contract delegate = - Contract_manager_storage.is_manager_key_revealed ctxt delegate - >>=? fun known_delegate -> - error_unless known_delegate (Unregistered_delegate delegate) >>?= fun () -> - registered ctxt delegate >>= fun is_registered -> - error_unless is_registered (Unregistered_delegate delegate) >>?= fun () -> - Contract_delegate_storage.init ctxt contract delegate >>=? fun ctxt -> - Contract_storage.get_balance_and_frozen_bonds ctxt contract - >>=? fun balance_and_frozen_bonds -> - Stake_storage.add_stake ctxt delegate balance_and_frozen_bonds +module Contract = struct + let init ctxt contract delegate = + Contract_manager_storage.is_manager_key_revealed ctxt delegate + >>=? fun known_delegate -> + error_unless known_delegate (Unregistered_delegate delegate) >>?= fun () -> + registered ctxt delegate >>= fun is_registered -> + error_unless is_registered (Unregistered_delegate delegate) >>?= fun () -> + Contract_delegate_storage.init ctxt contract delegate >>=? fun ctxt -> + Contract_storage.get_balance_and_frozen_bonds ctxt contract + >>=? fun balance_and_frozen_bonds -> + Stake_storage.add_stake ctxt delegate balance_and_frozen_bonds -let set c contract delegate = - match delegate with - | None -> ( - (* check if contract is a registered delegate *) - (match contract with - | Contract_repr.Implicit pkh -> - registered c pkh >>= fun is_registered -> - fail_when is_registered (No_deletion pkh) - | Originated _ -> return_unit) - >>=? fun () -> - Contract_delegate_storage.find c contract >>=? function - | None -> return c - | Some delegate -> - (* Removes the balance of the contract from the delegate *) - Contract_storage.get_balance_and_frozen_bonds c contract - >>=? fun balance_and_frozen_bonds -> - Stake_storage.remove_stake c delegate balance_and_frozen_bonds - >>=? fun c -> Contract_delegate_storage.delete c contract) - | Some delegate -> - Contract_manager_storage.is_manager_key_revealed c delegate - >>=? fun known_delegate -> - registered c delegate >>= fun registered_delegate -> - let self_delegation = - match contract with - | Implicit pkh -> Signature.Public_key_hash.equal pkh delegate - | Originated _ -> false - in - if (not known_delegate) || not (registered_delegate || self_delegation) - then fail (Unregistered_delegate delegate) - else - Contract_delegate_storage.find c contract >>=? fun current_delegate -> - (match current_delegate with - | Some current_delegate - when Signature.Public_key_hash.equal delegate current_delegate -> - if self_delegation then - Delegate_activation_storage.is_inactive c delegate >>=? function - | true -> return_unit - | false -> fail Active_delegate - else fail Current_delegate - | None | Some _ -> return_unit) - >>=? fun () -> + let set c contract delegate = + match delegate with + | None -> ( (* check if contract is a registered delegate *) (match contract with | Contract_repr.Implicit pkh -> registered c pkh >>= fun is_registered -> - (* allow self-delegation to re-activate *) - if (not self_delegation) && is_registered then - fail (No_deletion pkh) - else return_unit + fail_when is_registered (No_deletion pkh) | Originated _ -> return_unit) >>=? fun () -> - Contract_storage.allocated c contract >>= fun exists -> - error_when - (self_delegation && not exists) - (Empty_delegate_account delegate) - >>?= fun () -> - Contract_storage.get_balance_and_frozen_bonds c contract - >>=? fun balance_and_frozen_bonds -> - Stake_storage.remove_contract_stake c contract balance_and_frozen_bonds - >>=? fun c -> - Contract_delegate_storage.set c contract delegate >>=? fun c -> - Stake_storage.add_stake c delegate balance_and_frozen_bonds - >>=? fun c -> - if self_delegation then - Storage.Delegates.add c delegate >>= fun c -> - Stake_storage.set_active c delegate - else return c + Contract_delegate_storage.find c contract >>=? function + | None -> return c + | Some delegate -> + (* Removes the balance of the contract from the delegate *) + Contract_storage.get_balance_and_frozen_bonds c contract + >>=? fun balance_and_frozen_bonds -> + Stake_storage.remove_stake c delegate balance_and_frozen_bonds + >>=? fun c -> Contract_delegate_storage.delete c contract) + | Some delegate -> + Contract_manager_storage.is_manager_key_revealed c delegate + >>=? fun known_delegate -> + registered c delegate >>= fun registered_delegate -> + let self_delegation = + match contract with + | Implicit pkh -> Signature.Public_key_hash.equal pkh delegate + | Originated _ -> false + in + if (not known_delegate) || not (registered_delegate || self_delegation) + then fail (Unregistered_delegate delegate) + else + Contract_delegate_storage.find c contract >>=? fun current_delegate -> + (match current_delegate with + | Some current_delegate + when Signature.Public_key_hash.equal delegate current_delegate -> + if self_delegation then + Delegate_activation_storage.is_inactive c delegate >>=? function + | true -> return_unit + | false -> fail Active_delegate + else fail Current_delegate + | None | Some _ -> return_unit) + >>=? fun () -> + (* check if contract is a registered delegate *) + (match contract with + | Implicit pkh -> + registered c pkh >>= fun is_registered -> + (* allow self-delegation to re-activate *) + if (not self_delegation) && is_registered then + fail (No_deletion pkh) + else return_unit + | Originated _ -> return_unit) + >>=? fun () -> + Contract_storage.allocated c contract >>= fun exists -> + error_when + (self_delegation && not exists) + (Empty_delegate_account delegate) + >>?= fun () -> + Contract_storage.get_balance_and_frozen_bonds c contract + >>=? fun balance_and_frozen_bonds -> + Stake_storage.remove_contract_stake + c + contract + balance_and_frozen_bonds + >>=? fun c -> + Contract_delegate_storage.set c contract delegate >>=? fun c -> + Stake_storage.add_stake c delegate balance_and_frozen_bonds + >>=? fun c -> + if self_delegation then + Storage.Delegates.add c delegate >>= fun c -> + Stake_storage.set_active c delegate + else return c +end diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index afa43e5df789..3c747f8d89c5 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -97,19 +97,32 @@ val delegated_balance : val full_balance : Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t -(** Allow to register a delegate when creating an account. *) -val init : - Raw_context.t -> - Contract_repr.t -> - Signature.Public_key_hash.t -> - Raw_context.t tzresult Lwt.t - -(** Allow to set the delegate of an account. *) -val set : - Raw_context.t -> - Contract_repr.t -> - Signature.Public_key_hash.t option -> - Raw_context.t tzresult Lwt.t +module Contract : sig + (** [init ctxt contract delegate] allows to register a delegate when + creating a contract. + + This function is undefined if [contract] is not allocated, or if + [contract] has already a delegate, or if [delegate] is not a registered + delegate. *) + val init : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t -> + Raw_context.t tzresult Lwt.t + + (** [set ctxt contract delegate_opt] allows to set or unsetthe + delegate of a contract. + + This function is undefined if [contract] is not allocated. When + [delegate = contract], the function also register the contract + as a delegate. Otherwide, the function is undefined if + [delegate] is not a registered delegate *) + val set : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t option -> + Raw_context.t tzresult Lwt.t +end val pubkey : Raw_context.t -> -- GitLab From b7805367328becb7a7ede12af36d0e11c857ebb4 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 14 Apr 2022 23:37:43 +0200 Subject: [PATCH 08/42] Proto: merge `Seed.cycle_end` into `Delegate.cycle_end` --- src/proto_alpha/lib_protocol/alpha_context.mli | 4 ---- src/proto_alpha/lib_protocol/apply.ml | 3 +-- src/proto_alpha/lib_protocol/delegate_cycles.ml | 3 ++- src/proto_alpha/lib_protocol/delegate_cycles.mli | 1 - 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 38171381971d..a60c950db1f1 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1234,9 +1234,6 @@ module Seed : sig val for_cycle : context -> Cycle.t -> seed tzresult Lwt.t - val cycle_end : - context -> Cycle.t -> (context * Nonce.unrevealed list) tzresult Lwt.t - val seed_encoding : seed Data_encoding.t end @@ -2283,7 +2280,6 @@ module Delegate : sig val cycle_end : context -> Cycle.t -> - Nonce.unrevealed list -> (context * Receipt.balance_updates * Signature.Public_key_hash.t list) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 8c5d7560af35..62e8ca461a08 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -3214,8 +3214,7 @@ let may_start_new_cycle ctxt = match Level.dawn_of_a_new_cycle ctxt with | None -> return (ctxt, [], []) | Some last_cycle -> - Seed.cycle_end ctxt last_cycle >>=? fun (ctxt, unrevealed) -> - Delegate.cycle_end ctxt last_cycle unrevealed + Delegate.cycle_end ctxt last_cycle >>=? fun (ctxt, balance_updates, deactivated) -> Bootstrap.cycle_end ctxt last_cycle >|=? fun ctxt -> (ctxt, balance_updates, deactivated) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 57cf944e033a..1fec466d8e38 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -189,7 +189,8 @@ let freeze_deposits ?(origin = Receipt_repr.Block_application) ctxt ~new_cycle delegates_to_remove (ctxt, balance_updates) -let cycle_end ctxt last_cycle unrevealed_nonces = +let cycle_end ctxt last_cycle = + Seed_storage.cycle_end ctxt last_cycle >>=? fun (ctxt, unrevealed_nonces) -> let new_cycle = Cycle_repr.add last_cycle 1 in Delegate_sampler.select_new_distribution_at_cycle_end ctxt ~new_cycle >>=? fun ctxt -> diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.mli b/src/proto_alpha/lib_protocol/delegate_cycles.mli index 0814d32d45b8..ebcecb05d925 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.mli +++ b/src/proto_alpha/lib_protocol/delegate_cycles.mli @@ -32,7 +32,6 @@ val cycle_end : Raw_context.t -> Cycle_repr.t -> - Storage.Seed.unrevealed_nonce list -> (Raw_context.t * Receipt_repr.balance_updates * Signature.Public_key_hash.t list) -- GitLab From e096aebc1b424b0a8d93a20a6420705209cc83e6 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 23 Apr 2022 13:14:16 +0200 Subject: [PATCH 09/42] Proto/Alpha_context: always use `public_key` and `public_key_hash` --- .../lib_protocol/alpha_context.mli | 112 +++++++----------- 1 file changed, 43 insertions(+), 69 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index a60c950db1f1..688174be8918 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1692,7 +1692,7 @@ end module Tx_rollup_withdraw : sig type order = { - claimer : Signature.Public_key_hash.t; + claimer : public_key_hash; ticket_hash : Ticket_hash.t; amount : Tx_rollup_l2_qty.t; } @@ -1815,7 +1815,7 @@ module Tx_rollup_reveal : sig ty : Script.lazy_expr; ticketer : Contract.t; amount : Tx_rollup_l2_qty.t; - claimer : Signature.Public_key_hash.t; + claimer : public_key_hash; } val encoding : t Data_encoding.t @@ -1969,7 +1969,7 @@ module Tx_rollup_commitment : sig type nonrec t = { commitment : Compact.t; commitment_hash : Tx_rollup_commitment_hash.t; - committer : Signature.Public_key_hash.t; + committer : public_key_hash; submitted_at : Raw_level.t; finalized_at : Raw_level.t option; } @@ -2000,10 +2000,9 @@ module Tx_rollup_commitment : sig context -> Tx_rollup.t -> Tx_rollup_state.t -> - Signature.public_key_hash -> + public_key_hash -> Full.t -> - (context * Tx_rollup_state.t * Signature.public_key_hash option) tzresult - Lwt.t + (context * Tx_rollup_state.t * public_key_hash option) tzresult Lwt.t val find : context -> @@ -2039,16 +2038,10 @@ module Tx_rollup_commitment : sig (context * Submitted_commitment.t) tzresult Lwt.t val pending_bonded_commitments : - context -> - Tx_rollup.t -> - Signature.public_key_hash -> - (context * int) tzresult Lwt.t + context -> Tx_rollup.t -> public_key_hash -> (context * int) tzresult Lwt.t val has_bond : - context -> - Tx_rollup.t -> - Signature.public_key_hash -> - (context * bool) tzresult Lwt.t + context -> Tx_rollup.t -> public_key_hash -> (context * bool) tzresult Lwt.t val finalize_commitment : context -> @@ -2063,16 +2056,10 @@ module Tx_rollup_commitment : sig (context * Tx_rollup_state.t * Tx_rollup_level.t) tzresult Lwt.t val remove_bond : - context -> - Tx_rollup.t -> - Signature.public_key_hash -> - context tzresult Lwt.t + context -> Tx_rollup.t -> public_key_hash -> context tzresult Lwt.t val slash_bond : - context -> - Tx_rollup.t -> - Signature.public_key_hash -> - (context * bool) tzresult Lwt.t + context -> Tx_rollup.t -> public_key_hash -> (context * bool) tzresult Lwt.t val reject_commitment : context -> @@ -2118,8 +2105,8 @@ module Tx_rollup_errors : sig } | Level_already_has_commitment of Tx_rollup_level.t | Wrong_inbox_hash - | Bond_does_not_exist of Signature.public_key_hash - | Bond_in_use of Signature.public_key_hash + | Bond_does_not_exist of public_key_hash + | Bond_in_use of public_key_hash | No_uncommitted_inbox | No_commitment_to_finalize | No_commitment_to_remove @@ -2215,7 +2202,7 @@ module Receipt : sig | Baking_bonuses | Storage_fees | Double_signing_punishments - | Lost_endorsing_rewards of Signature.Public_key_hash.t * bool * bool + | Lost_endorsing_rewards of public_key_hash * bool * bool | Liquidity_baking_subsidies | Burned | Commitments of Blinded_public_key_hash.t @@ -2249,10 +2236,10 @@ end module Delegate : sig val frozen_deposits_limit : - context -> Signature.Public_key_hash.t -> Tez.t option tzresult Lwt.t + context -> public_key_hash -> Tez.t option tzresult Lwt.t val set_frozen_deposits_limit : - context -> Signature.Public_key_hash.t -> Tez.t option -> context Lwt.t + context -> public_key_hash -> Tez.t option -> context Lwt.t val fold : context -> @@ -2280,9 +2267,7 @@ module Delegate : sig val cycle_end : context -> Cycle.t -> - (context * Receipt.balance_updates * Signature.Public_key_hash.t list) - tzresult - Lwt.t + (context * Receipt.balance_updates * public_key_hash list) tzresult Lwt.t val check_and_record_already_slashed_for_double_endorsing : context -> public_key_hash -> Level.t -> (context * bool) tzresult Lwt.t @@ -2306,15 +2291,15 @@ module Delegate : sig val record_baking_activity_and_pay_rewards_and_fees : context -> - payload_producer:Signature.Public_key_hash.t -> - block_producer:Signature.Public_key_hash.t -> + payload_producer:public_key_hash -> + block_producer:public_key_hash -> baking_reward:Tez.t -> reward_bonus:Tez.t option -> (context * Receipt.balance_updates) tzresult Lwt.t val record_endorsing_participation : context -> - delegate:Signature.Public_key_hash.t -> + delegate:public_key_hash -> participation:level_participation -> endorsing_power:int -> context tzresult Lwt.t @@ -2323,22 +2308,18 @@ module Delegate : sig val frozen_deposits : context -> public_key_hash -> deposits tzresult Lwt.t - val staking_balance : - context -> Signature.Public_key_hash.t -> Tez.t tzresult Lwt.t + val staking_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t - val delegated_contracts : - context -> Signature.Public_key_hash.t -> Contract.t list Lwt.t + val delegated_contracts : context -> public_key_hash -> Contract.t list Lwt.t - val delegated_balance : - context -> Signature.Public_key_hash.t -> Tez.t tzresult Lwt.t + val delegated_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t - val registered : context -> Signature.public_key_hash -> bool Lwt.t + val registered : context -> public_key_hash -> bool Lwt.t - val deactivated : - context -> Signature.Public_key_hash.t -> bool tzresult Lwt.t + val deactivated : context -> public_key_hash -> bool tzresult Lwt.t val last_cycle_before_deactivation : - context -> Signature.Public_key_hash.t -> Cycle.t tzresult Lwt.t + context -> public_key_hash -> Cycle.t tzresult Lwt.t val pubkey : context -> public_key_hash -> public_key tzresult Lwt.t @@ -2401,8 +2382,7 @@ module Vote : sig val recorded_proposal_count_for_delegate : context -> public_key_hash -> int tzresult Lwt.t - val listings_encoding : - (Signature.Public_key_hash.t * int64) list Data_encoding.t + val listings_encoding : (public_key_hash * int64) list Data_encoding.t val update_listings : context -> context tzresult Lwt.t @@ -2426,13 +2406,12 @@ module Vote : sig val delegate_info_encoding : delegate_info Data_encoding.t val get_delegate_info : - context -> Signature.Public_key_hash.t -> delegate_info tzresult Lwt.t + context -> public_key_hash -> delegate_info tzresult Lwt.t - val get_voting_power_free : - context -> Signature.Public_key_hash.t -> int64 tzresult Lwt.t + val get_voting_power_free : context -> public_key_hash -> int64 tzresult Lwt.t val get_voting_power : - context -> Signature.Public_key_hash.t -> (context * int64) tzresult Lwt.t + context -> public_key_hash -> (context * int64) tzresult Lwt.t val get_total_voting_power_free : context -> int64 tzresult Lwt.t @@ -2501,8 +2480,7 @@ module Sc_rollup : sig type rollup := t - module Staker : - S.SIGNATURE_PUBLIC_KEY_HASH with type t = Signature.Public_key_hash.t + module Staker : S.SIGNATURE_PUBLIC_KEY_HASH with type t = public_key_hash module State_hash : S.HASH @@ -3135,7 +3113,7 @@ module Block_header : sig Liquidity_baking_repr.liquidity_baking_toggle_vote; } - type protocol_data = {contents : contents; signature : Signature.t} + type protocol_data = {contents : contents; signature : signature} type t = {shell : Block_header.shell_header; protocol_data : protocol_data} @@ -3192,8 +3170,7 @@ module Block_header : sig predecessor_round:Round.t -> unit tzresult - val check_signature : - t -> Chain_id.t -> Signature.Public_key.t -> unit tzresult + val check_signature : t -> Chain_id.t -> public_key -> unit tzresult val begin_validate_block_header : block_header:t -> @@ -3202,7 +3179,7 @@ module Block_header : sig predecessor_round:Round.t -> fitness:Fitness.t -> timestamp:Time.t -> - delegate_pk:Signature.public_key -> + delegate_pk:public_key -> round_durations:Round.round_durations -> proof_of_work_threshold:int64 -> expected_commitment:bool -> @@ -3365,7 +3342,7 @@ val consensus_content_encoding : consensus_content Data_encoding.t val pp_consensus_content : Format.formatter -> consensus_content -> unit type origination = { - delegate : Signature.Public_key_hash.t option; + delegate : public_key_hash option; script : Script.t; credit : Tez.tez; } @@ -3377,7 +3354,7 @@ type 'kind operation = { and 'kind protocol_data = { contents : 'kind contents_list; - signature : Signature.t option; + signature : signature option; } and _ contents_list = @@ -3418,13 +3395,13 @@ and _ contents = } -> Kind.activate_account contents | Proposals : { - source : Signature.Public_key_hash.t; + source : public_key_hash; period : int32; proposals : Protocol_hash.t list; } -> Kind.proposals contents | Ballot : { - source : Signature.Public_key_hash.t; + source : public_key_hash; period : int32; proposal : Protocol_hash.t; ballot : Vote.ballot; @@ -3432,7 +3409,7 @@ and _ contents = -> Kind.ballot contents | Failing_noop : string -> Kind.failing_noop contents | Manager_operation : { - source : Signature.Public_key_hash.t; + source : public_key_hash; fee : Tez.tez; counter : counter; operation : 'kind manager_operation; @@ -3442,7 +3419,7 @@ and _ contents = -> 'kind Kind.manager contents and _ manager_operation = - | Reveal : Signature.Public_key.t -> Kind.reveal manager_operation + | Reveal : public_key -> Kind.reveal manager_operation | Transaction : { amount : Tez.tez; parameters : Script.lazy_expr; @@ -3451,9 +3428,7 @@ and _ manager_operation = } -> Kind.transaction manager_operation | Origination : origination -> Kind.origination manager_operation - | Delegation : - Signature.Public_key_hash.t option - -> Kind.delegation manager_operation + | Delegation : public_key_hash option -> Kind.delegation manager_operation | Register_global_constant : { value : Script.lazy_expr; } @@ -3833,8 +3808,7 @@ module Stake_distribution : sig val delegate_pubkey : context -> public_key_hash -> public_key tzresult Lwt.t - val get_staking_balance : - context -> Signature.Public_key_hash.t -> Tez.t tzresult Lwt.t + val get_staking_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t end module Commitment : sig @@ -4009,8 +3983,8 @@ module Token : sig type container = [ `Contract of Contract.t | `Collected_commitments of Blinded_public_key_hash.t - | `Delegate_balance of Signature.Public_key_hash.t - | `Frozen_deposits of Signature.Public_key_hash.t + | `Delegate_balance of public_key_hash + | `Frozen_deposits of public_key_hash | `Block_fees | `Frozen_bonds of Contract.t * Bond_id.t ] @@ -4031,7 +4005,7 @@ module Token : sig type sink = [ `Storage_fees | `Double_signing_punishments - | `Lost_endorsing_rewards of Signature.Public_key_hash.t * bool * bool + | `Lost_endorsing_rewards of public_key_hash * bool * bool | `Burned | `Tx_rollup_rejection_punishments | `Sc_rollup_refutation_punishments -- GitLab From 8967a9d84d8f168015ab5c28974ae372ba11350f Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 10/42] Proto/Delegate: remove dead code --- src/proto_alpha/lib_protocol/alpha_context.ml | 2 -- src/proto_alpha/lib_protocol/alpha_context.mli | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 7a6a515ce76c..0908294beb9d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -465,8 +465,6 @@ module Stake_distribution = struct let slot_owner = Delegate_sampler.slot_owner - let delegate_pubkey = Delegate_storage.pubkey - let get_staking_balance = Delegate_storage.staking_balance end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 688174be8918..7b0f4f1c0004 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3806,8 +3806,6 @@ module Stake_distribution : sig Slot.t -> (context * (public_key * public_key_hash)) tzresult Lwt.t - val delegate_pubkey : context -> public_key_hash -> public_key tzresult Lwt.t - val get_staking_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t end -- GitLab From 2b599c3b1430b52db880e67ba675bb61e5eb2453 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:43:07 +0200 Subject: [PATCH 11/42] Proto: rename `Delegate.delegate_participation_info` --- src/proto_alpha/lib_protocol/alpha_context.mli | 2 +- .../lib_protocol/delegate_missed_endorsements_storage.ml | 2 +- .../lib_protocol/delegate_missed_endorsements_storage.mli | 2 +- src/proto_alpha/lib_protocol/delegate_services.ml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 7b0f4f1c0004..d53139b193e4 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2261,7 +2261,7 @@ module Delegate : sig expected_endorsing_rewards : Tez.t; } - val delegate_participation_info : + val participation_info : context -> public_key_hash -> participation_info tzresult Lwt.t val cycle_end : diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml index 508d2852e8a3..6d28a0beacfa 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -133,7 +133,7 @@ type participation_info = { } (* Inefficient, only for RPC *) -let delegate_participation_info ctxt delegate = +let participation_info ctxt delegate = let level = Level_storage.current ctxt in Stake_storage.get_selected_distribution ctxt level.cycle >>=? fun stake_distribution -> diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli index 3ac64a03ae96..7f8f7b1a4df7 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli @@ -63,7 +63,7 @@ type participation_info = { [delegate_participation_info] and [!val:check_delegate] forms the implementation of RPC call "/context/delegates//participation". *) -val delegate_participation_info : +val participation_info : Raw_context.t -> Signature.Public_key_hash.t -> participation_info tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index b0c8da4709a4..f05ee611020b 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -425,7 +425,7 @@ let register () = Vote.get_delegate_info ctxt pkh) ; register1 ~chunked:false S.participation (fun ctxt pkh () () -> Delegate.check_registered ctxt pkh >>=? fun () -> - Delegate.delegate_participation_info ctxt pkh) + Delegate.participation_info ctxt pkh) let list ctxt block ?(active = true) ?(inactive = false) ?(with_minimal_stake = true) ?(without_minimal_stake = false) () = -- GitLab From 47ad7d4ef0814fd11f433f05ea4d746ecd927e91 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 26 Apr 2022 10:29:20 +0000 Subject: [PATCH 12/42] Proto: improve doc in `Delegate_table_storage`. --- .../contract_delegate_storage.mli | 2 +- .../lib_protocol/delegate_storage.mli | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli index 1bdd5d5d1895..7fe992903bc0 100644 --- a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli @@ -32,7 +32,7 @@ val find : (** [init ctxt contract delegate] sets the [delegate] associated to [contract]. - This function is undefined if [contract] has already a delegate. *) + This function returns an error if [contract] has already a delegate. *) val init : Raw_context.t -> Contract_repr.t -> diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 3c747f8d89c5..885f3e097ea8 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -98,25 +98,29 @@ val full_balance : Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t module Contract : sig - (** [init ctxt contract delegate] allows to register a delegate when + (** [init ctxt contract delegate] registers a delegate when creating a contract. - This function is undefined if [contract] is not allocated, or if - [contract] has already a delegate, or if [delegate] is not a registered - delegate. *) + This functions assumes that [contract] is allocated. + This function returns an error if [contract] already has a delegate or + if [delegate] is not a registered delegate. *) val init : Raw_context.t -> Contract_repr.t -> Signature.Public_key_hash.t -> Raw_context.t tzresult Lwt.t - (** [set ctxt contract delegate_opt] allows to set or unsetthe - delegate of a contract. - - This function is undefined if [contract] is not allocated. When - [delegate = contract], the function also register the contract - as a delegate. Otherwide, the function is undefined if - [delegate] is not a registered delegate *) + (** [set ctxt contract delegate_opt] allows to set the + delegate of a contract to [delegate] when [delegate_opt = Some delegate] + or to unset the delegate when [delegate_opt = None]. + When [delegate_opt = Some contract] (aka self-delegation), + the function also registers the contract as a delegate and + sets the delegate as {{!module:Delegate_activation_storage}active}. + + It returns an error when trying to set the delegate to an unregistered delegate. + It returns an error when trying to unset or change the delegate of a registered delegate. + It returns an error when self-delegating and the delegate is not {{!Contract_storage.allocated}allocated}. + It returns an error when self-delegating and the delegate is already active. *) val set : Raw_context.t -> Contract_repr.t -> -- GitLab From 07fdb4a0c5ebdd2b930a0c6b8aa91cc0a205e20a Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Wed, 27 Apr 2022 11:08:02 +0200 Subject: [PATCH 13/42] Proto: refactor `Delegate_table_storage.Contract.set` --- .../lib_protocol/delegate_storage.ml | 150 ++++++++++-------- 1 file changed, 83 insertions(+), 67 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 4f9fda6a3b3b..454f849ea20a 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -227,6 +227,11 @@ let full_balance ctxt delegate = Lwt.return Tez_repr.(frozen_deposits.current_amount +? balance_and_frozen_bonds) +(** This module ensures the following invariants: + - registered delegates are self-delegated and appears in `Storage.Delegate`, + i.e. registered delegate cannot change their delegation + - stake is properly moved when changing delegation. +*) module Contract = struct let init ctxt contract delegate = Contract_manager_storage.is_manager_key_revealed ctxt delegate @@ -239,74 +244,85 @@ module Contract = struct >>=? fun balance_and_frozen_bonds -> Stake_storage.add_stake ctxt delegate balance_and_frozen_bonds - let set c contract delegate = + let set_self_delegate c delegate = + let open Lwt_tzresult_syntax in + let*! is_registered = registered c delegate in + if is_registered then + let* () = + let* is_inactive = Delegate_activation_storage.is_inactive c delegate in + fail_unless is_inactive Active_delegate + in + Stake_storage.set_active c delegate + else + let contract = Contract_repr.Implicit delegate in + let* () = + let* is_pk_revealed = + Contract_manager_storage.is_manager_key_revealed c delegate + in + fail_unless is_pk_revealed (Unregistered_delegate delegate) + in + let* () = + let*! is_allocated = Contract_storage.allocated c contract in + fail_unless is_allocated (Empty_delegate_account delegate) + in + let* balance_and_frozen_bonds = + Contract_storage.get_balance_and_frozen_bonds c contract + in + let* c = + Stake_storage.remove_contract_stake c contract balance_and_frozen_bonds + in + let* c = Contract_delegate_storage.set c contract delegate in + let* c = Stake_storage.add_stake c delegate balance_and_frozen_bonds in + let*! c = Storage.Delegates.add c delegate in + let* c = Stake_storage.set_active c delegate in + return c + + let set_delegate c contract delegate = + let open Lwt_tzresult_syntax in + let* () = + match contract with + | Contract_repr.Originated _ -> return_unit + | Implicit pkh -> + let*! is_registered = registered c pkh in + fail_when is_registered (No_deletion pkh) + in + let* () = + let* current_delegate = Contract_delegate_storage.find c contract in + match (delegate, current_delegate) with + | None, None -> + (* we don't fail in this case in order not to risk breaking + existing smart contracts. *) + return_unit + | Some delegate, Some current_delegate + when Signature.Public_key_hash.equal delegate current_delegate -> + fail Current_delegate + | _ -> return_unit + in + let* balance_and_frozen_bonds = + Contract_storage.get_balance_and_frozen_bonds c contract + in + let* c = + Stake_storage.remove_contract_stake c contract balance_and_frozen_bonds + in match delegate with - | None -> ( - (* check if contract is a registered delegate *) - (match contract with - | Contract_repr.Implicit pkh -> - registered c pkh >>= fun is_registered -> - fail_when is_registered (No_deletion pkh) - | Originated _ -> return_unit) - >>=? fun () -> - Contract_delegate_storage.find c contract >>=? function - | None -> return c - | Some delegate -> - (* Removes the balance of the contract from the delegate *) - Contract_storage.get_balance_and_frozen_bonds c contract - >>=? fun balance_and_frozen_bonds -> - Stake_storage.remove_stake c delegate balance_and_frozen_bonds - >>=? fun c -> Contract_delegate_storage.delete c contract) + | None -> + let* c = Contract_delegate_storage.delete c contract in + return c | Some delegate -> - Contract_manager_storage.is_manager_key_revealed c delegate - >>=? fun known_delegate -> - registered c delegate >>= fun registered_delegate -> - let self_delegation = - match contract with - | Implicit pkh -> Signature.Public_key_hash.equal pkh delegate - | Originated _ -> false + let* () = + let*! is_delegate_registered = registered c delegate in + fail_when + (not is_delegate_registered) + (Unregistered_delegate delegate) in - if (not known_delegate) || not (registered_delegate || self_delegation) - then fail (Unregistered_delegate delegate) - else - Contract_delegate_storage.find c contract >>=? fun current_delegate -> - (match current_delegate with - | Some current_delegate - when Signature.Public_key_hash.equal delegate current_delegate -> - if self_delegation then - Delegate_activation_storage.is_inactive c delegate >>=? function - | true -> return_unit - | false -> fail Active_delegate - else fail Current_delegate - | None | Some _ -> return_unit) - >>=? fun () -> - (* check if contract is a registered delegate *) - (match contract with - | Implicit pkh -> - registered c pkh >>= fun is_registered -> - (* allow self-delegation to re-activate *) - if (not self_delegation) && is_registered then - fail (No_deletion pkh) - else return_unit - | Originated _ -> return_unit) - >>=? fun () -> - Contract_storage.allocated c contract >>= fun exists -> - error_when - (self_delegation && not exists) - (Empty_delegate_account delegate) - >>?= fun () -> - Contract_storage.get_balance_and_frozen_bonds c contract - >>=? fun balance_and_frozen_bonds -> - Stake_storage.remove_contract_stake - c - contract - balance_and_frozen_bonds - >>=? fun c -> - Contract_delegate_storage.set c contract delegate >>=? fun c -> - Stake_storage.add_stake c delegate balance_and_frozen_bonds - >>=? fun c -> - if self_delegation then - Storage.Delegates.add c delegate >>= fun c -> - Stake_storage.set_active c delegate - else return c + let* c = Contract_delegate_storage.set c contract delegate in + let* c = Stake_storage.add_stake c delegate balance_and_frozen_bonds in + return c + + let set c contract delegate = + match (delegate, contract) with + | Some delegate, Contract_repr.Implicit source + when Signature.Public_key_hash.equal source delegate -> + set_self_delegate c delegate + | _ -> set_delegate c contract delegate end -- GitLab From 156ee7efcc2e72ae9bfb0acc017091e56944bf01 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 13:08:21 +0200 Subject: [PATCH 14/42] Proto: no error for `expected_slots_for_given_active_stake` --- .../delegate_missed_endorsements_storage.ml | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml index 6d28a0beacfa..6517bf97ad9c 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -36,13 +36,12 @@ let expected_slots_for_given_active_stake ctxt ~total_active_stake ~active_stake let number_of_endorsements_per_cycle = blocks_per_cycle * consensus_committee_size in - Result.return - (Z.to_int - (Z.div - (Z.mul - (Z.of_int64 (Tez_repr.to_mutez active_stake)) - (Z.of_int number_of_endorsements_per_cycle)) - (Z.of_int64 (Tez_repr.to_mutez total_active_stake)))) + Z.to_int + (Z.div + (Z.mul + (Z.of_int64 (Tez_repr.to_mutez active_stake)) + (Z.of_int number_of_endorsements_per_cycle)) + (Z.of_int64 (Tez_repr.to_mutez total_active_stake))) type level_participation = Participated | Didn't_participate @@ -79,11 +78,12 @@ let record_endorsing_participation ctxt ~delegate ~participation | Some active_stake -> Stake_storage.get_total_active_stake ctxt level.cycle >>=? fun total_active_stake -> - expected_slots_for_given_active_stake - ctxt - ~total_active_stake - ~active_stake - >>?= fun expected_slots -> + let expected_slots = + expected_slots_for_given_active_stake + ctxt + ~total_active_stake + ~active_stake + in let Ratio_repr.{numerator; denominator} = Constants_storage.minimal_participation_ratio ctxt in @@ -157,11 +157,12 @@ let participation_info ctxt delegate = | Some active_stake -> Stake_storage.get_total_active_stake ctxt level.cycle >>=? fun total_active_stake -> - expected_slots_for_given_active_stake - ctxt - ~total_active_stake - ~active_stake - >>?= fun expected_cycle_activity -> + let expected_cycle_activity = + expected_slots_for_given_active_stake + ctxt + ~total_active_stake + ~active_stake + in let Ratio_repr.{numerator; denominator} = Constants_storage.minimal_participation_ratio ctxt in @@ -234,11 +235,12 @@ let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = let has_revealed_nonces = delegate_has_revealed_nonces delegate unrevealed_nonces_set in - expected_slots_for_given_active_stake - ctxt - ~total_active_stake - ~active_stake - >>?= fun expected_slots -> + let expected_slots = + expected_slots_for_given_active_stake + ctxt + ~total_active_stake + ~active_stake + in let rewards = Tez_repr.mul_exn endorsing_reward_per_slot expected_slots in (if sufficient_participation && has_revealed_nonces then (* Sufficient participation: we pay the rewards *) -- GitLab From 5832e80e2245d8bf5b92b0711d5e2a96bfb7ea23 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 13:08:38 +0200 Subject: [PATCH 15/42] Proto: move `distribute_endorsing_rewards` into `Delegate_cycles` --- .../lib_protocol/delegate_cycles.ml | 62 +++++++++++++++-- .../delegate_missed_endorsements_storage.ml | 68 ++----------------- .../delegate_missed_endorsements_storage.mli | 19 ++++-- 3 files changed, 78 insertions(+), 71 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 1fec466d8e38..53a0c38c2146 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -189,6 +189,63 @@ let freeze_deposits ?(origin = Receipt_repr.Block_application) ctxt ~new_cycle delegates_to_remove (ctxt, balance_updates) +let delegate_has_revealed_nonces delegate unrevelead_nonces_set = + not (Signature.Public_key_hash.Set.mem delegate unrevelead_nonces_set) + +let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = + let endorsing_reward_per_slot = + Constants_storage.endorsing_reward_per_slot ctxt + in + let unrevealed_nonces_set = + List.fold_left + (fun set {Storage.Seed.nonce_hash = _; delegate} -> + Signature.Public_key_hash.Set.add delegate set) + Signature.Public_key_hash.Set.empty + unrevealed_nonces + in + Stake_storage.get_total_active_stake ctxt last_cycle + >>=? fun total_active_stake -> + Stake_storage.get_selected_distribution ctxt last_cycle >>=? fun delegates -> + List.fold_left_es + (fun (ctxt, balance_updates) (delegate, active_stake) -> + let delegate_contract = Contract_repr.Implicit delegate in + Delegate_missed_endorsements_storage.reset_delegate_participation + ctxt + delegate + >>=? fun (ctxt, sufficient_participation) -> + let has_revealed_nonces = + delegate_has_revealed_nonces delegate unrevealed_nonces_set + in + let expected_slots = + Delegate_missed_endorsements_storage + .expected_slots_for_given_active_stake + ctxt + ~total_active_stake + ~active_stake + in + let rewards = Tez_repr.mul_exn endorsing_reward_per_slot expected_slots in + if sufficient_participation && has_revealed_nonces then + (* Sufficient participation: we pay the rewards *) + Token.transfer + ctxt + `Endorsing_rewards + (`Contract delegate_contract) + rewards + >|=? fun (ctxt, payed_rewards_receipts) -> + (ctxt, payed_rewards_receipts @ balance_updates) + else + (* Insufficient participation or unrevealed nonce: no rewards *) + Token.transfer + ctxt + `Endorsing_rewards + (`Lost_endorsing_rewards + (delegate, not sufficient_participation, not has_revealed_nonces)) + rewards + >|=? fun (ctxt, payed_rewards_receipts) -> + (ctxt, payed_rewards_receipts @ balance_updates)) + (ctxt, []) + delegates + let cycle_end ctxt last_cycle = Seed_storage.cycle_end ctxt last_cycle >>=? fun (ctxt, unrevealed_nonces) -> let new_cycle = Cycle_repr.add last_cycle 1 in @@ -198,10 +255,7 @@ let cycle_end ctxt last_cycle = ctxt ~new_cycle >>= fun ctxt -> - Delegate_missed_endorsements_storage.distribute_endorsing_rewards - ctxt - last_cycle - unrevealed_nonces + distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces >>=? fun (ctxt, balance_updates) -> freeze_deposits ctxt ~new_cycle ~balance_updates >>=? fun (ctxt, balance_updates) -> diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml index 6517bf97ad9c..96d22c2888cd 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -204,65 +204,11 @@ let participation_info ctxt delegate = expected_endorsing_rewards; } -let delegate_participated_enough ctxt delegate = - Storage.Contract.Missed_endorsements.find ctxt delegate >>=? function - | None -> return_true +let reset_delegate_participation ctxt delegate = + let contract = Contract_repr.Implicit delegate in + Storage.Contract.Missed_endorsements.find ctxt contract >>=? fun missed -> + match missed with + | None -> return (ctxt, true) | Some missed_endorsements -> - return Compare.Int.(missed_endorsements.remaining_slots >= 0) - -let delegate_has_revealed_nonces delegate unrevelead_nonces_set = - not (Signature.Public_key_hash.Set.mem delegate unrevelead_nonces_set) - -let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = - let endorsing_reward_per_slot = - Constants_storage.endorsing_reward_per_slot ctxt - in - let unrevealed_nonces_set = - List.fold_left - (fun set {Storage.Seed.nonce_hash = _; delegate} -> - Signature.Public_key_hash.Set.add delegate set) - Signature.Public_key_hash.Set.empty - unrevealed_nonces - in - Stake_storage.get_total_active_stake ctxt last_cycle - >>=? fun total_active_stake -> - Stake_storage.get_selected_distribution ctxt last_cycle >>=? fun delegates -> - List.fold_left_es - (fun (ctxt, balance_updates) (delegate, active_stake) -> - let delegate_contract = Contract_repr.Implicit delegate in - delegate_participated_enough ctxt delegate_contract - >>=? fun sufficient_participation -> - let has_revealed_nonces = - delegate_has_revealed_nonces delegate unrevealed_nonces_set - in - let expected_slots = - expected_slots_for_given_active_stake - ctxt - ~total_active_stake - ~active_stake - in - let rewards = Tez_repr.mul_exn endorsing_reward_per_slot expected_slots in - (if sufficient_participation && has_revealed_nonces then - (* Sufficient participation: we pay the rewards *) - Token.transfer - ctxt - `Endorsing_rewards - (`Contract delegate_contract) - rewards - >|=? fun (ctxt, payed_rewards_receipts) -> - (ctxt, payed_rewards_receipts @ balance_updates) - else - (* Insufficient participation or unrevealed nonce: no rewards *) - Token.transfer - ctxt - `Endorsing_rewards - (`Lost_endorsing_rewards - (delegate, not sufficient_participation, not has_revealed_nonces)) - rewards - >|=? fun (ctxt, payed_rewards_receipts) -> - (ctxt, payed_rewards_receipts @ balance_updates)) - >>=? fun (ctxt, balance_updates) -> - Storage.Contract.Missed_endorsements.remove ctxt delegate_contract - >>= fun ctxt -> return (ctxt, balance_updates)) - (ctxt, []) - delegates + Storage.Contract.Missed_endorsements.remove ctxt contract >>= fun ctxt -> + return (ctxt, Compare.Int.(missed_endorsements.remaining_slots >= 0)) diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli index 7f8f7b1a4df7..d2267d33a6a3 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli @@ -25,6 +25,12 @@ (* *) (*****************************************************************************) +val expected_slots_for_given_active_stake : + Raw_context.t -> + total_active_stake:Tez_repr.tez -> + active_stake:Tez_repr.tez -> + int + type level_participation = Participated | Didn't_participate (** Record the participation of a delegate as a validator. *) @@ -35,6 +41,13 @@ val record_endorsing_participation : endorsing_power:int -> Raw_context.t tzresult Lwt.t +(** Check that a delegate participated enough in the last cycle, + and then reset the participation for preparing the next cycle. *) +val reset_delegate_participation : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Raw_context.t * bool) tzresult Lwt.t + (** Participation information. We denote by: - "static" information that does not change during the cycle - "dynamic" information that may change during the cycle *) @@ -78,9 +91,3 @@ val record_baking_activity_and_pay_rewards_and_fees : baking_reward:Tez_repr.t -> reward_bonus:Tez_repr.t option -> (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t - -val distribute_endorsing_rewards : - Raw_context.t -> - Cycle_repr.t -> - Storage.Seed.unrevealed_nonce list -> - (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t -- GitLab From 27f4b67e05c62611ed3b65fc3864b038fd590aa3 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 14:31:00 +0200 Subject: [PATCH 16/42] Proto: remove unused error in `Delegate_storage` --- .../client_proto_context_commands.ml | 6 +- .../lib_protocol/delegate_storage.ml | 222 ++++++++---------- .../lib_protocol/delegate_storage.mli | 21 +- .../integration/consensus/test_delegation.ml | 8 +- 4 files changed, 110 insertions(+), 147 deletions(-) diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index 85b14f76ad3e..0553bc9a97bd 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -1420,7 +1420,11 @@ let commands_rw () = src_pk >>= function | Ok _ -> return_unit - | Error [Environment.Ecoproto_error Delegate_storage.Active_delegate] -> + | Error + [ + Environment.Ecoproto_error + Delegate_storage.Contract.Active_delegate; + ] -> cctxt#message "Delegate already activated." >>= fun () -> return_unit | Error el -> Lwt.return_error el); diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 454f849ea20a..cc7509a47399 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -25,132 +25,9 @@ (* *) (*****************************************************************************) -type error += - | (* `Permanent *) No_deletion of Signature.Public_key_hash.t - | (* `Temporary *) Active_delegate - | (* `Temporary *) Current_delegate - | (* `Permanent *) Empty_delegate_account of Signature.Public_key_hash.t - | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t - | (* `Permanent *) Unassigned_validation_slot_for_level of Level_repr.t * int - | (* `Permanent *) - Cannot_find_active_stake of { - cycle : Cycle_repr.t; - delegate : Signature.Public_key_hash.t; - } - | (* `Temporary *) Not_registered of Signature.Public_key_hash.t +type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t let () = - register_error_kind - `Permanent - ~id:"delegate.no_deletion" - ~title:"Forbidden delegate deletion" - ~description:"Tried to unregister a delegate" - ~pp:(fun ppf delegate -> - Format.fprintf - ppf - "Delegate deletion is forbidden (%a)" - Signature.Public_key_hash.pp - delegate) - Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) - (function No_deletion c -> Some c | _ -> None) - (fun c -> No_deletion c) ; - register_error_kind - `Temporary - ~id:"delegate.already_active" - ~title:"Delegate already active" - ~description:"Useless delegate reactivation" - ~pp:(fun ppf () -> - Format.fprintf ppf "The delegate is still active, no need to refresh it") - Data_encoding.empty - (function Active_delegate -> Some () | _ -> None) - (fun () -> Active_delegate) ; - register_error_kind - `Temporary - ~id:"delegate.unchanged" - ~title:"Unchanged delegated" - ~description:"Contract already delegated to the given delegate" - ~pp:(fun ppf () -> - Format.fprintf - ppf - "The contract is already delegated to the same delegate") - Data_encoding.empty - (function Current_delegate -> Some () | _ -> None) - (fun () -> Current_delegate) ; - register_error_kind - `Permanent - ~id:"delegate.empty_delegate_account" - ~title:"Empty delegate account" - ~description:"Cannot register a delegate when its implicit account is empty" - ~pp:(fun ppf delegate -> - Format.fprintf - ppf - "Delegate registration is forbidden when the delegate\n\ - \ implicit account is empty (%a)" - Signature.Public_key_hash.pp - delegate) - Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) - (function Empty_delegate_account c -> Some c | _ -> None) - (fun c -> Empty_delegate_account c) ; - (* Unregistered delegate *) - register_error_kind - `Permanent - ~id:"contract.manager.unregistered_delegate" - ~title:"Unregistered delegate" - ~description:"A contract cannot be delegated to an unregistered delegate" - ~pp:(fun ppf k -> - Format.fprintf - ppf - "The provided public key (with hash %a) is not registered as valid \ - delegate key." - Signature.Public_key_hash.pp - k) - Data_encoding.(obj1 (req "hash" Signature.Public_key_hash.encoding)) - (function Unregistered_delegate k -> Some k | _ -> None) - (fun k -> Unregistered_delegate k) ; - (* Unassigned_validation_slot_for_level *) - register_error_kind - `Permanent - ~id:"delegate.unassigned_validation_slot_for_level" - ~title:"Unassigned validation slot for level" - ~description: - "The validation slot for the given level is not assigned. Nobody payed \ - for that slot, or the level is either in the past or too far in the \ - future (further than the validatiors_selection_offset constant)" - ~pp:(fun ppf (l, slot) -> - Format.fprintf - ppf - "The validation slot %i for the level %a is not assigned. Nobody payed \ - for that slot, or the level is either in the past or too far in the \ - future (further than the validatiors_selection_offset constant)" - slot - Level_repr.pp - l) - Data_encoding.(obj2 (req "level" Level_repr.encoding) (req "slot" int31)) - (function - | Unassigned_validation_slot_for_level (l, s) -> Some (l, s) | _ -> None) - (fun (l, s) -> Unassigned_validation_slot_for_level (l, s)) ; - register_error_kind - `Permanent - ~id:"delegate.cannot_find_active_stake" - ~title:"Cannot find active stake" - ~description: - "The active stake of a delegate cannot be found for the given cycle." - ~pp:(fun ppf (cycle, delegate) -> - Format.fprintf - ppf - "The active stake of the delegate %a cannot be found for the cycle %a." - Cycle_repr.pp - cycle - Signature.Public_key_hash.pp - delegate) - Data_encoding.( - obj2 - (req "cycle" Cycle_repr.encoding) - (req "delegate" Signature.Public_key_hash.encoding)) - (function - | Cannot_find_active_stake {cycle; delegate} -> Some (cycle, delegate) - | _ -> None) - (fun (cycle, delegate) -> Cannot_find_active_stake {cycle; delegate}) ; register_error_kind `Temporary ~id:"delegate.not_registered" @@ -182,12 +59,6 @@ let fold = Storage.Delegates.fold let list = Storage.Delegates.elements -let pubkey ctxt pkh = - Contract_manager_storage.get_manager_key - ctxt - pkh - ~error:(Unregistered_delegate pkh) - let frozen_deposits_limit ctxt delegate = Storage.Contract.Frozen_deposits_limit.find ctxt @@ -233,6 +104,27 @@ let full_balance ctxt delegate = - stake is properly moved when changing delegation. *) module Contract = struct + type error += + | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t + + let () = + (* Unregistered delegate *) + register_error_kind + `Permanent + ~id:"contract.manager.unregistered_delegate" + ~title:"Unregistered delegate" + ~description:"A contract cannot be delegated to an unregistered delegate" + ~pp:(fun ppf k -> + Format.fprintf + ppf + "The provided public key (with hash %a) is not registered as valid \ + delegate key." + Signature.Public_key_hash.pp + k) + Data_encoding.(obj1 (req "hash" Signature.Public_key_hash.encoding)) + (function Unregistered_delegate k -> Some k | _ -> None) + (fun k -> Unregistered_delegate k) + let init ctxt contract delegate = Contract_manager_storage.is_manager_key_revealed ctxt delegate >>=? fun known_delegate -> @@ -244,6 +136,38 @@ module Contract = struct >>=? fun balance_and_frozen_bonds -> Stake_storage.add_stake ctxt delegate balance_and_frozen_bonds + type error += + | (* `Temporary *) Active_delegate + | (* `Permanent *) Empty_delegate_account of Signature.Public_key_hash.t + + let () = + register_error_kind + `Temporary + ~id:"delegate.already_active" + ~title:"Delegate already active" + ~description:"Useless delegate reactivation" + ~pp:(fun ppf () -> + Format.fprintf ppf "The delegate is still active, no need to refresh it") + Data_encoding.empty + (function Active_delegate -> Some () | _ -> None) + (fun () -> Active_delegate) ; + register_error_kind + `Permanent + ~id:"delegate.empty_delegate_account" + ~title:"Empty delegate account" + ~description: + "Cannot register a delegate when its implicit account is empty" + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegate registration is forbidden when the delegate\n\ + \ implicit account is empty (%a)" + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Empty_delegate_account c -> Some c | _ -> None) + (fun c -> Empty_delegate_account c) + let set_self_delegate c delegate = let open Lwt_tzresult_syntax in let*! is_registered = registered c delegate in @@ -277,6 +201,38 @@ module Contract = struct let* c = Stake_storage.set_active c delegate in return c + type error += + | (* `Permanent *) No_deletion of Signature.Public_key_hash.t + | (* `Temporary *) Current_delegate + + let () = + register_error_kind + `Permanent + ~id:"delegate.no_deletion" + ~title:"Forbidden delegate deletion" + ~description:"Tried to unregister a delegate" + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "Delegate deletion is forbidden (%a)" + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function No_deletion c -> Some c | _ -> None) + (fun c -> No_deletion c) ; + register_error_kind + `Temporary + ~id:"delegate.unchanged" + ~title:"Unchanged delegated" + ~description:"Contract already delegated to the given delegate" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The contract is already delegated to the same delegate") + Data_encoding.empty + (function Current_delegate -> Some () | _ -> None) + (fun () -> Current_delegate) + let set_delegate c contract delegate = let open Lwt_tzresult_syntax in let* () = @@ -326,3 +282,9 @@ module Contract = struct set_self_delegate c delegate | _ -> set_delegate c contract delegate end + +let pubkey ctxt pkh = + Contract_manager_storage.get_manager_key + ~error:(Contract.Unregistered_delegate pkh) + ctxt + pkh diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 885f3e097ea8..8096594f8fab 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -25,19 +25,7 @@ (* *) (*****************************************************************************) -type error += - | (* `Permanent *) No_deletion of Signature.Public_key_hash.t - | (* `Temporary *) Active_delegate - | (* `Temporary *) Current_delegate - | (* `Permanent *) Empty_delegate_account of Signature.Public_key_hash.t - | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t - | (* `Permanent *) Unassigned_validation_slot_for_level of Level_repr.t * int - | (* `Permanent *) - Cannot_find_active_stake of { - cycle : Cycle_repr.t; - delegate : Signature.Public_key_hash.t; - } - | (* `Temporary *) Not_registered of Signature.Public_key_hash.t +type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t (** Has a delegate been registered in the delegate table? *) val registered : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t @@ -98,6 +86,13 @@ val full_balance : Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t module Contract : sig + type error += + | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t + | (* `Temporary *) Active_delegate + | (* `Permanent *) Empty_delegate_account of Signature.Public_key_hash.t + | (* `Permanent *) No_deletion of Signature.Public_key_hash.t + | (* `Temporary *) Current_delegate + (** [init ctxt contract delegate] registers a delegate when creating a contract. diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml index 086678fa2c54..bf50fdd56926 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_delegation.ml @@ -56,7 +56,7 @@ let expect_error err = function let expect_alpha_error err = expect_error (Environment.Ecoproto_error err) let expect_no_change_registered_delegate_pkh pkh = function - | Environment.Ecoproto_error (Delegate_storage.No_deletion pkh0) :: _ + | Environment.Ecoproto_error (Delegate_storage.Contract.No_deletion pkh0) :: _ when pkh0 = pkh -> return_unit | _ -> failwith "Delegate can not be deleted and operation should fail." @@ -204,7 +204,8 @@ let bootstrap_manager_already_registered_delegate ~fee () = else Incremental.add_operation ~expect_apply_failure:(function - | Environment.Ecoproto_error Delegate_storage.Active_delegate :: _ -> + | Environment.Ecoproto_error Delegate_storage.Contract.Active_delegate + :: _ -> return_unit | _ -> failwith "Delegate is already active and operation should fail.") i @@ -441,7 +442,8 @@ let tests_bootstrap_contracts = two possibilities of 1a for non-credited contracts. *) let expect_unregistered_key pkh = function - | Environment.Ecoproto_error (Delegate_storage.Unregistered_delegate pkh0) + | Environment.Ecoproto_error + (Delegate_storage.Contract.Unregistered_delegate pkh0) :: _ when pkh = pkh0 -> return_unit -- GitLab From 7babbbb1d7d115f8f176420ca2229a7d95eb4847 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Tue, 10 May 2022 02:57:07 +0200 Subject: [PATCH 17/42] Proto: add some doc for `Delegate_storage` --- .../delegate_missed_endorsements_storage.ml | 4 ++++ src/proto_alpha/lib_protocol/delegate_sampler.ml | 7 +++++++ .../lib_protocol/delegate_slashed_deposits_storage.ml | 4 ++++ src/proto_alpha/lib_protocol/delegate_storage.ml | 11 +++++++++++ 4 files changed, 26 insertions(+) diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml index 96d22c2888cd..7869cfca16ec 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -25,6 +25,10 @@ (* *) (*****************************************************************************) +(** This module is responsible for: + - [Storage.Contract.Missed_endorsements] +*) + let expected_slots_for_given_active_stake ctxt ~total_active_stake ~active_stake = let blocks_per_cycle = diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 71b837b7ef60..9d5af86363fd 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -25,6 +25,13 @@ (* *) (*****************************************************************************) +(** This module is responsible for: + - [Storage.Seed.For_cycle] + + And the submodule `Delegate_sampler_state` is responsible for: + - [Storage.Delegate_sampler_state] +*) + module Delegate_sampler_state = struct module Cache_client = struct type cached_value = 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 043f8c117346..c3975dc709c0 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -25,6 +25,10 @@ (* *) (*****************************************************************************) +(** This module is responsible for: + - [Storage.Slashed_deposits] +*) + let check_and_record_already_slashed_for_double_baking ctxt delegate (level : Level_repr.t) = let open Lwt_tzresult_syntax in diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index cc7509a47399..daa8c60c0a06 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -25,6 +25,17 @@ (* *) (*****************************************************************************) +(** This is module regroups everything related to delegate registration + (see the invariant maintained by the submodule `Contract`. + + It also regroups "trivial" getter/setter related to delegates. + + It is responsible for: + - [Storage.Contract.Frozen_deposits_limit] + - [Storage.Delegates] + +*) + type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t let () = -- GitLab From c44edd0dfedeaaeea00208024e55f97eccdbd088 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 16 May 2022 11:16:32 +0200 Subject: [PATCH 18/42] Proto: merge `Delegate.check_and_record_...` into `punish` --- .../lib_protocol/alpha_context.mli | 8 +- src/proto_alpha/lib_protocol/apply.ml | 29 +--- .../delegate_slashed_deposits_storage.ml | 130 ++++++++++-------- .../delegate_slashed_deposits_storage.mli | 40 +++--- 4 files changed, 97 insertions(+), 110 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index d53139b193e4..e4cc05df4326 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2269,20 +2269,16 @@ module Delegate : sig Cycle.t -> (context * Receipt.balance_updates * public_key_hash list) tzresult Lwt.t - val check_and_record_already_slashed_for_double_endorsing : - context -> public_key_hash -> Level.t -> (context * bool) tzresult Lwt.t - - val check_and_record_already_slashed_for_double_baking : - context -> public_key_hash -> Level.t -> (context * bool) tzresult Lwt.t - val punish_double_endorsing : context -> public_key_hash -> + Level.t -> (context * Tez.t * Receipt.balance_updates) tzresult Lwt.t val punish_double_baking : context -> public_key_hash -> + Level.t -> (context * Tez.t * Receipt.balance_updates) tzresult Lwt.t val full_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 62e8ca461a08..d78690abc55c 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -108,7 +108,6 @@ type error += delegate1 : Signature.Public_key_hash.t; delegate2 : Signature.Public_key_hash.t; } - | Unrequired_denunciation | Too_early_denunciation of { kind : denunciation_kind; level : Raw_level.t; @@ -619,19 +618,6 @@ let () = | _ -> None) (fun (kind, delegate1, delegate2) -> Inconsistent_denunciation {kind; delegate1; delegate2}) ; - register_error_kind - `Branch - ~id:"block.unrequired_denunciation" - ~title:"Unrequired denunciation" - ~description:"A denunciation is unrequired" - ~pp:(fun ppf _ -> - Format.fprintf - ppf - "A valid denunciation cannot be applied: the associated delegate has \ - already been denounced for this level.") - Data_encoding.unit - (function Unrequired_denunciation -> Some () | _ -> None) - (fun () -> Unrequired_denunciation) ; register_error_kind `Temporary ~id:"block.too_early_denunciation" @@ -2860,19 +2846,12 @@ let check_denunciation_age ctxt kind given_level = {kind; level = given_level; last_cycle = last_slashable_cycle}) let punish_delegate ctxt delegate level mistake mk_result ~payload_producer = - let check_and_record_already_slashed, punish = + let punish = match mistake with - | `Double_baking -> - ( Delegate.check_and_record_already_slashed_for_double_baking, - Delegate.punish_double_baking ) - | `Double_endorsing -> - ( Delegate.check_and_record_already_slashed_for_double_endorsing, - Delegate.punish_double_endorsing ) + | `Double_baking -> Delegate.punish_double_baking + | `Double_endorsing -> Delegate.punish_double_endorsing in - check_and_record_already_slashed ctxt delegate level - >>=? fun (ctxt, slashed) -> - fail_when slashed Unrequired_denunciation >>=? fun () -> - punish ctxt delegate >>=? fun (ctxt, burned, punish_balance_updates) -> + punish ctxt delegate level >>=? fun (ctxt, burned, punish_balance_updates) -> (match Tez.(burned /? 2L) with | Ok reward -> Token.transfer 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 c3975dc709c0..a67b302e57ba 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -29,58 +29,46 @@ - [Storage.Slashed_deposits] *) -let check_and_record_already_slashed_for_double_baking ctxt delegate - (level : Level_repr.t) = - let open Lwt_tzresult_syntax in - let* slashed = - Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) - in - let already_slashed, updated_slashed = - match slashed with - | None -> - (false, {Storage.for_double_baking = true; for_double_endorsing = false}) - | Some slashed -> - (slashed.for_double_baking, {slashed with for_double_baking = true}) - in - let*! ctxt = - Storage.Slashed_deposits.add - (ctxt, level.cycle) - (level.level, delegate) - updated_slashed - in - return (ctxt, already_slashed) +type error += Unrequired_denunciation + +let () = + register_error_kind + `Branch + ~id:"block.unrequired_denunciation" + ~title:"Unrequired denunciation" + ~description:"A denunciation is unrequired" + ~pp:(fun ppf _ -> + Format.fprintf + ppf + "A valid denunciation cannot be applied: the associated delegate has \ + already been denounced for this level.") + Data_encoding.unit + (function Unrequired_denunciation -> Some () | _ -> None) + (fun () -> Unrequired_denunciation) -let check_and_record_already_slashed_for_double_endorsing ctxt delegate - (level : Level_repr.t) = +let clear_outdated_slashed_deposits ctxt ~new_cycle = + let max_slashable_period = Constants_storage.max_slashing_period ctxt in + match Cycle_repr.(sub new_cycle max_slashable_period) with + | None -> Lwt.return ctxt + | Some outdated_cycle -> Storage.Slashed_deposits.clear (ctxt, outdated_cycle) + +let punish_double_endorsing ctxt delegate (level : Level_repr.t) = let open Lwt_tzresult_syntax in let* slashed = Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) in - let already_slashed, updated_slashed = + let* updated_slashed = match slashed with | None -> - (false, {Storage.for_double_endorsing = true; for_double_baking = false}) + return {Storage.for_double_endorsing = true; for_double_baking = false} | Some slashed -> - ( slashed.for_double_endorsing, - {slashed with for_double_endorsing = true} ) - in - let*! ctxt = - Storage.Slashed_deposits.add - (ctxt, level.cycle) - (level.level, delegate) - updated_slashed + let* () = + fail_when slashed.for_double_endorsing Unrequired_denunciation + in + return {slashed with for_double_endorsing = true} in - return (ctxt, already_slashed) - -let clear_outdated_slashed_deposits ctxt ~new_cycle = - let max_slashable_period = Constants_storage.max_slashing_period ctxt in - match Cycle_repr.(sub new_cycle max_slashable_period) with - | None -> Lwt.return ctxt - | Some outdated_cycle -> Storage.Slashed_deposits.clear (ctxt, outdated_cycle) - -let punish_double_endorsing ctxt delegate = let delegate_contract = Contract_repr.Implicit delegate in - Frozen_deposits_storage.get ctxt delegate_contract >>=? fun frozen_deposits -> + let* frozen_deposits = Frozen_deposits_storage.get ctxt delegate_contract in let slashing_ratio : Ratio_repr.t = Constants_storage.ratio_of_frozen_deposits_slashed_per_double_endorsement ctxt @@ -94,29 +82,55 @@ let punish_double_endorsing ctxt delegate = let amount_to_burn = Tez_repr.(min frozen_deposits.current_amount punish_value) in - Token.transfer - ctxt - (`Frozen_deposits delegate) - `Double_signing_punishments - amount_to_burn - >>=? fun (ctxt, balance_updates) -> - Stake_storage.remove_stake ctxt delegate amount_to_burn >>=? fun ctxt -> + let* ctxt, balance_updates = + Token.transfer + ctxt + (`Frozen_deposits delegate) + `Double_signing_punishments + amount_to_burn + in + let* ctxt = Stake_storage.remove_stake ctxt delegate amount_to_burn in + let*! ctxt = + Storage.Slashed_deposits.add + (ctxt, level.cycle) + (level.level, delegate) + updated_slashed + in return (ctxt, amount_to_burn, balance_updates) -let punish_double_baking ctxt delegate = +let punish_double_baking ctxt delegate (level : Level_repr.t) = + let open Lwt_tzresult_syntax in + let* slashed = + Storage.Slashed_deposits.find (ctxt, level.cycle) (level.level, delegate) + in + let* updated_slashed = + match slashed with + | None -> + return {Storage.for_double_baking = true; for_double_endorsing = false} + | Some slashed -> + let* () = fail_when slashed.for_double_baking Unrequired_denunciation in + return {slashed with for_double_baking = true} + in let delegate_contract = Contract_repr.Implicit delegate in - Frozen_deposits_storage.get ctxt delegate_contract >>=? fun frozen_deposits -> + let* frozen_deposits = Frozen_deposits_storage.get ctxt delegate_contract in let slashing_for_one_block = Constants_storage.double_baking_punishment ctxt in let amount_to_burn = Tez_repr.(min frozen_deposits.current_amount slashing_for_one_block) in - Token.transfer - ctxt - (`Frozen_deposits delegate) - `Double_signing_punishments - amount_to_burn - >>=? fun (ctxt, balance_updates) -> - Stake_storage.remove_stake ctxt delegate amount_to_burn >>=? fun ctxt -> + let* ctxt, balance_updates = + Token.transfer + ctxt + (`Frozen_deposits delegate) + `Double_signing_punishments + amount_to_burn + in + let* ctxt = Stake_storage.remove_stake ctxt delegate amount_to_burn in + let*! ctxt = + Storage.Slashed_deposits.add + (ctxt, level.cycle) + (level.level, delegate) + updated_slashed + in return (ctxt, amount_to_burn, balance_updates) diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli index 474456f6c49d..189a37d29011 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli @@ -25,37 +25,35 @@ (* *) (*****************************************************************************) -(** Burn some frozen deposit for a delegate at a given level. Returns - the burned amount. *) -val punish_double_endorsing : - Raw_context.t -> - Signature.Public_key_hash.t -> - (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t +type error += Unrequired_denunciation -val punish_double_baking : - Raw_context.t -> - Signature.Public_key_hash.t -> - (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t +(** Burn some frozen deposit for a delegate at a given level and + record in the context that the given delegate has now been slashed + for double endorsing for the given level. + + Returns the burned amount. -(** Returns true if the given delegate has already been slashed - for double baking for the given level, and record in the context - that the given delegate has now been slashed for double baking - for the given level. *) -val check_and_record_already_slashed_for_double_baking : + Fails with [Unrequired_denunciation] if the given delegate has + already been slashed for double endorsing for the given level. *) +val punish_double_endorsing : Raw_context.t -> Signature.Public_key_hash.t -> Level_repr.t -> - (Raw_context.t * bool) tzresult Lwt.t + (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t -(** Returns true if the given delegate has already been slashed for - double preendorsing or double endorsing for the given level, and +(** Burn some frozen deposit for a delegate at a given level and record in the context that the given delegate has now been slashed - for double preendorsing or double endorsing for the given level. *) -val check_and_record_already_slashed_for_double_endorsing : + for double baking for the given level. + + Returns the burned amount. + + Fails with [Unrequired_denunciation] if the given delegate has + already been slashed for double baking for the given level. *) +val punish_double_baking : Raw_context.t -> Signature.Public_key_hash.t -> Level_repr.t -> - (Raw_context.t * bool) tzresult Lwt.t + (Raw_context.t * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t val clear_outdated_slashed_deposits : Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t Lwt.t -- GitLab From 7fb8bb4e88d209aa910be2a6cdbf961569ba489c Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 2 Jun 2022 12:59:20 +0200 Subject: [PATCH 19/42] Proto: add doc strings to delegate-related modules --- .../contract_delegate_storage.mli | 3 +++ .../delegate_activation_storage.mli | 11 ++++++----- .../delegate_missed_endorsements_storage.ml | 4 ---- .../delegate_missed_endorsements_storage.mli | 5 +++++ .../lib_protocol/delegate_sampler.ml | 7 ------- .../lib_protocol/delegate_sampler.mli | 10 ++++++++++ .../delegate_slashed_deposits_storage.ml | 4 ---- .../delegate_slashed_deposits_storage.mli | 4 ++++ .../lib_protocol/delegate_storage.ml | 16 ---------------- .../lib_protocol/delegate_storage.mli | 19 +++++++++++++++++++ .../lib_protocol/stake_storage.mli | 12 ++++++++++-- 11 files changed, 57 insertions(+), 38 deletions(-) diff --git a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli index 7fe992903bc0..a0c97c1c5349 100644 --- a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli @@ -23,6 +23,9 @@ (* *) (*****************************************************************************) +(** This module deals with the delegates of a contract. It is responsible for + maintaining the table {!Storage.Contract.Delegate}. *) + (** [find ctxt contract] returns the delegate associated to [contract], or [None] if [contract] has no delegate. *) val find : diff --git a/src/proto_alpha/lib_protocol/delegate_activation_storage.mli b/src/proto_alpha/lib_protocol/delegate_activation_storage.mli index 9f5f0e47969a..911bf6c30b08 100644 --- a/src/proto_alpha/lib_protocol/delegate_activation_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_activation_storage.mli @@ -23,12 +23,13 @@ (* *) (*****************************************************************************) -(** This module provides functions related to delegates' activity. +(** This module deals with delegates' activity. Typically, the provided + functions can be used to deactivate a delegate that has not shown activity + for a certain number of cycles, and to reactivate it when appropriate. - Typically, they can be used to deactivate a delegate that has not shown - activity for a certain number of cycles, and to reactivate it when - appropriate. -*) + This module is responsible for maintaining the following tables: + - {!Storage.Contract.Inactive_delegate} + - {!Storage.Contract.Delegate_last_cycle_before_deactivation} *) val is_inactive : Raw_context.t -> Signature.Public_key_hash.t -> bool tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml index 7869cfca16ec..96d22c2888cd 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -25,10 +25,6 @@ (* *) (*****************************************************************************) -(** This module is responsible for: - - [Storage.Contract.Missed_endorsements] -*) - let expected_slots_for_given_active_stake ctxt ~total_active_stake ~active_stake = let blocks_per_cycle = diff --git a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli index d2267d33a6a3..03ce915c9fd7 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.mli @@ -25,6 +25,11 @@ (* *) (*****************************************************************************) +(** This modules deals with delegates' participation in consensus. + + This module is responsible for maintaining the + {!Storage.Contract.Missed_endorsements} table. *) + val expected_slots_for_given_active_stake : Raw_context.t -> total_active_stake:Tez_repr.tez -> diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 9d5af86363fd..71b837b7ef60 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -25,13 +25,6 @@ (* *) (*****************************************************************************) -(** This module is responsible for: - - [Storage.Seed.For_cycle] - - And the submodule `Delegate_sampler_state` is responsible for: - - [Storage.Delegate_sampler_state] -*) - module Delegate_sampler_state = struct module Cache_client = struct type cached_value = diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.mli b/src/proto_alpha/lib_protocol/delegate_sampler.mli index 194c5a50468b..cf4cf8dc6bd9 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.mli +++ b/src/proto_alpha/lib_protocol/delegate_sampler.mli @@ -25,6 +25,16 @@ (* *) (*****************************************************************************) +(** This module draws random values for a cycle based on the {!Seed_repr.seed} + associated that cycle. These random values are: + - delegates associated with slots + - snapshot indexes. + The selection of delegates is done by {i sampling} from a particular + distribution of the stake among the active delegates. + + This module is responsible for maintaining the tables + {!Storage.Delegate_sampler_state} and {!Storage.Seed.For_cycle}. *) + (** Participation slots potentially associated to accounts. The accounts that didn't place a deposit will be excluded from this list. This function should only be used to compute the deposits to 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 a67b302e57ba..3601db429048 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.ml @@ -25,10 +25,6 @@ (* *) (*****************************************************************************) -(** This module is responsible for: - - [Storage.Slashed_deposits] -*) - type error += Unrequired_denunciation let () = diff --git a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli index 189a37d29011..236be3438db2 100644 --- a/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_slashed_deposits_storage.mli @@ -25,6 +25,10 @@ (* *) (*****************************************************************************) +(** This module maintains the storage related to slashing of delegates for + double signing. In particular, it is responsible for maintaining the + {!Storage.Slashed_deposits} table. *) + type error += Unrequired_denunciation (** Burn some frozen deposit for a delegate at a given level and diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index daa8c60c0a06..41a367cbbf5c 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -25,17 +25,6 @@ (* *) (*****************************************************************************) -(** This is module regroups everything related to delegate registration - (see the invariant maintained by the submodule `Contract`. - - It also regroups "trivial" getter/setter related to delegates. - - It is responsible for: - - [Storage.Contract.Frozen_deposits_limit] - - [Storage.Delegates] - -*) - type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t let () = @@ -109,11 +98,6 @@ let full_balance ctxt delegate = Lwt.return Tez_repr.(frozen_deposits.current_amount +? balance_and_frozen_bonds) -(** This module ensures the following invariants: - - registered delegates are self-delegated and appears in `Storage.Delegate`, - i.e. registered delegate cannot change their delegation - - stake is properly moved when changing delegation. -*) module Contract = struct type error += | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 8096594f8fab..42db919d947e 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -25,6 +25,16 @@ (* *) (*****************************************************************************) +(** This module groups everything related to delegate registration. + For the invariants maintained, see the submodule {!Contract}. + + It also groups "trivial" getters/setters related to delegates. + + It is responsible for maintaining the following tables: + - {!Storage.Contract.Frozen_deposits_limit} + - {!Storage.Delegates} +*) + type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t (** Has a delegate been registered in the delegate table? *) @@ -85,6 +95,13 @@ val delegated_balance : val full_balance : Raw_context.t -> Signature.Public_key_hash.t -> Tez_repr.t tzresult Lwt.t +(** This module ensures the following invariants: + - registered delegates (i.e. those that appear in {!Storage.Delegates}) are + self-delegated (i.e. {!Contract_delegate_storage.find} [delegate] returns [delegate]), + - registered delegates have their public keys revealed, + - registered delegates cannot change their delegation, + - stake is properly moved when changing delegation. +*) module Contract : sig type error += | (* `Permanent *) Unregistered_delegate of Signature.Public_key_hash.t @@ -123,6 +140,8 @@ module Contract : sig Raw_context.t tzresult Lwt.t end +(** Returns the public key of a registered delegate. Returns the error + {!Contract.Unregistered_delegate} if the delegate is not registered. *) val pubkey : Raw_context.t -> Signature.Public_key_hash.t -> diff --git a/src/proto_alpha/lib_protocol/stake_storage.mli b/src/proto_alpha/lib_protocol/stake_storage.mli index e41693973461..49774f23d3aa 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.mli +++ b/src/proto_alpha/lib_protocol/stake_storage.mli @@ -23,8 +23,16 @@ (* *) (*****************************************************************************) -(** This library provides basic operations (accessors and setters) on - staking tokens. *) +(** This module provides basic operations (accessors and setters) on + staking tokens. + + It is responsible for maintaining the following tables: + - {!Storage.Stake.Selected_distribution_for_cycle} + - {!Storage.Stake.Staking_balance} + - {!Storage.Stake.Active_delegate_with_one_roll} + - {!Storage.Stake.Last_snapshot} + - {!Storage.Total_active_stake} +*) val remove_stake : Raw_context.t -> -- GitLab From dc1823a4394b7e24e2a42aece613ed72407f684a Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 2 Jun 2022 13:08:38 +0200 Subject: [PATCH 20/42] Proto: move Total_active_stake into Stake for consistency --- src/proto_alpha/lib_protocol/stake_storage.ml | 6 +++--- src/proto_alpha/lib_protocol/stake_storage.mli | 2 +- src/proto_alpha/lib_protocol/storage.ml | 2 +- src/proto_alpha/lib_protocol/storage.mli | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index c668430b87bd..ec4442592ac5 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.ml +++ b/src/proto_alpha/lib_protocol/stake_storage.ml @@ -134,14 +134,14 @@ let max_snapshot_index = Storage.Stake.Last_snapshot.get let set_selected_distribution_for_cycle ctxt cycle stakes total_stake = let stakes = List.sort (fun (_, x) (_, y) -> Tez_repr.compare y x) stakes in Selected_distribution_for_cycle.init ctxt cycle stakes >>=? fun ctxt -> - Storage.Total_active_stake.add ctxt cycle total_stake >>= fun ctxt -> + Storage.Stake.Total_active_stake.add ctxt cycle total_stake >>= fun ctxt -> (* cleanup snapshots *) Storage.Stake.Staking_balance.Snapshot.clear ctxt >>= fun ctxt -> Storage.Stake.Active_delegate_with_one_roll.Snapshot.clear ctxt >>= fun ctxt -> Storage.Stake.Last_snapshot.update ctxt 0 let clear_cycle ctxt cycle = - Storage.Total_active_stake.remove_existing ctxt cycle >>=? fun ctxt -> + Storage.Stake.Total_active_stake.remove_existing ctxt cycle >>=? fun ctxt -> Selected_distribution_for_cycle.remove_existing ctxt cycle let fold ctxt ~f ~order init = @@ -197,7 +197,7 @@ let prepare_stake_distribution ctxt = ctxt stake_distribution) -let get_total_active_stake = Storage.Total_active_stake.get +let get_total_active_stake = Storage.Stake.Total_active_stake.get let remove_contract_stake ctxt contract amount = Contract_delegate_storage.find ctxt contract >>=? function diff --git a/src/proto_alpha/lib_protocol/stake_storage.mli b/src/proto_alpha/lib_protocol/stake_storage.mli index 49774f23d3aa..aad1f9dfdc29 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.mli +++ b/src/proto_alpha/lib_protocol/stake_storage.mli @@ -31,7 +31,7 @@ - {!Storage.Stake.Staking_balance} - {!Storage.Stake.Active_delegate_with_one_roll} - {!Storage.Stake.Last_snapshot} - - {!Storage.Total_active_stake} + - {!Storage.Stake.Total_active_stake} *) val remove_stake : diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index f5f916ec2278..797fb61c3d0a 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1063,6 +1063,7 @@ module Stake = struct end) module Selected_distribution_for_cycle = Cycle.Selected_stake_distribution + module Total_active_stake = Cycle.Total_active_stake (* This is an index that is set to 0 by calls to {!val:Stake_storage.selected_new_distribution_at_cycle_end} and incremented @@ -1088,7 +1089,6 @@ module Stake = struct (Encoding.UInt16) end -module Total_active_stake = Cycle.Total_active_stake module Delegate_sampler_state = Cycle.Delegate_sampler_state (** Votes *) diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index e6aa79faa30a..9a67e8c74caf 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -383,14 +383,14 @@ module Stake : sig with type key = Cycle_repr.t and type value = (Signature.Public_key_hash.t * Tez_repr.t) list and type t := Raw_context.t -end -(** Sum of the active stakes of all the delegates with rolls *) -module Total_active_stake : - Indexed_data_storage - with type key = Cycle_repr.t - and type value = Tez_repr.t - and type t := Raw_context.t + (** Sum of the active stakes of all the delegates with rolls *) + module Total_active_stake : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Tez_repr.t + and type t := Raw_context.t +end (** State of the sampler used to select delegates. Managed synchronously with [Stake.Selected_distribution_for_cycle]. *) -- GitLab From 52035633eabb413a4eb6aa2d1ae1db206b615159 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 2 Jun 2022 15:20:58 +0200 Subject: [PATCH 21/42] Proto: access seeds only through Seed_storage --- src/proto_alpha/lib_protocol/alpha_context.ml | 2 ++ .../lib_protocol/delegate_sampler.ml | 9 ++++---- .../lib_protocol/delegate_sampler.mli | 4 ++-- src/proto_alpha/lib_protocol/seed_storage.ml | 8 ++++--- src/proto_alpha/lib_protocol/seed_storage.mli | 22 ++++++++++++++++--- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 0908294beb9d..b56c77663948 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -473,6 +473,8 @@ module Nonce = Nonce_storage module Seed = struct include Seed_repr include Seed_storage + + let for_cycle = for_cycle_with_checks end module Fitness = struct diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 71b837b7ef60..2912e019dfad 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -118,7 +118,7 @@ module Random = struct [Raw_context.set_sampler_for_cycle]. *) let sampler_for_cycle ctxt cycle = let read ctxt = - Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> + Seed_storage.for_cycle ctxt cycle >>=? fun seed -> Delegate_sampler_state.get ctxt cycle >>=? fun state -> return (seed, state) in @@ -199,12 +199,12 @@ let compute_snapshot_index_for_seed ~max_snapshot_index seed = |> fst |> Int32.to_int |> return let compute_snapshot_index ctxt cycle ~max_snapshot_index = - Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> + Seed_storage.for_cycle ctxt cycle >>=? fun seed -> compute_snapshot_index_for_seed ~max_snapshot_index seed let select_distribution_for_cycle ctxt cycle = Stake_storage.max_snapshot_index ctxt >>=? fun max_snapshot_index -> - Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> + Seed_storage.for_cycle ctxt cycle >>=? fun seed -> compute_snapshot_index_for_seed ~max_snapshot_index seed >>=? fun selected_index -> get_stakes_for_selected_index ctxt selected_index @@ -238,5 +238,4 @@ let clear_outdated_sampling_data ctxt ~new_cycle = | None -> return ctxt | Some outdated_cycle -> Delegate_sampler_state.remove_existing ctxt outdated_cycle - >>=? fun ctxt -> - Storage.Seed.For_cycle.remove_existing ctxt outdated_cycle + >>=? fun ctxt -> Seed_storage.remove_for_cycle ctxt outdated_cycle diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.mli b/src/proto_alpha/lib_protocol/delegate_sampler.mli index cf4cf8dc6bd9..b011b056c2b6 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.mli +++ b/src/proto_alpha/lib_protocol/delegate_sampler.mli @@ -32,8 +32,8 @@ The selection of delegates is done by {i sampling} from a particular distribution of the stake among the active delegates. - This module is responsible for maintaining the tables - {!Storage.Delegate_sampler_state} and {!Storage.Seed.For_cycle}. *) + This module is responsible for maintaining the table + {!Storage.Delegate_sampler_state}. *) (** Participation slots potentially associated to accounts. The accounts that didn't place a deposit will be excluded from this diff --git a/src/proto_alpha/lib_protocol/seed_storage.ml b/src/proto_alpha/lib_protocol/seed_storage.ml index 0985e678da7a..c9b5d55fffcf 100644 --- a/src/proto_alpha/lib_protocol/seed_storage.ml +++ b/src/proto_alpha/lib_protocol/seed_storage.ml @@ -30,8 +30,6 @@ type error += latest : Cycle_repr.t; } -(* `Permanent *) - let () = register_error_kind `Permanent @@ -87,7 +85,9 @@ let compute_for_cycle c ~revealed cycle = >>=? fun (c, seed, unrevealed) -> Storage.Seed.For_cycle.init c cycle seed >|=? fun c -> (c, unrevealed) -let for_cycle ctxt cycle = +let for_cycle = Storage.Seed.For_cycle.get + +let for_cycle_with_checks ctxt cycle = let preserved = Constants_storage.preserved_cycles ctxt in let current_level = Level_storage.current ctxt in let current_cycle = current_level.cycle in @@ -125,3 +125,5 @@ let cycle_end ctxt last_cycle = (* cycle with revelations *) let inited_seed_cycle = Cycle_repr.add last_cycle (preserved + 1) in compute_for_cycle ctxt ~revealed inited_seed_cycle + +let remove_for_cycle = Storage.Seed.For_cycle.remove_existing diff --git a/src/proto_alpha/lib_protocol/seed_storage.mli b/src/proto_alpha/lib_protocol/seed_storage.mli index de05bd8a4bb1..236365d1352a 100644 --- a/src/proto_alpha/lib_protocol/seed_storage.mli +++ b/src/proto_alpha/lib_protocol/seed_storage.mli @@ -23,22 +23,33 @@ (* *) (*****************************************************************************) +(** This modules handles the storage of random nonce seeds. + + This module is responsible for maintaining the table + {!Storage.Seed.For_cycle}. *) + type error += - | Unknown of { + | (* `Permanent *) + Unknown of { oldest : Cycle_repr.t; cycle : Cycle_repr.t; latest : Cycle_repr.t; } -(* `Permanent *) - (** Generates the first [preserved_cycles+2] seeds for which there are no nonces. *) val init : ?initial_seed:State_hash.t -> Raw_context.t -> Raw_context.t tzresult Lwt.t +(** Returns the seed associated with the given cycle. Returns a generic storage + error when the seed is not available. *) val for_cycle : Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t +(** Returns the seed associated with the given cycle. Returns the {!Unknown} + error when the seed is not available. *) +val for_cycle_with_checks : + Raw_context.t -> Cycle_repr.t -> Seed_repr.seed tzresult Lwt.t + (** If it is the end of the cycle, computes and stores the seed of cycle at distance [preserved_cycle+2] in the future using the seed of the previous cycle and the revelations of the current one. *) @@ -46,3 +57,8 @@ val cycle_end : Raw_context.t -> Cycle_repr.t -> (Raw_context.t * Nonce_storage.unrevealed list) tzresult Lwt.t + +(** Removes the seed associated with the given cycle from the storage. It + assumes the seed exists. If it does not it returns a generic storage error. *) +val remove_for_cycle : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t -- GitLab From 761e9b359ebafd4f391ac52b5932791630bdf61e Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Fri, 3 Jun 2022 14:59:27 +0200 Subject: [PATCH 22/42] Proto: move Not_registered error to Delegate_services --- .../client_proto_context_commands.ml | 6 ++- .../lib_protocol/alpha_context.mli | 2 - .../lib_protocol/delegate_services.ml | 54 ++++++++++++++----- .../lib_protocol/delegate_services.mli | 2 + .../lib_protocol/delegate_storage.ml | 28 ---------- .../lib_protocol/delegate_storage.mli | 6 --- 6 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index 0553bc9a97bd..ba32ccbd17f0 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -1530,7 +1530,8 @@ let commands_rw () = >>= function | Ok voting_power -> return (voting_power <> 0L) | Error - (Environment.Ecoproto_error (Delegate_storage.Not_registered _) + (Environment.Ecoproto_error + (Delegate_services.Not_registered _) :: _) -> return false | Error _ as err -> Lwt.return err) @@ -1723,7 +1724,8 @@ let commands_rw () = >>= function | Ok voting_power -> return (voting_power <> 0L) | Error - (Environment.Ecoproto_error (Delegate_storage.Not_registered _) + (Environment.Ecoproto_error + (Delegate_services.Not_registered _) :: _) -> return false | Error _ as err -> Lwt.return err) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index e4cc05df4326..905de2577a38 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2250,8 +2250,6 @@ module Delegate : sig val list : context -> public_key_hash list Lwt.t - val check_registered : context -> public_key_hash -> unit tzresult Lwt.t - type participation_info = { expected_cycle_activity : int; minimal_cycle_activity : int; diff --git a/src/proto_alpha/lib_protocol/delegate_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index f05ee611020b..306c91216444 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -29,6 +29,29 @@ open Alpha_context type error += Balance_rpc_non_delegate of public_key_hash +type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t + +let () = + register_error_kind + `Temporary + ~id:"delegate.not_registered" + ~title:"Not a registered delegate" + ~description: + "The provided public key hash is not the address of a registered \ + delegate." + ~pp:(fun ppf pkh -> + Format.fprintf + ppf + "The provided public key hash (%a) is not the address of a registered \ + delegate. If you own this account and want to register it as a \ + delegate, use a delegation operation to delegate the account to \ + itself." + Signature.Public_key_hash.pp + pkh) + Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding)) + (function Not_registered pkh -> Some pkh | _ -> None) + (fun pkh -> Not_registered pkh) + let () = register_error_kind `Temporary @@ -332,6 +355,11 @@ module S = struct RPC_path.(path / "participation") end +let check_delegate_registered ctxt pkh = + Delegate.registered ctxt pkh >>= function + | true -> return_unit + | false -> fail (Not_registered pkh) + let register () = let open Services_registration in register0 ~chunked:true S.list_delegate (fun ctxt q () -> @@ -366,7 +394,7 @@ let register () = | {with_minimal_stake = false; without_minimal_stake = false; _} -> return delegates) ; register1 ~chunked:false S.info (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.full_balance ctxt pkh >>=? fun full_balance -> Delegate.frozen_deposits ctxt pkh >>=? fun frozen_deposits -> Delegate.staking_balance ctxt pkh >>=? fun staking_balance -> @@ -389,42 +417,42 @@ let register () = voting_info; }) ; register1 ~chunked:false S.full_balance (fun ctxt pkh () () -> - trace (Balance_rpc_non_delegate pkh) (Delegate.check_registered ctxt pkh) + trace (Balance_rpc_non_delegate pkh) (check_delegate_registered ctxt pkh) >>=? fun () -> Delegate.full_balance ctxt pkh) ; register1 ~chunked:false S.current_frozen_deposits (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.frozen_deposits ctxt pkh >>=? fun deposits -> return deposits.current_amount) ; register1 ~chunked:false S.frozen_deposits (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.frozen_deposits ctxt pkh >>=? fun deposits -> return deposits.initial_amount) ; register1 ~chunked:false S.staking_balance (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.staking_balance ctxt pkh) ; register1 ~chunked:false S.frozen_deposits_limit (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.frozen_deposits_limit ctxt pkh) ; register1 ~chunked:true S.delegated_contracts (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.delegated_contracts ctxt pkh >|= ok) ; register1 ~chunked:false S.delegated_balance (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.delegated_balance ctxt pkh) ; register1 ~chunked:false S.deactivated (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.deactivated ctxt pkh) ; register1 ~chunked:false S.grace_period (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.last_cycle_before_deactivation ctxt pkh) ; register1 ~chunked:false S.voting_power (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Vote.get_voting_power_free ctxt pkh) ; register1 ~chunked:false S.voting_info (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Vote.get_delegate_info ctxt pkh) ; register1 ~chunked:false S.participation (fun ctxt pkh () () -> - Delegate.check_registered ctxt pkh >>=? fun () -> + check_delegate_registered ctxt pkh >>=? fun () -> Delegate.participation_info ctxt pkh) let list ctxt block ?(active = true) ?(inactive = false) diff --git a/src/proto_alpha/lib_protocol/delegate_services.mli b/src/proto_alpha/lib_protocol/delegate_services.mli index 8092f2c368cd..a5eda671e57d 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.mli +++ b/src/proto_alpha/lib_protocol/delegate_services.mli @@ -31,6 +31,8 @@ open Alpha_context +type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t + val list : 'a #RPC_context.simple -> 'a -> diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 41a367cbbf5c..6d38d9350119 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -25,36 +25,8 @@ (* *) (*****************************************************************************) -type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t - -let () = - register_error_kind - `Temporary - ~id:"delegate.not_registered" - ~title:"Not a registered delegate" - ~description: - "The provided public key hash is not the address of a registered \ - delegate." - ~pp:(fun ppf pkh -> - Format.fprintf - ppf - "The provided public key hash (%a) is not the address of a registered \ - delegate. If you own this account and want to register it as a \ - delegate, use a delegation operation to delegate the account to \ - itself." - Signature.Public_key_hash.pp - pkh) - Data_encoding.(obj1 (req "pkh" Signature.Public_key_hash.encoding)) - (function Not_registered pkh -> Some pkh | _ -> None) - (fun pkh -> Not_registered pkh) - let registered = Storage.Delegates.mem -let check_registered ctxt pkh = - registered ctxt pkh >>= function - | true -> return_unit - | false -> fail (Not_registered pkh) - let fold = Storage.Delegates.fold let list = Storage.Delegates.elements diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 42db919d947e..262a49ce3f52 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -35,15 +35,9 @@ - {!Storage.Delegates} *) -type error += (* `Temporary *) Not_registered of Signature.Public_key_hash.t - (** Has a delegate been registered in the delegate table? *) val registered : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t -(** Check that a given implicit account is a registered delegate. *) -val check_registered : - Raw_context.t -> Signature.Public_key_hash.t -> unit tzresult Lwt.t - (** Iterate on all registered delegates. *) val fold : Raw_context.t -> -- GitLab From cb3298ae2348125a9fe59c3b9d4840ef6da81168 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Fri, 3 Jun 2022 16:06:25 +0200 Subject: [PATCH 23/42] Proto: use a proper Permanent error for invalid ballot and proposals --- src/proto_alpha/lib_protocol/apply.ml | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index d78690abc55c..ebbb69b3991f 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -94,6 +94,8 @@ type error += } | Set_deposits_limit_on_unregistered_delegate of Signature.Public_key_hash.t | Set_deposits_limit_too_high of {limit : Tez.t; max_limit : Tez.t} + | Ballot_on_unregistered_delegate of Signature.Public_key_hash.t + | Proposals_on_unregistered_delegate of Signature.Public_key_hash.t | Empty_transaction of Contract.t | Tx_rollup_feature_disabled | Tx_rollup_invalid_transaction_ticket_amount @@ -449,6 +451,35 @@ let () = (function | Set_deposits_limit_on_unregistered_delegate c -> Some c | _ -> None) (fun c -> Set_deposits_limit_on_unregistered_delegate c) ; + register_error_kind + `Permanent + ~id:"operation.ballot_on_unregistered_delegate" + ~title:"Ballot with an unregistered delegate" + ~description:"Cannot cast a ballot with an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot cast a ballot for public key hash %a (unregistered delegate)." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Ballot_on_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Ballot_on_unregistered_delegate c) ; + register_error_kind + `Permanent + ~id:"operation.proposals_on_unregistered_delegate" + ~title:"Proposals with an unregistered delegate" + ~description:"Cannot submit proposals with an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot submit proposals for public key hash %a (unregistered \ + delegate)." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Proposals_on_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Proposals_on_unregistered_delegate c) ; register_error_kind `Permanent ~id:"operation.set_deposits_limit_too_high" @@ -3121,6 +3152,9 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode >>=? fun (ctxt, bupds) -> return (ctxt, Single_result (Activate_account_result bupds)) | Single (Proposals {source; period; proposals}) -> + Delegate.registered ctxt source >>= fun is_registered -> + error_unless is_registered (Proposals_on_unregistered_delegate source) + >>?= fun () -> Delegate.pubkey ctxt source >>=? fun delegate -> Operation.check_signature delegate chain_id operation >>?= fun () -> Voting_period.get_current ctxt >>=? fun {index = current_period; _} -> @@ -3131,6 +3165,9 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode Amendment.record_proposals ctxt source proposals >|=? fun ctxt -> (ctxt, Single_result Proposals_result) | Single (Ballot {source; period; proposal; ballot}) -> + Delegate.registered ctxt source >>= fun is_registered -> + error_unless is_registered (Ballot_on_unregistered_delegate source) + >>?= fun () -> Delegate.pubkey ctxt source >>=? fun delegate -> Operation.check_signature delegate chain_id operation >>?= fun () -> Voting_period.get_current ctxt >>=? fun {index = current_period; _} -> -- GitLab From 7a89e55a387cf9eb2f00a3f6252d10fcd814df67 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 24/42] Proto/Delegate: rename `pubkey` into `manager_pubkey` --- scripts/yes-wallet/yes_wallet_lib.ml | 2 +- src/proto_alpha/lib_protocol/alpha_context.mli | 5 ++++- src/proto_alpha/lib_protocol/apply.ml | 4 ++-- src/proto_alpha/lib_protocol/delegate_sampler.ml | 2 +- src/proto_alpha/lib_protocol/delegate_storage.ml | 2 +- src/proto_alpha/lib_protocol/delegate_storage.mli | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/scripts/yes-wallet/yes_wallet_lib.ml b/scripts/yes-wallet/yes_wallet_lib.ml index b49196122b25..9c3359aa2f0c 100644 --- a/scripts/yes-wallet/yes_wallet_lib.ml +++ b/scripts/yes-wallet/yes_wallet_lib.ml @@ -449,7 +449,7 @@ let get_delegates (proto : protocol) context ~init:(Ok ([], Alpha_context.Tez.zero)) ~f:(fun pkh acc -> let* pk = - let*! r = Alpha_context.Delegate.pubkey ctxt pkh in + let*! r = Alpha_context.Delegate.manager_pubkey ctxt pkh in Lwt.return @@ Environment.wrap_tzresult r in let*? key_list_acc, staking_balance_acc = acc in diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 905de2577a38..f47b61ba1c0d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2315,7 +2315,10 @@ module Delegate : sig val last_cycle_before_deactivation : context -> public_key_hash -> Cycle.t tzresult Lwt.t - val pubkey : context -> public_key_hash -> public_key tzresult Lwt.t + val manager_pubkey : + context -> + Signature.public_key_hash -> + Signature.Public_key.t tzresult Lwt.t val prepare_stake_distribution : context -> context tzresult Lwt.t end diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index ebbb69b3991f..d25c9f357702 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -3155,7 +3155,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode Delegate.registered ctxt source >>= fun is_registered -> error_unless is_registered (Proposals_on_unregistered_delegate source) >>?= fun () -> - Delegate.pubkey ctxt source >>=? fun delegate -> + Delegate.manager_pubkey ctxt source >>=? fun delegate -> Operation.check_signature delegate chain_id operation >>?= fun () -> Voting_period.get_current ctxt >>=? fun {index = current_period; _} -> error_unless @@ -3168,7 +3168,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode Delegate.registered ctxt source >>= fun is_registered -> error_unless is_registered (Ballot_on_unregistered_delegate source) >>?= fun () -> - Delegate.pubkey ctxt source >>=? fun delegate -> + Delegate.manager_pubkey ctxt source >>=? fun delegate -> Operation.check_signature delegate chain_id operation >>?= fun () -> Voting_period.get_current ctxt >>=? fun {index = current_period; _} -> error_unless diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 2912e019dfad..d6b4dca1c52f 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -217,7 +217,7 @@ let select_distribution_for_cycle ctxt cycle = >>=? fun ctxt -> List.fold_left_es (fun acc (pkh, stake) -> - Delegate_storage.pubkey ctxt pkh >|=? fun pk -> + Delegate_storage.manager_pubkey ctxt pkh >|=? fun pk -> ((pk, pkh), Tez_repr.to_mutez stake) :: acc) [] stakes diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 6d38d9350119..38281f92c2a5 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -250,7 +250,7 @@ module Contract = struct | _ -> set_delegate c contract delegate end -let pubkey ctxt pkh = +let manager_pubkey ctxt pkh = Contract_manager_storage.get_manager_key ~error:(Contract.Unregistered_delegate pkh) ctxt diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 262a49ce3f52..75bf7a34c519 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -136,7 +136,7 @@ end (** Returns the public key of a registered delegate. Returns the error {!Contract.Unregistered_delegate} if the delegate is not registered. *) -val pubkey : +val manager_pubkey : Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t tzresult Lwt.t -- GitLab From 05b8429278615c95290c8cc2a4e24e13f7bc774b Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 25/42] Proto/Delegate: add `Storage.Contracts.Consensus_key` --- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 3 + .../lib_protocol/alpha_context.mli | 34 +++ .../lib_protocol/delegate_consensus_key.ml | 202 ++++++++++++++ .../lib_protocol/delegate_consensus_key.mli | 89 ++++++ .../lib_protocol/delegate_cycles.ml | 16 ++ .../lib_protocol/delegate_cycles.mli | 4 + .../lib_protocol/delegate_storage.ml | 11 +- src/proto_alpha/lib_protocol/dune | 5 + src/proto_alpha/lib_protocol/init_storage.ml | 4 +- src/proto_alpha/lib_protocol/level_repr.ml | 9 + src/proto_alpha/lib_protocol/level_repr.mli | 2 + src/proto_alpha/lib_protocol/raw_context.ml | 11 + src/proto_alpha/lib_protocol/raw_context.mli | 2 + src/proto_alpha/lib_protocol/storage.ml | 17 ++ src/proto_alpha/lib_protocol/storage.mli | 14 + .../lib_protocol/test/unit/main.ml | 1 + .../test/unit/test_consensus_key.ml | 257 ++++++++++++++++++ 18 files changed, 676 insertions(+), 6 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/delegate_consensus_key.ml create mode 100644 src/proto_alpha/lib_protocol/delegate_consensus_key.mli create mode 100644 src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 5126b741fe92..a1fa14acd571 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -123,6 +123,7 @@ "Stake_storage", "Contract_storage", "Token", + "Delegate_consensus_key", "Delegate_storage", "Delegate_missed_endorsements_storage", "Delegate_slashed_deposits_storage", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index b56c77663948..5db6129465e1 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -434,6 +434,7 @@ module Bond_id = struct end module Receipt = Receipt_repr +module Consensus_key = Delegate_consensus_key module Delegate = struct include Delegate_storage @@ -454,6 +455,8 @@ module Delegate = struct let prepare_stake_distribution = Stake_storage.prepare_stake_distribution let delegated_contracts = Contract_delegate_storage.delegated_contracts + + module Consensus_key = Delegate_consensus_key end module Stake_distribution = struct diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index f47b61ba1c0d..943d35584b98 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2234,6 +2234,23 @@ module Receipt : sig val group_balance_updates : balance_updates -> balance_updates tzresult end +module Consensus_key : sig + type pk = { + delegate : public_key_hash; + delegate_public_key : public_key; + consensus_key : public_key_hash; + consensus_public_key : public_key; + } + + type t = {delegate : public_key_hash; consensus_key : public_key_hash} + + val zero : t + + val pp : Format.formatter -> t -> unit + + val pkh : pk -> t +end + module Delegate : sig val frozen_deposits_limit : context -> public_key_hash -> Tez.t option tzresult Lwt.t @@ -2320,6 +2337,23 @@ module Delegate : sig Signature.public_key_hash -> Signature.Public_key.t tzresult Lwt.t + module Consensus_key : sig + val active_pubkey : + context -> public_key_hash -> Consensus_key.pk tzresult Lwt.t + + val pending_updates : + context -> + public_key_hash -> + (Cycle.t * public_key_hash) list tzresult Lwt.t + + val register_update : + context -> + public_key_hash -> + Cycle.t -> + public_key -> + context tzresult Lwt.t + end + val prepare_stake_distribution : context -> context tzresult Lwt.t end diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml new file mode 100644 index 000000000000..4085320e4e34 --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml @@ -0,0 +1,202 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Invalid_consensus_key_update_cycle of Cycle_repr.t + | Invalid_consensus_key_update_noop of Cycle_repr.t + +let () = + register_error_kind + `Permanent + ~id:"delegate.consensus_key.invalid_cycle" + ~title:"Invalid cycle for consensus key update" + ~description:"Tried to update the consensus key for an invalid cycle" + ~pp:(fun ppf cycle -> + Format.fprintf + ppf + "Invalid cycle while updating a consensus key (expected: %a)." + Cycle_repr.pp + cycle) + Data_encoding.(obj1 (req "cycle" Cycle_repr.encoding)) + (function Invalid_consensus_key_update_cycle c -> Some c | _ -> None) + (fun c -> Invalid_consensus_key_update_cycle c) ; + register_error_kind + `Permanent + ~id:"delegate.consensus_key.invalid_noop" + ~title:"Invalid key for consensus key update" + ~description:"Tried to update the consensus key with an active key" + ~pp:(fun ppf cycle -> + Format.fprintf + ppf + "Invalid key while updating a consensus key (active since %a)." + Cycle_repr.pp + cycle) + Data_encoding.(obj1 (req "cycle" Cycle_repr.encoding)) + (function Invalid_consensus_key_update_noop c -> Some c | _ -> None) + (fun c -> Invalid_consensus_key_update_noop c) + +type pk = { + delegate : Signature.public_key_hash; + delegate_public_key : Signature.public_key; + consensus_key : Signature.public_key_hash; + consensus_public_key : Signature.public_key; +} + +type t = { + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; +} + +let pkh + {delegate; delegate_public_key = _; consensus_key; consensus_public_key = _} + = + {delegate; consensus_key} + +let zero = + { + delegate = Signature.Public_key_hash.zero; + consensus_key = Signature.Public_key_hash.zero; + } + +let pp ppf {delegate; consensus_key} = + Format.fprintf ppf "@[%a" Signature.Public_key_hash.pp delegate ; + if not (Signature.Public_key_hash.equal delegate consensus_key) then + Format.fprintf + ppf + "@,Active key: %a" + Signature.Public_key_hash.pp + consensus_key ; + Format.fprintf ppf "@]" + +let init ctxt delegate pk = + Storage.Contract.Consensus_key.init ctxt (Contract_repr.Implicit delegate) pk + +let active_pubkey ctxt delegate = + let open Lwt_tzresult_syntax in + let* consensus_public_key = + Storage.Contract.Consensus_key.get ctxt (Contract_repr.Implicit delegate) + in + let consensus_key = Signature.Public_key.hash consensus_public_key in + let* delegate_public_key = + Contract_manager_storage.get_manager_key ctxt delegate + in + return {delegate; delegate_public_key; consensus_key; consensus_public_key} + +let active_key ctxt delegate = + let open Lwt_tzresult_syntax in + let* pk = active_pubkey ctxt delegate in + return (pkh pk) + +let raw_pending_updates ctxt delegate = + let open Lwt_tzresult_syntax in + let*! pendings = + Storage.Contract.Pending_consensus_keys.bindings + (ctxt, Contract_repr.Implicit delegate) + in + return pendings + +let pending_updates ctxt delegate = + let open Lwt_tzresult_syntax in + let* updates = raw_pending_updates ctxt delegate in + let updates = + List.sort (fun (c1, _) (c2, _) -> Cycle_repr.compare c1 c2) updates + in + return (List.map (fun (c, pk) -> (c, Signature.Public_key.hash pk)) updates) + +let raw_active_pubkey_for_cycle ctxt delegate cycle = + let open Lwt_tzresult_syntax in + let* pendings = raw_pending_updates ctxt delegate in + let* active = active_pubkey ctxt delegate in + let current_level = Raw_context.current_level ctxt in + let active_for_cycle = + List.fold_left + (fun (c1, active) (c2, pk) -> + if Cycle_repr.(c1 < c2 && c2 <= cycle) then (c2, pk) else (c1, active)) + (current_level.cycle, active.consensus_public_key) + pendings + in + return active_for_cycle + +let active_pubkey_for_cycle ctxt delegate cycle = + let open Lwt_tzresult_syntax in + let* _, consensus_public_key = + raw_active_pubkey_for_cycle ctxt delegate cycle + in + let consensus_key = Signature.Public_key.hash consensus_public_key in + let* delegate_public_key = + Contract_manager_storage.get_manager_key ctxt delegate + in + return {delegate; delegate_public_key; consensus_key; consensus_public_key} + +let register_update ctxt delegate cycle pk = + let open Lwt_tzresult_syntax in + let* () = + let current_level = Raw_context.current_level ctxt in + let preserved_cycles = Constants_storage.preserved_cycles ctxt in + let required_cycle = + Cycle_repr.add current_level.cycle (preserved_cycles + 1) + in + fail_when + Cycle_repr.(cycle <> required_cycle) + (Invalid_consensus_key_update_cycle required_cycle) + in + let* () = + let* cycle, active_pubkey = + raw_active_pubkey_for_cycle ctxt delegate cycle + in + fail_when + Signature.Public_key.(pk = active_pubkey) + (Invalid_consensus_key_update_noop cycle) + in + let*! ctxt = + Storage.Contract.Pending_consensus_keys.add + (ctxt, Contract_repr.Implicit delegate) + cycle + pk + in + return ctxt + +let activate ctxt ~new_cycle = + let open Lwt_tzresult_syntax in + Storage.Delegates.fold + ctxt + ~order:`Undefined + ~init:(ok ctxt) + ~f:(fun delegate ctxt -> + let*? ctxt = ctxt in + let delegate = Contract_repr.Implicit delegate in + let* update = + Storage.Contract.Pending_consensus_keys.find (ctxt, delegate) new_cycle + in + match update with + | None -> return ctxt + | Some pk -> + let*! ctxt = Storage.Contract.Consensus_key.add ctxt delegate pk in + let*! ctxt = + Storage.Contract.Pending_consensus_keys.remove + (ctxt, delegate) + new_cycle + in + return ctxt) diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli new file mode 100644 index 000000000000..d3a4abd3567c --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli @@ -0,0 +1,89 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +type error += + | Invalid_consensus_key_update_cycle of Cycle_repr.t + | Invalid_consensus_key_update_noop of Cycle_repr.t + +(** The public key of a consensus key and the associated delegate. *) +type pk = { + delegate : Signature.public_key_hash; + delegate_public_key : Signature.public_key; + consensus_key : Signature.public_key_hash; + consensus_public_key : Signature.public_key; +} + +(** The public key hash of a consensus key and the associated delegate. *) +type t = { + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; +} + +val zero : t + +val pp : Format.formatter -> t -> unit + +val pkh : pk -> t + +(** Initialize the consensus key when registering a delegate. *) +val init : + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key.t -> + Raw_context.t tzresult Lwt.t + +(** Returns the active consensus key for the current cycle. *) +val active_pubkey : + Raw_context.t -> Signature.Public_key_hash.t -> pk tzresult Lwt.t + +(** Returns the active consensus key for the current cycle. *) +val active_key : + Raw_context.t -> Signature.Public_key_hash.t -> t tzresult Lwt.t + +(** Returns the active consensus key for the given cycle. *) +val active_pubkey_for_cycle : + Raw_context.t -> + Signature.Public_key_hash.t -> + Cycle_repr.t -> + pk tzresult Lwt.t + +(** Returns the list of pending consensus-key updates in upcoming cycles. *) +val pending_updates : + Raw_context.t -> + Signature.Public_key_hash.t -> + (Cycle_repr.t * Signature.Public_key_hash.t) list tzresult Lwt.t + +(** Register a consensus-key update in a given cycles. *) +val register_update : + Raw_context.t -> + Signature.Public_key_hash.t -> + Cycle_repr.t -> + Signature.Public_key.t -> + Raw_context.t tzresult Lwt.t + +(** Activate consensus keys at the beggining of cycle [new_cycle]. + This function iterates on all registered delegates. *) +val activate : + Raw_context.t -> new_cycle:Cycle_repr.t -> Raw_context.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 53a0c38c2146..ebcfed0618a5 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -251,6 +251,7 @@ let cycle_end ctxt last_cycle = let new_cycle = Cycle_repr.add last_cycle 1 in Delegate_sampler.select_new_distribution_at_cycle_end ctxt ~new_cycle >>=? fun ctxt -> + Delegate_consensus_key.activate ctxt ~new_cycle >>=? fun ctxt -> Delegate_slashed_deposits_storage.clear_outdated_slashed_deposits ctxt ~new_cycle @@ -278,3 +279,18 @@ let init_first_cycles ctxt ~origin = >>=? fun ctxt -> let cycle = (Raw_context.current_level ctxt).cycle in freeze_deposits ~origin ~new_cycle:cycle ~balance_updates:[] ctxt + +module Migration_from_Jakarta = struct + let update_delegate ctxt pkh = + let open Lwt_tzresult_syntax in + (* Consensus key*) + let* pk = Contract_manager_storage.get_manager_key ctxt pkh in + let* ctxt = Delegate_consensus_key.init ctxt pkh pk in + return ctxt + + let update ctxt = + let open Lwt_tzresult_syntax in + let*! delegates = Storage.Delegates.elements ctxt in + let* ctxt = List.fold_left_es update_delegate ctxt delegates in + return ctxt +end diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.mli b/src/proto_alpha/lib_protocol/delegate_cycles.mli index ebcecb05d925..a51e8a9a16e2 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.mli +++ b/src/proto_alpha/lib_protocol/delegate_cycles.mli @@ -47,3 +47,7 @@ val init_first_cycles : Raw_context.t -> origin:Receipt_repr.update_origin -> (Raw_context.t * Receipt_repr.balance_updates) tzresult Lwt.t + +module Migration_from_Jakarta : sig + val update : Raw_context.t -> Raw_context.t tzresult Lwt.t +end diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 38281f92c2a5..b942efebfcb0 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -146,11 +146,11 @@ module Contract = struct Stake_storage.set_active c delegate else let contract = Contract_repr.Implicit delegate in - let* () = - let* is_pk_revealed = - Contract_manager_storage.is_manager_key_revealed c delegate - in - fail_unless is_pk_revealed (Unregistered_delegate delegate) + let* pk = + Contract_manager_storage.get_manager_key + c + ~error:(Unregistered_delegate delegate) + delegate in let* () = let*! is_allocated = Contract_storage.allocated c contract in @@ -165,6 +165,7 @@ module Contract = struct let* c = Contract_delegate_storage.set c contract delegate in let* c = Stake_storage.add_stake c delegate balance_and_frozen_bonds in let*! c = Storage.Delegates.add c delegate in + let* c = Delegate_consensus_key.init c delegate pk in let* c = Stake_storage.set_active c delegate in return c diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index de1967c75846..3da09ab3fb7b 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -148,6 +148,7 @@ Stake_storage Contract_storage Token + Delegate_consensus_key Delegate_storage Delegate_missed_endorsements_storage Delegate_slashed_deposits_storage @@ -374,6 +375,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml delegate_missed_endorsements_storage.mli @@ -587,6 +589,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml delegate_missed_endorsements_storage.mli @@ -820,6 +823,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml delegate_missed_endorsements_storage.mli @@ -1049,6 +1053,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml delegate_missed_endorsements_storage.mli diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index e5195fe38233..81ccb3ba85e6 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -118,7 +118,9 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = if that is done, do not set Storage.Tenderbake.First_level_of_protocol. *) Raw_level_repr.of_int32 level >>?= fun level -> Storage.Tenderbake.First_level_of_protocol.update ctxt level - >>=? fun ctxt -> return (ctxt, [])) + >>=? fun ctxt -> + Delegate_cycles.Migration_from_Jakarta.update ctxt >>=? fun ctxt -> + return (ctxt, [])) >>=? fun (ctxt, balance_updates) -> Receipt_repr.group_balance_updates balance_updates >>?= fun balance_updates -> Storage.Pending_migration.Balance_updates.add ctxt balance_updates diff --git a/src/proto_alpha/lib_protocol/level_repr.ml b/src/proto_alpha/lib_protocol/level_repr.ml index 0b5926f387f5..f3100a55a188 100644 --- a/src/proto_alpha/lib_protocol/level_repr.ml +++ b/src/proto_alpha/lib_protocol/level_repr.ml @@ -340,4 +340,13 @@ module Internal_for_tests = struct let raw_level = level.level in let new_raw_level = Raw_level_repr.add raw_level n in {level with level = new_raw_level} + + let add_cycles ~blocks_per_cycle level n = + { + level with + cycle = Cycle_repr.add level.cycle n; + level = Raw_level_repr.add level.level (n * blocks_per_cycle); + level_position = + Int32.add level.level_position (Int32.of_int (n * blocks_per_cycle)); + } end diff --git a/src/proto_alpha/lib_protocol/level_repr.mli b/src/proto_alpha/lib_protocol/level_repr.mli index b595ce324e69..d6ab68499ba8 100644 --- a/src/proto_alpha/lib_protocol/level_repr.mli +++ b/src/proto_alpha/lib_protocol/level_repr.mli @@ -111,6 +111,8 @@ val last_of_cycle : cycle_eras:cycle_eras -> level -> bool module Internal_for_tests : sig val add_level : t -> int -> t + + val add_cycles : blocks_per_cycle:int -> t -> int -> t end (**/**) diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index f14d37096401..400d1d9d5c0d 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -1288,6 +1288,17 @@ module Internal_for_tests = struct let new_level = Level_repr.Internal_for_tests.add_level ctxt.back.level l in let new_back = {ctxt.back with level = new_level} in {ctxt with back = new_back} + + let add_cycles ctxt l = + let blocks_per_cycle = Int32.to_int (constants ctxt).blocks_per_cycle in + let new_level = + Level_repr.Internal_for_tests.add_cycles + ~blocks_per_cycle + ctxt.back.level + l + in + let new_back = {ctxt.back with level = new_level} in + {ctxt with back = new_back} end module type CONSENSUS = sig diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index 906b187e6930..eea016f1bdc3 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -261,6 +261,8 @@ val init_stake_distribution_for_current_cycle : module Internal_for_tests : sig val add_level : t -> int -> t + + val add_cycles : t -> int -> t end module type CONSENSUS = sig diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 797fb61c3d0a..32dd345ffd42 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -209,6 +209,23 @@ module Contract = struct end) (Manager_repr) + module Consensus_key = + Indexed_context.Make_map + (Registered) + (struct + let name = ["consensus_key"; "active"] + end) + (Signature.Public_key) + + module Pending_consensus_keys = + Make_indexed_data_storage + (Make_subcontext (Registered) (Indexed_context.Raw_context) + (struct + let name = ["consensus_key"; "pendings"] + end)) + (Make_index (Cycle_repr.Index)) + (Signature.Public_key) + module Delegate = Indexed_context.Make_map (struct diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 9a67e8c74caf..cd1069a8b931 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -104,6 +104,20 @@ module Contract : sig and type value = Manager_repr.t and type t := Raw_context.t + (** The active consensus key of a delegate *) + module Consensus_key : + Indexed_data_storage + with type key = Contract_repr.t + and type value = Signature.Public_key.t + and type t := Raw_context.t + + (** The pending consensus key of a delegate *) + module Pending_consensus_keys : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = Signature.Public_key.t + and type t := Raw_context.t * Contract_repr.t + (** The delegate of a contract, if any. *) module Delegate : Indexed_data_storage diff --git a/src/proto_alpha/lib_protocol/test/unit/main.ml b/src/proto_alpha/lib_protocol/test/unit/main.ml index b99d723fcd8c..e981a9c8f83e 100644 --- a/src/proto_alpha/lib_protocol/test/unit/main.ml +++ b/src/proto_alpha/lib_protocol/test/unit/main.ml @@ -80,5 +80,6 @@ let () = Unit_test.spec "sc rollup management protocol" Test_sc_rollup_management_protocol.tests; + Unit_test.spec "Delegate_consensus_key.ml" Test_consensus_key.tests; ] |> Lwt_main.run diff --git a/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml b/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml new file mode 100644 index 000000000000..f6d6978c0836 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml @@ -0,0 +1,257 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 G.B. Fefe, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(** Testing + ------- + Component: Protocol (delegate_consensus_key) + Invocation: dune exec src/proto_alpha/lib_protocol/test/unit/main.exe \ + -- test "^\[Unit\] Delegate_consensus_key.ml" + Subject: Functions from the module `Delegate_consensus_key` +*) + +open Protocol + +let create () = + let open Lwt_result_syntax in + let accounts = Account.generate_accounts 2 in + let a1, a2 = + match accounts with + | [(a1, _, _); (a2, _, _)] -> (a1, a2) + | _ -> assert false + in + let* ctxt = Block.alpha_context accounts in + return (Alpha_context.Internal_for_tests.to_raw ctxt, a1, a2) + +module Consensus_key = struct + let active_key ctxt pkh = + Delegate_consensus_key.active_key ctxt pkh >|= Environment.wrap_tzresult + + let active_pubkey ctxt pkh = + Delegate_consensus_key.active_pubkey ctxt pkh >|= Environment.wrap_tzresult + + let active_pubkey_for_cycle ctxt pkh cycle = + Delegate_consensus_key.active_pubkey_for_cycle + ctxt + pkh + (Cycle_repr.of_int32_exn (Int32.of_int cycle)) + >|= Environment.wrap_tzresult + + let pending_updates ctxt pkh = + Delegate_consensus_key.pending_updates ctxt pkh + >|= Environment.wrap_tzresult + + let register_update ctxt pkh cycle pk = + Delegate_consensus_key.register_update + ctxt + pkh + (Cycle_repr.of_int32_exn (Int32.of_int cycle)) + pk + >|= Environment.wrap_tzresult + + let activate ctxt ~new_cycle = + Delegate_consensus_key.activate ctxt ~new_cycle + >|= Environment.wrap_tzresult +end + +module Assert = struct + include Assert + + let equal_pkh ~__LOC__ a b = + Assert.equal + ~loc:__LOC__ + Signature.Public_key_hash.equal + "pkh" + Signature.Public_key_hash.pp + a + b + + let equal_pk ~__LOC__ a b = + Assert.equal + ~loc:__LOC__ + Signature.Public_key.equal + "pk" + Signature.Public_key.pp + a + b + + let active_keys ~__LOC__ ctxt delegate l = + List.iter_es + (fun (c, pk) -> + let open Lwt_result_syntax in + let* active_pk = + Consensus_key.active_pubkey_for_cycle ctxt delegate c + in + equal_pk ~__LOC__ active_pk.consensus_public_key pk) + l +end + +let rec add_cycles ctxt n = + if n <= 0 then return ctxt + else + let open Lwt_result_syntax in + let current_level = Raw_context.current_level ctxt in + let new_cycle = Cycle_repr.succ current_level.cycle in + let* ctxt = Consensus_key.activate ctxt ~new_cycle in + let ctxt = Raw_context.Internal_for_tests.add_cycles ctxt 1 in + add_cycles ctxt (n - 1) + +let test_consensus_key_storage () = + let open Lwt_result_syntax in + let* ctxt, del1, del2 = create () in + let a1 = Account.new_account () in + let a2 = Account.new_account () in + let preserved_cycles = Constants_storage.preserved_cycles ctxt in + let* () = Assert.equal_int ~loc:__LOC__ preserved_cycles 3 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_key del1.pkh + in + let* () = + let* active_pk = Consensus_key.active_pubkey ctxt del1.pkh in + Assert.equal_pk ~__LOC__ active_pk.consensus_public_key del1.pk + in + let* () = + let* active_pk = Consensus_key.active_pubkey_for_cycle ctxt del1.pkh 3 in + Assert.equal_pk ~__LOC__ active_pk.consensus_public_key del1.pk + in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh 3 a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_cycle c -> + c = Cycle_repr.of_int32_exn 4l + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del1.pkh 4 a1.pk in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh 4 a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_noop c -> + c = Cycle_repr.of_int32_exn 4l + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del2.pkh 4 del1.pk in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh 5 a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_cycle c -> + c = Cycle_repr.of_int32_exn 4l + | _ -> false) + in + let* () = + Assert.active_keys + ~__LOC__ + ctxt + del1.pkh + [ + (0, del1.pk); + (1, del1.pk); + (2, del1.pk); + (2, del1.pk); + (3, del1.pk); + (4, a1.pk); + (5, a1.pk); + ] + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_key del1.pkh + in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh 4 a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_cycle c -> + c = Cycle_repr.of_int32_exn 5l + | _ -> false) + in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh 5 a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_noop c -> + c = Cycle_repr.of_int32_exn 4l + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del1.pkh 5 a2.pk in + let* ctxt = Consensus_key.register_update ctxt del2.pkh 5 a1.pk in + let* ctxt = Consensus_key.register_update ctxt del2.pkh 5 del2.pk in + let* () = + Assert.active_keys + ~__LOC__ + ctxt + del1.pkh + [ + (1, del1.pk); + (2, del1.pk); + (2, del1.pk); + (3, del1.pk); + (4, a1.pk); + (5, a2.pk); + (6, a2.pk); + ] + in + let* ctxt = add_cycles ctxt 2 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_key del1.pkh + in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh 7 a2.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_noop c -> + c = Cycle_repr.of_int32_exn 5l + | _ -> false) + in + let* ctxt = Consensus_key.register_update ctxt del1.pkh 7 a1.pk in + let* () = + Assert.active_keys + ~__LOC__ + ctxt + del1.pkh + [(3, del1.pk); (4, a1.pk); (5, a2.pk); (6, a2.pk); (7, a1.pk); (8, a1.pk)] + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_key a1.pkh + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_key a2.pkh + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_key a2.pkh + in + let* ctxt = add_cycles ctxt 1 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_key a1.pkh + in + return () + +let tests = + [Tztest.tztest "consensus_key_storage" `Quick test_consensus_key_storage] -- GitLab From 0030ec8eba7340e6c230732e98e55f46e2b2cf76 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 26/42] Proto/Delegate: forbid two delegates with the same consensus key --- .../lib_protocol/delegate_consensus_key.ml | 36 ++++++++++++++++++- .../lib_protocol/delegate_consensus_key.mli | 1 + src/proto_alpha/lib_protocol/storage.ml | 8 +++++ src/proto_alpha/lib_protocol/storage.mli | 6 ++++ .../test/unit/test_consensus_key.ml | 12 +++++++ 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml index 4085320e4e34..0b24cd14e74a 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml @@ -26,6 +26,7 @@ type error += | Invalid_consensus_key_update_cycle of Cycle_repr.t | Invalid_consensus_key_update_noop of Cycle_repr.t + | Invalid_consensus_key_update_active let () = register_error_kind @@ -55,7 +56,20 @@ let () = cycle) Data_encoding.(obj1 (req "cycle" Cycle_repr.encoding)) (function Invalid_consensus_key_update_noop c -> Some c | _ -> None) - (fun c -> Invalid_consensus_key_update_noop c) + (fun c -> Invalid_consensus_key_update_noop c) ; + register_error_kind + `Permanent + ~id:"delegate.consensus_key.active" + ~title:"Active consensus key" + ~description: + "The delegate consensus key is already used by another delegate" + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The delegate consensus key is already used by another delegate") + Data_encoding.empty + (function Invalid_consensus_key_update_active -> Some () | _ -> None) + (fun () -> Invalid_consensus_key_update_active) type pk = { delegate : Signature.public_key_hash; @@ -90,7 +104,20 @@ let pp ppf {delegate; consensus_key} = consensus_key ; Format.fprintf ppf "@]" +let check_inactive ctxt pkh = + let open Lwt_tzresult_syntax in + let*! is_active = Storage.Consensus_keys.mem ctxt pkh in + fail_when is_active Invalid_consensus_key_update_active + +let set_inactive = Storage.Consensus_keys.remove + +let set_active = Storage.Consensus_keys.add + let init ctxt delegate pk = + let open Lwt_tzresult_syntax in + let pkh = Signature.Public_key.hash pk in + let* () = check_inactive ctxt pkh in + let*! ctxt = set_active ctxt pkh in Storage.Contract.Consensus_key.init ctxt (Contract_repr.Implicit delegate) pk let active_pubkey ctxt delegate = @@ -170,6 +197,13 @@ let register_update ctxt delegate cycle pk = Signature.Public_key.(pk = active_pubkey) (Invalid_consensus_key_update_noop cycle) in + let pkh = Signature.Public_key.hash pk in + let* () = check_inactive ctxt pkh in + let*! ctxt = set_active ctxt pkh in + let* {consensus_key = old_pkh; _} = + active_pubkey_for_cycle ctxt delegate cycle + in + let*! ctxt = set_inactive ctxt old_pkh in let*! ctxt = Storage.Contract.Pending_consensus_keys.add (ctxt, Contract_repr.Implicit delegate) diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli index d3a4abd3567c..5a539c4cf48a 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli @@ -26,6 +26,7 @@ type error += | Invalid_consensus_key_update_cycle of Cycle_repr.t | Invalid_consensus_key_update_noop of Cycle_repr.t + | Invalid_consensus_key_update_active (** The public key of a consensus key and the associated delegate. *) type pk = { diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 32dd345ffd42..2c2369f03a88 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -922,6 +922,14 @@ module Delegates = end)) (Public_key_hash_index) +module Consensus_keys = + Make_data_set_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["consensus_keys"] + end)) + (Public_key_hash_index) + (** Per cycle storage *) type slashed_level = {for_double_endorsing : bool; for_double_baking : bool} diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index cd1069a8b931..7356fd245d42 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -359,6 +359,12 @@ module Delegates : with type t := Raw_context.t and type elt = Signature.Public_key_hash.t +(** Set of all active consensus keys in cycle `current + preserved_cycles + 1` *) +module Consensus_keys : + Data_set_storage + with type t := Raw_context.t + and type elt = Signature.Public_key_hash.t + type slashed_level = {for_double_endorsing : bool; for_double_baking : bool} (** Set used to avoid slashing multiple times the same event *) diff --git a/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml b/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml index f6d6978c0836..cd5baaea65a0 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml @@ -136,6 +136,12 @@ let test_consensus_key_storage () = let* active_pk = Consensus_key.active_pubkey_for_cycle ctxt del1.pkh 3 in Assert.equal_pk ~__LOC__ active_pk.consensus_public_key del1.pk in + let* () = + let*! err = Consensus_key.register_update ctxt del1.pkh 4 del2.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_active -> true + | _ -> false) + in let* () = let*! err = Consensus_key.register_update ctxt del1.pkh 3 a1.pk in Assert.proto_error ~loc:__LOC__ err (function @@ -151,6 +157,12 @@ let test_consensus_key_storage () = c = Cycle_repr.of_int32_exn 4l | _ -> false) in + let* () = + let*! err = Consensus_key.register_update ctxt del2.pkh 4 a1.pk in + Assert.proto_error ~loc:__LOC__ err (function + | Delegate_consensus_key.Invalid_consensus_key_update_active -> true + | _ -> false) + in let* ctxt = Consensus_key.register_update ctxt del2.pkh 4 del1.pk in let* () = let*! err = Consensus_key.register_update ctxt del1.pkh 5 a1.pk in -- GitLab From 733fb44f141d189cbe25086b8fd99574a6a5791c Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 27/42] Proto/Operation: add manager operation `Update_consensus_key` --- src/proto_alpha/lib_client/injection.ml | 3 + .../lib_client/operation_result.ml | 11 +++ src/proto_alpha/lib_injector/l1_operation.ml | 1 + .../lib_protocol/alpha_context.mli | 12 ++++ src/proto_alpha/lib_protocol/apply.ml | 34 +++++++++- src/proto_alpha/lib_protocol/apply_results.ml | 68 +++++++++++++++++++ .../lib_protocol/apply_results.mli | 4 ++ .../lib_protocol/operation_repr.ml | 35 ++++++++++ .../lib_protocol/operation_repr.mli | 14 ++++ .../lib_protocol/test/helpers/block.ml | 7 +- .../lib_protocol/test/helpers/op.ml | 16 +++++ .../lib_protocol/test/helpers/op.mli | 12 ++++ .../operations/manager_operation_helpers.ml | 22 +++++- .../test_manager_operation_precheck.ml | 5 +- 14 files changed, 235 insertions(+), 9 deletions(-) diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index 178052c418bc..061a921e80f4 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -314,6 +314,7 @@ let estimated_gas_single (type kind) | Delegation_result {consumed_gas} -> Ok consumed_gas | Register_global_constant_result {consumed_gas; _} -> Ok consumed_gas | Set_deposits_limit_result {consumed_gas} -> Ok consumed_gas + | Update_consensus_key_result {consumed_gas} -> Ok consumed_gas | Tx_rollup_origination_result {consumed_gas; _} -> Ok consumed_gas | Tx_rollup_submit_batch_result {consumed_gas; _} -> Ok consumed_gas | Tx_rollup_commit_result {consumed_gas; _} -> Ok consumed_gas @@ -388,6 +389,7 @@ let estimated_storage_single (type kind) ~tx_rollup_origination_size | Register_global_constant_result {size_of_constant; _} -> Ok size_of_constant | Set_deposits_limit_result _ -> Ok Z.zero + | Update_consensus_key_result _ -> Ok Z.zero | Tx_rollup_origination_result _ -> Ok tx_rollup_origination_size | Tx_rollup_submit_batch_result {paid_storage_size_diff; _} | Sc_rollup_execute_outbox_message_result {paid_storage_size_diff; _} -> @@ -487,6 +489,7 @@ let originated_contracts_single (type kind) | Reveal_result _ -> Ok [] | Delegation_result _ -> Ok [] | Set_deposits_limit_result _ -> Ok [] + | Update_consensus_key_result _ -> Ok [] | Tx_rollup_origination_result _ -> Ok [] | Tx_rollup_submit_batch_result _ -> Ok [] | Tx_rollup_commit_result _ -> Ok [] diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 90d681a1d383..036e5dd9e2c4 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -183,6 +183,14 @@ let pp_manager_operation_content (type kind) source ppf match limit_opt with | None -> Format.pp_print_string ppf "Unlimited deposits" | Some limit -> Format.fprintf ppf "Limit: %a" Tez.pp limit) + | Update_consensus_key (cycle, pk) -> + Format.fprintf + ppf + "Update_consensus_key:@,Cycle: %a@,Public key hash: %a" + Cycle.pp + cycle + Signature.Public_key_hash.pp + (Signature.Public_key.hash pk) | Tx_rollup_origination -> Format.fprintf ppf "Tx rollup origination:@,From: %a" Contract.pp source | Tx_rollup_submit_batch {tx_rollup; content; burn_limit = _} -> @@ -694,6 +702,7 @@ let pp_manager_operation_contents_result ppf op_result = | Delegation_result _ -> "delegation" | Register_global_constant_result _ -> "global constant registration" | Set_deposits_limit_result _ -> "deposits limit modification" + | Update_consensus_key_result _ -> "consensus key update" | Tx_rollup_origination_result _ -> "transaction rollup origination" | Tx_rollup_submit_batch_result _ -> "transaction rollup batch submission" | Tx_rollup_commit_result _ -> "transaction rollup commitment" @@ -726,6 +735,8 @@ let pp_manager_operation_contents_result ppf op_result = | Delegation_result {consumed_gas} -> pp_consumed_gas ppf consumed_gas | Set_deposits_limit_result {consumed_gas} -> pp_consumed_gas ppf consumed_gas + | Update_consensus_key_result {consumed_gas} -> + pp_consumed_gas ppf consumed_gas | Transaction_result tx -> pp_transaction_result ppf tx | Origination_result op_res -> pp_origination_result ppf op_res | Register_global_constant_result _ as op -> diff --git a/src/proto_alpha/lib_injector/l1_operation.ml b/src/proto_alpha/lib_injector/l1_operation.ml index baa74380c535..22fd86f21b4f 100644 --- a/src/proto_alpha/lib_injector/l1_operation.ml +++ b/src/proto_alpha/lib_injector/l1_operation.ml @@ -81,6 +81,7 @@ module Manager_operation = struct | Delegation _ -> delegation_case | Register_global_constant _ -> register_global_constant_case | Set_deposits_limit _ -> set_deposits_limit_case + | Update_consensus_key _ -> update_consensus_key_case | Tx_rollup_origination -> tx_rollup_origination_case | Tx_rollup_submit_batch _ -> tx_rollup_submit_batch_case | Tx_rollup_commit _ -> tx_rollup_commit_case diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 943d35584b98..1de25f877cef 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3279,6 +3279,8 @@ module Kind : sig type set_deposits_limit = Set_deposits_limit_kind + type update_consensus_key = Update_consensus_key_kind + type failing_noop = Failing_noop_kind type register_global_constant = Register_global_constant_kind @@ -3327,6 +3329,7 @@ module Kind : sig | Delegation_manager_kind : delegation manager | Register_global_constant_manager_kind : register_global_constant manager | Set_deposits_limit_manager_kind : set_deposits_limit manager + | Update_consensus_key_manager_kind : update_consensus_key manager | Tx_rollup_origination_manager_kind : tx_rollup_origination manager | Tx_rollup_submit_batch_manager_kind : tx_rollup_submit_batch manager | Tx_rollup_commit_manager_kind : tx_rollup_commit manager @@ -3467,6 +3470,9 @@ and _ manager_operation = | Set_deposits_limit : Tez.t option -> Kind.set_deposits_limit manager_operation + | Update_consensus_key : + Cycle.t * Signature.Public_key.t + -> Kind.update_consensus_key manager_operation | Tx_rollup_origination : Kind.tx_rollup_origination manager_operation | Tx_rollup_submit_batch : { tx_rollup : Tx_rollup.t; @@ -3698,6 +3704,8 @@ module Operation : sig val delegation_case : Kind.delegation Kind.manager case + val update_consensus_key_case : Kind.update_consensus_key Kind.manager case + val tx_rollup_origination_case : Kind.tx_rollup_origination Kind.manager case @@ -3769,6 +3777,10 @@ module Operation : sig val delegation_case : Kind.delegation case + val update_consensus_key_tag : int + + val update_consensus_key_case : Kind.update_consensus_key case + val register_global_constant_case : Kind.register_global_constant case val set_deposits_limit_case : Kind.set_deposits_limit case diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index d25c9f357702..f0b2cefa4dd9 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -96,6 +96,7 @@ type error += | Set_deposits_limit_too_high of {limit : Tez.t; max_limit : Tez.t} | Ballot_on_unregistered_delegate of Signature.Public_key_hash.t | Proposals_on_unregistered_delegate of Signature.Public_key_hash.t + | Update_consensus_key_on_unregistered_delegate of Signature.Public_key_hash.t | Empty_transaction of Contract.t | Tx_rollup_feature_disabled | Tx_rollup_invalid_transaction_ticket_amount @@ -501,6 +502,21 @@ let () = | Set_deposits_limit_too_high {limit; max_limit} -> Some (limit, max_limit) | _ -> None) (fun (limit, max_limit) -> Set_deposits_limit_too_high {limit; max_limit}) ; + register_error_kind + `Temporary + ~id:"operation.update_consensus_key_on_unregistered_delegate" + ~title:"Update consensus key on an unregistered delegate" + ~description:"Cannot update consensus key an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot update the consensus key on the unregistered delegate %a." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function + | Update_consensus_key_on_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Update_consensus_key_on_unregistered_delegate c) ; register_error_kind `Branch ~id:"contract.empty_transaction" @@ -1569,6 +1585,19 @@ let apply_external_manager_operation_content : Set_deposits_limit_result {consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt}, [] ) + | Update_consensus_key (cycle, pk) -> + Delegate.registered ctxt source >>= fun is_registered -> + error_unless + is_registered + (Update_consensus_key_on_unregistered_delegate source) + >>?= fun () -> + Delegate.Consensus_key.register_update ctxt source cycle pk + >>=? fun ctxt -> + return + ( ctxt, + Update_consensus_key_result + {consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt}, + [] ) | Tx_rollup_origination -> Tx_rollup.originate ctxt >>=? fun (ctxt, originated_tx_rollup) -> let result = @@ -1991,7 +2020,7 @@ let precheck_manager_contents (type kind) ctxt (op : kind Kind.manager contents) consume_decoding_gas ctxt script.storage ) | Register_global_constant {value} -> Lwt.return @@ consume_decoding_gas ctxt value - | Delegation _ | Set_deposits_limit _ -> return ctxt + | Delegation _ | Set_deposits_limit _ | Update_consensus_key _ -> return ctxt | Tx_rollup_origination -> assert_tx_rollup_feature_enabled ctxt >|=? fun () -> ctxt | Tx_rollup_submit_batch {content; _} -> @@ -2189,7 +2218,8 @@ let burn_manager_storage_fees : size_of_constant = payload.size_of_constant; global_address = payload.global_address; } ) - | Set_deposits_limit_result _ -> return (ctxt, storage_limit, smopr) + | Set_deposits_limit_result _ | Update_consensus_key_result _ -> + return (ctxt, storage_limit, smopr) | Tx_rollup_origination_result payload -> Fees.burn_tx_rollup_origination_fees ctxt ~storage_limit ~payer >|=? fun (ctxt, storage_limit, origination_bus) -> diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index 591e5ec23847..2ba3deeb698e 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -162,6 +162,10 @@ type _ successful_manager_operation_result = consumed_gas : Gas.Arith.fp; } -> Kind.set_deposits_limit successful_manager_operation_result + | Update_consensus_key_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.update_consensus_key successful_manager_operation_result | Tx_rollup_origination_result : { balance_updates : Receipt.balance_updates; consumed_gas : Gas.Arith.fp; @@ -665,6 +669,26 @@ module Manager_result = struct assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; Delegation_result {consumed_gas = consumed_milligas}) + let update_consensus_key_case = + make + ~op_case:Operation.Encoding.Manager_operations.update_consensus_key_case + ~encoding: + Data_encoding.( + obj2 + (dft "consumed_gas" Gas.Arith.n_integral_encoding Gas.Arith.zero) + (dft "consumed_milligas" Gas.Arith.n_fp_encoding Gas.Arith.zero)) + ~select:(function + | Successful_manager_result (Update_consensus_key_result _ as op) -> + Some op + | _ -> None) + ~kind:Kind.Update_consensus_key_manager_kind + ~proj:(function[@coq_match_with_default] + | Update_consensus_key_result {consumed_gas} -> + (Gas.Arith.ceil consumed_gas, consumed_gas)) + ~inj:(fun (consumed_gas, consumed_milligas) -> + assert (Gas.Arith.(equal (ceil consumed_milligas) consumed_gas)) ; + Update_consensus_key_result {consumed_gas = consumed_milligas}) + let set_deposits_limit_case = make ~op_case:Operation.Encoding.Manager_operations.set_deposits_limit_case @@ -1544,6 +1568,7 @@ let successful_manager_operation_result_encoding : make Manager_result.transaction_case; make Manager_result.origination_case; make Manager_result.delegation_case; + make Manager_result.update_consensus_key_case; make Manager_result.set_deposits_limit_case; make Manager_result.sc_rollup_originate_case; ] @@ -1611,6 +1636,10 @@ let equal_manager_kind : | Kind.Origination_manager_kind, _ -> None | Kind.Delegation_manager_kind, Kind.Delegation_manager_kind -> Some Eq | Kind.Delegation_manager_kind, _ -> None + | ( Kind.Update_consensus_key_manager_kind, + Kind.Update_consensus_key_manager_kind ) -> + Some Eq + | Kind.Update_consensus_key_manager_kind, _ -> None | ( Kind.Register_global_constant_manager_kind, Kind.Register_global_constant_manager_kind ) -> Some Eq @@ -2032,6 +2061,17 @@ module Encoding = struct Some (op, res) | _ -> None) + let[@coq_axiom_with_reason "gadt"] update_consensus_key_case = + make_manager_case + Operation.Encoding.update_consensus_key_case + Manager_result.update_consensus_key_case + (function + | Contents_and_result + ( (Manager_operation {operation = Update_consensus_key _; _} as op), + res ) -> + Some (op, res) + | _ -> None) + let[@coq_axiom_with_reason "gadt"] register_global_constant_case = make_manager_case Operation.Encoding.register_global_constant_case @@ -2294,6 +2334,7 @@ let contents_result_encoding = make delegation_case; make register_global_constant_case; make set_deposits_limit_case; + make update_consensus_key_case; make tx_rollup_origination_case; make tx_rollup_submit_batch_case; make tx_rollup_commit_case; @@ -2353,6 +2394,7 @@ let contents_and_result_encoding = make delegation_case; make register_global_constant_case; make set_deposits_limit_case; + make update_consensus_key_case; make tx_rollup_origination_case; make tx_rollup_submit_batch_case; make tx_rollup_commit_case; @@ -2594,6 +2636,32 @@ let kind_equal : } ) -> Some Eq | Manager_operation {operation = Delegation _; _}, _ -> None + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + {operation_result = Applied (Update_consensus_key_result _); _} ) -> + Some Eq + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + {operation_result = Backtracked (Update_consensus_key_result _, _); _} ) + -> + Some Eq + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + { + operation_result = + Failed (Alpha_context.Kind.Update_consensus_key_manager_kind, _); + _; + } ) -> + Some Eq + | ( Manager_operation {operation = Update_consensus_key _; _}, + Manager_operation_result + { + operation_result = + Skipped Alpha_context.Kind.Update_consensus_key_manager_kind; + _; + } ) -> + Some Eq + | Manager_operation {operation = Update_consensus_key _; _}, _ -> None | ( Manager_operation {operation = Register_global_constant _; _}, Manager_operation_result {operation_result = Applied (Register_global_constant_result _); _} ) -> diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 009fbdbbc340..ab1abfbb7961 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -228,6 +228,10 @@ and _ successful_manager_operation_result = consumed_gas : Gas.Arith.fp; } -> Kind.set_deposits_limit successful_manager_operation_result + | Update_consensus_key_result : { + consumed_gas : Gas.Arith.fp; + } + -> Kind.update_consensus_key successful_manager_operation_result | Tx_rollup_origination_result : { balance_updates : Receipt.balance_updates; consumed_gas : Gas.Arith.fp; diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 4e737928a4de..5a9c72db3db3 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -70,6 +70,8 @@ module Kind = struct type set_deposits_limit = Set_deposits_limit_kind + type update_consensus_key = Update_consensus_key_kind + type failing_noop = Failing_noop_kind type register_global_constant = Register_global_constant_kind @@ -118,6 +120,7 @@ module Kind = struct | Delegation_manager_kind : delegation manager | Register_global_constant_manager_kind : register_global_constant manager | Set_deposits_limit_manager_kind : set_deposits_limit manager + | Update_consensus_key_manager_kind : update_consensus_key manager | Tx_rollup_origination_manager_kind : tx_rollup_origination manager | Tx_rollup_submit_batch_manager_kind : tx_rollup_submit_batch manager | Tx_rollup_commit_manager_kind : tx_rollup_commit manager @@ -327,6 +330,9 @@ and _ manager_operation = | Set_deposits_limit : Tez_repr.t option -> Kind.set_deposits_limit manager_operation + | Update_consensus_key : + Cycle_repr.t * Signature.Public_key.t + -> Kind.update_consensus_key manager_operation | Tx_rollup_origination : Kind.tx_rollup_origination manager_operation | Tx_rollup_submit_batch : { tx_rollup : Tx_rollup_repr.t; @@ -443,6 +449,7 @@ let manager_kind : type kind. kind manager_operation -> kind Kind.manager = | Delegation _ -> Kind.Delegation_manager_kind | Register_global_constant _ -> Kind.Register_global_constant_manager_kind | Set_deposits_limit _ -> Kind.Set_deposits_limit_manager_kind + | Update_consensus_key _ -> Kind.Update_consensus_key_manager_kind | Tx_rollup_origination -> Kind.Tx_rollup_origination_manager_kind | Tx_rollup_submit_batch _ -> Kind.Tx_rollup_submit_batch_manager_kind | Tx_rollup_commit _ -> Kind.Tx_rollup_commit_manager_kind @@ -690,6 +697,28 @@ module Encoding = struct inj = (fun key -> Set_deposits_limit key); } + let update_consensus_key_tag = 6 + + let[@coq_axiom_with_reason "gadt"] update_consensus_key_case = + MCase + { + tag = update_consensus_key_tag; + name = "update_consensus_key"; + encoding = + obj2 + (req "cycle" Cycle_repr.encoding) + (req "pk" Signature.Public_key.encoding); + select = + (function + | Manager (Update_consensus_key _ as op) -> Some op | _ -> None); + proj = + (function + | Update_consensus_key (cycle, consensus_pk) -> (cycle, consensus_pk)); + inj = + (fun (cycle, consensus_pk) -> + Update_consensus_key (cycle, consensus_pk)); + } + let[@coq_axiom_with_reason "gadt"] tx_rollup_origination_case = MCase { @@ -1475,6 +1504,9 @@ module Encoding = struct let set_deposits_limit_case = make_manager_case 112 Manager_operations.set_deposits_limit_case + let update_consensus_key_case = + make_manager_case 113 Manager_operations.update_consensus_key_case + let tx_rollup_origination_case = make_manager_case tx_rollup_operation_tag_offset @@ -1592,6 +1624,7 @@ module Encoding = struct make origination_case; make delegation_case; make set_deposits_limit_case; + make update_consensus_key_case; make failing_noop_case; make register_global_constant_case; make tx_rollup_origination_case; @@ -1804,6 +1837,8 @@ let equal_manager_operation_kind : | Register_global_constant _, _ -> None | Set_deposits_limit _, Set_deposits_limit _ -> Some Eq | Set_deposits_limit _, _ -> None + | Update_consensus_key _, Update_consensus_key _ -> Some Eq + | Update_consensus_key _, _ -> None | Tx_rollup_origination, Tx_rollup_origination -> Some Eq | Tx_rollup_origination, _ -> None | Tx_rollup_submit_batch _, Tx_rollup_submit_batch _ -> Some Eq diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index 0277f6fad073..ff724a8fc3c8 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -99,6 +99,8 @@ module Kind : sig type set_deposits_limit = Set_deposits_limit_kind + type update_consensus_key = Update_consensus_key_kind + type failing_noop = Failing_noop_kind type register_global_constant = Register_global_constant_kind @@ -147,6 +149,7 @@ module Kind : sig | Delegation_manager_kind : delegation manager | Register_global_constant_manager_kind : register_global_constant manager | Set_deposits_limit_manager_kind : set_deposits_limit manager + | Update_consensus_key_manager_kind : update_consensus_key manager | Tx_rollup_origination_manager_kind : tx_rollup_origination manager | Tx_rollup_submit_batch_manager_kind : tx_rollup_submit_batch manager | Tx_rollup_commit_manager_kind : tx_rollup_commit manager @@ -365,6 +368,11 @@ and _ manager_operation = | Set_deposits_limit : Tez_repr.t option -> Kind.set_deposits_limit manager_operation + (* [Update_consensus_key (cycle, pk)] updates the consensus key of + the signing delegate to [pk] starting at [cycle]. *) + | Update_consensus_key : + Cycle_repr.t * Signature.Public_key.t + -> Kind.update_consensus_key manager_operation (* [Tx_rollup_origination] allows an implicit contract to originate a new transactional rollup. *) | Tx_rollup_origination : Kind.tx_rollup_origination manager_operation @@ -613,6 +621,8 @@ module Encoding : sig val delegation_case : Kind.delegation Kind.manager case + val update_consensus_key_case : Kind.update_consensus_key Kind.manager case + val register_global_constant_case : Kind.register_global_constant Kind.manager case @@ -682,6 +692,10 @@ module Encoding : sig val delegation_case : Kind.delegation case + val update_consensus_key_tag : int + + val update_consensus_key_case : Kind.update_consensus_key case + val register_global_constant_case : Kind.register_global_constant case val set_deposits_limit_case : Kind.set_deposits_limit case diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 8d941c7d07a9..8482f21b4559 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -759,9 +759,9 @@ let bake_n_with_all_balance_updates ?(baking_mode = Application) ?policy fun (Successful_manager_result r) -> match r with | Reveal_result _ | Delegation_result _ - | Set_deposits_limit_result _ | Tx_rollup_origination_result _ - | Tx_rollup_submit_batch_result _ | Tx_rollup_commit_result _ - | Tx_rollup_return_bond_result _ + | Update_consensus_key_result _ | Set_deposits_limit_result _ + | Tx_rollup_origination_result _ | Tx_rollup_submit_batch_result _ + | Tx_rollup_commit_result _ | Tx_rollup_return_bond_result _ | Tx_rollup_finalize_commitment_result _ | Tx_rollup_remove_commitment_result _ | Tx_rollup_rejection_result _ | Transfer_ticket_result _ @@ -799,6 +799,7 @@ let bake_n_with_origination_results ?(baking_mode = Application) ?policy n b = function | Successful_manager_result (Reveal_result _) | Successful_manager_result (Delegation_result _) + | Successful_manager_result (Update_consensus_key_result _) | Successful_manager_result (Transaction_result _) | Successful_manager_result (Register_global_constant_result _) | Successful_manager_result (Set_deposits_limit_result _) diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index 53da6f52100b..4b650a380f80 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -481,6 +481,22 @@ let set_deposits_limit ?force_reveal ?fee ?gas_limit ?storage_limit ?counter Context.Contract.manager ctxt source >|=? fun account -> sign account.sk ctxt sop +let update_consensus_key ?force_reveal ?fee ?gas_limit ?storage_limit ?counter + ctxt source cycle public_key = + let top = Update_consensus_key (cycle, public_key) in + manager_operation + ?force_reveal + ?fee + ?counter + ?storage_limit + ?gas_limit + ~source + ctxt + top + >>=? fun sop -> + Context.Contract.manager ctxt source >|=? fun account -> + sign account.sk ctxt sop + let activation ctxt (pkh : Signature.Public_key_hash.t) activation_code = (match pkh with | Ed25519 edpkh -> return edpkh diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index df18aab209c1..6f9639d069bc 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -132,6 +132,18 @@ val set_deposits_limit : Tez.tez option -> Operation.packed tzresult Lwt.t +val update_consensus_key : + ?force_reveal:bool -> + ?fee:Tez.tez -> + ?gas_limit:gas_limit -> + ?storage_limit:Z.t -> + ?counter:Z.t -> + Context.t -> + Contract.t -> + Cycle.t -> + public_key -> + Operation.packed tzresult Lwt.t + (** [revelation ?fee ?gas_limit ?forge_pkh ctxt pkh] Creates a new [Reveal] {!manager_operation} to reveal a public key [pkh] applying to current context [ctxt]. diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/manager_operation_helpers.ml b/src/proto_alpha/lib_protocol/test/integration/operations/manager_operation_helpers.ml index 2b20bee48b5f..afee9a78847f 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/manager_operation_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/manager_operation_helpers.ml @@ -299,6 +299,19 @@ let mk_set_deposits_limit ?counter ?fee ?gas_limit ?storage_limit ?force_reveal source None +let mk_update_consensus_key ?counter ?fee ?gas_limit ?storage_limit + ?force_reveal ~source (infos : infos) = + Op.update_consensus_key + ?force_reveal + ?fee + ?gas_limit + ?storage_limit + ?counter + (B infos.block) + source + Cycle.(add root 5) (* FIXME GB.FEFE *) + infos.account3.pk + let mk_reveal ?counter ?fee ?gas_limit ?storage_limit ?force_reveal:_ ~source (infos : infos) = let open Lwt_result_syntax in @@ -652,6 +665,7 @@ type manager_operation_kind = | K_Undelegation | K_Self_delegation | K_Set_deposits_limit + | K_Update_consensus_key | K_Reveal | K_Tx_rollup_origination | K_Tx_rollup_submit_batch @@ -680,6 +694,7 @@ let select_op = function | K_Undelegation -> mk_undelegation | K_Self_delegation -> mk_self_delegation | K_Set_deposits_limit -> mk_set_deposits_limit + | K_Update_consensus_key -> mk_update_consensus_key | K_Reveal -> mk_reveal | K_Tx_rollup_origination -> mk_tx_rollup_origination | K_Tx_rollup_submit_batch -> mk_tx_rollup_submit_batch @@ -706,6 +721,7 @@ let string_of_kind = function | K_Undelegation -> "Undelegation" | K_Self_delegation -> "Self-delegation" | K_Set_deposits_limit -> "Set deposits limit" + | K_Update_consensus_key -> "Update_consensus_key" | K_Origination -> "Origination" | K_Register_global_constant -> "Register global constant" | K_Reveal -> "Revelation" @@ -852,6 +868,7 @@ let subjects = K_Undelegation; K_Self_delegation; K_Set_deposits_limit; + K_Update_consensus_key; K_Reveal; K_Tx_rollup_origination; K_Tx_rollup_submit_batch; @@ -876,8 +893,9 @@ let subjects = let except_not_consumer_in_precheck_subjects = List.filter (function - | K_Set_deposits_limit | K_Reveal | K_Self_delegation | K_Delegation - | K_Undelegation | K_Tx_rollup_origination | K_Tx_rollup_submit_batch + | K_Set_deposits_limit | K_Update_consensus_key | K_Reveal + | K_Self_delegation | K_Delegation | K_Undelegation + | K_Tx_rollup_origination | K_Tx_rollup_submit_batch | K_Tx_rollup_finalize | K_Tx_rollup_commit | K_Tx_rollup_return_bond | K_Tx_rollup_remove_commitment | K_Tx_rollup_reject | K_Sc_rollup_add_messages | K_Sc_rollup_origination | K_Sc_rollup_refute diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_manager_operation_precheck.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_manager_operation_precheck.ml index f13c4796e890..55fe6f27129e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/test_manager_operation_precheck.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_manager_operation_precheck.ml @@ -61,6 +61,7 @@ let ensure_kind infos kind = | Delegation _, K_Self_delegation | Register_global_constant _, K_Register_global_constant | Set_deposits_limit _, K_Set_deposits_limit + | Update_consensus_key _, K_Update_consensus_key | Tx_rollup_origination, K_Tx_rollup_origination | Tx_rollup_submit_batch _, K_Tx_rollup_submit_batch | Tx_rollup_commit _, K_Tx_rollup_commit @@ -81,8 +82,8 @@ let ensure_kind infos kind = | Dal_publish_slot_header _, K_Dal_publish_slot_header -> return_unit | ( ( Transaction _ | Origination _ | Register_global_constant _ - | Delegation _ | Set_deposits_limit _ | Reveal _ - | Tx_rollup_origination | Tx_rollup_submit_batch _ + | Delegation _ | Set_deposits_limit _ | Update_consensus_key _ + | Reveal _ | Tx_rollup_origination | Tx_rollup_submit_batch _ | Tx_rollup_commit _ | Tx_rollup_return_bond _ | Tx_rollup_finalize_commitment _ | Tx_rollup_remove_commitment _ | Tx_rollup_dispatch_tickets _ | Transfer_ticket _ -- GitLab From 83d305fa831b86bc3a8f57656c4cf4c863c514ad Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 28/42] Proto/Client: add `tezos-client set consensus key for to ` --- .../lib_client/client_proto_context.ml | 35 ++++++++++++++++ .../lib_client/client_proto_context.mli | 16 ++++++++ .../client_proto_context_commands.ml | 40 +++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index fd8a161c13cd..38cabdf98846 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -315,6 +315,41 @@ let register_as_delegate cctxt ~chain ~block ?confirmations ?dry_run ~fee_parameter (Some source) +let update_consensus_key cctxt ~chain ~block ?confirmations ?dry_run + ?verbose_signing ?simulation ?fee ~consensus_pk ~manager_sk ~fee_parameter + cycle src_pk = + let source = Signature.Public_key.hash src_pk in + let operation = Update_consensus_key (cycle, consensus_pk) in + let operation = + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + operation + in + let operation = Annotated_manager_operation.Single_manager operation in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~successor_level:true + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + >>=? fun (oph, _, op, result) -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return (oph, op, result) + let set_deposits_limit cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing ?simulation ?fee contract ~src_pk ~manager_sk ~fee_parameter limit_opt = diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index 2404bb012e2b..bdd669cf8c95 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -131,6 +131,22 @@ val set_delegate : public_key_hash option -> Kind.delegation Kind.manager Injection.result tzresult Lwt.t +val update_consensus_key : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + ?fee:Tez.tez -> + consensus_pk:Signature.public_key -> + manager_sk:Client_keys.sk_uri -> + fee_parameter:Injection.fee_parameter -> + Cycle.t -> + Signature.public_key -> + Kind.update_consensus_key Kind.manager Injection.result tzresult Lwt.t + val set_deposits_limit : #Protocol_client_context.full -> chain:Shell_services.chain -> diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index ba32ccbd17f0..c2292f027c9e 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -1428,6 +1428,46 @@ let commands_rw () = cctxt#message "Delegate already activated." >>= fun () -> return_unit | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Update the consensus key of a delegate." + (args4 fee_arg dry_run_switch verbose_signing_switch fee_parameter_args) + (prefixes ["set"; "consensus"; "key"; "for"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["to"] + @@ Public_key.source_param ~name:"key" ~desc:"the consensus key" + @@ stop) + (fun (fee, dry_run, verbose_signing, fee_parameter) + delegate_pkh + (name_pk, consensus_pk) + cctxt -> + (match consensus_pk with + | Some pk -> return pk + | None -> Client_keys.public_key name_pk) + >>=? fun consensus_pk -> + Client_keys.get_key cctxt delegate_pkh + >>=? fun (_, delegate_pk, delegate_sk) -> + Alpha_services.Constants.all cctxt (cctxt#chain, cctxt#block) + >>=? fun {parametric = {preserved_cycles; _}; _} -> + Plugin.RPC.current_level cctxt ~offset:1l (cctxt#chain, cctxt#block) + >>=? fun l -> + let cycle = Cycle.(succ (add l.cycle preserved_cycles)) in + update_consensus_key + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~fee_parameter + ~verbose_signing + ?fee + ~consensus_pk + ~manager_sk:delegate_sk + cycle + delegate_pk + >>= function + | Ok _ -> return_unit + | Error el -> Lwt.return_error el); command ~desc:"Wait until an operation is included in a block" (args3 -- GitLab From 7be5cab6a016bcf54d335bea1126dbcd379ea14f Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 29/42] Proto/Client: add `tezos-client register key as delegate with consensus key ` --- .../lib_client/client_proto_context.ml | 93 ++++++++++++++----- .../lib_client/client_proto_context.mli | 8 +- .../client_proto_context_commands.ml | 40 ++++++++ 3 files changed, 118 insertions(+), 23 deletions(-) diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index 38cabdf98846..31c31fb1a960 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -298,35 +298,84 @@ let set_delegate cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing ~fee_parameter opt_delegate +let build_update_consensus_key ?fee ?gas_limit ?storage_limit cycle consensus_pk + = + let operation = Update_consensus_key (cycle, consensus_pk) in + Injection.prepare_manager_operation + ~fee:(Limit.of_option fee) + ~gas_limit:(Limit.of_option gas_limit) + ~storage_limit:(Limit.of_option storage_limit) + operation + let register_as_delegate cctxt ~chain ~block ?confirmations ?dry_run - ?verbose_signing ?fee ~manager_sk ~fee_parameter src_pk = + ?verbose_signing ?fee ~manager_sk ~fee_parameter ?consensus_pk src_pk = let source = Signature.Public_key.hash src_pk in - delegate_contract - cctxt - ~chain - ~block - ?confirmations - ?dry_run - ?verbose_signing - ~source - ~src_pk - ~src_sk:manager_sk - ?fee - ~fee_parameter - (Some source) + let delegate_op = build_delegate_operation ?fee (Some source) in + match consensus_pk with + | None -> ( + let operation = Annotated_manager_operation.Single_manager delegate_op in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + >>=? fun (oph, _, op, result) -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> + return ((oph, op, result), None)) + | Some consensus_pk -> ( + Alpha_services.Constants.all cctxt (chain, block) + >>=? fun {parametric = {preserved_cycles; _}; _} -> + Plugin.RPC.current_level cctxt ~offset:1l (chain, block) >>=? fun l -> + let cycle = Cycle.(succ (add l.cycle preserved_cycles)) in + let operation = + Annotated_manager_operation.Cons_manager + ( delegate_op, + Annotated_manager_operation.Single_manager + (build_update_consensus_key ?fee cycle consensus_pk) ) + in + Injection.inject_manager_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ~successor_level:true + ~source + ~fee:(Limit.of_option fee) + ~gas_limit:Limit.unknown + ~storage_limit:Limit.unknown + ~src_pk + ~src_sk:manager_sk + ~fee_parameter + operation + >>=? fun (oph, _, op, result) -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result + (Manager_operation _, Manager_operation_result _) -> + . + | Apply_results.Cons_and_result + ( (Manager_operation _ as op1), + res1, + Single_and_result ((Manager_operation _ as op2), res2) ) -> + return ((oph, op1, res1), Some (op2, res2))) let update_consensus_key cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing ?simulation ?fee ~consensus_pk ~manager_sk ~fee_parameter cycle src_pk = let source = Signature.Public_key.hash src_pk in - let operation = Update_consensus_key (cycle, consensus_pk) in - let operation = - Injection.prepare_manager_operation - ~fee:(Limit.of_option fee) - ~gas_limit:Limit.unknown - ~storage_limit:Limit.unknown - operation - in + let operation = build_update_consensus_key ?fee cycle consensus_pk in let operation = Annotated_manager_operation.Single_manager operation in Injection.inject_manager_operation cctxt diff --git a/src/proto_alpha/lib_client/client_proto_context.mli b/src/proto_alpha/lib_client/client_proto_context.mli index bdd669cf8c95..0aed3c23d8a5 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -173,8 +173,14 @@ val register_as_delegate : ?fee:Tez.tez -> manager_sk:Client_keys.sk_uri -> fee_parameter:Injection.fee_parameter -> + ?consensus_pk:public_key -> public_key -> - Kind.delegation Kind.manager Injection.result tzresult Lwt.t + (Kind.delegation Kind.manager Injection.result + * (Kind.update_consensus_key Kind.manager contents + * Kind.update_consensus_key Kind.manager Apply_results.contents_result) + option) + tzresult + Lwt.t val save_contract : force:bool -> diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index c2292f027c9e..c5b784b1f0c5 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -1428,6 +1428,46 @@ let commands_rw () = cctxt#message "Delegate already activated." >>= fun () -> return_unit | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Register the public key hash as a delegate." + (args4 fee_arg dry_run_switch verbose_signing_switch fee_parameter_args) + (prefixes ["register"; "key"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["as"; "delegate"; "with"; "consensus"; "key"] + @@ Public_key.source_param ~name:"key" ~desc:"the consensus key" + @@ stop) + (fun (fee, dry_run, verbose_signing, fee_parameter) + src_pkh + (name_pk, consensus_pk) + cctxt -> + Client_keys.get_key cctxt src_pkh >>=? fun (_, src_pk, src_sk) -> + (match consensus_pk with + | Some pk -> return pk + | None -> Client_keys.public_key name_pk) + >>=? fun consensus_pk -> + register_as_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~fee_parameter + ~verbose_signing + ?fee + ~manager_sk:src_sk + ~consensus_pk + src_pk + >>= function + | Ok _ -> return_unit + | Error + [ + Environment.Ecoproto_error + Delegate_storage.Contract.Active_delegate; + ] -> + cctxt#message "Delegate already activated." >>= fun () -> + return_unit + | Error el -> Lwt.return_error el); command ~group ~desc:"Update the consensus key of a delegate." -- GitLab From 65c4cd65c2aeaf31b7f89b9035804dd70644854a Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 30/42] Proto/RPC: add an RPC for querying a delegate's consensus key --- .../lib_protocol/delegate_services.ml | 55 +++++++++++++++++-- .../lib_protocol/delegate_services.mli | 10 ++++ .../lib_protocol/test/helpers/context.ml | 4 ++ .../lib_protocol/test/helpers/context.mli | 7 +++ ...lient) RPC regression tests- delegates.out | 3 +- ...light) RPC regression tests- delegates.out | 3 +- ...proxy) RPC regression tests- delegates.out | 3 +- ...a_dir) RPC regression tests- delegates.out | 3 +- ...r_rpc) RPC regression tests- delegates.out | 3 +- 9 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index 306c91216444..d1571231e1a3 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -83,6 +83,8 @@ type info = { deactivated : bool; grace_period : Cycle.t; voting_info : Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; } let info_encoding = @@ -99,6 +101,8 @@ let info_encoding = deactivated; grace_period; voting_info; + active_consensus_key; + pending_consensus_keys; } -> ( ( full_balance, current_frozen_deposits, @@ -109,7 +113,7 @@ let info_encoding = delegated_balance, deactivated, grace_period ), - voting_info )) + (voting_info, (active_consensus_key, pending_consensus_keys)) )) (fun ( ( full_balance, current_frozen_deposits, frozen_deposits, @@ -119,7 +123,7 @@ let info_encoding = delegated_balance, deactivated, grace_period ), - voting_info ) -> + (voting_info, (active_consensus_key, pending_consensus_keys)) ) -> { full_balance; current_frozen_deposits; @@ -131,6 +135,8 @@ let info_encoding = deactivated; grace_period; voting_info; + active_consensus_key; + pending_consensus_keys; }) (merge_objs (obj9 @@ -143,7 +149,17 @@ let info_encoding = (req "delegated_balance" Tez.encoding) (req "deactivated" bool) (req "grace_period" Cycle.encoding)) - Vote.delegate_info_encoding) + (merge_objs + Vote.delegate_info_encoding + (obj2 + (req "active_consensus_key" Signature.Public_key_hash.encoding) + (dft + "pending_consensus_keys" + (list + (obj2 + (req "cycle" Cycle.encoding) + (req "pkh" Signature.Public_key_hash.encoding))) + [])))) let participation_info_encoding = let open Data_encoding in @@ -331,6 +347,25 @@ module S = struct ~output:Vote.delegate_info_encoding RPC_path.(path / "voting_info") + let consensus_key = + RPC_service.get_service + ~description: + "The active consensus key for a given delegate and the pending \ + consensus keys." + ~query:RPC_query.empty + ~output: + Data_encoding.( + obj2 + (req "active" Signature.Public_key_hash.encoding) + (dft + "pendings" + (list + (obj2 + (req "cycle" Cycle.encoding) + (req "pkh" Signature.Public_key_hash.encoding))) + [])) + RPC_path.(path / "consensus_key") + let participation = RPC_service.get_service ~description: @@ -403,7 +438,9 @@ let register () = Delegate.delegated_balance ctxt pkh >>=? fun delegated_balance -> Delegate.deactivated ctxt pkh >>=? fun deactivated -> Delegate.last_cycle_before_deactivation ctxt pkh >>=? fun grace_period -> - Vote.get_delegate_info ctxt pkh >|=? fun voting_info -> + Vote.get_delegate_info ctxt pkh >>=? fun voting_info -> + Delegate.Consensus_key.active_pubkey ctxt pkh >>=? fun active_pk -> + Delegate.Consensus_key.pending_updates ctxt pkh >|=? fun pendings -> { full_balance; current_frozen_deposits = frozen_deposits.current_amount; @@ -415,6 +452,8 @@ let register () = deactivated; grace_period; voting_info; + active_consensus_key = active_pk.consensus_key; + pending_consensus_keys = pendings; }) ; register1 ~chunked:false S.full_balance (fun ctxt pkh () () -> trace (Balance_rpc_non_delegate pkh) (check_delegate_registered ctxt pkh) @@ -451,6 +490,11 @@ let register () = register1 ~chunked:false S.voting_info (fun ctxt pkh () () -> check_delegate_registered ctxt pkh >>=? fun () -> Vote.get_delegate_info ctxt pkh) ; + register1 ~chunked:false S.consensus_key (fun ctxt pkh () () -> + check_delegate_registered ctxt pkh >>=? fun () -> + Delegate.Consensus_key.active_pubkey ctxt pkh >>=? fun active_pk -> + Delegate.Consensus_key.pending_updates ctxt pkh >>=? fun pendings -> + return (active_pk.consensus_key, pendings)) ; register1 ~chunked:false S.participation (fun ctxt pkh () () -> check_delegate_registered ctxt pkh >>=? fun () -> Delegate.participation_info ctxt pkh) @@ -499,5 +543,8 @@ let voting_power ctxt block pkh = let voting_info ctxt block pkh = RPC_context.make_call1 S.voting_info ctxt block pkh () () +let consensus_key ctxt block pkh = + RPC_context.make_call1 S.consensus_key ctxt block pkh () () + let participation ctxt block pkh = RPC_context.make_call1 S.participation ctxt block pkh () () diff --git a/src/proto_alpha/lib_protocol/delegate_services.mli b/src/proto_alpha/lib_protocol/delegate_services.mli index a5eda671e57d..d1d235e47f57 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.mli +++ b/src/proto_alpha/lib_protocol/delegate_services.mli @@ -54,6 +54,8 @@ type info = { deactivated : bool; grace_period : Cycle.t; voting_info : Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; } val info_encoding : info Data_encoding.t @@ -127,6 +129,14 @@ val voting_info : public_key_hash -> Vote.delegate_info shell_tzresult Lwt.t +val consensus_key : + 'a #RPC_context.simple -> + 'a -> + Signature.Public_key_hash.t -> + (Signature.Public_key_hash.t * (Cycle.t * Signature.Public_key_hash.t) list) + shell_tzresult + Lwt.t + val participation : 'a #RPC_context.simple -> 'a -> diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.ml b/src/proto_alpha/lib_protocol/test/helpers/context.ml index 245918e388de..d042a0813737 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -328,6 +328,8 @@ module Delegate = struct deactivated : bool; grace_period : Cycle.t; voting_info : Alpha_context.Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; } let info ctxt pkh = Delegate_services.info rpc_ctxt ctxt pkh @@ -350,6 +352,8 @@ module Delegate = struct let voting_info ctxt d = Alpha_services.Delegate.voting_info rpc_ctxt ctxt d + let consensus_key ctxt pkh = Delegate_services.consensus_key rpc_ctxt ctxt pkh + let participation ctxt pkh = Delegate_services.participation rpc_ctxt ctxt pkh end diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli index 344e0ba7fbff..1e5df902b7e9 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli @@ -164,6 +164,8 @@ module Delegate : sig deactivated : bool; grace_period : Cycle.t; voting_info : Vote.delegate_info; + active_consensus_key : Signature.Public_key_hash.t; + pending_consensus_keys : (Cycle.t * Signature.Public_key_hash.t) list; } val info : t -> public_key_hash -> Delegate_services.info tzresult Lwt.t @@ -185,6 +187,11 @@ module Delegate : sig val voting_info : t -> public_key_hash -> Vote.delegate_info tzresult Lwt.t + val consensus_key : + t -> + public_key_hash -> + (public_key_hash * (Cycle.t * public_key_hash) list) tzresult Lwt.t + val participation : t -> public_key_hash -> Delegate.participation_info tzresult Lwt.t end diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- delegates.out index c5963596007d..7e05acf2dbfb 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- delegates.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- delegates.out @@ -21,7 +21,8 @@ "frozen_deposits": "200000000000", "staking_balance": "4000000000000", "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], "delegated_balance": "0", "deactivated": false, "grace_period": 5, - "voting_power": "4000000000000", "remaining_proposals": 20 } + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' "4000000000000" diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- delegates.out index 874166ce630e..839186e69dcc 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- delegates.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- delegates.out @@ -23,7 +23,8 @@ protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenes "frozen_deposits": "200000000000", "staking_balance": "4000000000000", "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], "delegated_balance": "0", "deactivated": false, "grace_period": 5, - "voting_power": "4000000000000", "remaining_proposals": 20 } + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode light rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- delegates.out index 8cc972f14b26..faaa3dc4e853 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- delegates.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- delegates.out @@ -23,7 +23,8 @@ protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGen "frozen_deposits": "200000000000", "staking_balance": "4000000000000", "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], "delegated_balance": "0", "deactivated": false, "grace_period": 5, - "voting_power": "4000000000000", "remaining_proposals": 20 } + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode proxy rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- delegates.out index c5963596007d..7e05acf2dbfb 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- delegates.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- delegates.out @@ -21,7 +21,8 @@ "frozen_deposits": "200000000000", "staking_balance": "4000000000000", "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], "delegated_balance": "0", "deactivated": false, "grace_period": 5, - "voting_power": "4000000000000", "remaining_proposals": 20 } + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' "4000000000000" diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- delegates.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- delegates.out index c5963596007d..7e05acf2dbfb 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- delegates.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- delegates.out @@ -21,7 +21,8 @@ "frozen_deposits": "200000000000", "staking_balance": "4000000000000", "delegated_contracts": [ "[PUBLIC_KEY_HASH]" ], "delegated_balance": "0", "deactivated": false, "grace_period": 5, - "voting_power": "4000000000000", "remaining_proposals": 20 } + "voting_power": "4000000000000", "remaining_proposals": 20, + "active_consensus_key": "[PUBLIC_KEY_HASH]" } ./tezos-client rpc get '/chains/main/blocks/head/context/delegates/[PUBLIC_KEY_HASH]/full_balance' "4000000000000" -- GitLab From d4a2dfcd05a3ced3f6cd1890b9df29529f9fca6e Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 31/42] Proto/Bootstrap: allow to register a consensus key for bootstrap accounts --- src/lib_store/test/alpha_utils.ml | 8 +- src/proto_alpha/lib_client/mockup.ml | 66 ++++------------ .../lib_parameters/default_parameters.ml | 12 ++- .../lib_parameters/default_parameters.mli | 3 +- .../lib_protocol/alpha_context.mli | 3 + .../lib_protocol/bootstrap_storage.ml | 8 +- .../lib_protocol/parameters_repr.ml | 75 +++++++++++++++++-- .../lib_protocol/parameters_repr.mli | 3 + .../lib_protocol/test/helpers/block.ml | 3 +- .../lib_protocol/test/helpers/context.ml | 5 +- .../test/integration/consensus/test_baking.ml | 2 +- 11 files changed, 121 insertions(+), 67 deletions(-) diff --git a/src/lib_store/test/alpha_utils.ml b/src/lib_store/test/alpha_utils.ml index 6369a58503c4..31a14e77165b 100644 --- a/src/lib_store/test/alpha_utils.ml +++ b/src/lib_store/test/alpha_utils.ml @@ -110,7 +110,13 @@ module Account = struct let account_to_bootstrap ({pkh; pk; _}, amount, delegate_to) = let open Parameters in - ({public_key_hash = pkh; public_key = Some pk; amount; delegate_to} + ({ + public_key_hash = pkh; + public_key = Some pk; + amount; + delegate_to; + consensus_key = None; + } : bootstrap_account) let commitment_secret = diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml index 61f6f7764854..bcb373b34fb2 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -1144,6 +1144,7 @@ module Parsed_account = struct public_key = Some public_key; amount = repr.amount; delegate_to = None; + consensus_key = None; } let default_to_json (cctxt : Tezos_client_base.Client_context.full) : @@ -1195,37 +1196,17 @@ module Bootstrap_account = struct let encoding : Parameters.bootstrap_account Data_encoding.t = let open Data_encoding in let open Parameters in - union - [ - case - ~title:"No delegate" - (Tag 0) - (obj3 - (req "public_key_hash" Signature.Public_key_hash.encoding) - (opt "public_key" Signature.Public_key.encoding) - (req "amount" Tez.encoding)) - (function - | {public_key_hash; public_key; amount; delegate_to = None} -> - Some (public_key_hash, public_key, amount) - | _ -> None) - (fun (public_key_hash, public_key, amount) -> - {public_key_hash; public_key; amount; delegate_to = None}); - case - ~title:"With delegate" - (Tag 1) - (obj4 - (req "public_key_hash" Signature.Public_key_hash.encoding) - (opt "public_key" Signature.Public_key.encoding) - (req "amount" Tez.encoding) - (req "delegate_to" Signature.Public_key_hash.encoding)) - (function - | {public_key_hash; public_key; amount; delegate_to = Some delegate} - -> - Some (public_key_hash, public_key, amount, delegate) - | _ -> None) - (fun (public_key_hash, public_key, amount, delegate) -> - {public_key_hash; public_key; amount; delegate_to = Some delegate}); - ] + conv + (fun {public_key_hash; public_key; amount; delegate_to; consensus_key} -> + (public_key_hash, public_key, amount, delegate_to, consensus_key)) + (fun (public_key_hash, public_key, amount, delegate_to, consensus_key) -> + {public_key_hash; public_key; amount; delegate_to; consensus_key}) + (obj5 + (req "public_key_hash" Signature.Public_key_hash.encoding) + (opt "public_key" Signature.Public_key.encoding) + (req "amount" Tez.encoding) + (opt "delegate_to" Signature.Public_key_hash.encoding) + (opt "consensus_key" Signature.Public_key.encoding)) end module Bootstrap_contract = struct @@ -1282,31 +1263,12 @@ module Protocol_parameters = struct end (* This encoding extends [Protocol_constants_overrides.encoding] to allow - reading json files as produced by lib_parameters. Sadly, this require - copying partially [bootstrap_account_encoding], which is not exposed - in parameters_repr.ml. *) + reading json files as produced by lib_parameters. *) let lib_parameters_json_encoding = - let bootstrap_account_encoding = - let open Data_encoding in - conv - (function - | {Parameters.public_key; amount; _} -> ( - match public_key with - | None -> assert false - | Some pk -> (pk, amount))) - (fun (pk, amount) -> - { - Parameters.public_key = Some pk; - public_key_hash = Signature.Public_key.hash pk; - amount; - delegate_to = None; - }) - (tup2 Signature.Public_key.encoding Tez.encoding) - in Data_encoding.( merge_objs (obj2 - (opt "bootstrap_accounts" (list bootstrap_account_encoding)) + (opt "bootstrap_accounts" (list Parameters.bootstrap_account_encoding)) (opt "commitments" (list Commitment.encoding))) Protocol_constants_overrides.encoding) diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 36ce5101dabd..5b6332237ac4 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -313,12 +313,20 @@ let compute_accounts = public_key = Some public_key; amount = bootstrap_balance; delegate_to = None; + consensus_key = None; }) let bootstrap_accounts = compute_accounts bootstrap_accounts_strings -let make_bootstrap_account (pkh, pk, amount, delegate_to) = - Parameters.{public_key_hash = pkh; public_key = Some pk; amount; delegate_to} +let make_bootstrap_account (pkh, pk, amount, delegate_to, consensus_key) = + Parameters. + { + public_key_hash = pkh; + public_key = Some pk; + amount; + delegate_to; + consensus_key; + } let parameters_of_constants ?(bootstrap_accounts = bootstrap_accounts) ?(bootstrap_contracts = []) ?(commitments = []) constants = diff --git a/src/proto_alpha/lib_parameters/default_parameters.mli b/src/proto_alpha/lib_parameters/default_parameters.mli index 8aeb40866526..eff7da674972 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.mli +++ b/src/proto_alpha/lib_parameters/default_parameters.mli @@ -38,7 +38,8 @@ val make_bootstrap_account : Signature.public_key_hash * Signature.public_key * Tez.t - * Signature.public_key_hash option -> + * Signature.public_key_hash option + * Signature.public_key option -> Parameters.bootstrap_account val parameters_of_constants : diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 1de25f877cef..a688448f5cea 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3926,6 +3926,7 @@ module Parameters : sig public_key : public_key option; amount : Tez.t; delegate_to : public_key_hash option; + consensus_key : public_key option; } type bootstrap_contract = { @@ -3943,6 +3944,8 @@ module Parameters : sig no_reward_cycles : int option; } + val bootstrap_account_encoding : bootstrap_account Data_encoding.t + val encoding : t Data_encoding.t end diff --git a/src/proto_alpha/lib_protocol/bootstrap_storage.ml b/src/proto_alpha/lib_protocol/bootstrap_storage.ml index d37f5c3c699e..af0f71358bb6 100644 --- a/src/proto_alpha/lib_protocol/bootstrap_storage.ml +++ b/src/proto_alpha/lib_protocol/bootstrap_storage.ml @@ -24,7 +24,7 @@ (*****************************************************************************) let init_account (ctxt, balance_updates) - ({public_key_hash; public_key; amount; delegate_to} : + ({public_key_hash; public_key; amount; delegate_to; consensus_key} : Parameters_repr.bootstrap_account) = let contract = Contract_repr.Implicit public_key_hash in Token.transfer @@ -45,6 +45,12 @@ let init_account (ctxt, balance_updates) ctxt contract (Some (Option.value ~default:public_key_hash delegate_to)) + >>=? fun ctxt -> + (match consensus_key with + | None -> return ctxt + | Some consensus_key -> + Delegate_consensus_key.init ctxt public_key_hash consensus_key) + >>=? fun ctxt -> return ctxt | None -> return ctxt) >|=? fun ctxt -> (ctxt, new_balance_updates @ balance_updates) diff --git a/src/proto_alpha/lib_protocol/parameters_repr.ml b/src/proto_alpha/lib_protocol/parameters_repr.ml index 3ab238b23d48..13604ffdc600 100644 --- a/src/proto_alpha/lib_protocol/parameters_repr.ml +++ b/src/proto_alpha/lib_protocol/parameters_repr.ml @@ -29,6 +29,7 @@ type bootstrap_account = { public_key : Signature.Public_key.t option; amount : Tez_repr.t; delegate_to : Signature.Public_key_hash.t option; + consensus_key : Signature.Public_key.t option; } type bootstrap_contract = { @@ -60,30 +61,50 @@ let bootstrap_account_encoding = public_key = Some public_key; amount; delegate_to = None; + consensus_key = None; } -> assert ( Signature.Public_key_hash.equal (Signature.Public_key.hash public_key) public_key_hash) ; Some (public_key, amount) - | {public_key = None; _} | {delegate_to = Some _; _} -> None) + | {public_key = None; _} + | {delegate_to = Some _; _} + | {consensus_key = Some _; _} -> + None) (fun (public_key, amount) -> { public_key = Some public_key; public_key_hash = Signature.Public_key.hash public_key; amount; delegate_to = None; + consensus_key = None; }); case (Tag 1) ~title:"Public_key_unknown" (tup2 Signature.Public_key_hash.encoding Tez_repr.encoding) (function - | {public_key_hash; public_key = None; amount; delegate_to = None} -> + | { + public_key_hash; + public_key = None; + amount; + delegate_to = None; + consensus_key = None; + } -> Some (public_key_hash, amount) - | {public_key = Some _; _} | {delegate_to = Some _; _} -> None) + | {public_key = Some _; _} + | {delegate_to = Some _; _} + | {consensus_key = Some _; _} -> + None) (fun (public_key_hash, amount) -> - {public_key = None; public_key_hash; amount; delegate_to = None}); + { + public_key = None; + public_key_hash; + amount; + delegate_to = None; + consensus_key = None; + }); case (Tag 2) ~title:"Public_key_known_with_delegate" @@ -97,19 +118,24 @@ let bootstrap_account_encoding = public_key = Some public_key; amount; delegate_to = Some delegate; + consensus_key = None; } -> assert ( Signature.Public_key_hash.equal (Signature.Public_key.hash public_key) public_key_hash) ; Some (public_key, amount, delegate) - | {public_key = None; _} | {delegate_to = None; _} -> None) + | {public_key = None; _} + | {delegate_to = None; _} + | {consensus_key = Some _; _} -> + None) (fun (public_key, amount, delegate) -> { public_key = Some public_key; public_key_hash = Signature.Public_key.hash public_key; amount; delegate_to = Some delegate; + consensus_key = None; }); case (Tag 3) @@ -124,15 +150,52 @@ let bootstrap_account_encoding = public_key = None; amount; delegate_to = Some delegate; + consensus_key = None; } -> Some (public_key_hash, amount, delegate) - | {public_key = Some _; _} | {delegate_to = None; _} -> None) + | {public_key = Some _; _} + | {delegate_to = None; _} + | {consensus_key = Some _; _} -> + None) (fun (public_key_hash, amount, delegate) -> { public_key = None; public_key_hash; amount; delegate_to = Some delegate; + consensus_key = None; + }); + case + (Tag 4) + ~title:"Public_key_known_with_consensus_key" + (tup3 + Signature.Public_key.encoding + Tez_repr.encoding + Signature.Public_key.encoding) + (function + | { + public_key_hash; + public_key = Some public_key; + amount; + delegate_to = None; + consensus_key = Some consensus_key; + } -> + assert ( + Signature.Public_key_hash.equal + (Signature.Public_key.hash public_key) + public_key_hash) ; + Some (public_key, amount, consensus_key) + | {public_key = None; _} + | {delegate_to = Some _; _} + | {consensus_key = None; _} -> + None) + (fun (public_key, amount, consensus_key) -> + { + public_key = Some public_key; + public_key_hash = Signature.Public_key.hash public_key; + amount; + delegate_to = None; + consensus_key = Some consensus_key; }); ] diff --git a/src/proto_alpha/lib_protocol/parameters_repr.mli b/src/proto_alpha/lib_protocol/parameters_repr.mli index 844e54ba3753..97bad09f1ccb 100644 --- a/src/proto_alpha/lib_protocol/parameters_repr.mli +++ b/src/proto_alpha/lib_protocol/parameters_repr.mli @@ -33,6 +33,7 @@ type bootstrap_account = { public_key : Signature.Public_key.t option; amount : Tez_repr.t; delegate_to : Signature.Public_key_hash.t option; + consensus_key : Signature.Public_key.t option; } (** An originated contract initially existing on a chain since genesis. *) @@ -53,6 +54,8 @@ type t = { no_reward_cycles : int option; } +val bootstrap_account_encoding : bootstrap_account Data_encoding.t + val encoding : t Data_encoding.t val check_params : t -> unit tzresult diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 8482f21b4559..b23a0bfae818 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -276,7 +276,8 @@ let prepare_main_init_params ?bootstrap_contracts commitments constants let bootstrap_accounts = List.map (fun (Account.{pk; pkh; _}, amount, delegate_to) -> - Default_parameters.make_bootstrap_account (pkh, pk, amount, delegate_to)) + Default_parameters.make_bootstrap_account + (pkh, pk, amount, delegate_to, None)) initial_accounts in let parameters = diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.ml b/src/proto_alpha/lib_protocol/test/helpers/context.ml index d042a0813737..0b1eac01bff5 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -461,7 +461,7 @@ let init_with_constants_gen tup constants = List.map (fun (acc, tez, delegate_to) -> Default_parameters.make_bootstrap_account - (acc.Account.pkh, acc.Account.pk, tez, delegate_to)) + (acc.Account.pkh, acc.Account.pk, tez, delegate_to, None)) accounts in let parameters = @@ -484,7 +484,8 @@ let default_raw_context () = let bootstrap_accounts = List.map (fun (Account.{pk; pkh; _}, amount, delegate_to) -> - Default_parameters.make_bootstrap_account (pkh, pk, amount, delegate_to)) + Default_parameters.make_bootstrap_account + (pkh, pk, amount, delegate_to, None)) initial_accounts in Block.prepare_initial_context_params initial_accounts diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml index 6a6bd357fc3c..f7179edab1b3 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_baking.ml @@ -344,7 +344,7 @@ let test_committee_sampling () = List.map (fun (acc, tez, delegate_to) -> Default_parameters.make_bootstrap_account - (acc.Account.pkh, acc.Account.pk, tez, delegate_to)) + (acc.Account.pkh, acc.Account.pk, tez, delegate_to, None)) accounts in let consensus_committee_size = max_round in -- GitLab From 993ccef540ec9f1713943ea9f7c265e5605d4cea Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 32/42] Proto: make room for more ghosts in `Storage_functors`. --- src/proto_alpha/lib_protocol/storage.ml | 37 ++++++++++++++++++- .../lib_protocol/storage_functors.ml | 16 ++++++-- src/proto_alpha/lib_protocol/storage_sigs.ml | 4 +- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 2c2369f03a88..804aca54990c 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -190,6 +190,7 @@ module Contract = struct module Spendable_balance = Indexed_context.Make_map + (Registered) (struct let name = ["balance"] end) @@ -197,6 +198,7 @@ module Contract = struct module Missed_endorsements = Indexed_context.Make_map + (Registered) (struct let name = ["missed_endorsements"] end) @@ -204,6 +206,7 @@ module Contract = struct module Manager = Indexed_context.Make_map + (Registered) (struct let name = ["manager"] end) @@ -228,6 +231,7 @@ module Contract = struct module Delegate = Indexed_context.Make_map + (Registered) (struct let name = ["delegate"] end) @@ -242,6 +246,7 @@ module Contract = struct module Delegate_last_cycle_before_deactivation = Indexed_context.Make_map + (Registered) (struct (* FIXME? Change the key name to reflect the functor's name *) let name = ["delegate_desactivation"] @@ -258,6 +263,7 @@ module Contract = struct module Counter = Indexed_context.Make_map + (Registered) (struct let name = ["counter"] end) @@ -271,8 +277,7 @@ module Contract = struct and type value = Script_repr.lazy_expr and type t := Raw_context.t = struct module I = - Indexed_context.Make_carbonated_map - (N) + Indexed_context.Make_carbonated_map (Registered) (N) (struct type t = Script_repr.lazy_expr @@ -341,6 +346,7 @@ module Contract = struct module Paid_storage_space = Indexed_context.Make_map + (Registered) (struct let name = ["paid_bytes"] end) @@ -348,6 +354,7 @@ module Contract = struct module Used_storage_space = Indexed_context.Make_map + (Registered) (struct let name = ["used_bytes"] end) @@ -355,6 +362,7 @@ module Contract = struct module Frozen_deposits = Indexed_context.Make_map + (Registered) (struct let name = ["frozen_deposits"] end) @@ -362,6 +370,7 @@ module Contract = struct module Frozen_deposits_limit = Indexed_context.Make_map + (Registered) (struct let name = ["frozen_deposits_limit"] end) @@ -377,6 +386,7 @@ module Contract = struct module Frozen_bonds = Bond_id_index.Make_carbonated_map + (Registered) (struct let name = ["frozen_bonds"] end) @@ -386,6 +396,7 @@ module Contract = struct module Total_frozen_bonds = Indexed_context.Make_map + (Registered) (struct let name = ["total_frozen_bonds"] end) @@ -470,6 +481,7 @@ module Big_map = struct module Total_bytes = Indexed_context.Make_map + (Registered) (struct let name = ["total_bytes"] end) @@ -477,6 +489,7 @@ module Big_map = struct module Key_type = Indexed_context.Make_map + (Registered) (struct let name = ["key_type"] end) @@ -488,6 +501,7 @@ module Big_map = struct module Value_type = Indexed_context.Make_map + (Registered) (struct let name = ["value_type"] end) @@ -599,6 +613,7 @@ module Sapling = struct module Total_bytes = Indexed_context.Make_map + (Registered) (struct let name = ["total_bytes"] end) @@ -967,6 +982,7 @@ module Cycle = struct module Selected_stake_distribution = Indexed_context.Make_map + (Registered) (struct let name = ["selected_stake_distribution"] end) @@ -983,6 +999,7 @@ module Cycle = struct module Total_active_stake = Indexed_context.Make_map + (Registered) (struct let name = ["total_active_stake"] end) @@ -996,6 +1013,7 @@ module Cycle = struct module Delegate_sampler_state = Indexed_context.Make_map + (Registered) (struct let name = ["delegate_sampler_state"] end) @@ -1050,6 +1068,7 @@ module Cycle = struct module Seed = Indexed_context.Make_map + (Registered) (struct let name = ["random_seed"] end) @@ -1442,6 +1461,7 @@ module Tx_rollup = struct module State = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["state"] end) @@ -1457,6 +1477,7 @@ module Tx_rollup = struct module Inbox = Level_context.Make_carbonated_map + (Registered) (struct let name = ["inbox"] end) @@ -1468,6 +1489,7 @@ module Tx_rollup = struct module Revealed_withdrawals = Level_context.Make_carbonated_map + (Registered) (struct let name = ["withdrawals"] end) @@ -1475,6 +1497,7 @@ module Tx_rollup = struct module Commitment = Level_context.Make_carbonated_map + (Registered) (struct let name = ["commitment"] end) @@ -1490,6 +1513,7 @@ module Tx_rollup = struct module Commitment_bond = Bond_indexed_context.Make_carbonated_map + (Registered) (struct let name = ["commitment"] end) @@ -1561,6 +1585,7 @@ module Sc_rollup = struct module PVM_kind = Indexed_context.Make_map + (Registered) (struct let name = ["kind"] end) @@ -1572,6 +1597,7 @@ module Sc_rollup = struct module Boot_sector = Indexed_context.Make_map + (Registered) (struct let name = ["boot_sector"] end) @@ -1583,6 +1609,7 @@ module Sc_rollup = struct module Parameters_type = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["parameters_type"] end) @@ -1594,6 +1621,7 @@ module Sc_rollup = struct module Initial_level = Indexed_context.Make_map + (Registered) (struct let name = ["initial_level"] end) @@ -1605,6 +1633,7 @@ module Sc_rollup = struct module Inbox = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["inbox"] end) @@ -1616,6 +1645,7 @@ module Sc_rollup = struct module Last_cemented_commitment = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["last_cemented_commitment"] end) @@ -1640,6 +1670,7 @@ module Sc_rollup = struct module Staker_count = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["staker_count"] end) @@ -1777,6 +1808,7 @@ module Sc_rollup = struct module Applied_outbox_messages = Level_index_context.Make_carbonated_map + (Registered) (struct let name = ["applied_outbox_messages"] end) @@ -1804,6 +1836,7 @@ module Dal = struct to index each header directly. *) module Slot_headers = Level_context.Make_map + (Registered) (struct let name = ["slots"] end) diff --git a/src/proto_alpha/lib_protocol/storage_functors.ml b/src/proto_alpha/lib_protocol/storage_functors.ml index d32d3f00c456..8652c9598192 100644 --- a/src/proto_alpha/lib_protocol/storage_functors.ml +++ b/src/proto_alpha/lib_protocol/storage_functors.ml @@ -882,7 +882,7 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : [@@coq_axiom_with_reason "stack overflow in Coq"] end - module Make_map (N : NAME) (V : VALUE) : + module Make_map (R : REGISTER) (N : NAME) (V : VALUE) : Indexed_data_storage with type t = t and type key = key and type value = V.t = struct type t = C.t @@ -966,16 +966,20 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : let () = let open Storage_description in let unpack = unpack I.args in + let description = + if R.ghost then Storage_description.create () + else Raw_context.description + in register_value ~get:(fun c -> let c, k = unpack c in find c k) - (register_named_subcontext Raw_context.description N.name) + (register_named_subcontext description N.name) V.encoding [@@coq_axiom_with_reason "stack overflow in Coq"] end - module Make_carbonated_map (N : NAME) (V : VALUE) : + module Make_carbonated_map (R : REGISTER) (N : NAME) (V : VALUE) : Non_iterable_indexed_carbonated_data_storage with type t = t and type key = key @@ -1082,11 +1086,15 @@ module Make_indexed_subcontext (C : Raw_context.T) (I : INDEX) : let () = let open Storage_description in let unpack = unpack I.args in + let description = + if R.ghost then Storage_description.create () + else Raw_context.description + in register_value ~get:(fun c -> let c, k = unpack c in find c k >|=? fun (_, v) -> v) - (register_named_subcontext Raw_context.description N.name) + (register_named_subcontext description N.name) V.encoding [@@coq_axiom_with_reason "stack overflow in Coq"] end diff --git a/src/proto_alpha/lib_protocol/storage_sigs.ml b/src/proto_alpha/lib_protocol/storage_sigs.ml index ad16d90af855..b38b18ae7c08 100644 --- a/src/proto_alpha/lib_protocol/storage_sigs.ml +++ b/src/proto_alpha/lib_protocol/storage_sigs.ml @@ -410,10 +410,10 @@ module type Indexed_raw_context = sig module Make_set (_ : REGISTER) (_ : NAME) : Data_set_storage with type t = t and type elt = key - module Make_map (_ : NAME) (V : VALUE) : + module Make_map (_ : REGISTER) (_ : NAME) (V : VALUE) : Indexed_data_storage with type t = t and type key = key and type value = V.t - module Make_carbonated_map (_ : NAME) (V : VALUE) : + module Make_carbonated_map (_ : REGISTER) (_ : NAME) (V : VALUE) : Non_iterable_indexed_carbonated_data_storage with type t = t and type key = key -- GitLab From 5942ce62309bf9b50852f845b24003ae7a902efc Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 33/42] Proto/Delegate: capture the consensus key in the sampler state --- .../test/tenderbrute/lib/tenderbrute.ml | 2 +- src/proto_alpha/lib_protocol/alpha_context.ml | 13 +++++-- .../lib_protocol/delegate_consensus_key.ml | 2 +- .../lib_protocol/delegate_consensus_key.mli | 2 +- .../lib_protocol/delegate_cycles.ml | 13 +++++++ .../lib_protocol/delegate_sampler.ml | 29 +++++++++++---- .../lib_protocol/delegate_sampler.mli | 14 ++++---- src/proto_alpha/lib_protocol/raw_context.ml | 36 ++++++++++++++++--- src/proto_alpha/lib_protocol/raw_context.mli | 32 ++++++++--------- src/proto_alpha/lib_protocol/storage.ml | 35 +++++++++++++----- src/proto_alpha/lib_protocol/storage.mli | 12 +++++-- 11 files changed, 141 insertions(+), 49 deletions(-) diff --git a/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml b/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml index fa99d708a0a1..944f29aab6ec 100644 --- a/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml +++ b/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml @@ -102,7 +102,7 @@ let check ctxt ~selection = (fun (level, round) delegate ctxt -> Delegate_sampler.baking_rights_owner ctxt level ~round >|= Environment.wrap_tzresult - >>=? fun (ctxt, _, (_, pkh)) -> + >>=? fun (ctxt, _, {delegate = pkh; _}) -> if not (Signature.Public_key_hash.equal delegate pkh) then raise Exit else return ctxt) selection diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 5db6129465e1..d874607f4aa2 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -464,9 +464,16 @@ module Stake_distribution = struct let compute_snapshot_index = Delegate_sampler.compute_snapshot_index - let baking_rights_owner = Delegate_sampler.baking_rights_owner - - let slot_owner = Delegate_sampler.slot_owner + let baking_rights_owner ctxt lvl ~round = + (* GB.FEFE: temporary hack removed in a later patch *) + Delegate_sampler.baking_rights_owner ctxt lvl ~round + >>=? fun (ctxt, slot, owner) -> + return (ctxt, slot, (owner.delegate_public_key, owner.delegate)) + + let slot_owner ctxt lvl slot = + (* GB.FEFE: temporary hack removed in a later patch *) + Delegate_sampler.slot_owner ctxt lvl slot >>=? fun (ctxt, owner) -> + return (ctxt, (owner.delegate_public_key, owner.delegate)) let get_staking_balance = Delegate_storage.staking_balance end diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml index 0b24cd14e74a..5a0b7937641a 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml @@ -71,7 +71,7 @@ let () = (function Invalid_consensus_key_update_active -> Some () | _ -> None) (fun () -> Invalid_consensus_key_update_active) -type pk = { +type pk = Raw_context.consensus_pk = { delegate : Signature.public_key_hash; delegate_public_key : Signature.public_key; consensus_key : Signature.public_key_hash; diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli index 5a539c4cf48a..1d3cd639258b 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli @@ -29,7 +29,7 @@ type error += | Invalid_consensus_key_update_active (** The public key of a consensus key and the associated delegate. *) -type pk = { +type pk = Raw_context.consensus_pk = { delegate : Signature.public_key_hash; delegate_public_key : Signature.public_key; consensus_key : Signature.public_key_hash; diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index ebcfed0618a5..438d57d7aece 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -292,5 +292,18 @@ module Migration_from_Jakarta = struct let open Lwt_tzresult_syntax in let*! delegates = Storage.Delegates.elements ctxt in let* ctxt = List.fold_left_es update_delegate ctxt delegates in + let*! cycles = + Storage.Migration_from_Jakarta.Delegate_sampler_state.keys ctxt + in + let*! ctxt = + Storage.Migration_from_Jakarta.Delegate_sampler_state.clear ctxt + in + let*? ctxt = Raw_context.Migration_from_Jakarta.reset_samplers ctxt in + let* ctxt = + List.fold_left_es + Delegate_sampler.Migration_from_Jakarta.update_sampler + ctxt + cycles + in return ctxt end diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index d6b4dca1c52f..62a11223690d 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -27,8 +27,7 @@ module Delegate_sampler_state = struct module Cache_client = struct - type cached_value = - (Signature.public_key * Signature.public_key_hash) Sampler.t + type cached_value = Delegate_consensus_key.pk Sampler.t let namespace = Cache_repr.create_namespace "sampler_state" @@ -133,8 +132,8 @@ module Random = struct let elt, _ = take_int64 mass_bound state in (Int64.to_int i, elt) in - let pk, pkh = Sampler.sample state sample in - return (c, (pk, pkh)) + let pk = Sampler.sample state sample in + return (c, pk) end let slot_owner c level slot = Random.owner c level (Slot_repr.to_int slot) @@ -217,8 +216,8 @@ let select_distribution_for_cycle ctxt cycle = >>=? fun ctxt -> List.fold_left_es (fun acc (pkh, stake) -> - Delegate_storage.manager_pubkey ctxt pkh >|=? fun pk -> - ((pk, pkh), Tez_repr.to_mutez stake) :: acc) + Delegate_consensus_key.active_pubkey_for_cycle ctxt pkh cycle + >|=? fun pk -> (pk, Tez_repr.to_mutez stake) :: acc) [] stakes >>=? fun stakes_pk -> @@ -239,3 +238,21 @@ let clear_outdated_sampling_data ctxt ~new_cycle = | Some outdated_cycle -> Delegate_sampler_state.remove_existing ctxt outdated_cycle >>=? fun ctxt -> Seed_storage.remove_for_cycle ctxt outdated_cycle + +module Migration_from_Jakarta = struct + let update_sampler ctxt cycle = + let open Lwt_tzresult_syntax in + let* stakes = Stake_storage.get_selected_distribution ctxt cycle in + let* stakes_pk = + List.fold_left_es + (fun acc (delegate, stake) -> + Delegate_consensus_key.active_pubkey ctxt delegate >>=? fun pk -> + return ((pk, Tez_repr.to_mutez stake) :: acc)) + [] + stakes + in + let state = Sampler.create stakes_pk in + Delegate_sampler_state.init ctxt cycle state >>=? fun ctxt -> + Storage.Seed.For_cycle.get ctxt cycle >>=? fun seed -> + Lwt.return (Raw_context.init_sampler_for_cycle ctxt cycle seed state) +end diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.mli b/src/proto_alpha/lib_protocol/delegate_sampler.mli index b011b056c2b6..b798625758df 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.mli +++ b/src/proto_alpha/lib_protocol/delegate_sampler.mli @@ -45,18 +45,13 @@ val slot_owner : Raw_context.t -> Level_repr.t -> Slot_repr.t -> - (Raw_context.t * (Signature.public_key * Signature.public_key_hash)) tzresult - Lwt.t + (Raw_context.t * Delegate_consensus_key.pk) tzresult Lwt.t val baking_rights_owner : Raw_context.t -> Level_repr.t -> round:Round_repr.round -> - (Raw_context.t - * Slot_repr.t - * (Signature.public_key * Signature.public_key_hash)) - tzresult - Lwt.t + (Raw_context.t * Slot_repr.t * Delegate_consensus_key.pk) tzresult Lwt.t (** [compute_snapshot_index ctxt cycle max_snapshot_index] Returns the index of the selected snapshot for the [cycle] passed as argument, and for the max @@ -73,3 +68,8 @@ val clear_outdated_sampling_data : val select_distribution_for_cycle : Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t + +module Migration_from_Jakarta : sig + val update_sampler : + Raw_context.t -> Cycle_repr.t -> Raw_context.t tzresult Lwt.t +end diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 400d1d9d5c0d..e45011558c42 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -73,6 +73,31 @@ module Sc_rollup_address_map_builder = *) +type consensus_pk = { + delegate : Signature.public_key_hash; + delegate_public_key : Signature.public_key; + consensus_key : Signature.public_key_hash; + consensus_public_key : Signature.public_key; +} + +let consensus_pk_encoding = + let open Data_encoding in + conv + (fun {delegate; delegate_public_key; consensus_key; consensus_public_key} -> + if Signature.Public_key_hash.equal consensus_key delegate then + (consensus_public_key, None) + else (consensus_public_key, Some delegate_public_key)) + (fun (consensus_public_key, delegate_public_key) -> + let consensus_key = Signature.Public_key.hash consensus_public_key in + let delegate_public_key = + Option.value ~default:consensus_public_key delegate_public_key + in + let delegate = Signature.Public_key.hash delegate_public_key in + {delegate; delegate_public_key; consensus_public_key; consensus_key}) + (obj2 + (req "consensus_key" Signature.Public_key.encoding) + (opt "delegate" Signature.Public_key.encoding)) + module Raw_consensus = struct (** Consensus operations are indexed by their [initial slots]. Given a delegate, the [initial slot] is the lowest slot assigned to @@ -238,10 +263,7 @@ type back = { unlimited_operation_gas : bool; consensus : Raw_consensus.t; non_consensus_operations_rev : Operation_hash.t list; - sampler_state : - (Seed_repr.seed - * (Signature.Public_key.t * Signature.Public_key_hash.t) Sampler.t) - Cycle_repr.Map.t; + sampler_state : (Seed_repr.seed * consensus_pk Sampler.t) Cycle_repr.Map.t; stake_distribution_for_current_cycle : Tez_repr.t Signature.Public_key_hash.Map.t option; tx_rollup_current_messages : @@ -1250,6 +1272,12 @@ let record_non_consensus_operation_hash ctxt operation_hash = let non_consensus_operations ctxt = List.rev (non_consensus_operations_rev ctxt) +module Migration_from_Jakarta = struct + let reset_samplers ctxt = + let ctxt = update_sampler_state ctxt Cycle_repr.Map.empty in + ok ctxt +end + let init_sampler_for_cycle ctxt cycle seed state = let map = sampler_state ctxt in if Cycle_repr.Map.mem cycle map then error (Sampler_already_set cycle) diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index eea016f1bdc3..7b0c3a70f6c3 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -221,14 +221,19 @@ val record_non_consensus_operation_hash : t -> Operation_hash.t -> t val non_consensus_operations : t -> Operation_hash.t list +type consensus_pk = { + delegate : Signature.public_key_hash; + delegate_public_key : Signature.public_key; + consensus_key : Signature.public_key_hash; + consensus_public_key : Signature.public_key; +} + +val consensus_pk_encoding : consensus_pk Data_encoding.t + (** [init_sampler_for_cycle ctxt cycle seed state] caches the seeded stake sampler (a.k.a. [seed, state]) for [cycle] in memory for quick access. *) val init_sampler_for_cycle : - t -> - Cycle_repr.t -> - Seed_repr.seed -> - (Signature.public_key * Signature.public_key_hash) Sampler.t -> - t tzresult + t -> Cycle_repr.t -> Seed_repr.seed -> consensus_pk Sampler.t -> t tzresult (** [sampler_for_cycle ~read ctxt cycle] returns the seeded stake sampler for [cycle]. The sampler is read in memory if @@ -237,19 +242,10 @@ val init_sampler_for_cycle : the [read] function and then cached in [ctxt] like [init_sampler_for_cycle]. *) val sampler_for_cycle : - read: - (t -> - (Seed_repr.seed - * (Signature.public_key * Signature.public_key_hash) Sampler.t) - tzresult - Lwt.t) -> + read:(t -> (Seed_repr.seed * consensus_pk Sampler.t) tzresult Lwt.t) -> t -> Cycle_repr.t -> - (t - * Seed_repr.seed - * (Signature.public_key * Signature.public_key_hash) Sampler.t) - tzresult - Lwt.t + (t * Seed_repr.seed * consensus_pk Sampler.t) tzresult Lwt.t (* The stake distribution is stored both in [t] and in the cache. It may be sufficient to only store it in the cache. *) @@ -410,3 +406,7 @@ module Dal : sig [endorser] for the current level. *) val shards : t -> endorser:Signature.Public_key_hash.t -> int list end + +module Migration_from_Jakarta : sig + val reset_samplers : t -> t tzresult +end diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 804aca54990c..027047aa2b82 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1005,11 +1005,26 @@ module Cycle = struct end) (Tez_repr) - let public_key_with_ghost_hash_encoding = - Data_encoding.conv - fst - (fun x -> (x, Signature.Public_key.hash x)) - Signature.Public_key.encoding + module Migration_from_Jakarta = struct + let public_key_with_ghost_hash_encoding = + Data_encoding.conv + fst + (fun x -> (x, Signature.Public_key.hash x)) + Signature.Public_key.encoding + + module Delegate_sampler_state = + Indexed_context.Make_map + (Ghost) + (struct + let name = ["delegate_sampler_state"] + end) + (struct + type t = + (Signature.Public_key.t * Signature.Public_key_hash.t) Sampler.t + + let encoding = Sampler.encoding public_key_with_ghost_hash_encoding + end) + end module Delegate_sampler_state = Indexed_context.Make_map @@ -1018,10 +1033,9 @@ module Cycle = struct let name = ["delegate_sampler_state"] end) (struct - type t = - (Signature.Public_key.t * Signature.Public_key_hash.t) Sampler.t + type t = Raw_context.consensus_pk Sampler.t - let encoding = Sampler.encoding public_key_with_ghost_hash_encoding + let encoding = Sampler.encoding Raw_context.consensus_pk_encoding end) type unrevealed_nonce = { @@ -1846,3 +1860,8 @@ module Dal = struct let encoding = Data_encoding.(list Dal_slot_repr.encoding) end) end + +module Migration_from_Jakarta = struct + module Delegate_sampler_state = + Cycle.Migration_from_Jakarta.Delegate_sampler_state +end diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 7356fd245d42..21f5411aaa1e 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -417,8 +417,7 @@ end module Delegate_sampler_state : Indexed_data_storage with type key = Cycle_repr.t - and type value = - (Signature.Public_key.t * Signature.Public_key_hash.t) Sampler.t + and type value = Raw_context.consensus_pk Sampler.t and type t := Raw_context.t (** Votes *) @@ -852,3 +851,12 @@ module Dal : sig and type key = Raw_level_repr.t and type value = Dal_slot_repr.slot list end + +module Migration_from_Jakarta : sig + module Delegate_sampler_state : + Indexed_data_storage + with type key = Cycle_repr.t + and type value = + (Signature.Public_key.t * Signature.Public_key_hash.t) Sampler.t + and type t := Raw_context.t +end -- GitLab From 47ba7b7262cdf60944de15bbec96907451ba58fb Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 11 Jun 2022 01:26:04 +0200 Subject: [PATCH 34/42] Proto/Delegate: propagate `Consensus_key.pk` (part 1) Propagate the consensus key captured in the sampler state through: - `Alpha_context.Stake_distribution` --- src/proto_alpha/lib_protocol/alpha_context.ml | 13 +-- .../lib_protocol/alpha_context.mli | 7 +- src/proto_alpha/lib_protocol/apply.ml | 79 ++++++++++--------- src/proto_alpha/lib_protocol/baking.ml | 19 ++--- 4 files changed, 56 insertions(+), 62 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index d874607f4aa2..5db6129465e1 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -464,16 +464,9 @@ module Stake_distribution = struct let compute_snapshot_index = Delegate_sampler.compute_snapshot_index - let baking_rights_owner ctxt lvl ~round = - (* GB.FEFE: temporary hack removed in a later patch *) - Delegate_sampler.baking_rights_owner ctxt lvl ~round - >>=? fun (ctxt, slot, owner) -> - return (ctxt, slot, (owner.delegate_public_key, owner.delegate)) - - let slot_owner ctxt lvl slot = - (* GB.FEFE: temporary hack removed in a later patch *) - Delegate_sampler.slot_owner ctxt lvl slot >>=? fun (ctxt, owner) -> - return (ctxt, (owner.delegate_public_key, owner.delegate)) + let baking_rights_owner = Delegate_sampler.baking_rights_owner + + let slot_owner = Delegate_sampler.slot_owner let get_staking_balance = Delegate_storage.staking_balance end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index a688448f5cea..39ca847f9f65 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3841,13 +3841,10 @@ module Stake_distribution : sig context -> Level.t -> round:Round.t -> - (context * Slot.t * (public_key * public_key_hash)) tzresult Lwt.t + (context * Slot.t * Consensus_key.pk) tzresult Lwt.t val slot_owner : - context -> - Level.t -> - Slot.t -> - (context * (public_key * public_key_hash)) tzresult Lwt.t + context -> Level.t -> Slot.t -> (context * Consensus_key.pk) tzresult Lwt.t val get_staking_balance : context -> public_key_hash -> Tez.t tzresult Lwt.t end diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index f0b2cefa4dd9..b8037cfce9ee 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2961,20 +2961,20 @@ let punish_double_endorsement_or_preendorsement (type kind) ctxt ~chain_id (* Disambiguate: levels are equal *) let level = Level.from_raw ctxt e1.level in check_denunciation_age ctxt kind level.level >>=? fun () -> - Stake_distribution.slot_owner ctxt level e1.slot - >>=? fun (ctxt, (delegate1_pk, delegate1)) -> - Stake_distribution.slot_owner ctxt level e2.slot - >>=? fun (ctxt, (_delegate2_pk, delegate2)) -> + Stake_distribution.slot_owner ctxt level e1.slot >>=? fun (ctxt, pk1) -> + Stake_distribution.slot_owner ctxt level e2.slot >>=? fun (ctxt, pk2) -> fail_unless - (Signature.Public_key_hash.equal delegate1 delegate2) - (Inconsistent_denunciation {kind; delegate1; delegate2}) + (Signature.Public_key_hash.equal pk1.delegate pk2.delegate) + (Inconsistent_denunciation + {kind; delegate1 = pk1.delegate; delegate2 = pk2.delegate}) >>=? fun () -> - let delegate_pk, delegate = (delegate1_pk, delegate1) in - Operation.check_signature delegate_pk chain_id op1 >>?= fun () -> - Operation.check_signature delegate_pk chain_id op2 >>?= fun () -> + Operation.check_signature pk1.delegate_public_key chain_id op1 + >>?= fun () -> + Operation.check_signature pk2.delegate_public_key chain_id op2 + >>?= fun () -> punish_delegate ctxt - delegate + pk1.delegate level `Double_endorsing mk_result @@ -3003,21 +3003,21 @@ let punish_double_baking ctxt chain_id bh1 bh2 ~payload_producer = let level = Level.from_raw ctxt raw_level in let committee_size = Constants.consensus_committee_size ctxt in Round.to_slot round1 ~committee_size >>?= fun slot1 -> - Stake_distribution.slot_owner ctxt level slot1 - >>=? fun (ctxt, (delegate1_pk, delegate1)) -> + Stake_distribution.slot_owner ctxt level slot1 >>=? fun (ctxt, pk1) -> Round.to_slot round2 ~committee_size >>?= fun slot2 -> - Stake_distribution.slot_owner ctxt level slot2 - >>=? fun (ctxt, (_delegate2_pk, delegate2)) -> + Stake_distribution.slot_owner ctxt level slot2 >>=? fun (ctxt, pk2) -> fail_unless - Signature.Public_key_hash.(delegate1 = delegate2) - (Inconsistent_denunciation {kind = Block; delegate1; delegate2}) + Signature.Public_key_hash.(pk1.delegate = pk2.delegate) + (Inconsistent_denunciation + {kind = Block; delegate1 = pk1.delegate; delegate2 = pk2.delegate}) >>=? fun () -> - let delegate_pk, delegate = (delegate1_pk, delegate1) in - Block_header.check_signature bh1 chain_id delegate_pk >>?= fun () -> - Block_header.check_signature bh2 chain_id delegate_pk >>?= fun () -> + Block_header.check_signature bh1 chain_id pk1.delegate_public_key + >>?= fun () -> + Block_header.check_signature bh2 chain_id pk2.delegate_public_key + >>?= fun () -> punish_delegate ctxt - delegate + pk1.delegate level `Double_baking ~payload_producer @@ -3043,17 +3043,18 @@ let validate_grand_parent_endorsement ctxt chain_id match op.protocol_data.contents with | Single (Endorsement e) -> let level = Level.from_raw ctxt e.level in - Stake_distribution.slot_owner ctxt level e.slot - >>=? fun (ctxt, (delegate_pk, pkh)) -> - Operation.check_signature delegate_pk chain_id op >>?= fun () -> - Consensus.record_grand_parent_endorsement ctxt pkh >>?= fun ctxt -> + Stake_distribution.slot_owner ctxt level e.slot >>=? fun (ctxt, pk) -> + Operation.check_signature pk.delegate_public_key chain_id op + >>?= fun () -> + Consensus.record_grand_parent_endorsement ctxt pk.delegate + >>?= fun ctxt -> return ( ctxt, Single_result (Endorsement_result { balance_updates = []; - delegate = pkh; + delegate = pk.delegate; endorsement_power = 0 (* dummy endorsement power: this will never be used *); }) ) @@ -3467,17 +3468,18 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level >>?= fun () -> let current_level = Level.current ctxt in Stake_distribution.baking_rights_owner ctxt current_level ~round - >>=? fun (ctxt, _slot, (_block_producer_pk, block_producer)) -> - Delegate.frozen_deposits ctxt block_producer >>=? fun frozen_deposits -> + >>=? fun (ctxt, _slot, block_producer) -> + Delegate.frozen_deposits ctxt block_producer.delegate + >>=? fun frozen_deposits -> fail_unless Tez.(frozen_deposits.current_amount > zero) - (Zero_frozen_deposits block_producer) + (Zero_frozen_deposits block_producer.delegate) >>=? fun () -> Stake_distribution.baking_rights_owner ctxt current_level ~round:protocol_data.Block_header.payload_round - >>=? fun (ctxt, _slot, (_payload_producer_pk, payload_producer)) -> + >>=? fun (ctxt, _slot, payload_producer) -> init_allowed_consensus_operations ctxt ~endorsement_level:predecessor_level @@ -3491,8 +3493,8 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level { ctxt; protocol_data; - payload_producer; - block_producer; + payload_producer = payload_producer.delegate; + block_producer = block_producer.delegate; round; implicit_operations_results = liquidity_baking_operations_results; liquidity_baking_toggle_ema; @@ -3514,7 +3516,7 @@ let begin_application ctxt chain_id (block_header : Block_header.t) fitness let round = Fitness.round fitness in let current_level = Level.current ctxt in Stake_distribution.baking_rights_owner ctxt current_level ~round - >>=? fun (ctxt, _slot, (block_producer_pk, block_producer)) -> + >>=? fun (ctxt, _slot, block_producer) -> let timestamp = block_header.shell.timestamp in Block_header.begin_validate_block_header ~block_header @@ -3523,21 +3525,22 @@ let begin_application ctxt chain_id (block_header : Block_header.t) fitness ~predecessor_round ~fitness ~timestamp - ~delegate_pk:block_producer_pk + ~delegate_pk:block_producer.delegate_public_key ~round_durations:(Constants.round_durations ctxt) ~proof_of_work_threshold:(Constants.proof_of_work_threshold ctxt) ~expected_commitment:current_level.expected_commitment >>?= fun () -> - Delegate.frozen_deposits ctxt block_producer >>=? fun frozen_deposits -> + Delegate.frozen_deposits ctxt block_producer.delegate + >>=? fun frozen_deposits -> fail_unless Tez.(frozen_deposits.current_amount > zero) - (Zero_frozen_deposits block_producer) + (Zero_frozen_deposits block_producer.delegate) >>=? fun () -> Stake_distribution.baking_rights_owner ctxt current_level ~round:block_header.protocol_data.contents.payload_round - >>=? fun (ctxt, _slot, (payload_producer_pk, _payload_producer)) -> + >>=? fun (ctxt, _slot, payload_producer) -> init_allowed_consensus_operations ctxt ~endorsement_level:predecessor_level @@ -3552,8 +3555,8 @@ let begin_application ctxt chain_id (block_header : Block_header.t) fitness liquidity_baking_operations_results, liquidity_baking_toggle_ema ) -> ( ctxt, - payload_producer_pk, - block_producer, + payload_producer.delegate_public_key, + block_producer.delegate, liquidity_baking_operations_results, liquidity_baking_toggle_ema ) diff --git a/src/proto_alpha/lib_protocol/baking.ml b/src/proto_alpha/lib_protocol/baking.ml index 00bc864d9102..77f4cb10826a 100644 --- a/src/proto_alpha/lib_protocol/baking.ml +++ b/src/proto_alpha/lib_protocol/baking.ml @@ -72,8 +72,8 @@ let bonus_baking_reward ctxt ~endorsing_power = let baking_rights c level = let rec f c round = Stake_distribution.baking_rights_owner c level ~round - >>=? fun (c, _slot, (delegate, _)) -> - return (LCons (delegate, fun () -> f c (Round.succ round))) + >>=? fun (c, _slot, pk) -> + return (LCons (pk.delegate_public_key, fun () -> f c (Round.succ round))) in f c Round.zero @@ -86,10 +86,10 @@ let endorsing_rights (ctxt : t) level = Slot.Range.create ~min:0 ~count:consensus_committee_size >>?= fun slots -> Slot.Range.rev_fold_es (fun (ctxt, map) slot -> - Stake_distribution.slot_owner ctxt level slot >>=? fun (ctxt, (_, pkh)) -> + Stake_distribution.slot_owner ctxt level slot >>=? fun (ctxt, pk) -> let map = Signature.Public_key_hash.Map.update - pkh + pk.delegate (function None -> Some [slot] | Some slots -> Some (slot :: slots)) map in @@ -102,12 +102,13 @@ let endorsing_rights_by_first_slot ctxt level = >>?= fun slots -> Slot.Range.fold_es (fun (ctxt, (delegates_map, slots_map)) slot -> - Stake_distribution.slot_owner ctxt level slot - >|=? fun (ctxt, (pk, pkh)) -> + Stake_distribution.slot_owner ctxt level slot >|=? fun (ctxt, pk) -> let initial_slot, delegates_map = - match Signature.Public_key_hash.Map.find pkh delegates_map with + match Signature.Public_key_hash.Map.find pk.delegate delegates_map with | None -> - (slot, Signature.Public_key_hash.Map.add pkh slot delegates_map) + ( slot, + Signature.Public_key_hash.Map.add pk.delegate slot delegates_map + ) | Some initial_slot -> (initial_slot, delegates_map) in (* [slots_map]'keys are the minimal slots of delegates because @@ -116,7 +117,7 @@ let endorsing_rights_by_first_slot ctxt level = Slot.Map.update initial_slot (function - | None -> Some (pk, pkh, 1) + | None -> Some (pk.delegate_public_key, pk.delegate, 1) | Some (pk, pkh, count) -> Some (pk, pkh, count + 1)) slots_map in -- GitLab From a1ec77144cd45b112337fdb09d6a03c9f0146e6e Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 11 Jun 2022 01:40:14 +0200 Subject: [PATCH 35/42] Proto/Delegate: propagate `Consensus_key.pk` (part 2) Propagate the consensus key captured in the sampler state through: - `Baking` - `Alpha_context.Consensus` --- src/proto_alpha/lib_plugin/RPC.ml | 17 +++++++++--- .../lib_protocol/alpha_context.mli | 1 + src/proto_alpha/lib_protocol/apply.ml | 14 +++++----- src/proto_alpha/lib_protocol/baking.ml | 5 ++-- src/proto_alpha/lib_protocol/baking.mli | 6 ++--- src/proto_alpha/lib_protocol/raw_context.ml | 27 ++++++++----------- src/proto_alpha/lib_protocol/raw_context.mli | 15 +++++------ 7 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 03c8f89a1e06..69b935d21bef 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -2484,8 +2484,9 @@ module Baking_rights = struct let rec loop l acc round = if Compare.Int.(round > max_round) then return (List.rev acc) else - let (Misc.LCons (pk, next)) = l in - let delegate = Signature.Public_key.hash pk in + let (Misc.LCons (Consensus_key.{delegate; consensus_key = _}, next)) = + l + in estimated_time round_durations ~current_level @@ -2648,8 +2649,16 @@ module Endorsing_rights = struct >>?= fun estimated_time -> let rights = Slot.Map.fold - (fun first_slot (_pk, delegate, endorsing_power) acc -> - {delegate; first_slot; endorsing_power} :: acc) + (fun first_slot + ( Consensus_key. + { + delegate; + delegate_public_key = _; + consensus_key = _; + consensus_public_key = _; + }, + endorsing_power ) + acc -> {delegate; first_slot; endorsing_power} :: acc) rights [] in diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 39ca847f9f65..9ecc2aebc973 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4011,6 +4011,7 @@ module Consensus : sig and type 'a slot_map := 'a Slot.Map.t and type slot_set := Slot.Set.t and type round := Round.t + and type consensus_pk := Consensus_key.pk val store_endorsement_branch : context -> Block_hash.t * Block_payload_hash.t -> context Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index b8037cfce9ee..128377b7a69b 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2868,14 +2868,14 @@ let validate_consensus_contents (type kind) ctxt chain_id >>?= fun () -> match Slot.Map.find content.slot slot_map with | None -> fail Wrong_slot_used_for_consensus_operation - | Some (delegate_pk, delegate_pkh, voting_power) -> - Delegate.frozen_deposits ctxt delegate_pkh >>=? fun frozen_deposits -> + | Some (pk, voting_power) -> + Delegate.frozen_deposits ctxt pk.delegate >>=? fun frozen_deposits -> fail_unless Tez.(frozen_deposits.current_amount > zero) - (Zero_frozen_deposits delegate_pkh) + (Zero_frozen_deposits pk.delegate) >>=? fun () -> - Operation.check_signature delegate_pk chain_id operation >>?= fun () -> - return (ctxt, delegate_pkh, voting_power) + Operation.check_signature pk.delegate_public_key chain_id operation + >>?= fun () -> return (ctxt, pk.delegate, voting_power) let apply_manager_contents_list ctxt mode ~payload_producer chain_id prechecked_contents_list = @@ -3643,7 +3643,7 @@ let finalize_application_check_validity ctxt (mode : finalize_application_mode) let record_endorsing_participation ctxt = let validators = Consensus.allowed_endorsements ctxt in Slot.Map.fold_es - (fun initial_slot (_delegate_pk, delegate, power) ctxt -> + (fun initial_slot ((consensus_pk : Consensus_key.pk), power) ctxt -> let participation = if Slot.Set.mem initial_slot (Consensus.endorsements_seen ctxt) then Delegate.Participated @@ -3651,7 +3651,7 @@ let record_endorsing_participation ctxt = in Delegate.record_endorsing_participation ctxt - ~delegate + ~delegate:consensus_pk.delegate ~participation ~endorsing_power:power) validators diff --git a/src/proto_alpha/lib_protocol/baking.ml b/src/proto_alpha/lib_protocol/baking.ml index 77f4cb10826a..2712f61249d1 100644 --- a/src/proto_alpha/lib_protocol/baking.ml +++ b/src/proto_alpha/lib_protocol/baking.ml @@ -73,7 +73,7 @@ let baking_rights c level = let rec f c round = Stake_distribution.baking_rights_owner c level ~round >>=? fun (c, _slot, pk) -> - return (LCons (pk.delegate_public_key, fun () -> f c (Round.succ round))) + return (LCons (Consensus_key.pkh pk, fun () -> f c (Round.succ round))) in f c Round.zero @@ -117,8 +117,7 @@ let endorsing_rights_by_first_slot ctxt level = Slot.Map.update initial_slot (function - | None -> Some (pk.delegate_public_key, pk.delegate, 1) - | Some (pk, pkh, count) -> Some (pk, pkh, count + 1)) + | None -> Some (pk, 1) | Some (pk, count) -> Some (pk, count + 1)) slots_map in (ctxt, (delegates_map, slots_map))) diff --git a/src/proto_alpha/lib_protocol/baking.mli b/src/proto_alpha/lib_protocol/baking.mli index 9d9281b735a3..421848a5f503 100644 --- a/src/proto_alpha/lib_protocol/baking.mli +++ b/src/proto_alpha/lib_protocol/baking.mli @@ -48,14 +48,14 @@ val endorsing_rights : Level.t -> (context * ordered_slots Signature.Public_key_hash.Map.t) tzresult Lwt.t -(** Computes endorsing rights for a given level. +(** Computes endorsing rights for a given level. @return map from allocated first slots to their owner's public key, public key hash, and endorsing power. *) val endorsing_rights_by_first_slot : context -> Level.t -> - (context * (public_key * public_key_hash * int) Slot.Map.t) tzresult Lwt.t + (context * (Consensus_key.pk * int) Slot.Map.t) tzresult Lwt.t (** Computes the bonus baking reward depending on the endorsing power. *) val bonus_baking_reward : context -> endorsing_power:int -> Tez.t tzresult @@ -63,4 +63,4 @@ val bonus_baking_reward : context -> endorsing_power:int -> Tez.t tzresult (** [baking_rights ctxt level] is the lazy list of contract's public key hashes that are allowed to propose for [level] at each round. *) -val baking_rights : context -> Level.t -> public_key lazy_list +val baking_rights : context -> Level.t -> Consensus_key.t lazy_list diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index e45011558c42..b94a78fc61f9 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -106,16 +106,12 @@ module Raw_consensus = struct type t = { current_endorsement_power : int; (** Number of endorsement slots recorded for the current block. *) - allowed_endorsements : - (Signature.Public_key.t * Signature.Public_key_hash.t * int) - Slot_repr.Map.t; + allowed_endorsements : (consensus_pk * int) Slot_repr.Map.t; (** Endorsements rights for the current block. Only an endorsement for the lowest slot in the block can be recorded. The map associates to each initial slot the [pkh] associated to this slot with its power. *) - allowed_preendorsements : - (Signature.Public_key.t * Signature.Public_key_hash.t * int) - Slot_repr.Map.t; + allowed_preendorsements : (consensus_pk * int) Slot_repr.Map.t; (** Preendorsements rights for the current block. Only a preendorsement for the lowest slot in the block can be recorded. The map associates to each initial slot the [pkh] associated to this @@ -1340,20 +1336,18 @@ module type CONSENSUS = sig type round - val allowed_endorsements : - t -> (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map + type consensus_pk - val allowed_preendorsements : - t -> (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map + val allowed_endorsements : t -> (consensus_pk * int) slot_map + + val allowed_preendorsements : t -> (consensus_pk * int) slot_map val current_endorsement_power : t -> int val initialize_consensus_operation : t -> - allowed_endorsements: - (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map -> - allowed_preendorsements: - (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map -> + allowed_endorsements:(consensus_pk * int) slot_map -> + allowed_preendorsements:(consensus_pk * int) slot_map -> t val record_grand_parent_endorsement : @@ -1387,7 +1381,8 @@ module Consensus : and type slot := Slot_repr.t and type 'a slot_map := 'a Slot_repr.Map.t and type slot_set := Slot_repr.Set.t - and type round := Round_repr.t = struct + and type round := Round_repr.t + and type consensus_pk := consensus_pk = struct let[@inline] allowed_endorsements ctxt = ctxt.back.consensus.allowed_endorsements @@ -1545,7 +1540,7 @@ module Dal = struct let shards ctxt ~endorser = let max_shards = ctxt.back.constants.dal.number_of_shards in Slot_repr.Map.fold_e - (fun slot (_, public_key_hash, _) shards -> + (fun slot ({consensus_key = public_key_hash; _}, _) shards -> (* Early fail because 2048 < 7000 *) if Compare.Int.(Slot_repr.to_int slot >= max_shards) then Error shards else if Signature.Public_key_hash.(public_key_hash = endorser) then diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index 7b0c3a70f6c3..cdac57f30d98 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -272,17 +272,17 @@ module type CONSENSUS = sig type round + type consensus_pk + (** Returns a map where each endorser's pkh is associated to the list of its endorsing slots (in decreasing order) for a given level. *) - val allowed_endorsements : - t -> (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map + val allowed_endorsements : t -> (consensus_pk * int) slot_map (** Returns a map where each endorser's pkh is associated to the list of its endorsing slots (in decreasing order) for a given level. *) - val allowed_preendorsements : - t -> (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map + val allowed_preendorsements : t -> (consensus_pk * int) slot_map (** [endorsement power ctx] returns the endorsement power of the current block. *) @@ -293,10 +293,8 @@ module type CONSENSUS = sig any consensus operation. *) val initialize_consensus_operation : t -> - allowed_endorsements: - (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map -> - allowed_preendorsements: - (Signature.Public_key.t * Signature.Public_key_hash.t * int) slot_map -> + allowed_endorsements:(consensus_pk * int) slot_map -> + allowed_preendorsements:(consensus_pk * int) slot_map -> t (** [record_grand_parent_endorsement ctx pkh] records an @@ -358,6 +356,7 @@ module Consensus : and type 'a slot_map := 'a Slot_repr.Map.t and type slot_set := Slot_repr.Set.t and type round := Round_repr.t + and type consensus_pk := consensus_pk module Tx_rollup : sig val add_message : -- GitLab From 8a4fc829fefc1e6ee63fd3b3e3f7bcac3892e360 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 11 Jun 2022 01:54:58 +0200 Subject: [PATCH 36/42] Proto/Delegate: propagate `Consensus_key.pk` (part 3) Propagate the consensus key captured in the sampler state until: - the baking and endorsing rights RPC --- src/proto_alpha/lib_plugin/RPC.ml | 73 +++++++++++-------- src/proto_alpha/lib_protocol/baking.ml | 16 +++- src/proto_alpha/lib_protocol/baking.mli | 6 +- ...e client) RPC regression tests- others.out | 30 +++++--- ...de light) RPC regression tests- others.out | 30 +++++--- ...de proxy) RPC regression tests- others.out | 30 +++++--- ...data_dir) RPC regression tests- others.out | 30 +++++--- ...rver_rpc) RPC regression tests- others.out | 30 +++++--- 8 files changed, 161 insertions(+), 84 deletions(-) diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 69b935d21bef..d3168f7eca3c 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -813,7 +813,7 @@ module Scripts = struct let operation : _ operation = {shell; protocol_data} in let hash = Operation.hash {shell; protocol_data} in let ctxt = Origination_nonce.init ctxt hash in - let payload_producer = Signature.Public_key_hash.zero in + let payload_producer = Consensus_key.zero in match protocol_data.contents with | Single (Manager_operation _) as op -> Apply.precheck_manager_contents_list ctxt op ~mempool_mode:true @@ -822,7 +822,7 @@ module Scripts = struct Apply.apply_manager_contents_list ctxt Optimized - ~payload_producer + ~payload_producer:payload_producer.delegate chain_id prechecked_contents_list >|= fun (_ctxt, result) -> ok @@ ret result @@ -833,7 +833,7 @@ module Scripts = struct Apply.apply_manager_contents_list ctxt Optimized - ~payload_producer + ~payload_producer:payload_producer.delegate chain_id prechecked_contents_list >|= fun (_ctxt, result) -> ok @@ ret result @@ -856,7 +856,7 @@ module Scripts = struct grand_parent_round = Round.zero; }) Optimized - ~payload_producer + ~payload_producer:payload_producer.delegate operation operation.protocol_data.contents >|=? fun (_ctxt, result) -> ret result @@ -2402,7 +2402,8 @@ let requested_levels ~default_level ctxt cycles levels = module Baking_rights = struct type t = { level : Raw_level.t; - delegate : Signature.Public_key_hash.t; + delegate : public_key_hash; + consensus_key : public_key_hash; round : int; timestamp : Timestamp.t option; } @@ -2410,15 +2411,16 @@ module Baking_rights = struct let encoding = let open Data_encoding in conv - (fun {level; delegate; round; timestamp} -> - (level, delegate, round, timestamp)) - (fun (level, delegate, round, timestamp) -> - {level; delegate; round; timestamp}) - (obj4 + (fun {level; delegate; consensus_key; round; timestamp} -> + (level, delegate, round, timestamp, consensus_key)) + (fun (level, delegate, round, timestamp, consensus_key) -> + {level; delegate; consensus_key; round; timestamp}) + (obj5 (req "level" Raw_level.encoding) (req "delegate" Signature.Public_key_hash.encoding) (req "round" uint16) - (opt "estimated_time" Timestamp.encoding)) + (opt "estimated_time" Timestamp.encoding) + (req "consensus_key" Signature.Public_key_hash.encoding)) let default_max_round = 64 @@ -2484,9 +2486,7 @@ module Baking_rights = struct let rec loop l acc round = if Compare.Int.(round > max_round) then return (List.rev acc) else - let (Misc.LCons (Consensus_key.{delegate; consensus_key = _}, next)) = - l - in + let (Misc.LCons ({Consensus_key.consensus_key; delegate}, next)) = l in estimated_time round_durations ~current_level @@ -2495,7 +2495,10 @@ module Baking_rights = struct ~level ~round >>?= fun timestamp -> - let acc = {level = level.level; delegate; round; timestamp} :: acc in + let acc = + {level = level.level; delegate; consensus_key; round; timestamp} + :: acc + in next () >>=? fun l -> loop l acc (round + 1) in loop delegates [] 0 @@ -2557,7 +2560,8 @@ end module Endorsing_rights = struct type delegate_rights = { - delegate : Signature.Public_key_hash.t; + delegate : public_key_hash; + consensus_key : public_key_hash; first_slot : Slot.t; endorsing_power : int; } @@ -2571,14 +2575,15 @@ module Endorsing_rights = struct let delegate_rights_encoding = let open Data_encoding in conv - (fun {delegate; first_slot; endorsing_power} -> - (delegate, first_slot, endorsing_power)) - (fun (delegate, first_slot, endorsing_power) -> - {delegate; first_slot; endorsing_power}) - (obj3 + (fun {delegate; consensus_key; first_slot; endorsing_power} -> + (delegate, first_slot, endorsing_power, consensus_key)) + (fun (delegate, first_slot, endorsing_power, consensus_key) -> + {delegate; first_slot; endorsing_power; consensus_key}) + (obj4 (req "delegate" Signature.Public_key_hash.encoding) (req "first_slot" Slot.encoding) - (req "endorsing_power" uint16)) + (req "endorsing_power" uint16) + (req "consensus_key" Signature.Public_key_hash.encoding)) let encoding = let open Data_encoding in @@ -2654,11 +2659,12 @@ module Endorsing_rights = struct { delegate; delegate_public_key = _; - consensus_key = _; + consensus_key; consensus_public_key = _; }, endorsing_power ) - acc -> {delegate; first_slot; endorsing_power} :: acc) + acc -> + {delegate; consensus_key; first_slot; endorsing_power} :: acc) rights [] in @@ -2706,19 +2712,23 @@ end module Validators = struct type t = { level : Raw_level.t; - delegate : Signature.Public_key_hash.t; + delegate : public_key_hash; + consensus_key : public_key_hash; slots : Slot.t list; } let encoding = let open Data_encoding in conv - (fun {level; delegate; slots} -> (level, delegate, slots)) - (fun (level, delegate, slots) -> {level; delegate; slots}) - (obj3 + (fun {level; delegate; consensus_key; slots} -> + (level, delegate, slots, consensus_key)) + (fun (level, delegate, slots, consensus_key) -> + {level; delegate; consensus_key; slots}) + (obj4 (req "level" Raw_level.encoding) (req "delegate" Signature.Public_key_hash.encoding) - (req "slots" (list Slot.encoding))) + (req "slots" (list Slot.encoding)) + (req "consensus_key" Signature.Public_key_hash.encoding)) module S = struct open Data_encoding @@ -2756,8 +2766,9 @@ module Validators = struct let endorsing_slots_at_level ctxt level = Baking.endorsing_rights ctxt level >|=? fun (_, rights) -> Signature.Public_key_hash.Map.fold - (fun delegate slots acc -> {level = level.level; delegate; slots} :: acc) - (rights :> Slot.t list Signature.Public_key_hash.Map.t) + (fun _pkh {Baking.delegate; consensus_key; slots} acc -> + {level = level.level; delegate; consensus_key; slots} :: acc) + rights [] let register () = diff --git a/src/proto_alpha/lib_protocol/baking.ml b/src/proto_alpha/lib_protocol/baking.ml index 2712f61249d1..62cd99ba844f 100644 --- a/src/proto_alpha/lib_protocol/baking.ml +++ b/src/proto_alpha/lib_protocol/baking.ml @@ -77,7 +77,11 @@ let baking_rights c level = in f c Round.zero -type ordered_slots = Slot.t list +type ordered_slots = { + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + slots : Slot.t list; +} (* Slots returned by this function are assumed by consumers to be in increasing order, hence the use of [Slot.Range.rev_fold_es]. *) @@ -90,7 +94,15 @@ let endorsing_rights (ctxt : t) level = let map = Signature.Public_key_hash.Map.update pk.delegate - (function None -> Some [slot] | Some slots -> Some (slot :: slots)) + (function + | None -> + Some + { + delegate = pk.delegate; + consensus_key = pk.consensus_key; + slots = [slot]; + } + | Some slots -> Some {slots with slots = slot :: slots.slots}) map in return (ctxt, map)) diff --git a/src/proto_alpha/lib_protocol/baking.mli b/src/proto_alpha/lib_protocol/baking.mli index 421848a5f503..9e90eb4ea479 100644 --- a/src/proto_alpha/lib_protocol/baking.mli +++ b/src/proto_alpha/lib_protocol/baking.mli @@ -34,7 +34,11 @@ type error += consensus_threshold : int; } -type ordered_slots = private Slot.t list +type ordered_slots = private { + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; + slots : Slot.t list; +} (** For a given level computes who has the right to include an endorsement in the next block. diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out index 08af28a81f4b..2ea5de220b6c 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out @@ -56,15 +56,20 @@ ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 0, "estimated_time": "[TIMESTAMP]" }, + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 1, "estimated_time": "[TIMESTAMP]" }, + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 2, "estimated_time": "[TIMESTAMP]" }, + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 3, "estimated_time": "[TIMESTAMP]" }, + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 10, "estimated_time": "[TIMESTAMP]" } ] + "round": 10, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] ./tezos-client rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' { "level": 1, "level_position": 0, "cycle": 0, "cycle_position": 0, @@ -74,15 +79,20 @@ [ { "level": 1, "delegates": [ { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 11, "endorsing_power": 50 }, + "first_slot": 11, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 4, "endorsing_power": 47 }, + "first_slot": 4, "endorsing_power": 47, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 2, "endorsing_power": 46 }, + "first_slot": 2, "endorsing_power": 46, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 1, "endorsing_power": 55 }, + "first_slot": 1, "endorsing_power": 55, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 0, "endorsing_power": 58 } ] } ] + "first_slot": 0, "endorsing_power": 58, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] ./tezos-client rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle { "first": 1, "last": 8 } diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out index 5921e5de50ed..988a31bee72d 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out @@ -57,15 +57,20 @@ protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenes ./tezos-client --mode light rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 0, "estimated_time": "[TIMESTAMP]" }, + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 1, "estimated_time": "[TIMESTAMP]" }, + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 2, "estimated_time": "[TIMESTAMP]" }, + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 3, "estimated_time": "[TIMESTAMP]" }, + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 10, "estimated_time": "[TIMESTAMP]" } ] + "round": 10, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode light rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' @@ -77,15 +82,20 @@ protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenes [ { "level": 1, "delegates": [ { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 11, "endorsing_power": 50 }, + "first_slot": 11, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 4, "endorsing_power": 47 }, + "first_slot": 4, "endorsing_power": 47, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 2, "endorsing_power": 46 }, + "first_slot": 2, "endorsing_power": 46, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 1, "endorsing_power": 55 }, + "first_slot": 1, "endorsing_power": 55, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 0, "endorsing_power": 58 } ] } ] + "first_slot": 0, "endorsing_power": 58, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] protocol of light mode unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode light rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out index b10b690d4c7e..f297050b8fbf 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out @@ -57,15 +57,20 @@ protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGen ./tezos-client --mode proxy rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 0, "estimated_time": "[TIMESTAMP]" }, + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 1, "estimated_time": "[TIMESTAMP]" }, + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 2, "estimated_time": "[TIMESTAMP]" }, + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 3, "estimated_time": "[TIMESTAMP]" }, + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 2, "delegate": "[PUBLIC_KEY_HASH]", - "round": 10, "estimated_time": "[TIMESTAMP]" } ] + "round": 10, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode proxy rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' @@ -77,15 +82,20 @@ protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGen [ { "level": 1, "delegates": [ { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 11, "endorsing_power": 50 }, + "first_slot": 11, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 4, "endorsing_power": 47 }, + "first_slot": 4, "endorsing_power": 47, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 2, "endorsing_power": 46 }, + "first_slot": 2, "endorsing_power": 46, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 1, "endorsing_power": 55 }, + "first_slot": 1, "endorsing_power": 55, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 0, "endorsing_power": 58 } ] } ] + "first_slot": 0, "endorsing_power": 58, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] protocol of proxy unspecified, using the node's protocol: ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im ./tezos-client --mode proxy rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out index 9cec6efb7351..74a9a337ecd1 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out @@ -56,15 +56,20 @@ ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 0, "estimated_time": "[TIMESTAMP]" }, + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 1, "estimated_time": "[TIMESTAMP]" }, + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 2, "estimated_time": "[TIMESTAMP]" }, + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 3, "estimated_time": "[TIMESTAMP]" }, + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 4, "estimated_time": "[TIMESTAMP]" } ] + "round": 4, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] ./tezos-client rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, @@ -74,15 +79,20 @@ [ { "level": 2, "delegates": [ { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 10, "endorsing_power": 50 }, + "first_slot": 10, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 3, "endorsing_power": 50 }, + "first_slot": 3, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 2, "endorsing_power": 65 }, + "first_slot": 2, "endorsing_power": 65, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 1, "endorsing_power": 50 }, + "first_slot": 1, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 0, "endorsing_power": 41 } ] } ] + "first_slot": 0, "endorsing_power": 41, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] ./tezos-client rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle { "first": 1, "last": 8 } diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out index 9cec6efb7351..74a9a337ecd1 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out @@ -56,15 +56,20 @@ ./tezos-client rpc get /chains/main/blocks/head/helpers/baking_rights [ { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 0, "estimated_time": "[TIMESTAMP]" }, + "round": 0, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 1, "estimated_time": "[TIMESTAMP]" }, + "round": 1, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 2, "estimated_time": "[TIMESTAMP]" }, + "round": 2, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 3, "estimated_time": "[TIMESTAMP]" }, + "round": 3, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "level": 3, "delegate": "[PUBLIC_KEY_HASH]", - "round": 4, "estimated_time": "[TIMESTAMP]" } ] + "round": 4, "estimated_time": "[TIMESTAMP]", + "consensus_key": "[PUBLIC_KEY_HASH]" } ] ./tezos-client rpc get '/chains/main/blocks/head/helpers/current_level?offset=0' { "level": 2, "level_position": 1, "cycle": 0, "cycle_position": 1, @@ -74,15 +79,20 @@ [ { "level": 2, "delegates": [ { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 10, "endorsing_power": 50 }, + "first_slot": 10, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 3, "endorsing_power": 50 }, + "first_slot": 3, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 2, "endorsing_power": 65 }, + "first_slot": 2, "endorsing_power": 65, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 1, "endorsing_power": 50 }, + "first_slot": 1, "endorsing_power": 50, + "consensus_key": "[PUBLIC_KEY_HASH]" }, { "delegate": "[PUBLIC_KEY_HASH]", - "first_slot": 0, "endorsing_power": 41 } ] } ] + "first_slot": 0, "endorsing_power": 41, + "consensus_key": "[PUBLIC_KEY_HASH]" } ] } ] ./tezos-client rpc get /chains/main/blocks/head/helpers/levels_in_current_cycle { "first": 1, "last": 8 } -- GitLab From 01b8fa7a3cace2b3604578f6f5d703a87a071409 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 11 Jun 2022 01:53:28 +0200 Subject: [PATCH 37/42] Proto/Delegate: propagate `Consensus_key.pk` (part 4) Propagate the consensus key captured in the sampler state until: - block metadata - endorsement metadata --- .../lib_client/operation_result.ml | 15 ++--- .../client_baking_denunciation.ml | 8 +-- src/proto_alpha/lib_plugin/RPC.ml | 6 +- src/proto_alpha/lib_protocol/apply.ml | 46 ++++++++------ src/proto_alpha/lib_protocol/apply.mli | 18 +++--- src/proto_alpha/lib_protocol/apply_results.ml | 62 ++++++++++++------- .../lib_protocol/apply_results.mli | 10 +-- src/proto_alpha/lib_protocol/main.ml | 26 ++++---- src/proto_alpha/lib_protocol/main.mli | 12 ++-- 9 files changed, 114 insertions(+), 89 deletions(-) diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 036e5dd9e2c4..a7a593175bef 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -864,8 +864,8 @@ let pp_contents_and_result : pp_balance_updates bus | ( Preendorsement {level; _}, - Preendorsement_result {balance_updates; delegate; preendorsement_power} ) - -> + Preendorsement_result + {balance_updates; delegate; consensus_key; preendorsement_power} ) -> Format.fprintf ppf "@[Preendorsement:@,\ @@ -877,11 +877,12 @@ let pp_contents_and_result : level pp_balance_updates balance_updates - Signature.Public_key_hash.pp - delegate + Consensus_key.pp + {delegate; consensus_key} preendorsement_power | ( Endorsement {level; _}, - Endorsement_result {balance_updates; delegate; endorsement_power} ) -> + Endorsement_result + {balance_updates; delegate; consensus_key; endorsement_power} ) -> Format.fprintf ppf "@[Endorsement:@,\ @@ -893,8 +894,8 @@ let pp_contents_and_result : level pp_balance_updates balance_updates - Signature.Public_key_hash.pp - delegate + Consensus_key.pp + {delegate; consensus_key} endorsement_power | Dal_slot_availability _, Dal_slot_availability_result {delegate} -> Format.fprintf diff --git a/src/proto_alpha/lib_delegate/client_baking_denunciation.ml b/src/proto_alpha/lib_delegate/client_baking_denunciation.ml index 4f3638131307..2ebc4af5961e 100644 --- a/src/proto_alpha/lib_delegate/client_baking_denunciation.ml +++ b/src/proto_alpha/lib_delegate/client_baking_denunciation.ml @@ -264,13 +264,13 @@ let process_block (cctxt : #Protocol_client_context.full) state Option.value ~default:Delegate_Map.empty @@ HLevel.find state.blocks_table (chain_id, level, round) in - match Delegate_Map.find baker map with + match Delegate_Map.find baker.delegate map with | None -> return @@ HLevel.add state.blocks_table (chain_id, level, round) - (Delegate_Map.add baker new_hash map) + (Delegate_Map.add baker.delegate new_hash map) | Some existing_hash when Block_hash.(existing_hash = new_hash) -> (* This case should never happen *) Events.(emit double_baking_but_not) () >>= fun () -> @@ -278,7 +278,7 @@ let process_block (cctxt : #Protocol_client_context.full) state @@ HLevel.replace state.blocks_table (chain_id, level, round) - (Delegate_Map.add baker new_hash map) + (Delegate_Map.add baker.delegate new_hash map) | Some existing_hash -> (* If a previous block made by this pkh is found for the same (level, round) we inject a double_baking_evidence *) @@ -310,7 +310,7 @@ let process_block (cctxt : #Protocol_client_context.full) state @@ HLevel.replace state.blocks_table (chain_id, level, round) - (Delegate_Map.add baker new_hash map)) + (Delegate_Map.add baker.delegate new_hash map)) (* Remove levels that are lower than the [highest_level_encountered] minus [preserved_levels] *) diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index d3168f7eca3c..86feda691e03 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -822,7 +822,7 @@ module Scripts = struct Apply.apply_manager_contents_list ctxt Optimized - ~payload_producer:payload_producer.delegate + ~payload_producer chain_id prechecked_contents_list >|= fun (_ctxt, result) -> ok @@ ret result @@ -833,7 +833,7 @@ module Scripts = struct Apply.apply_manager_contents_list ctxt Optimized - ~payload_producer:payload_producer.delegate + ~payload_producer chain_id prechecked_contents_list >|= fun (_ctxt, result) -> ok @@ ret result @@ -856,7 +856,7 @@ module Scripts = struct grand_parent_round = Round.zero; }) Optimized - ~payload_producer:payload_producer.delegate + ~payload_producer operation operation.protocol_data.contents >|=? fun (_ctxt, result) -> ret result diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 128377b7a69b..0d72e1ddf671 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2400,7 +2400,7 @@ let apply_manager_contents (type kind) ctxt mode chain_id let rec mark_skipped : type kind. - payload_producer:Signature.Public_key_hash.t -> + payload_producer:Consensus_key.t -> Level.t -> kind Kind.manager prechecked_contents_list -> kind Kind.manager contents_result_list = @@ -2539,7 +2539,7 @@ let rec apply_manager_contents_list_rec : type kind. context -> Script_ir_translator.unparsing_mode -> - payload_producer:public_key_hash -> + payload_producer:Consensus_key.t -> Chain_id.t -> kind Kind.manager prechecked_contents_list -> (success_or_failure * kind Kind.manager contents_result_list) Lwt.t = @@ -2842,7 +2842,7 @@ let validate_consensus_contents (type kind) ctxt chain_id (operation_kind : kind consensus_operation_type) (operation : kind operation) (apply_mode : apply_mode) (content : consensus_content) : - (context * public_key_hash * int) tzresult Lwt.t = + (context * Consensus_key.t * int) tzresult Lwt.t = let current_level = Level.current ctxt in let proposal_level = get_predecessor_level apply_mode in let slot_map = @@ -2875,7 +2875,7 @@ let validate_consensus_contents (type kind) ctxt chain_id (Zero_frozen_deposits pk.delegate) >>=? fun () -> Operation.check_signature pk.delegate_public_key chain_id operation - >>?= fun () -> return (ctxt, pk.delegate, voting_power) + >>?= fun () -> return (ctxt, Consensus_key.pkh pk, voting_power) let apply_manager_contents_list ctxt mode ~payload_producer chain_id prechecked_contents_list = @@ -2918,7 +2918,7 @@ let punish_delegate ctxt delegate level mistake mk_result ~payload_producer = Token.transfer ctxt `Double_signing_evidence_rewards - (`Contract (Contract.Implicit payload_producer)) + (`Contract (Contract.Implicit payload_producer.Consensus_key.delegate)) reward | Error _ -> (* reward is Tez.zero *) return (ctxt, [])) >|=? fun (ctxt, reward_balance_updates) -> @@ -3055,6 +3055,7 @@ let validate_grand_parent_endorsement ctxt chain_id { balance_updates = []; delegate = pk.delegate; + consensus_key = pk.consensus_key; endorsement_power = 0 (* dummy endorsement power: this will never be used *); }) ) @@ -3077,7 +3078,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode operation apply_mode consensus_content - >>=? fun (ctxt, delegate, voting_power) -> + >>=? fun (ctxt, {delegate; consensus_key}, voting_power) -> Consensus.record_preendorsement ctxt ~initial_slot:consensus_content.slot @@ -3091,6 +3092,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode { balance_updates = []; delegate; + consensus_key; preendorsement_power = voting_power; }) ) | Single (Endorsement consensus_content) -> ( @@ -3112,7 +3114,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode operation apply_mode consensus_content - >>=? fun (ctxt, delegate, voting_power) -> + >>=? fun (ctxt, {delegate; consensus_key}, voting_power) -> Consensus.record_endorsement ctxt ~initial_slot:consensus_content.slot @@ -3125,6 +3127,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode { balance_updates = []; delegate; + consensus_key; endorsement_power = voting_power; }) )) | Single (Dal_slot_availability (endorser, slot_availability)) -> @@ -3148,7 +3151,9 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode let level = Level.from_raw ctxt level in Nonce.reveal ctxt level nonce >>=? fun ctxt -> let tip = Constants.seed_nonce_revelation_tip ctxt in - let contract = Contract.Implicit payload_producer in + let contract = + Contract.Implicit payload_producer.Consensus_key.delegate + in Token.transfer ctxt `Revelation_rewards (`Contract contract) tip >|=? fun (ctxt, balance_updates) -> (ctxt, Single_result (Seed_nonce_revelation_result balance_updates)) @@ -3448,8 +3453,8 @@ let apply_liquidity_baking_subsidy ctxt ~toggle_vote = type 'a full_construction = { ctxt : t; protocol_data : 'a; - payload_producer : Signature.public_key_hash; - block_producer : Signature.public_key_hash; + payload_producer : Consensus_key.t; + block_producer : Consensus_key.t; round : Round.t; implicit_operations_results : packed_successful_manager_operation_result list; liquidity_baking_toggle_ema : Liquidity_baking.Toggle_EMA.t; @@ -3493,8 +3498,8 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level { ctxt; protocol_data; - payload_producer = payload_producer.delegate; - block_producer = block_producer.delegate; + payload_producer = Consensus_key.pkh payload_producer; + block_producer = Consensus_key.pkh block_producer; round; implicit_operations_results = liquidity_baking_operations_results; liquidity_baking_toggle_ema; @@ -3525,7 +3530,7 @@ let begin_application ctxt chain_id (block_header : Block_header.t) fitness ~predecessor_round ~fitness ~timestamp - ~delegate_pk:block_producer.delegate_public_key + ~delegate_pk:block_producer.consensus_public_key ~round_durations:(Constants.round_durations ctxt) ~proof_of_work_threshold:(Constants.proof_of_work_threshold ctxt) ~expected_commitment:current_level.expected_commitment @@ -3555,8 +3560,8 @@ let begin_application ctxt chain_id (block_header : Block_header.t) fitness liquidity_baking_operations_results, liquidity_baking_toggle_ema ) -> ( ctxt, - payload_producer.delegate_public_key, - block_producer.delegate, + Consensus_key.pkh payload_producer, + Consensus_key.pkh block_producer, liquidity_baking_operations_results, liquidity_baking_toggle_ema ) @@ -3658,8 +3663,9 @@ let record_endorsing_participation ctxt = ctxt let finalize_application ctxt (mode : finalize_application_mode) protocol_data - ~payload_producer ~block_producer liquidity_baking_toggle_ema - implicit_operations_results ~round ~predecessor ~migration_balance_updates = + ~(payload_producer : Consensus_key.t) ~(block_producer : Consensus_key.t) + liquidity_baking_toggle_ema implicit_operations_results ~round ~predecessor + ~migration_balance_updates = (* Then we finalize the consensus. *) let level = Level.current ctxt in let block_endorsing_power = Consensus.current_endorsement_power ctxt in @@ -3694,7 +3700,7 @@ let finalize_application ctxt (mode : finalize_application_mode) protocol_data (match protocol_data.Block_header.seed_nonce_hash with | None -> return ctxt | Some nonce_hash -> - Nonce.record_hash ctxt {nonce_hash; delegate = block_producer}) + Nonce.record_hash ctxt {nonce_hash; delegate = block_producer.delegate}) >>=? fun ctxt -> (if required_endorsements then record_endorsing_participation ctxt >>=? fun ctxt -> @@ -3705,8 +3711,8 @@ let finalize_application ctxt (mode : finalize_application_mode) protocol_data let baking_reward = Constants.baking_reward_fixed_portion ctxt in Delegate.record_baking_activity_and_pay_rewards_and_fees ctxt - ~payload_producer - ~block_producer + ~payload_producer:payload_producer.delegate + ~block_producer:block_producer.delegate ~baking_reward ~reward_bonus >>=? fun (ctxt, baking_receipts) -> diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index f2b8258f2cdb..5910625769c0 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -60,8 +60,8 @@ val begin_partial_construction : type 'a full_construction = { ctxt : context; protocol_data : 'a; - payload_producer : Signature.public_key_hash; - block_producer : Signature.public_key_hash; + payload_producer : Consensus_key.t; + block_producer : Consensus_key.t; round : Round.t; implicit_operations_results : packed_successful_manager_operation_result list; liquidity_baking_toggle_ema : Liquidity_baking.Toggle_EMA.t; @@ -85,8 +85,8 @@ val begin_application : predecessor_level:Level.t -> predecessor_round:Round.t -> (t - * Signature.public_key - * Signature.public_key_hash + * Consensus_key.t + * Consensus_key.t * packed_successful_manager_operation_result list * Liquidity_baking.Toggle_EMA.t) tzresult @@ -120,7 +120,7 @@ val apply_operation : Chain_id.t -> apply_mode -> Script_ir_translator.unparsing_mode -> - payload_producer:public_key_hash -> + payload_producer:Consensus_key.t -> Operation_list_hash.elt -> 'a operation -> (context * 'a operation_metadata, error trace) result Lwt.t @@ -136,8 +136,8 @@ val finalize_application : context -> finalize_application_mode -> Block_header.contents -> - payload_producer:public_key_hash -> - block_producer:public_key_hash -> + payload_producer:Consensus_key.t -> + block_producer:Consensus_key.t -> Liquidity_baking.Toggle_EMA.t -> packed_successful_manager_operation_result list -> round:Round.t -> @@ -148,7 +148,7 @@ val finalize_application : val apply_manager_contents_list : context -> Script_ir_translator.unparsing_mode -> - payload_producer:public_key_hash -> + payload_producer:Consensus_key.t -> Chain_id.t -> 'a Kind.manager prechecked_contents_list -> (context * 'a Kind.manager contents_result_list) Lwt.t @@ -158,7 +158,7 @@ val apply_contents_list : Chain_id.t -> apply_mode -> Script_ir_translator.unparsing_mode -> - payload_producer:public_key_hash -> + payload_producer:Consensus_key.t -> 'kind operation -> 'kind contents_list -> (context * 'kind contents_result_list) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index 2ba3deeb698e..c3ae6ec547ab 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -1576,13 +1576,15 @@ let successful_manager_operation_result_encoding : type 'kind contents_result = | Preendorsement_result : { balance_updates : Receipt.balance_updates; - delegate : Signature.Public_key_hash.t; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; preendorsement_power : int; } -> Kind.preendorsement contents_result | Endorsement_result : { balance_updates : Receipt.balance_updates; - delegate : Signature.Public_key_hash.t; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; endorsement_power : int; } -> Kind.endorsement contents_result @@ -1743,10 +1745,11 @@ module Encoding = struct { op_case = Operation.Encoding.preendorsement_case; encoding = - obj3 + obj4 (dft "balance_updates" Receipt.balance_updates_encoding []) (req "delegate" Signature.Public_key_hash.encoding) - (req "preendorsement_power" int31); + (req "preendorsement_power" int31) + (req "consensus_key" Signature.Public_key_hash.encoding); select = (function | Contents_result (Preendorsement_result _ as op) -> Some op @@ -1758,12 +1761,13 @@ module Encoding = struct proj = (function | Preendorsement_result - {balance_updates; delegate; preendorsement_power} -> - (balance_updates, delegate, preendorsement_power)); + {balance_updates; delegate; consensus_key; preendorsement_power} + -> + (balance_updates, delegate, preendorsement_power, consensus_key)); inj = - (fun (balance_updates, delegate, preendorsement_power) -> + (fun (balance_updates, delegate, preendorsement_power, consensus_key) -> Preendorsement_result - {balance_updates; delegate; preendorsement_power}); + {balance_updates; delegate; consensus_key; preendorsement_power}); } let[@coq_axiom_with_reason "gadt"] endorsement_case = @@ -1771,10 +1775,11 @@ module Encoding = struct { op_case = Operation.Encoding.endorsement_case; encoding = - obj3 + obj4 (dft "balance_updates" Receipt.balance_updates_encoding []) (req "delegate" Signature.Public_key_hash.encoding) - (req "endorsement_power" int31); + (req "endorsement_power" int31) + (req "consensus_key" Signature.Public_key_hash.encoding); select = (function | Contents_result (Endorsement_result _ as op) -> Some op | _ -> None); @@ -1784,11 +1789,13 @@ module Encoding = struct | _ -> None); proj = (function - | Endorsement_result {balance_updates; delegate; endorsement_power} -> - (balance_updates, delegate, endorsement_power)); + | Endorsement_result + {balance_updates; delegate; consensus_key; endorsement_power} -> + (balance_updates, delegate, endorsement_power, consensus_key)); inj = - (fun (balance_updates, delegate, endorsement_power) -> - Endorsement_result {balance_updates; delegate; endorsement_power}); + (fun (balance_updates, delegate, endorsement_power, consensus_key) -> + Endorsement_result + {balance_updates; delegate; consensus_key; endorsement_power}); } let[@coq_axiom_with_reason "gadt"] dal_slot_availability_case = @@ -3299,8 +3306,8 @@ let operation_data_and_metadata_encoding = ] type block_metadata = { - proposer : Signature.Public_key_hash.t; - baker : Signature.Public_key_hash.t; + proposer : Consensus_key.t; + baker : Consensus_key.t; level_info : Level.t; voting_period_info : Voting_period.info; nonce_hash : Nonce_hash.t option; @@ -3317,8 +3324,9 @@ let block_metadata_encoding = def "block_header.alpha.metadata" @@ conv (fun { - proposer; - baker; + proposer = + {delegate = proposer; consensus_key = proposer_active_key}; + baker = {delegate = baker; consensus_key = baker_active_key}; level_info; voting_period_info; nonce_hash; @@ -3339,7 +3347,10 @@ let block_metadata_encoding = balance_updates, liquidity_baking_toggle_ema, implicit_operations_results ), - (consumed_gas, dal_slot_availability) )) + ( consumed_gas, + proposer_active_key, + baker_active_key, + dal_slot_availability ) )) (fun ( ( proposer, baker, level_info, @@ -3350,10 +3361,13 @@ let block_metadata_encoding = balance_updates, liquidity_baking_toggle_ema, implicit_operations_results ), - (_consumed_millgas, dal_slot_availability) ) -> + ( _consumed_millgas, + proposer_active_key, + baker_active_key, + dal_slot_availability ) ) -> { - proposer; - baker; + proposer = {delegate = proposer; consensus_key = proposer_active_key}; + baker = {delegate = baker; consensus_key = baker_active_key}; level_info; voting_period_info; nonce_hash; @@ -3380,8 +3394,10 @@ let block_metadata_encoding = (req "implicit_operations_results" (list successful_manager_operation_result_encoding))) - (obj2 + (obj4 (req "consumed_milligas" Gas.Arith.n_fp_encoding) + (req "proposer_consensus_key" Signature.Public_key_hash.encoding) + (req "baker_consensus_key" Signature.Public_key_hash.encoding) (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3119 This varopt is here while the DAL is behind a feature diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index ab1abfbb7961..81b9a28e10d2 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -89,13 +89,15 @@ and packed_contents_result_list = and 'kind contents_result = | Preendorsement_result : { balance_updates : Receipt.balance_updates; - delegate : Signature.Public_key_hash.t; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; preendorsement_power : int; } -> Kind.preendorsement contents_result | Endorsement_result : { balance_updates : Receipt.balance_updates; - delegate : Signature.Public_key_hash.t; + delegate : Signature.public_key_hash; + consensus_key : Signature.public_key_hash; endorsement_power : int; } -> Kind.endorsement contents_result @@ -415,8 +417,8 @@ val kind_equal_list : ('kind, 'kind2) eq option type block_metadata = { - proposer : Signature.Public_key_hash.t; - baker : Signature.Public_key_hash.t; + proposer : Consensus_key.t; + baker : Consensus_key.t; level_info : Level.t; voting_period_info : Voting_period.info; nonce_hash : Nonce_hash.t option; diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index 022ebeb62a76..628a1aeecfd2 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -94,16 +94,16 @@ type validation_mode = | Application of { block_header : Alpha_context.Block_header.t; fitness : Alpha_context.Fitness.t; - payload_producer : Alpha_context.public_key_hash; - block_producer : Alpha_context.public_key_hash; + payload_producer : Alpha_context.Consensus_key.t; + block_producer : Alpha_context.Consensus_key.t; predecessor_round : Alpha_context.Round.t; predecessor_level : Alpha_context.Level.t; } | Partial_application of { block_header : Alpha_context.Block_header.t; fitness : Alpha_context.Fitness.t; - payload_producer : Alpha_context.public_key_hash; - block_producer : Alpha_context.public_key_hash; + payload_producer : Alpha_context.Consensus_key.t; + block_producer : Alpha_context.Consensus_key.t; predecessor_level : Alpha_context.Level.t; predecessor_round : Alpha_context.Round.t; } @@ -117,8 +117,8 @@ type validation_mode = (* Baker only *) | Full_construction of { predecessor : Block_hash.t; - payload_producer : Alpha_context.public_key_hash; - block_producer : Alpha_context.public_key_hash; + payload_producer : Alpha_context.Consensus_key.t; + block_producer : Alpha_context.Consensus_key.t; protocol_data_contents : Alpha_context.Block_header.contents; level : Int32.t; round : Alpha_context.Round.t; @@ -162,7 +162,7 @@ let begin_partial_application ~chain_id ~ancestor_context:ctxt ~predecessor_level ~predecessor_round >>=? fun ( ctxt, - payload_producer_pk, + payload_producer, block_producer, liquidity_baking_operations_results, liquidity_baking_toggle_ema ) -> @@ -173,7 +173,7 @@ let begin_partial_application ~chain_id ~ancestor_context:ctxt fitness; predecessor_level; predecessor_round; - payload_producer = Signature.Public_key.hash payload_producer_pk; + payload_producer; block_producer; } in @@ -229,7 +229,7 @@ let begin_application ~chain_id ~predecessor_context:ctxt ~predecessor_timestamp fitness; predecessor_round; predecessor_level; - payload_producer = Signature.Public_key.hash payload_producer; + payload_producer; block_producer; } in @@ -443,7 +443,7 @@ let apply_operation ({mode; chain_id; ctxt; op_count; _} as data) data op_count operation - ~payload_producer:Signature.Public_key_hash.zero + ~payload_producer:Alpha_context.Consensus_key.zero | Full_construction { payload_producer; @@ -573,8 +573,8 @@ let finalize_block ( ctxt, Apply_results. { - proposer = Signature.Public_key_hash.zero; - baker = Signature.Public_key_hash.zero; + proposer = Alpha_context.Consensus_key.zero; + baker = Alpha_context.Consensus_key.zero; level_info; voting_period_info; nonce_hash = None; @@ -610,7 +610,7 @@ let finalize_block ( ctxt, Apply_results. { - proposer = Signature.Public_key_hash.zero; + proposer = Alpha_context.Consensus_key.zero; (* We cannot retrieve the proposer as it requires the frozen deposit that might not be available depending on the context given to the partial application. *) diff --git a/src/proto_alpha/lib_protocol/main.mli b/src/proto_alpha/lib_protocol/main.mli index a6e20a489ec4..ad796cee7971 100644 --- a/src/proto_alpha/lib_protocol/main.mli +++ b/src/proto_alpha/lib_protocol/main.mli @@ -56,8 +56,8 @@ type validation_mode = | Application of { block_header : Alpha_context.Block_header.t; fitness : Alpha_context.Fitness.t; - payload_producer : Alpha_context.public_key_hash; - block_producer : Alpha_context.public_key_hash; + payload_producer : Alpha_context.Consensus_key.t; + block_producer : Alpha_context.Consensus_key.t; predecessor_round : Alpha_context.Round.t; predecessor_level : Alpha_context.Level.t; } @@ -66,8 +66,8 @@ type validation_mode = | Partial_application of { block_header : Alpha_context.Block_header.t; fitness : Alpha_context.Fitness.t; - payload_producer : Alpha_context.public_key_hash; - block_producer : Alpha_context.public_key_hash; + payload_producer : Alpha_context.Consensus_key.t; + block_producer : Alpha_context.Consensus_key.t; predecessor_level : Alpha_context.Level.t; predecessor_round : Alpha_context.Round.t; } @@ -86,8 +86,8 @@ type validation_mode = {!val:Tezos_protocol_environment_sigs.V5.T.Updater.PROTOCOL.begin_construction} *) | Full_construction of { predecessor : Block_hash.t; - payload_producer : Alpha_context.public_key_hash; - block_producer : Alpha_context.public_key_hash; + payload_producer : Alpha_context.Consensus_key.t; + block_producer : Alpha_context.Consensus_key.t; protocol_data_contents : Alpha_context.Block_header.contents; level : Int32.t; round : Alpha_context.Round.t; -- GitLab From 7a20da9912e954a15ba2c9481851c5d80212429e Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 11 Jun 2022 01:59:16 +0200 Subject: [PATCH 38/42] Proto/Delegate: use consensus_key for consensus operations --- scripts/yes-wallet/yes_wallet_lib.ml | 7 ++++++- src/proto_alpha/lib_delegate/baking_state.ml | 2 +- src/proto_alpha/lib_protocol/apply.ml | 12 ++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/yes-wallet/yes_wallet_lib.ml b/scripts/yes-wallet/yes_wallet_lib.ml index 9c3359aa2f0c..428debb37ad7 100644 --- a/scripts/yes-wallet/yes_wallet_lib.ml +++ b/scripts/yes-wallet/yes_wallet_lib.ml @@ -449,7 +449,12 @@ let get_delegates (proto : protocol) context ~init:(Ok ([], Alpha_context.Tez.zero)) ~f:(fun pkh acc -> let* pk = - let*! r = Alpha_context.Delegate.manager_pubkey ctxt pkh in + let*! r = + let* pk = + Alpha_context.Delegate.Consensus_key.active_pubkey ctxt pkh + in + return pk.consensus_public_key + in Lwt.return @@ Environment.wrap_tzresult r in let*? key_list_acc, staking_balance_acc = acc in diff --git a/src/proto_alpha/lib_delegate/baking_state.ml b/src/proto_alpha/lib_delegate/baking_state.ml index c7370341ff79..3753157f3395 100644 --- a/src/proto_alpha/lib_delegate/baking_state.ml +++ b/src/proto_alpha/lib_delegate/baking_state.ml @@ -605,7 +605,7 @@ let compute_delegate_slots (cctxt : Protocol_client_context.full) let own_delegate_slots, all_delegate_slots = List.fold_left (fun (own_map, all_map) slot -> - let {Plugin.RPC.Validators.delegate; slots; _} = slot in + let {Plugin.RPC.Validators.consensus_key = delegate; slots; _} = slot in let endorsing_slot = {endorsing_power = List.length slots; delegate; slots} in diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 0d72e1ddf671..848878a6da1e 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2874,7 +2874,7 @@ let validate_consensus_contents (type kind) ctxt chain_id Tez.(frozen_deposits.current_amount > zero) (Zero_frozen_deposits pk.delegate) >>=? fun () -> - Operation.check_signature pk.delegate_public_key chain_id operation + Operation.check_signature pk.consensus_public_key chain_id operation >>?= fun () -> return (ctxt, Consensus_key.pkh pk, voting_power) let apply_manager_contents_list ctxt mode ~payload_producer chain_id @@ -2968,9 +2968,9 @@ let punish_double_endorsement_or_preendorsement (type kind) ctxt ~chain_id (Inconsistent_denunciation {kind; delegate1 = pk1.delegate; delegate2 = pk2.delegate}) >>=? fun () -> - Operation.check_signature pk1.delegate_public_key chain_id op1 + Operation.check_signature pk1.consensus_public_key chain_id op1 >>?= fun () -> - Operation.check_signature pk2.delegate_public_key chain_id op2 + Operation.check_signature pk2.consensus_public_key chain_id op2 >>?= fun () -> punish_delegate ctxt @@ -3011,9 +3011,9 @@ let punish_double_baking ctxt chain_id bh1 bh2 ~payload_producer = (Inconsistent_denunciation {kind = Block; delegate1 = pk1.delegate; delegate2 = pk2.delegate}) >>=? fun () -> - Block_header.check_signature bh1 chain_id pk1.delegate_public_key + Block_header.check_signature bh1 chain_id pk1.consensus_public_key >>?= fun () -> - Block_header.check_signature bh2 chain_id pk2.delegate_public_key + Block_header.check_signature bh2 chain_id pk2.consensus_public_key >>?= fun () -> punish_delegate ctxt @@ -3044,7 +3044,7 @@ let validate_grand_parent_endorsement ctxt chain_id | Single (Endorsement e) -> let level = Level.from_raw ctxt e.level in Stake_distribution.slot_owner ctxt level e.slot >>=? fun (ctxt, pk) -> - Operation.check_signature pk.delegate_public_key chain_id op + Operation.check_signature pk.consensus_public_key chain_id op >>?= fun () -> Consensus.record_grand_parent_endorsement ctxt pk.delegate >>?= fun ctxt -> -- GitLab From 6e57f8e96bec81d4bb12e6509ade1aaaa981068c Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 11 Jun 2022 02:13:15 +0200 Subject: [PATCH 39/42] Proto/Delegate: remove the delegate's public_key from sampler state --- src/proto_alpha/lib_plugin/RPC.ml | 8 +------- src/proto_alpha/lib_protocol/alpha_context.mli | 1 - .../lib_protocol/delegate_consensus_key.ml | 15 +++------------ .../lib_protocol/delegate_consensus_key.mli | 1 - src/proto_alpha/lib_protocol/raw_context.ml | 16 ++++++---------- src/proto_alpha/lib_protocol/raw_context.mli | 1 - 6 files changed, 10 insertions(+), 32 deletions(-) diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 86feda691e03..3c3a3c67407f 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -2655,13 +2655,7 @@ module Endorsing_rights = struct let rights = Slot.Map.fold (fun first_slot - ( Consensus_key. - { - delegate; - delegate_public_key = _; - consensus_key; - consensus_public_key = _; - }, + ( Consensus_key.{delegate; consensus_key; consensus_public_key = _}, endorsing_power ) acc -> {delegate; consensus_key; first_slot; endorsing_power} :: acc) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9ecc2aebc973..4659281b5665 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2237,7 +2237,6 @@ end module Consensus_key : sig type pk = { delegate : public_key_hash; - delegate_public_key : public_key; consensus_key : public_key_hash; consensus_public_key : public_key; } diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml index 5a0b7937641a..f827e32f2d8b 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml @@ -73,7 +73,6 @@ let () = type pk = Raw_context.consensus_pk = { delegate : Signature.public_key_hash; - delegate_public_key : Signature.public_key; consensus_key : Signature.public_key_hash; consensus_public_key : Signature.public_key; } @@ -83,9 +82,7 @@ type t = { consensus_key : Signature.public_key_hash; } -let pkh - {delegate; delegate_public_key = _; consensus_key; consensus_public_key = _} - = +let pkh {delegate; consensus_key; consensus_public_key = _} = {delegate; consensus_key} let zero = @@ -126,10 +123,7 @@ let active_pubkey ctxt delegate = Storage.Contract.Consensus_key.get ctxt (Contract_repr.Implicit delegate) in let consensus_key = Signature.Public_key.hash consensus_public_key in - let* delegate_public_key = - Contract_manager_storage.get_manager_key ctxt delegate - in - return {delegate; delegate_public_key; consensus_key; consensus_public_key} + return {delegate; consensus_key; consensus_public_key} let active_key ctxt delegate = let open Lwt_tzresult_syntax in @@ -172,10 +166,7 @@ let active_pubkey_for_cycle ctxt delegate cycle = raw_active_pubkey_for_cycle ctxt delegate cycle in let consensus_key = Signature.Public_key.hash consensus_public_key in - let* delegate_public_key = - Contract_manager_storage.get_manager_key ctxt delegate - in - return {delegate; delegate_public_key; consensus_key; consensus_public_key} + return {delegate; consensus_key; consensus_public_key} let register_update ctxt delegate cycle pk = let open Lwt_tzresult_syntax in diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli index 1d3cd639258b..4a3d639b936f 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli @@ -31,7 +31,6 @@ type error += (** The public key of a consensus key and the associated delegate. *) type pk = Raw_context.consensus_pk = { delegate : Signature.public_key_hash; - delegate_public_key : Signature.public_key; consensus_key : Signature.public_key_hash; consensus_public_key : Signature.public_key; } diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index b94a78fc61f9..d1cfc823655c 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -75,7 +75,6 @@ module Sc_rollup_address_map_builder = type consensus_pk = { delegate : Signature.public_key_hash; - delegate_public_key : Signature.public_key; consensus_key : Signature.public_key_hash; consensus_public_key : Signature.public_key; } @@ -83,20 +82,17 @@ type consensus_pk = { let consensus_pk_encoding = let open Data_encoding in conv - (fun {delegate; delegate_public_key; consensus_key; consensus_public_key} -> + (fun {delegate; consensus_key; consensus_public_key} -> if Signature.Public_key_hash.equal consensus_key delegate then (consensus_public_key, None) - else (consensus_public_key, Some delegate_public_key)) - (fun (consensus_public_key, delegate_public_key) -> + else (consensus_public_key, Some delegate)) + (fun (consensus_public_key, delegate) -> let consensus_key = Signature.Public_key.hash consensus_public_key in - let delegate_public_key = - Option.value ~default:consensus_public_key delegate_public_key - in - let delegate = Signature.Public_key.hash delegate_public_key in - {delegate; delegate_public_key; consensus_public_key; consensus_key}) + let delegate = Option.value ~default:consensus_key delegate in + {delegate; consensus_public_key; consensus_key}) (obj2 (req "consensus_key" Signature.Public_key.encoding) - (opt "delegate" Signature.Public_key.encoding)) + (opt "delegate" Signature.Public_key_hash.encoding)) module Raw_consensus = struct (** Consensus operations are indexed by their [initial slots]. Given diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index cdac57f30d98..662575520178 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -223,7 +223,6 @@ val non_consensus_operations : t -> Operation_hash.t list type consensus_pk = { delegate : Signature.public_key_hash; - delegate_public_key : Signature.public_key; consensus_key : Signature.public_key_hash; consensus_public_key : Signature.public_key; } -- GitLab From e46cb115feeb4400dc55aa84cef5f139534a5b80 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 11 Jun 2022 02:28:55 +0200 Subject: [PATCH 40/42] Proto/RPC: allow to filter baking/endorsing rights by consensus key --- src/proto_alpha/lib_plugin/RPC.ml | 170 +++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 48 deletions(-) diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 3c3a3c67407f..184de2da07a1 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -2433,18 +2433,21 @@ module Baking_rights = struct levels : Raw_level.t list; cycle : Cycle.t option; delegates : Signature.Public_key_hash.t list; + consensus_keys : Signature.Public_key_hash.t list; max_round : int option; all : bool; } let baking_rights_query = let open RPC_query in - query (fun levels cycle delegates max_round all -> - {levels; cycle; delegates; max_round; all}) + query (fun levels cycle delegates consensus_keys max_round all -> + {levels; cycle; delegates; consensus_keys; max_round; all}) |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) |+ opt_field "cycle" Cycle.rpc_arg (fun t -> t.cycle) |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> t.delegates) + |+ multi_field "consensus_key" Signature.Public_key_hash.rpc_arg (fun t -> + t.consensus_keys) |+ opt_field "max_round" RPC_arg.uint (fun t -> t.max_round) |+ flag "all" (fun t -> t.all) |> seal @@ -2461,9 +2464,10 @@ module Baking_rights = struct (valid) level(s) in the past or future at which the baking \ rights have to be returned.\n\ Parameter `delegate` can be used to restrict the results to the \ - given delegates. If parameter `all` is set, all the baking \ - opportunities for each baker at each level are returned, instead \ - of just the first one.\n\ + given delegates. Parameter `consensus_key` can be used to \ + restrict the results to the given consensus keys.\n\ + If parameter `all` is set, all the baking opportunities for each \ + baker at each level are returned, instead of just the first one.\n\ Returns the list of baking opportunities up to round %d. Also \ returns the minimal timestamps that correspond to these \ opportunities. The timestamps are omitted for levels in the \ @@ -2540,21 +2544,37 @@ module Baking_rights = struct if q.all then List.concat rights else List.concat_map remove_duplicated_delegates rights in - match q.delegates with - | [] -> rights - | _ :: _ as delegates -> - let is_requested p = - List.exists (Signature.Public_key_hash.equal p.delegate) delegates - in - List.filter is_requested rights) + let rights = + match q.delegates with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.delegate) + delegates + in + List.filter is_requested rights + in + let rights = + match q.consensus_keys with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.consensus_key) + delegates + in + List.filter is_requested rights + in + rights) - let get ctxt ?(levels = []) ?cycle ?(delegates = []) ?(all = false) ?max_round - block = + let get ctxt ?(levels = []) ?cycle ?(delegates = []) ?(consensus_keys = []) + ?(all = false) ?max_round block = RPC_context.make_call0 S.baking_rights ctxt block - {levels; cycle; delegates; max_round; all} + {levels; cycle; delegates; consensus_keys; max_round; all} () end @@ -2606,15 +2626,19 @@ module Endorsing_rights = struct levels : Raw_level.t list; cycle : Cycle.t option; delegates : Signature.Public_key_hash.t list; + consensus_keys : Signature.Public_key_hash.t list; } let endorsing_rights_query = let open RPC_query in - query (fun levels cycle delegates -> {levels; cycle; delegates}) + query (fun levels cycle delegates consensus_keys -> + {levels; cycle; delegates; consensus_keys}) |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) |+ opt_field "cycle" Cycle.rpc_arg (fun t -> t.cycle) |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> t.delegates) + |+ multi_field "consensus_key" Signature.Public_key_hash.rpc_arg (fun t -> + t.consensus_keys) |> seal let endorsing_rights = @@ -2626,7 +2650,8 @@ module Endorsing_rights = struct Parameters `level` and `cycle` can be used to specify the (valid) \ level(s) in the past or future at which the endorsing rights have \ to be returned. Parameter `delegate` can be used to restrict the \ - results to the given delegates.\n\ + results to the given delegates. Parameter `consensus_key` can be \ + used to restrict the results to the given consensus keys.\n\ Returns the smallest endorsing slots and the endorsing power. Also \ returns the minimal timestamp that corresponds to endorsing at the \ given level. The timestamps are omitted for levels in the past, and \ @@ -2676,30 +2701,53 @@ module Endorsing_rights = struct in List.map_es (endorsing_rights_at_level ctxt) levels >|=? fun rights_per_level -> - match q.delegates with - | [] -> rights_per_level - | _ :: _ as delegates -> - List.filter_map - (fun rights_at_level -> - let is_requested p = - List.exists - (Signature.Public_key_hash.equal p.delegate) - delegates - in - match - List.filter is_requested rights_at_level.delegates_rights - with - | [] -> None - | delegates_rights -> - Some {rights_at_level with delegates_rights}) - rights_per_level) - - let get ctxt ?(levels = []) ?cycle ?(delegates = []) block = + let rights_per_level = + match q.delegates with + | [] -> rights_per_level + | _ :: _ as delegates -> + List.filter_map + (fun rights_at_level -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.delegate) + delegates + in + match + List.filter is_requested rights_at_level.delegates_rights + with + | [] -> None + | delegates_rights -> + Some {rights_at_level with delegates_rights}) + rights_per_level + in + let rights_per_level = + match q.consensus_keys with + | [] -> rights_per_level + | _ :: _ as consensus_keys -> + List.filter_map + (fun rights_at_level -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.consensus_key) + consensus_keys + in + match + List.filter is_requested rights_at_level.delegates_rights + with + | [] -> None + | delegates_rights -> + Some {rights_at_level with delegates_rights}) + rights_per_level + in + rights_per_level) + + let get ctxt ?(levels = []) ?cycle ?(delegates = []) ?(consensus_keys = []) + block = RPC_context.make_call0 S.endorsing_rights ctxt block - {levels; cycle; delegates} + {levels; cycle; delegates; consensus_keys} () end @@ -2732,14 +2780,18 @@ module Validators = struct type validators_query = { levels : Raw_level.t list; delegates : Signature.Public_key_hash.t list; + consensus_keys : Signature.Public_key_hash.t list; } let validators_query = let open RPC_query in - query (fun levels delegates -> {levels; delegates}) + query (fun levels delegates consensus_keys -> + {levels; delegates; consensus_keys}) |+ multi_field "level" Raw_level.rpc_arg (fun t -> t.levels) |+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> t.delegates) + |+ multi_field "consensus_key" Signature.Public_key_hash.rpc_arg (fun t -> + t.consensus_keys) |> seal let validators = @@ -2751,7 +2803,8 @@ module Validators = struct Parameter `level` can be used to specify the (valid) level(s) in \ the past or future at which the endorsement rights have to be \ returned. Parameter `delegate` can be used to restrict the results \ - to the given delegates.\n" + to the given delegates. Parameter `consensus_key` can be used to \ + restrict the results to the given consensus keys.\n" ~query:validators_query ~output:(list encoding) path @@ -2772,16 +2825,37 @@ module Validators = struct in List.concat_map_es (endorsing_slots_at_level ctxt) levels >|=? fun rights -> - match q.delegates with - | [] -> rights - | _ :: _ as delegates -> - let is_requested p = - List.exists (Signature.Public_key_hash.equal p.delegate) delegates - in - List.filter is_requested rights) + let rights = + match q.delegates with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.delegate) + delegates + in + List.filter is_requested rights + in + let rights = + match q.consensus_keys with + | [] -> rights + | _ :: _ as delegates -> + let is_requested p = + List.exists + (Signature.Public_key_hash.equal p.consensus_key) + delegates + in + List.filter is_requested rights + in + rights) - let get ctxt ?(levels = []) ?(delegates = []) block = - RPC_context.make_call0 S.validators ctxt block {levels; delegates} () + let get ctxt ?(levels = []) ?(delegates = []) ?(consensus_keys = []) block = + RPC_context.make_call0 + S.validators + ctxt + block + {levels; delegates; consensus_keys} + () end module S = struct -- GitLab From 51b9b2a8e87bfd54280e2fe44cf252718f0c5011 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 41/42] Proto/Baker: display consensus key and delegate in logs --- .../lib_delegate/baking_actions.ml | 33 +++++----- .../lib_delegate/baking_actions.mli | 16 ++--- .../lib_delegate/baking_commands.ml | 4 +- src/proto_alpha/lib_delegate/baking_events.ml | 62 ++++++++--------- src/proto_alpha/lib_delegate/baking_lib.ml | 10 ++- src/proto_alpha/lib_delegate/baking_lib.mli | 8 +-- src/proto_alpha/lib_delegate/baking_nonces.ml | 2 +- .../lib_delegate/baking_nonces.mli | 2 +- .../lib_delegate/baking_scheduling.mli | 8 ++- src/proto_alpha/lib_delegate/baking_state.ml | 66 ++++++++++++------- src/proto_alpha/lib_delegate/baking_state.mli | 31 +++++---- .../lib_delegate/client_daemon.mli | 2 +- .../lib_delegate/state_transitions.ml | 8 +-- .../lib_delegate/state_transitions.mli | 10 +-- .../test/mockup_simulator/mockup_simulator.ml | 8 +-- .../mockup_simulator/mockup_simulator.mli | 2 +- 16 files changed, 152 insertions(+), 120 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 81dfefc9f74b..5ac946621647 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -117,7 +117,7 @@ type block_kind = type block_to_bake = { predecessor : block_info; round : Round.t; - delegate : Baking_state.delegate; + delegate : Baking_state.consensus_key_and_delegate; kind : block_kind; } @@ -125,11 +125,11 @@ type action = | Do_nothing | Inject_block of {block_to_bake : block_to_bake; updated_state : state} | Inject_preendorsements of { - preendorsements : (delegate * consensus_content) list; + preendorsements : (consensus_key_and_delegate * consensus_content) list; updated_state : state; } | Inject_endorsements of { - endorsements : (delegate * consensus_content) list; + endorsements : (consensus_key_and_delegate * consensus_content) list; updated_state : state; } | Update_to_level of level_update @@ -214,7 +214,9 @@ let sign_block_header state proposer unsigned_block_header = return {Block_header.shell; protocol_data = {contents; signature}} let inject_block ~state_recorder state block_to_bake ~updated_state = - let {predecessor; round; delegate; kind} = block_to_bake in + let {predecessor; round; delegate = (consensus_key, _) as delegate; kind} = + block_to_bake + in let cctxt = state.global_state.cctxt in let chain_id = state.global_state.chain_id in let simulation_mode = state.global_state.validation_mode in @@ -260,7 +262,7 @@ let inject_block ~state_recorder state block_to_bake ~updated_state = >>=? fun injection_level -> generate_seed_nonce_hash state.global_state.config.Baking_configuration.nonce - delegate + consensus_key injection_level >>=? fun seed_nonce_opt -> let seed_nonce_hash = Option.map fst seed_nonce_opt in @@ -292,7 +294,7 @@ let inject_block ~state_recorder state block_to_bake ~updated_state = simulation_kind state.global_state.constants.parametric >>=? fun {unsigned_block_header; operations} -> - sign_block_header state delegate unsigned_block_header + sign_block_header state consensus_key unsigned_block_header >>=? fun signed_block_header -> (match seed_nonce_opt with | None -> @@ -325,7 +327,7 @@ let inject_preendorsements ~state_recorder state ~preendorsements ~updated_state (* Don't parallelize signatures: the signer might not be able to handle concurrent requests *) List.filter_map_es - (fun (delegate, consensus_content) -> + (fun (((consensus_key, _) as delegate), consensus_content) -> Events.(emit signing_preendorsement delegate) >>= fun () -> let shell = { @@ -340,11 +342,10 @@ let inject_preendorsements ~state_recorder state ~preendorsements ~updated_state let block_location = Baking_files.resolve_location ~chain_id `Highwatermarks in - let delegate = delegate.public_key_hash in Baking_highwatermarks.may_sign_preendorsement cctxt block_location - ~delegate + ~delegate:consensus_key.public_key_hash ~level ~round >>=? function @@ -352,7 +353,7 @@ let inject_preendorsements ~state_recorder state ~preendorsements ~updated_state Baking_highwatermarks.record_preendorsement cctxt block_location - ~delegate + ~delegate:consensus_key.public_key_hash ~level ~round >>=? fun () -> return_true @@ -367,7 +368,8 @@ let inject_preendorsements ~state_recorder state ~preendorsements ~updated_state unsigned_operation in (* TODO: do we want to reload the sk uri or not ? *) - Client_keys.get_key cctxt delegate.public_key_hash >>=? fun (_, _, sk) -> + Client_keys.get_key cctxt consensus_key.public_key_hash + >>=? fun (_, _, sk) -> Client_keys.sign cctxt ~watermark sk unsigned_operation_bytes else fail (Baking_highwatermarks.Block_previously_preendorsed {round; level})) @@ -412,7 +414,7 @@ let sign_endorsements state endorsements = (* Don't parallelize signatures: the signer might not be able to handle concurrent requests *) List.filter_map_es - (fun (delegate, consensus_content) -> + (fun (((consensus_key, _) as delegate), consensus_content) -> Events.(emit signing_endorsement delegate) >>= fun () -> let shell = { @@ -433,7 +435,7 @@ let sign_endorsements state endorsements = Baking_highwatermarks.may_sign_endorsement cctxt block_location - ~delegate:delegate.public_key_hash + ~delegate:consensus_key.public_key_hash ~level ~round >>=? function @@ -441,7 +443,7 @@ let sign_endorsements state endorsements = Baking_highwatermarks.record_endorsement cctxt block_location - ~delegate:delegate.public_key_hash + ~delegate:consensus_key.public_key_hash ~level ~round >>=? fun () -> return_true @@ -456,7 +458,8 @@ let sign_endorsements state endorsements = unsigned_operation in (* TODO: do we want to reload the sk uri or not ? *) - Client_keys.get_key cctxt delegate.public_key_hash >>=? fun (_, _, sk) -> + Client_keys.get_key cctxt consensus_key.public_key_hash + >>=? fun (_, _, sk) -> Client_keys.sign cctxt ~watermark sk unsigned_operation_bytes else fail (Baking_highwatermarks.Block_previously_preendorsed {round; level})) diff --git a/src/proto_alpha/lib_delegate/baking_actions.mli b/src/proto_alpha/lib_delegate/baking_actions.mli index 83789e84892f..da181cda8c32 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.mli +++ b/src/proto_alpha/lib_delegate/baking_actions.mli @@ -39,7 +39,7 @@ type block_kind = type block_to_bake = { predecessor : block_info; round : Round.t; - delegate : delegate; + delegate : consensus_key_and_delegate; kind : block_kind; } @@ -47,11 +47,11 @@ type action = | Do_nothing | Inject_block of {block_to_bake : block_to_bake; updated_state : state} | Inject_preendorsements of { - preendorsements : (delegate * consensus_content) list; + preendorsements : (consensus_key_and_delegate * consensus_content) list; updated_state : state; } | Inject_endorsements of { - endorsements : (delegate * consensus_content) list; + endorsements : (consensus_key_and_delegate * consensus_content) list; updated_state : state; } | Update_to_level of level_update @@ -75,7 +75,7 @@ type t = action val generate_seed_nonce_hash : Baking_configuration.nonce_config -> - delegate -> + consensus_key -> Level.t -> (Nonce_hash.t * Nonce.t) option tzresult Lwt.t @@ -89,19 +89,19 @@ val inject_block : val inject_preendorsements : state_recorder:(new_state:state -> unit tzresult Lwt.t) -> state -> - preendorsements:(delegate * consensus_content) list -> + preendorsements:(consensus_key_and_delegate * consensus_content) list -> updated_state:state -> state tzresult Lwt.t val sign_endorsements : state -> - (delegate * consensus_content) list -> - (delegate * packed_operation) list tzresult Lwt.t + (consensus_key_and_delegate * consensus_content) list -> + (consensus_key_and_delegate * packed_operation) list tzresult Lwt.t val inject_endorsements : state_recorder:(new_state:state -> unit tzresult Lwt.t) -> state -> - endorsements:(delegate * consensus_content) list -> + endorsements:(consensus_key_and_delegate * consensus_content) list -> updated_state:state -> state tzresult Lwt.t diff --git a/src/proto_alpha/lib_delegate/baking_commands.ml b/src/proto_alpha/lib_delegate/baking_commands.ml index 78d6ec9e61a1..eae0f2d4beda 100644 --- a/src/proto_alpha/lib_delegate/baking_commands.ml +++ b/src/proto_alpha/lib_delegate/baking_commands.ml @@ -202,7 +202,9 @@ let sources_param = Clic.seq_of_param (Client_keys.Public_key_hash.source_param ~name:"baker" - ~desc:"name of the delegate owning the endorsement right") + ~desc: + "name of the delegate owning the endorsement/baking right or name of \ + the consensus key signing on the delegate's behalf") let delegate_commands () : Protocol_client_context.full Clic.command list = let open Clic in diff --git a/src/proto_alpha/lib_delegate/baking_events.ml b/src/proto_alpha/lib_delegate/baking_events.ml index d0e2f9a35f2e..dd8506d8c7fc 100644 --- a/src/proto_alpha/lib_delegate/baking_events.ml +++ b/src/proto_alpha/lib_delegate/baking_events.ml @@ -87,8 +87,8 @@ module State_transitions = struct ("level", Data_encoding.int32) ~pp3:Round.pp ("next_round", Round.encoding) - ~pp4:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp4:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let new_head_while_waiting_for_qc = declare_0 @@ -241,8 +241,8 @@ module State_transitions = struct ~name:"proposing_fresh_block" ~level:Info ~msg:"proposing fresh block for {delegate} at round {round}" - ~pp1:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) ~pp2:Round.pp ("round", Round.encoding) @@ -384,8 +384,8 @@ module Scheduling = struct ("round", Round.encoding) ~pp3:Timestamp.pp ("timestamp", Timestamp.encoding) - ~pp4:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp4:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let waiting_end_of_round = declare_3 @@ -499,8 +499,8 @@ module Actions = struct ~name:"skipping_preendorsement" ~level:Error ~msg:"skipping preendorsement for {delegate} -- {trace}" - ~pp1:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) ~pp2:Error_monad.pp_print_trace ("trace", Error_monad.trace_encoding) @@ -510,8 +510,8 @@ module Actions = struct ~name:"skipping_endorsement" ~level:Error ~msg:"skipping endorsement for {delegate} -- {trace}" - ~pp1:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) ~pp2:Error_monad.pp_print_trace ("trace", Error_monad.trace_encoding) @@ -521,8 +521,8 @@ module Actions = struct ~name:"failed_to_inject_preendorsement" ~level:Error ~msg:"failed to inject preendorsement for {delegate} -- {trace}" - ~pp1:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) ~pp2:Error_monad.pp_print_trace ("trace", Error_monad.trace_encoding) @@ -545,8 +545,8 @@ module Actions = struct ~msg:"injected preendorsement {ophash} for {delegate}" ~pp1:Operation_hash.pp ("ophash", Operation_hash.encoding) - ~pp2:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp2:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let endorsement_injected = declare_2 @@ -556,8 +556,8 @@ module Actions = struct ~msg:"injected endorsement {ophash} for {delegate}" ~pp1:Operation_hash.pp ("ophash", Operation_hash.encoding) - ~pp2:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp2:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let synchronizing_round = declare_1 @@ -573,29 +573,26 @@ module Actions = struct ~section ~name:"forging_block" ~level:Info - ~msg: - "forging block at level {level}, round {round} for delegate {delegate}" + ~msg:"forging block at level {level}, round {round} for {delegate}" ~pp1:pp_int32 ~pp2:Round.pp - ~pp3:Baking_state.pp_delegate + ~pp3:Baking_state.pp_consensus_key_and_delegate ("level", Data_encoding.int32) ("round", Round.encoding) - ("delegate", Baking_state.delegate_encoding) + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let injecting_block = declare_3 ~section ~name:"injecting_block" ~level:Debug - ~msg: - "injecting block at level {level}, round {round} for delegate \ - {delegate}" + ~msg:"injecting block at level {level}, round {round} for {delegate}" ~pp1:pp_int32 ~pp2:Round.pp - ~pp3:Baking_state.pp_delegate + ~pp3:Baking_state.pp_consensus_key_and_delegate ("level", Data_encoding.int32) ("round", Round.encoding) - ("delegate", Baking_state.delegate_encoding) + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let block_injected = declare_4 @@ -603,16 +600,15 @@ module Actions = struct ~name:"block_injected" ~level:Notice ~msg: - "block {block} at level {level}, round {round} injected for delegate \ - {delegate}" + "block {block} at level {level}, round {round} injected for {delegate}" ~pp1:Block_hash.pp ~pp2:pp_int32 ~pp3:Round.pp - ~pp4:Baking_state.pp_delegate + ~pp4:Baking_state.pp_consensus_key_and_delegate ("block", Block_hash.encoding) ("level", Data_encoding.int32) ("round", Round.encoding) - ("delegate", Baking_state.delegate_encoding) + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let signing_preendorsement = declare_1 @@ -620,8 +616,8 @@ module Actions = struct ~name:"signing_preendorsement" ~level:Info ~msg:"signing preendorsement for {delegate}" - ~pp1:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let signing_endorsement = declare_1 @@ -629,8 +625,8 @@ module Actions = struct ~name:"signing_endorsement" ~level:Info ~msg:"signing endorsement for {delegate}" - ~pp1:Baking_state.pp_delegate - ("delegate", Baking_state.delegate_encoding) + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) let invalid_json_file = declare_1 diff --git a/src/proto_alpha/lib_delegate/baking_lib.ml b/src/proto_alpha/lib_delegate/baking_lib.ml index 7ef044310a5f..7ec3ae000cd5 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.ml +++ b/src/proto_alpha/lib_delegate/baking_lib.ml @@ -80,7 +80,10 @@ let preendorse (cctxt : Protocol_client_context.full) ?(force = false) delegates let*! () = cctxt#message "@[Preendorsing for:@ %a@]" - Format.(pp_print_list ~pp_sep:pp_print_space Baking_state.pp_delegate) + Format.( + pp_print_list + ~pp_sep:pp_print_space + Baking_state.pp_consensus_key_and_delegate) (List.map fst consensus_list) in let state_recorder ~new_state = @@ -117,7 +120,10 @@ let endorse (cctxt : Protocol_client_context.full) ?(force = false) delegates = let*! () = cctxt#message "@[Endorsing for:@ %a@]" - Format.(pp_print_list ~pp_sep:pp_print_space Baking_state.pp_delegate) + Format.( + pp_print_list + ~pp_sep:pp_print_space + Baking_state.pp_consensus_key_and_delegate) (List.map fst consensus_list) in let state_recorder ~new_state = diff --git a/src/proto_alpha/lib_delegate/baking_lib.mli b/src/proto_alpha/lib_delegate/baking_lib.mli index 547822f25d1a..e37f01ac7bb5 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.mli +++ b/src/proto_alpha/lib_delegate/baking_lib.mli @@ -37,19 +37,19 @@ val bake : ?extra_operations:Baking_configuration.Operations_source.t -> ?monitor_node_mempool:bool -> ?context_path:string -> - Baking_state.delegate list -> + Baking_state.consensus_key list -> unit tzresult Lwt.t val preendorse : Protocol_client_context.full -> ?force:bool -> - Baking_state.delegate list -> + Baking_state.consensus_key list -> unit tzresult Lwt.t val endorse : Protocol_client_context.full -> ?force:bool -> - Baking_state.delegate list -> + Baking_state.consensus_key list -> unit tzresult Lwt.t val propose : @@ -61,5 +61,5 @@ val propose : ?minimal_timestamp:bool -> ?extra_operations:Baking_configuration.Operations_source.t -> ?context_path:string -> - Baking_state.delegate list -> + Baking_state.consensus_key list -> unit tzresult Lwt.t diff --git a/src/proto_alpha/lib_delegate/baking_nonces.ml b/src/proto_alpha/lib_delegate/baking_nonces.ml index 170bedfdb697..ce893c0a8b1c 100644 --- a/src/proto_alpha/lib_delegate/baking_nonces.ml +++ b/src/proto_alpha/lib_delegate/baking_nonces.ml @@ -199,7 +199,7 @@ let get_unrevealed_nonces ({cctxt; chain; _} as state) nonces = (* Nonce creation *) let generate_seed_nonce (nonce_config : Baking_configuration.nonce_config) - (delegate : Baking_state.delegate) level = + (delegate : Baking_state.consensus_key) level = (match nonce_config with | Deterministic -> let data = Data_encoding.Binary.to_bytes_exn Raw_level.encoding level in diff --git a/src/proto_alpha/lib_delegate/baking_nonces.mli b/src/proto_alpha/lib_delegate/baking_nonces.mli index baa6ebf23f18..5151c8909f24 100644 --- a/src/proto_alpha/lib_delegate/baking_nonces.mli +++ b/src/proto_alpha/lib_delegate/baking_nonces.mli @@ -84,7 +84,7 @@ val get_unrevealed_nonces : val generate_seed_nonce : Baking_configuration.nonce_config -> - Baking_state.delegate -> + Baking_state.consensus_key -> Raw_level.t -> (Nonce_hash.t * Nonce.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_delegate/baking_scheduling.mli b/src/proto_alpha/lib_delegate/baking_scheduling.mli index a641b7f892fc..83e167cfcf34 100644 --- a/src/proto_alpha/lib_delegate/baking_scheduling.mli +++ b/src/proto_alpha/lib_delegate/baking_scheduling.mli @@ -44,7 +44,9 @@ val wait_next_event : val compute_next_round_time : state -> (Time.Protocol.t * Round.t) option val first_potential_round_at_next_level : - state -> earliest_round:Round.t -> (Round.t * delegate) option + state -> + earliest_round:Round.t -> + (Round.t * consensus_key_and_delegate) option val compute_next_potential_baking_time_at_next_level : state -> (Time.Protocol.t * Round.t) option Lwt.t @@ -58,7 +60,7 @@ val create_initial_state : Baking_configuration.t -> Operation_worker.t -> current_proposal:proposal -> - delegate trace -> + consensus_key list -> state tzresult Lwt.t val compute_bootstrap_event : state -> event tzresult @@ -79,5 +81,5 @@ val run : ?on_error:(tztrace -> unit tzresult Lwt.t) -> chain:Chain_services.chain -> Baking_configuration.t -> - delegate trace -> + consensus_key list -> unit tzresult Lwt.t diff --git a/src/proto_alpha/lib_delegate/baking_state.ml b/src/proto_alpha/lib_delegate/baking_state.ml index 3753157f3395..0d07cba1b012 100644 --- a/src/proto_alpha/lib_delegate/baking_state.ml +++ b/src/proto_alpha/lib_delegate/baking_state.ml @@ -26,16 +26,16 @@ open Protocol open Alpha_context -(** A delegate (aka, a validator) is identified by its alias name, its +(** A consenssus key (aka, a validator) is identified by its alias name, its public key, its public key hash, and its secret key. *) -type delegate = { +type consensus_key = { alias : string option; public_key : Signature.Public_key.t; public_key_hash : Signature.Public_key_hash.t; secret_key_uri : Client_keys.sk_uri; } -let delegate_encoding = +let consensus_key_encoding = let open Data_encoding in conv (fun {alias; public_key; public_key_hash; secret_key_uri} -> @@ -59,7 +59,7 @@ let delegate_encoding = (req "public_key_hash" Signature.Public_key_hash.encoding) (req "secret_key_uri" string)) -let pp_delegate fmt {alias; public_key_hash; _} = +let pp_consensus_key fmt {alias; public_key_hash; _} = match alias with | None -> Format.fprintf fmt "%a" Signature.Public_key_hash.pp public_key_hash | Some alias -> @@ -70,6 +70,26 @@ let pp_delegate fmt {alias; public_key_hash; _} = Signature.Public_key_hash.pp public_key_hash +type consensus_key_and_delegate = consensus_key * Signature.Public_key_hash.t + +let consensus_key_and_delegate_encoding = + let open Data_encoding in + merge_objs + consensus_key_encoding + (obj1 (req "delegate" Signature.Public_key_hash.encoding)) + +let pp_consensus_key_and_delegate fmt (consensus_key, delegate) = + if Signature.Public_key_hash.equal consensus_key.public_key_hash delegate then + pp_consensus_key fmt consensus_key + else + Format.fprintf + fmt + "%a@,on behalf of %a" + pp_consensus_key + consensus_key + Signature.Public_key_hash.pp + delegate + type validation_mode = Node | Local of Abstract_context_index.t type prequorum = { @@ -96,7 +116,7 @@ type block_info = { type cache = { known_timestamps : Timestamp.time Baking_cache.Timestamp_of_round_cache.t; round_timestamps : - (Timestamp.time * Round.t * delegate) + (Timestamp.time * Round.t * consensus_key_and_delegate) Baking_cache.Round_timestamp_interval_cache.t; } @@ -116,7 +136,7 @@ type global_state = { (* the validation mode used by the baker*) validation_mode : validation_mode; (* the delegates on behalf of which the baker is running *) - delegates : delegate list; + delegates : consensus_key list; cache : cache; } @@ -215,11 +235,7 @@ module SlotMap : Map.S with type key = Slot.t = Map.Make (Slot) list of slots (i.e., a list of position indexes in the slot map, in other words the list of rounds when it will be the proposer), and its endorsing power. *) -type endorsing_slot = { - delegate : Signature.Public_key_hash.t; - slots : Slot.t list; - endorsing_power : int; -} +type endorsing_slot = {slots : Slot.t list; endorsing_power : int} (* FIXME: determine if the slot map should contain all slots or just the first one *) @@ -228,7 +244,7 @@ type endorsing_slot = { type delegate_slots = { (* be careful not to duplicate endorsing slots with different slots keys: always use the first slot in the slots list *) - own_delegate_slots : (delegate * endorsing_slot) SlotMap.t; + own_delegate_slots : (consensus_key_and_delegate * endorsing_slot) SlotMap.t; all_delegate_slots : endorsing_slot SlotMap.t; all_slots_by_round : Slot.t array; } @@ -575,7 +591,7 @@ let may_load_endorsable_data state = module DelegateSet = struct include Set.Make (struct - type t = delegate + type t = consensus_key let compare {public_key_hash = pkh; _} {public_key_hash = pkh'; _} = Signature.Public_key_hash.compare pkh pkh' @@ -605,10 +621,8 @@ let compute_delegate_slots (cctxt : Protocol_client_context.full) let own_delegate_slots, all_delegate_slots = List.fold_left (fun (own_map, all_map) slot -> - let {Plugin.RPC.Validators.consensus_key = delegate; slots; _} = slot in - let endorsing_slot = - {endorsing_power = List.length slots; delegate; slots} - in + let {Plugin.RPC.Validators.consensus_key; delegate; slots; _} = slot in + let endorsing_slot = {endorsing_power = List.length slots; slots} in let all_map = List.fold_left (fun all_map slot -> SlotMap.add slot endorsing_slot all_map) @@ -616,11 +630,14 @@ let compute_delegate_slots (cctxt : Protocol_client_context.full) slots in let own_map = - match DelegateSet.find_pkh delegate own_delegates with - | Some delegate -> + match DelegateSet.find_pkh consensus_key own_delegates with + | Some consensus_key -> List.fold_left (fun own_map slot -> - SlotMap.add slot (delegate, endorsing_slot) own_map) + SlotMap.add + slot + ((consensus_key, delegate), endorsing_slot) + own_map) own_map slots | None -> own_map @@ -658,7 +675,7 @@ let pp_global_state fmt {chain_id; config; validation_mode; delegates; _} = config pp_validation_mode validation_mode - Format.(pp_print_list pp_delegate) + Format.(pp_print_list pp_consensus_key) delegates let pp_option pp fmt = function @@ -739,14 +756,15 @@ let pp_elected_block fmt {proposal; endorsement_qc} = proposal.block (List.length endorsement_qc) -let pp_endorsing_slot fmt (delegate, {delegate = _; slots; endorsing_power}) = +let pp_endorsing_slot fmt (consensus_key_and_delegate, {slots; endorsing_power}) + = Format.fprintf fmt "slots: @[[%a]@],@ delegate: %a,@ endorsing_power: %d" Format.(pp_print_list ~pp_sep:pp_print_space Slot.pp) slots - pp_delegate - delegate + pp_consensus_key_and_delegate + consensus_key_and_delegate endorsing_power let pp_delegate_slots fmt {own_delegate_slots; _} = diff --git a/src/proto_alpha/lib_delegate/baking_state.mli b/src/proto_alpha/lib_delegate/baking_state.mli index 45f325e509d1..3650fc322708 100644 --- a/src/proto_alpha/lib_delegate/baking_state.mli +++ b/src/proto_alpha/lib_delegate/baking_state.mli @@ -26,16 +26,24 @@ open Protocol open Alpha_context -type delegate = { +type consensus_key = { alias : string option; public_key : Signature.public_key; public_key_hash : Signature.public_key_hash; secret_key_uri : Client_keys.sk_uri; } -val delegate_encoding : delegate Data_encoding.t +val consensus_key_encoding : consensus_key Data_encoding.t -val pp_delegate : Format.formatter -> delegate -> unit +val pp_consensus_key : Format.formatter -> consensus_key -> unit + +type consensus_key_and_delegate = consensus_key * Signature.Public_key_hash.t + +val consensus_key_and_delegate_encoding : + consensus_key_and_delegate Data_encoding.t + +val pp_consensus_key_and_delegate : + Format.formatter -> consensus_key_and_delegate -> unit type validation_mode = Node | Local of Abstract_context_index.t @@ -65,7 +73,7 @@ type block_info = { type cache = { known_timestamps : Timestamp.time Baking_cache.Timestamp_of_round_cache.t; round_timestamps : - (Timestamp.time * Round.t * delegate) + (Timestamp.time * Round.t * consensus_key_and_delegate) Baking_cache.Round_timestamp_interval_cache.t; } @@ -77,7 +85,7 @@ type global_state = { round_durations : Round.round_durations; operation_worker : Operation_worker.t; validation_mode : validation_mode; - delegates : delegate list; + delegates : consensus_key list; cache : cache; } @@ -87,14 +95,10 @@ val round_of_shell_header : Block_header.shell_header -> Round.t tzresult module SlotMap : Map.S with type key = Slot.t -type endorsing_slot = { - delegate : Signature.public_key_hash; - slots : Slot.t trace; - endorsing_power : int; -} +type endorsing_slot = {slots : Slot.t list; endorsing_power : int} type delegate_slots = { - own_delegate_slots : (delegate * endorsing_slot) SlotMap.t; + own_delegate_slots : (consensus_key_and_delegate * endorsing_slot) SlotMap.t; all_delegate_slots : endorsing_slot SlotMap.t; all_slots_by_round : Slot.t array; } @@ -189,7 +193,7 @@ val compute_delegate_slots : ?block:Block_services.block -> level:int32 -> chain:Shell_services.chain -> - delegate list -> + consensus_key list -> delegate_slots tzresult Lwt.t val create_cache : unit -> cache @@ -211,7 +215,8 @@ val pp_endorsable_payload : Format.formatter -> endorsable_payload -> unit val pp_elected_block : Format.formatter -> elected_block -> unit -val pp_endorsing_slot : Format.formatter -> delegate * endorsing_slot -> unit +val pp_endorsing_slot : + Format.formatter -> consensus_key_and_delegate * endorsing_slot -> unit val pp_delegate_slots : Format.formatter -> delegate_slots -> unit diff --git a/src/proto_alpha/lib_delegate/client_daemon.mli b/src/proto_alpha/lib_delegate/client_daemon.mli index 0e6f79986105..790d03cee1c2 100644 --- a/src/proto_alpha/lib_delegate/client_daemon.mli +++ b/src/proto_alpha/lib_delegate/client_daemon.mli @@ -39,7 +39,7 @@ module Baker : sig chain:Shell_services.chain -> context_path:string -> keep_alive:bool -> - Baking_state.delegate list -> + Baking_state.consensus_key list -> unit tzresult Lwt.t end diff --git a/src/proto_alpha/lib_delegate/state_transitions.ml b/src/proto_alpha/lib_delegate/state_transitions.ml index dd978072e535..6e8dd27e6284 100644 --- a/src/proto_alpha/lib_delegate/state_transitions.ml +++ b/src/proto_alpha/lib_delegate/state_transitions.ml @@ -79,8 +79,8 @@ let make_consensus_list state proposal = let round = proposal.block.round in let block_payload_hash = proposal.block.payload_hash in SlotMap.fold - (fun _slot (delegate, slots) acc -> - ( delegate, + (fun _slot (consensus_key_and_delegate, slots) acc -> + ( consensus_key_and_delegate, {slot = Stdlib.List.hd slots.slots; level; round; block_payload_hash} ) :: acc) state.level_state.delegate_slots.own_delegate_slots @@ -96,7 +96,7 @@ let make_preendorse_action state proposal = in {state with round_state} in - let preendorsements : (delegate * consensus_content) list = + let preendorsements : (consensus_key_and_delegate * consensus_content) list = make_consensus_list state proposal in Inject_preendorsements {preendorsements; updated_state} @@ -598,7 +598,7 @@ let make_endorse_action state proposal = proposal.block.round proposal.block.payload_hash in - let endorsements : (delegate * consensus_content) list = + let endorsements : (consensus_key_and_delegate * consensus_content) list = make_consensus_list state proposal in Inject_endorsements {endorsements; updated_state} diff --git a/src/proto_alpha/lib_delegate/state_transitions.mli b/src/proto_alpha/lib_delegate/state_transitions.mli index 4b14864cb1de..9dde0efaf02b 100644 --- a/src/proto_alpha/lib_delegate/state_transitions.mli +++ b/src/proto_alpha/lib_delegate/state_transitions.mli @@ -36,7 +36,7 @@ val is_acceptable_proposal_for_current_level : state -> proposal -> proposal_acceptance Lwt.t val make_consensus_list : - state -> proposal -> (delegate * consensus_content) list + state -> proposal -> (consensus_key_and_delegate * consensus_content) list val make_preendorse_action : state -> proposal -> action @@ -51,21 +51,21 @@ val handle_new_proposal : state -> proposal -> (state * action) Lwt.t val round_proposer : state -> - (delegate * endorsing_slot) SlotMap.t -> + (consensus_key_and_delegate * endorsing_slot) SlotMap.t -> Round.t -> - (delegate * endorsing_slot) option + (consensus_key_and_delegate * endorsing_slot) option val propose_fresh_block_action : endorsements:Kind.endorsement Operation.t list -> ?last_proposal:block_info -> predecessor:block_info -> state -> - delegate -> + consensus_key_and_delegate -> Round.t -> action Lwt.t val propose_block_action : - state -> delegate -> Round.t -> proposal -> action Lwt.t + state -> consensus_key_and_delegate -> Round.t -> proposal -> action Lwt.t (** Increase the current round and propose at the new round (same level), if the baker has a proposer slot. *) diff --git a/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml b/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml index 5194f4dd2cea..001336b30a94 100644 --- a/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml +++ b/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml @@ -135,7 +135,7 @@ module type Hooks = sig val on_start_baker : baker_position:int -> - delegates:Baking_state.delegate list -> + delegates:Baking_state.consensus_key list -> cctxt:Protocol_client_context.full -> unit Lwt.t @@ -738,7 +738,7 @@ let create_fake_node_state ~i ~live_depth } (** Start baker process. *) -let baker_process ~(delegates : Baking_state.delegate list) ~base_dir +let baker_process ~(delegates : Baking_state.consensus_key list) ~base_dir ~(genesis_block : Block_header.t * Environment_context.rpc_context) ~i ~global_chain_table ~broadcast_pipes ~(user_hooks : (module Hooks)) = let broadcast_pipe = @@ -766,7 +766,7 @@ let baker_process ~(delegates : Baking_state.delegate list) ~base_dir User_hooks.on_start_baker ~baker_position:i ~delegates ~cctxt >>= fun () -> List.iter_es (fun ({alias; public_key; public_key_hash; secret_key_uri} : - Baking_state.delegate) -> + Baking_state.consensus_key) -> let open Tezos_client_base in let name = alias |> WithExceptions.Option.get ~loc:__LOC__ in Client_keys.neuterize secret_key_uri >>=? fun public_key_uri -> @@ -1064,7 +1064,7 @@ let default_config = let make_baking_delegate ( (account : Alpha_context.Parameters.bootstrap_account), (secret : Tezos_mockup_commands.Mockup_wallet.bootstrap_secret) ) : - Baking_state.delegate = + Baking_state.consensus_key = Baking_state. { alias = Some secret.name; diff --git a/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.mli b/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.mli index 25b73e0c6182..9704b16d57be 100644 --- a/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.mli +++ b/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.mli @@ -116,7 +116,7 @@ module type Hooks = sig bakers that were started for this run. *) val on_start_baker : baker_position:int -> - delegates:Baking_state.delegate list -> + delegates:Baking_state.consensus_key list -> cctxt:Protocol_client_context.full -> unit Lwt.t -- GitLab From bfd5cf79514c27a3cb5bf3f0e07827b0bf3eddbe Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 42/42] Proto: add a minimal `tezt` scenario for consensus key --- .../client_proto_context_commands.ml | 2 +- tezt/lib_tezos/client.ml | 37 ++- tezt/lib_tezos/client.mli | 25 +- tezt/tests/consensus_key.ml | 314 ++++++++++++++++++ tezt/tests/main.ml | 1 + 5 files changed, 365 insertions(+), 14 deletions(-) create mode 100644 tezt/tests/consensus_key.ml diff --git a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml index c5b784b1f0c5..2ba59dc4778e 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_context_commands.ml @@ -959,7 +959,7 @@ let commands_rw () = ?fee ~src_pk ~manager_sk - >>= fun _ -> return_unit); + >>=? fun _ -> return_unit); command ~group ~desc:"Launch a smart contract on the blockchain." diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 921987916535..9a16ec2eca10 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -508,7 +508,7 @@ let spawn_bake_for ?endpoint ?protocol ?(keys = [Constant.bootstrap1.alias]) let bake_for ?endpoint ?protocol ?keys ?minimal_fees ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ?minimal_timestamp - ?mempool ?ignore_node_mempool ?force ?context_path client = + ?mempool ?ignore_node_mempool ?force ?context_path ?expect_failure client = spawn_bake_for ?endpoint ?keys @@ -522,7 +522,7 @@ let bake_for ?endpoint ?protocol ?keys ?minimal_fees ?context_path ?protocol client - |> Process.check + |> Process.check ?expect_failure let node_of_endpoint = function Node n -> Some n | Proxy_server _ -> None @@ -811,7 +811,7 @@ let get_delegate ?endpoint ~src client = Lwt.return (output =~* rex "(tz[a-zA-Z0-9]+) \\(.*\\)") let set_delegate ?endpoint ?(wait = "none") ?fee ?fee_cap - ?(force_low_fee = false) ~src ~delegate client = + ?(force_low_fee = false) ?expect_failure ~src ~delegate client = let value = spawn_command ?endpoint @@ -822,7 +822,7 @@ let set_delegate ?endpoint ?(wait = "none") ?fee ?fee_cap @ optional_arg "fee-cap" Tez.to_string fee_cap @ if force_low_fee then ["--force-low-fee"] else []) in - {value; run = Process.check} + {value; run = Process.check ?expect_failure} let reveal ?endpoint ?(wait = "none") ?fee ?fee_cap ?(force_low_fee = false) ~src client = @@ -842,10 +842,11 @@ let spawn_withdraw_delegate ?endpoint ?(wait = "none") ~src client = spawn_command ?endpoint client - (["--wait"; wait] @ ["withdraw"; "delegate"; "for"; src]) + (["--wait"; wait] @ ["withdraw"; "delegate"; "from"; src]) -let withdraw_delegate ?endpoint ?wait ~src client = - spawn_withdraw_delegate ?endpoint ?wait ~src client |> Process.check +let withdraw_delegate ?endpoint ?wait ?expect_failure ~src client = + spawn_withdraw_delegate ?endpoint ?wait ~src client + |> Process.check ?expect_failure let spawn_get_balance_for ?endpoint ~account client = spawn_command ?endpoint client ["get"; "balance"; "for"; account] @@ -917,6 +918,17 @@ let unset_deposits_limit ?hooks ?endpoint ?(wait = "none") ~src client = (["--wait"; wait] @ ["unset"; "deposits"; "limit"; "for"; src]) |> Process.check_and_read_stdout +let update_consensus_key ?hooks ?endpoint ?(wait = "none") ?burn_cap + ?expect_failure ~src ~pk client = + spawn_command + ?hooks + ?endpoint + client + (["--wait"; wait] + @ ["set"; "consensus"; "key"; "for"; src; "to"; pk] + @ optional_arg "burn-cap" Tez.to_string burn_cap) + |> Process.check ?expect_failure + let spawn_originate_contract ?hooks ?log_output ?endpoint ?(wait = "none") ?init ?burn_cap ~alias ~amount ~src ~prg client = spawn_command @@ -1876,12 +1888,17 @@ let init_with_protocol ?path ?admin_path ?name ?color ?base_dir ?event_level let* _ = Node.wait_for_level node 1 in return (node, client) -let spawn_register_key owner client = +let spawn_register_key ?consensus owner client = spawn_command client - ["--wait"; "none"; "register"; "key"; owner; "as"; "delegate"] + (["--wait"; "none"; "register"; "key"; owner; "as"; "delegate"] + @ + match consensus with + | None -> [] + | Some pk -> ["with"; "consensus"; "key"; pk]) -let register_key owner client = spawn_register_key owner client |> Process.check +let register_key ?consensus owner client = + spawn_register_key ?consensus owner client |> Process.check let contract_storage ?unparsing_mode address client = spawn_command diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index 62f4bd513e4b..b182bf6c956a 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -370,6 +370,7 @@ val bake_for : ?ignore_node_mempool:bool -> ?force:bool -> ?context_path:string -> + ?expect_failure:bool -> t -> unit Lwt.t @@ -635,6 +636,7 @@ val set_delegate : ?fee:Tez.t -> ?fee_cap:Tez.t -> ?force_low_fee:bool -> + ?expect_failure:bool -> src:string -> delegate:string -> t -> @@ -653,7 +655,12 @@ val reveal : (** Run [tezos-client withdraw delegate from ]. *) val withdraw_delegate : - ?endpoint:endpoint -> ?wait:string -> src:string -> t -> unit Lwt.t + ?endpoint:endpoint -> + ?wait:string -> + ?expect_failure:bool -> + src:string -> + t -> + unit Lwt.t (** Same as [withdraw_delegate], but do not wait for the process to exit. *) val spawn_withdraw_delegate : @@ -736,6 +743,18 @@ val unset_deposits_limit : t -> string Lwt.t +(** Run [tezos-client use as consensus key for delegate ] *) +val update_consensus_key : + ?hooks:Process.hooks -> + ?endpoint:endpoint -> + ?wait:string -> + ?burn_cap:Tez.t -> + ?expect_failure:bool -> + src:string -> + pk:string -> + t -> + unit Lwt.t + (* TODO: https://gitlab.com/tezos/tezos/-/issues/2336 [amount] should be named [transferring] *) (* TODO: https://gitlab.com/tezos/tezos/-/issues/2336 @@ -1399,10 +1418,10 @@ val spawn_command : Process.t (** Register public key for given account with given client. *) -val spawn_register_key : string -> t -> Process.t +val spawn_register_key : ?consensus:string -> string -> t -> Process.t (** Register public key for given account with given client. *) -val register_key : string -> t -> unit Lwt.t +val register_key : ?consensus:string -> string -> t -> unit Lwt.t (** Get contract storage for a contract. Returns a Micheline expression representing the storage as a string. *) diff --git a/tezt/tests/consensus_key.ml b/tezt/tests/consensus_key.ml new file mode 100644 index 000000000000..34576df6a454 --- /dev/null +++ b/tezt/tests/consensus_key.ml @@ -0,0 +1,314 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 G.B. Fefe *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +(* Testing + ------- + Component: Baker + Invocation: dune exec tezt/tests/main.exe -- --file consensus_key.ml + Subject: Test the operation `Update_consensus_key` and its effects + on the baker. +*) + +module Helpers = struct + type level = { + level : int; + level_position : int; + cycle : int; + cycle_position : int; + expected_commitment : bool; + } + + let level_type : level Check.typ = + Check.convert + (fun {level; level_position; cycle; cycle_position; expected_commitment} -> + (level, level_position, cycle, cycle_position, expected_commitment)) + Check.(tuple5 int int int int bool) + + let decode_level json = + let level = JSON.(json |-> "level" |> as_int) in + let level_position = JSON.(json |-> "level_position" |> as_int) in + let cycle = JSON.(json |-> "cycle" |> as_int) in + let cycle_position = JSON.(json |-> "cycle_position" |> as_int) in + let expected_commitment = + JSON.(json |-> "expected_commitment" |> as_bool) + in + {level; level_position; cycle; cycle_position; expected_commitment} + + let get_current_level client = + let* json = RPC.get_current_level client in + return (decode_level json) + + let check_current_level client expected_level = + let* level = get_current_level client in + Check.((level = expected_level) level_type) + ~error_msg:"expected current_period = %R, got %L" ; + unit + + let bake_and_wait_block node client = + let* level_json = RPC.get_current_level client in + let level = JSON.(level_json |-> "level" |> as_int) in + let* () = + Client.bake_for ~context_path:(Node.data_dir node // "context") client + in + let* _i = Node.wait_for_level node (level + 1) in + Lwt.return_unit +end + +open Helpers + +let test_update_consensus_key = + Protocol.register_test + ~__FILE__ + ~title:"update consensus key" + ~tags:["consensus_key"] + @@ fun protocol -> + let parameters = + (* we update paramaters for faster testing: no need to wait + 5 cycles for the consensus key to activate. *) + [(["blocks_per_cycle"], Some "4"); (["preserved_cycles"], Some "0")] + in + let* parameter_file = + Protocol.write_parameter_file ~base:(Right (protocol, None)) parameters + in + let* _, client = + Client.init_with_protocol ~parameter_file ~protocol `Client () + in + let* key_a = Client.gen_and_show_keys client in + let* key_b = Client.gen_and_show_keys client in + let* key_c = Client.gen_and_show_keys client in + + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:(Tez.of_int 1_000_000) + ~giver:Constant.bootstrap1.alias + ~receiver:key_b.alias + client + in + let* () = Client.bake_for_and_wait client in + + (* Trying multiple invalid updates: + - changing the consensus key of an unregistered delegate + - changing the consensus key to its actual value + - changing the consensus key to an active consensus key (bootstrap) + *) + let* () = + Client.update_consensus_key + ~expect_failure:true + ~src:key_b.alias + ~pk:Constant.bootstrap1.alias + client + in + let* () = + Client.update_consensus_key + ~expect_failure:true + ~src:Constant.bootstrap1.alias + ~pk:Constant.bootstrap1.alias + client + in + let* () = + Client.update_consensus_key + ~expect_failure:true + ~src:Constant.bootstrap2.alias + ~pk:Constant.bootstrap1.alias + client + in + + (* Trying a valid consensus key update. *) + let* () = + Client.update_consensus_key + ~src:Constant.bootstrap1.alias + ~pk:key_a.alias + client + in + let* () = Client.bake_for_and_wait client in + + (* Invalid update: + - changing the consensus key to an active consensus key (set) *) + let* () = + Client.update_consensus_key + ~expect_failure:true + ~src:Constant.bootstrap2.alias + ~pk:key_a.alias + client + in + + (* Register a delegate with a consensus key. *) + let* () = Client.register_key ~consensus:key_c.alias key_b.alias client in + + (* Bake until the end of the cycle... *) + let* () = Client.bake_for_and_wait client in + let* () = + check_current_level + client + { + level = 4; + level_position = 3; + cycle = 0; + cycle_position = 3; + expected_commitment = true; + } + in + + (* Bootstrap1 should not be able to bake anymore... *) + let* () = + Client.bake_for + ~expect_failure:true + ~keys:[Constant.bootstrap1.alias] + client + in + + (* ... meanwhile `key_a` and `key_c` are able to bake. *) + let* () = Client.bake_for_and_wait ~keys:[key_a.alias] client in + let* () = Client.bake_for_and_wait ~keys:[key_c.alias] client in + + (* Switch back to the initial consensus key. *) + let* () = + Client.update_consensus_key + ~src:Constant.bootstrap1.alias + ~pk:Constant.bootstrap1.alias + client + in + let* () = + Client.update_consensus_key ~src:key_b.alias ~pk:key_b.alias client + in + + (* Bake until the end of the cycle. *) + let* () = Client.bake_for_and_wait ~keys:[key_a.alias] client in + let* () = Client.bake_for_and_wait ~keys:[key_a.alias] client in + let* () = + check_current_level + client + { + level = 8; + level_position = 7; + cycle = 1; + cycle_position = 3; + expected_commitment = true; + } + in + + (* We are not able to bake with `key_a` anymore... *) + let* () = Client.bake_for ~expect_failure:true ~keys:[key_a.alias] client in + + (* ... but are able to bake again with `bootstrap1` and `key_b`... *) + let* () = Client.bake_for_and_wait ~keys:[Constant.bootstrap1.alias] client in + let* () = Client.bake_for_and_wait ~keys:[key_b.alias] client in + + (* Set the consensus key for all delegates... *) + let* () = + Client.update_consensus_key + ~src:Constant.bootstrap1.alias + ~pk:key_a.alias + client + in + let* () = + Client.update_consensus_key + ~src:Constant.bootstrap2.alias + ~pk:key_a.alias + client + in + let* () = + Client.update_consensus_key + ~src:Constant.bootstrap3.alias + ~pk:key_a.alias + client + in + let* () = + Client.update_consensus_key + ~src:Constant.bootstrap4.alias + ~pk:key_a.alias + client + in + let* () = + Client.update_consensus_key + ~src:Constant.bootstrap5.alias + ~pk:key_a.alias + client + in + (* Bake until the end of the cycle. *) + let* () = Client.bake_for_and_wait ~keys:[Constant.bootstrap1.alias] client in + let* () = Client.bake_for_and_wait ~keys:[Constant.bootstrap1.alias] client in + let* () = + check_current_level + client + { + level = 12; + level_position = 11; + cycle = 2; + cycle_position = 3; + expected_commitment = true; + } + in + + (* Bootstrap's accounts should not be able to bake anymore... *) + let* () = + Client.bake_for + ~expect_failure:true + ~keys:[Constant.bootstrap1.alias] + client + in + let* () = + Client.bake_for + ~expect_failure:true + ~keys:[Constant.bootstrap2.alias] + client + in + let* () = + Client.bake_for + ~expect_failure:true + ~keys:[Constant.bootstrap3.alias] + client + in + let* () = + Client.bake_for + ~expect_failure:true + ~keys:[Constant.bootstrap4.alias] + client + in + let* () = + Client.bake_for + ~expect_failure:true + ~keys:[Constant.bootstrap5.alias] + client + in + let* () = Client.bake_for_and_wait ~keys:[key_a.alias] client in + let* () = Client.bake_for_and_wait ~keys:[key_a.alias] client in + let* () = Client.bake_for_and_wait ~keys:[key_a.alias] client in + let* () = Client.bake_for_and_wait ~keys:[key_a.alias] client in + let* () = + check_current_level + client + { + level = 16; + level_position = 15; + cycle = 3; + cycle_position = 3; + expected_commitment = true; + } + in + unit + +let register ~protocols = test_update_consensus_key protocols diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index d3fd21067b0e..64466e2ddbb5 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -127,6 +127,7 @@ let () = Sapling.register ~protocols:[Alpha] ; Client_run_view.register ~protocols:[Alpha] ; Multinode_snapshot.register ~protocols:[Alpha] ; + Consensus_key.register ~protocols:[Alpha] ; Config.register () ; (* Test.run () should be the last statement, don't register afterwards! *) Test.run () -- GitLab