From 61f186157cbdf4eba2f85b5c087e5288332d1771 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 14 Apr 2022 23:37:43 +0200 Subject: [PATCH 01/48] 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 0a8af4e50aaf..e8c49f63ca92 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -112,6 +112,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 a8171c397beb..b522a619e883 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -398,6 +398,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; @@ -419,15 +424,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 d32e6023936b..5676d5d37e50 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2236,22 +2236,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 183dfb0524c7..8ebb49accef8 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2903,18 +2903,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 73761c300e8d..7b7cc9980b21 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -139,6 +139,10 @@ Contract_storage Token Delegate_storage + Delegate_missed_endorsements_storage + Delegate_slashed_deposits_storage + Delegate_sampler + Delegate_cycles Bootstrap_storage Vote_storage Fees_storage @@ -352,6 +356,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 @@ -551,6 +560,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 @@ -770,6 +784,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 @@ -985,6 +1004,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 9301a568bc654400ad305af075dcea8d4a9176fb Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 21 Apr 2022 10:38:31 +0200 Subject: [PATCH 02/48] 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 eab4a563ee5a6380ddd7dd9389c52e3781b69ba5 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 21 Apr 2022 11:55:00 +0200 Subject: [PATCH 03/48] 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 5676d5d37e50..3e4e4e39c0e5 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2214,7 +2214,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 b3daf7ff85bc..544711c5ad83 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -365,7 +365,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 -> @@ -388,42 +388,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 5febbae3d85567f3fde8296bc6e1204facc9c6eb Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 16:32:16 +0200 Subject: [PATCH 04/48] 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 b522a619e883..507c555c80f7 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -414,8 +414,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 3e4e4e39c0e5..40c34ddb07fa 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2284,7 +2284,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 8ebb49accef8..c1d24d86d620 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1501,7 +1501,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 b51897528ad7f8d2d280783d9444b2f365b70389 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 14 Apr 2022 23:37:43 +0200 Subject: [PATCH 05/48] 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 997cbc82f38da5e45905090d317d6efc568ff3cd Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 13:41:44 +0200 Subject: [PATCH 06/48] 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 507c555c80f7..136f4eb95ea4 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -238,6 +238,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 @@ -414,8 +422,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 40c34ddb07fa..06d0192345e7 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1586,6 +1586,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 @@ -2188,17 +2201,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 c1d24d86d620..05840c044a4f 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -794,7 +794,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 = @@ -1063,7 +1063,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 ee2a3a66a40e..bb0115cc0942 100644 --- a/src/proto_alpha/lib_protocol/contract_services.ml +++ b/src/proto_alpha/lib_protocol/contract_services.ml @@ -370,7 +370,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 @@ -501,7 +501,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 d12451168919..20a147c187b1 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_token.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_token.ml @@ -505,13 +505,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 e923c18a22e3c24cd1163f012a97f9a415eb81df Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 16:39:20 +0200 Subject: [PATCH 07/48] 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 136f4eb95ea4..8649672c9df2 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -241,9 +241,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 06d0192345e7..9c5e8cbde009 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1586,17 +1586,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 c2f697d06eeb74875fd0d4415f2120f2fb87960b Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 14 Apr 2022 23:37:43 +0200 Subject: [PATCH 08/48] 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 9c5e8cbde009..450db04c630c 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1202,9 +1202,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 @@ -2232,7 +2229,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 05840c044a4f..5529711fa4b1 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -3240,8 +3240,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 2001a1bc7e887dcbb9cdf62daf8cdf4966f6b21d Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 23 Apr 2022 13:14:16 +0200 Subject: [PATCH 09/48] 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 450db04c630c..7df05c1db2fe 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1654,7 +1654,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; } @@ -1777,7 +1777,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 @@ -1931,7 +1931,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; } @@ -1962,10 +1962,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 -> @@ -2001,16 +2000,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 -> @@ -2025,16 +2018,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 -> @@ -2080,8 +2067,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 @@ -2165,7 +2152,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 @@ -2198,10 +2185,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 -> @@ -2229,9 +2216,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 @@ -2255,15 +2240,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 @@ -2272,22 +2257,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 @@ -2350,8 +2331,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 @@ -2375,13 +2355,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 @@ -2456,8 +2435,7 @@ module Sc_rollup : sig val encoding : t Data_encoding.t end - 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 @@ -2747,7 +2725,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} @@ -2804,8 +2782,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 -> @@ -2814,7 +2791,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 -> @@ -2967,7 +2944,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; } @@ -2979,7 +2956,7 @@ type 'kind operation = { and 'kind protocol_data = { contents : 'kind contents_list; - signature : Signature.t option; + signature : signature option; } and _ contents_list = @@ -3017,13 +2994,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; @@ -3031,7 +3008,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; @@ -3041,7 +3018,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; @@ -3050,9 +3027,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; } @@ -3409,8 +3384,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 @@ -3585,8 +3559,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 ] @@ -3607,7 +3581,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 | container ] -- GitLab From 3b87a36093f3eb0d9b41962318ccc7b2b463507f Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 10/48] 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 8649672c9df2..8b291cc38354 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -432,8 +432,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 7df05c1db2fe..11ec5d1fd525 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3382,8 +3382,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 5fc671d4c683675e7d1e791eb8fd7ebeea668b1f Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:43:07 +0200 Subject: [PATCH 11/48] 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 11ec5d1fd525..c8a56aa4c2b7 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2210,7 +2210,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 544711c5ad83..26b149982247 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -424,7 +424,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 c8dc03ddb44476e944923bf956fc2ed410345e0b Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 26 Apr 2022 10:29:20 +0000 Subject: [PATCH 12/48] 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 11bd76e297bf144a7a32292e4a7aa6a994feee19 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Wed, 27 Apr 2022 11:08:02 +0200 Subject: [PATCH 13/48] 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 222bf2c2d882833c3e8aa41cc8aa4e0c47be5171 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 13:08:21 +0200 Subject: [PATCH 14/48] 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 ab6aa935044ffad8c3e65c9c712859fbe5fc1d8d Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 13:08:38 +0200 Subject: [PATCH 15/48] 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 c48a03d4a55aeff239688d6be99609378ac3b228 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sat, 7 May 2022 14:31:00 +0200 Subject: [PATCH 16/48] Proto: remove unused error in `Delegate_storage` --- .../client_proto_context_commands.ml | 6 +- .../lib_protocol/delegate_storage.ml | 215 +++++++----------- .../lib_protocol/delegate_storage.mli | 21 +- .../integration/consensus/test_delegation.ml | 8 +- 4 files changed, 105 insertions(+), 145 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 7ace7e77ed5c..0fff31de6b21 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 @@ -1482,7 +1482,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..997e86f304ea 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" @@ -183,10 +60,7 @@ 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) + Contract_manager_storage.get_manager_key ctxt pkh ~error:(Not_registered pkh) let frozen_deposits_limit ctxt delegate = Storage.Contract.Frozen_deposits_limit.find @@ -233,6 +107,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 +139,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 +204,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* () = 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 41299b62d68a..1aa2a163f01f 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." @@ -203,7 +203,8 @@ let bootstrap_manager_already_registered_delegate ~fee () = else Incremental.add_operation ~expect_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 @@ -440,7 +441,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 13223856121a00222f5a3b0548448c388f030166 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Tue, 10 May 2022 02:57:07 +0200 Subject: [PATCH 17/48] 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 997e86f304ea..b4e7deaf3ddc 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 5ccfe823be948781a7995a7969eff5feb6150292 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 16 May 2022 11:16:32 +0200 Subject: [PATCH 18/48] 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 c8a56aa4c2b7..43c150907559 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2218,20 +2218,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 5529711fa4b1..7cee1882adfd 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -107,7 +107,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; @@ -617,19 +616,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" @@ -2903,19 +2889,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 bbdb9f0c350dd35474077ca598a879492a7af59d Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 19/48] Proto: Make room for more ghosts in `Storage_functors`. --- src/proto_alpha/lib_protocol/storage.ml | 36 +++++++++++++++++-- .../lib_protocol/storage_functors.ml | 16 ++++++--- src/proto_alpha/lib_protocol/storage_sigs.ml | 4 +-- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 46c941431516..f314b79f273a 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) @@ -211,6 +214,7 @@ module Contract = struct module Delegate = Indexed_context.Make_map + (Registered) (struct let name = ["delegate"] end) @@ -225,6 +229,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"] @@ -241,6 +246,7 @@ module Contract = struct module Counter = Indexed_context.Make_map + (Registered) (struct let name = ["counter"] end) @@ -254,8 +260,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 @@ -324,6 +329,7 @@ module Contract = struct module Paid_storage_space = Indexed_context.Make_map + (Registered) (struct let name = ["paid_bytes"] end) @@ -331,6 +337,7 @@ module Contract = struct module Used_storage_space = Indexed_context.Make_map + (Registered) (struct let name = ["used_bytes"] end) @@ -338,6 +345,7 @@ module Contract = struct module Frozen_deposits = Indexed_context.Make_map + (Registered) (struct let name = ["frozen_deposits"] end) @@ -345,6 +353,7 @@ module Contract = struct module Frozen_deposits_limit = Indexed_context.Make_map + (Registered) (struct let name = ["frozen_deposits_limit"] end) @@ -360,6 +369,7 @@ module Contract = struct module Frozen_bonds = Bond_id_index.Make_carbonated_map + (Registered) (struct let name = ["frozen_bonds"] end) @@ -369,6 +379,7 @@ module Contract = struct module Total_frozen_bonds = Indexed_context.Make_map + (Registered) (struct let name = ["total_frozen_bonds"] end) @@ -453,6 +464,7 @@ module Big_map = struct module Total_bytes = Indexed_context.Make_map + (Registered) (struct let name = ["total_bytes"] end) @@ -460,6 +472,7 @@ module Big_map = struct module Key_type = Indexed_context.Make_map + (Registered) (struct let name = ["key_type"] end) @@ -471,6 +484,7 @@ module Big_map = struct module Value_type = Indexed_context.Make_map + (Registered) (struct let name = ["value_type"] end) @@ -582,6 +596,7 @@ module Sapling = struct module Total_bytes = Indexed_context.Make_map + (Registered) (struct let name = ["total_bytes"] end) @@ -942,6 +957,7 @@ module Cycle = struct module Selected_stake_distribution = Indexed_context.Make_map + (Registered) (struct let name = ["selected_stake_distribution"] end) @@ -958,6 +974,7 @@ module Cycle = struct module Total_active_stake = Indexed_context.Make_map + (Registered) (struct let name = ["total_active_stake"] end) @@ -971,6 +988,7 @@ module Cycle = struct module Delegate_sampler_state = Indexed_context.Make_map + (Registered) (struct let name = ["delegate_sampler_state"] end) @@ -1025,6 +1043,7 @@ module Cycle = struct module Seed = Indexed_context.Make_map + (Registered) (struct let name = ["random_seed"] end) @@ -1417,6 +1436,7 @@ module Tx_rollup = struct module State = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["state"] end) @@ -1432,6 +1452,7 @@ module Tx_rollup = struct module Inbox = Level_context.Make_carbonated_map + (Registered) (struct let name = ["inbox"] end) @@ -1443,6 +1464,7 @@ module Tx_rollup = struct module Revealed_withdrawals = Level_context.Make_carbonated_map + (Registered) (struct let name = ["withdrawals"] end) @@ -1450,6 +1472,7 @@ module Tx_rollup = struct module Commitment = Level_context.Make_carbonated_map + (Registered) (struct let name = ["commitment"] end) @@ -1465,6 +1488,7 @@ module Tx_rollup = struct module Commitment_bond = Bond_indexed_context.Make_carbonated_map + (Registered) (struct let name = ["commitment"] end) @@ -1492,6 +1516,7 @@ module Sc_rollup = struct module PVM_kind = Indexed_context.Make_map + (Registered) (struct let name = ["kind"] end) @@ -1503,6 +1528,7 @@ module Sc_rollup = struct module Boot_sector = Indexed_context.Make_map + (Registered) (struct let name = ["boot_sector"] end) @@ -1514,6 +1540,7 @@ module Sc_rollup = struct module Parameters_type = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["parameters_type"] end) @@ -1525,6 +1552,7 @@ module Sc_rollup = struct module Initial_level = Indexed_context.Make_map + (Registered) (struct let name = ["initial_level"] end) @@ -1536,6 +1564,7 @@ module Sc_rollup = struct module Inbox = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["inbox"] end) @@ -1547,6 +1576,7 @@ module Sc_rollup = struct module Last_cemented_commitment = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["last_cemented_commitment"] end) @@ -1571,6 +1601,7 @@ module Sc_rollup = struct module Staker_count = Indexed_context.Make_carbonated_map + (Registered) (struct let name = ["staker_count"] end) @@ -1714,6 +1745,7 @@ module Sc_rollup = struct module Applied_outbox_messages = Level_index_context.Make_carbonated_map + (Registered) (struct let name = ["applied_outbox_messages"] 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 a145a5c2fbb5b1777f2b6a9a814bfd281cdc8677 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 20/48] Proto/Delegate: Add a `Storage.Contracts.Consensus_key` --- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 2 + .../lib_protocol/alpha_context.mli | 16 ++ .../lib_protocol/delegate_consensus_key.ml | 155 +++++++++++++ .../lib_protocol/delegate_consensus_key.mli | 73 ++++++ .../lib_protocol/delegate_cycles.ml | 1 + .../lib_protocol/delegate_sampler.ml | 4 +- .../lib_protocol/delegate_storage.ml | 26 ++- .../lib_protocol/delegate_storage.mli | 4 + src/proto_alpha/lib_protocol/dune | 5 + src/proto_alpha/lib_protocol/init_storage.ml | 4 +- 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 | 210 ++++++++++++++++++ 15 files changed, 525 insertions(+), 8 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 e8c49f63ca92..07845e66f02d 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -111,6 +111,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 8b291cc38354..242c1d1fe8c9 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -421,6 +421,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 43c150907559..45a2f2784fb5 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2268,6 +2268,22 @@ module Delegate : sig val pubkey : context -> public_key_hash -> public_key tzresult Lwt.t + module Consensus_key : sig + val active_pubkey : context -> public_key_hash -> public_key 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..2303e0287a1b --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml @@ -0,0 +1,155 @@ +(*****************************************************************************) +(* *) +(* 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 (%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) + +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* pk = + Storage.Contract.Consensus_key.get ctxt (Contract_repr.Implicit delegate) + in + return pk + +let active_key ctxt delegate = + let open Lwt_tzresult_syntax in + let* pk = active_pubkey ctxt delegate in + return (Signature.Public_key.hash 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) + pendings + in + return active_for_cycle + +let active_pubkey_for_cycle ctxt delegate cycle = + let open Lwt_tzresult_syntax in + let* _, active = raw_active_pubkey_for_cycle ctxt delegate cycle in + return active + +let register_update ctxt delegate cycle pk = + let open Lwt_tzresult_syntax in + let* () = + let current_level = Raw_context.current_level ctxt in + fail_when + Cycle_repr.(cycle <= current_level.cycle) + (Invalid_consensus_key_update_cycle 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..8ca12e0beb8b --- /dev/null +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli @@ -0,0 +1,73 @@ +(*****************************************************************************) +(* *) +(* 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 + +(** 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 -> + Signature.Public_key.t tzresult Lwt.t + +(** Returns the active consensus key for the current cycle. *) +val active_key : + Raw_context.t -> + Signature.Public_key_hash.t -> + Signature.Public_key_hash.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 -> + Signature.Public_key.t 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..e4cf195b7a21 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 diff --git a/src/proto_alpha/lib_protocol/delegate_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index 9d5af86363fd..b2611be04dfd 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -224,8 +224,8 @@ let select_distribution_for_cycle ctxt cycle = >>=? 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) + Delegate_consensus_key.active_pubkey_for_cycle ctxt pkh cycle + >|=? fun pk -> ((pk, pkh), Tez_repr.to_mutez stake) :: acc) [] stakes >>=? fun stakes_pk -> diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index b4e7deaf3ddc..d5765cc8fb47 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -193,11 +193,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 @@ -212,6 +212,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 @@ -296,3 +297,18 @@ module Contract = struct set_self_delegate c delegate | _ -> set_delegate c contract delegate end + +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_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 8096594f8fab..29e649efdefd 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -127,3 +127,7 @@ val pubkey : Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t 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/dune b/src/proto_alpha/lib_protocol/dune index 7b7cc9980b21..5f889852a9dd 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -138,6 +138,7 @@ Stake_storage Contract_storage Token + Delegate_consensus_key Delegate_storage Delegate_missed_endorsements_storage Delegate_slashed_deposits_storage @@ -355,6 +356,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 @@ -559,6 +561,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 @@ -783,6 +786,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 @@ -1003,6 +1007,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..ea7eb7858dbb 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_storage.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/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index f314b79f273a..3ffcddec2f46 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -212,6 +212,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 (Registered) diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 667740f8fe60..27eec55eb3df 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 8e1f03660c12..42bc5a90aa75 100644 --- a/src/proto_alpha/lib_protocol/test/unit/main.ml +++ b/src/proto_alpha/lib_protocol/test/unit/main.ml @@ -79,5 +79,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..2b66644bcdd0 --- /dev/null +++ b/src/proto_alpha/lib_protocol/test/unit/test_consensus_key.ml @@ -0,0 +1,210 @@ +(*****************************************************************************) +(* *) +(* 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 1 in + let account = + match accounts with [(account, _, _)] -> account | _ -> assert false + in + let* ctxt = Block.alpha_context accounts in + return (Alpha_context.Internal_for_tests.to_raw ctxt, account) + +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:(Cycle_repr.of_int32_exn (Int32.of_int 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 pk) + l +end + +let test_consensus_key_storage () = + let open Lwt_result_syntax in + let* ctxt, delegate = create () in + let a1 = Account.new_account () in + let a2 = Account.new_account () in + let* () = + let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh delegate.pkh + in + let* () = + let* active_pk = Consensus_key.active_pubkey ctxt delegate.pkh in + Assert.equal_pk ~__LOC__ active_pk delegate.pk + in + let* () = + let* active_pk = + Consensus_key.active_pubkey_for_cycle ctxt delegate.pkh 5 + in + Assert.equal_pk ~__LOC__ active_pk delegate.pk + in + let* ctxt = Consensus_key.register_update ctxt delegate.pkh 2 a1.pk in + let* ctxt = Consensus_key.register_update ctxt delegate.pkh 5 a2.pk in + let* () = + Assert.active_keys + ~__LOC__ + ctxt + delegate.pkh + [ + (0, delegate.pk); + (1, delegate.pk); + (2, a1.pk); + (3, a1.pk); + (4, a1.pk); + (5, a2.pk); + (6, a2.pk); + ] + in + let* () = + let*! err = Consensus_key.register_update ctxt delegate.pkh 2 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 2l + | _ -> false) + in + let* () = + let*! err = Consensus_key.register_update ctxt delegate.pkh 3 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 2l + | _ -> false) + in + let* () = + let*! err = Consensus_key.register_update ctxt delegate.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 2l + | _ -> false) + in + let* () = + let*! err = Consensus_key.register_update ctxt delegate.pkh 5 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* () = + let*! err = Consensus_key.register_update ctxt delegate.pkh 6 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.activate ctxt ~new_cycle:1 in + let* ctxt = Consensus_key.activate ctxt ~new_cycle:2 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh a1.pkh + in + let* ctxt = Consensus_key.activate ctxt ~new_cycle:3 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh a1.pkh + in + let* ctxt = Consensus_key.activate ctxt ~new_cycle:4 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh a1.pkh + in + let* ctxt = Consensus_key.activate ctxt ~new_cycle:5 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh a2.pkh + in + let* ctxt = Consensus_key.activate ctxt ~new_cycle:6 in + let* () = + let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh a2.pkh + in + return () + +let tests = + [Tztest.tztest "consensus_key_storage" `Quick test_consensus_key_storage] -- GitLab From 3f6ddd3e4df4b73a0ff0667196e9fddeeeb68290 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 21/48] 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_storage.ml | 2 +- src/proto_alpha/lib_protocol/delegate_storage.mli | 2 +- 5 files changed, 9 insertions(+), 6 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 45a2f2784fb5..4586aec9670e 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2266,7 +2266,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 module Consensus_key : sig val active_pubkey : context -> public_key_hash -> public_key tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 7cee1882adfd..0511dc1c0c36 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -3147,7 +3147,7 @@ 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.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 @@ -3157,7 +3157,7 @@ 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.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_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index d5765cc8fb47..29268f00b595 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -70,7 +70,7 @@ let fold = Storage.Delegates.fold let list = Storage.Delegates.elements -let pubkey ctxt pkh = +let manager_pubkey ctxt pkh = Contract_manager_storage.get_manager_key ctxt pkh ~error:(Not_registered pkh) let frozen_deposits_limit ctxt delegate = diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 29e649efdefd..bf603fdd3806 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -123,7 +123,7 @@ module Contract : sig Raw_context.t tzresult Lwt.t end -val pubkey : +val manager_pubkey : Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t tzresult Lwt.t -- GitLab From 9d6283d2fd8e38d83ec61ac9a8a8cb4d3e8b1ea9 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 22/48] 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 +++ .../rpc/alpha.client.delegates.out | 3 +- .../rpc/alpha.light.delegates.out | 3 +- .../rpc/alpha.proxy.delegates.out | 3 +- .../alpha.proxy_server_data_dir.delegates.out | 3 +- .../rpc/alpha.proxy_server_rpc.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 26b149982247..ebbc02a7152c 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -60,6 +60,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 = @@ -76,6 +78,8 @@ let info_encoding = deactivated; grace_period; voting_info; + active_consensus_key; + pending_consensus_keys; } -> ( ( full_balance, current_frozen_deposits, @@ -86,7 +90,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, @@ -96,7 +100,7 @@ let info_encoding = delegated_balance, deactivated, grace_period ), - voting_info ) -> + (voting_info, (active_consensus_key, pending_consensus_keys)) ) -> { full_balance; current_frozen_deposits; @@ -108,6 +112,8 @@ let info_encoding = deactivated; grace_period; voting_info; + active_consensus_key; + pending_consensus_keys; }) (merge_objs (obj9 @@ -120,7 +126,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 @@ -307,6 +323,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: @@ -374,7 +409,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 consensus_key -> + Delegate.Consensus_key.pending_updates ctxt pkh >|=? fun pendings -> { full_balance; current_frozen_deposits = frozen_deposits.current_amount; @@ -386,6 +423,8 @@ let register () = deactivated; grace_period; voting_info; + active_consensus_key = Signature.Public_key.hash consensus_key; + pending_consensus_keys = pendings; }) ; register1 ~chunked:false S.full_balance (fun ctxt pkh () () -> trace (Balance_rpc_non_delegate pkh) (Delegate.check_registered ctxt pkh) @@ -422,6 +461,11 @@ let register () = register1 ~chunked:false S.voting_info (fun ctxt pkh () () -> Delegate.check_registered ctxt pkh >>=? fun () -> Vote.get_delegate_info ctxt pkh) ; + register1 ~chunked:false S.consensus_key (fun ctxt pkh () () -> + Delegate.check_registered ctxt pkh >>=? fun () -> + Delegate.Consensus_key.active_pubkey ctxt pkh >>=? fun pk -> + Delegate.Consensus_key.pending_updates ctxt pkh >>=? fun pendings -> + return (Signature.Public_key.hash pk, pendings)) ; register1 ~chunked:false S.participation (fun ctxt pkh () () -> Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.participation_info ctxt pkh) @@ -470,5 +514,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 8092f2c368cd..e53ac412ba16 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.mli +++ b/src/proto_alpha/lib_protocol/delegate_services.mli @@ -52,6 +52,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 @@ -125,6 +127,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 c5f7874c415c..c2af8dd2d839 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -330,6 +330,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 @@ -352,6 +354,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 38f49f94fe3d..9378ee1c0b3e 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/_regressions/rpc/alpha.client.delegates.out b/tezt/_regressions/rpc/alpha.client.delegates.out index 5b87aa0650a6..648f09344be0 100644 --- a/tezt/_regressions/rpc/alpha.client.delegates.out +++ b/tezt/_regressions/rpc/alpha.client.delegates.out @@ -22,7 +22,8 @@ rpc/alpha.client.delegates.out "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/_regressions/rpc/alpha.light.delegates.out b/tezt/_regressions/rpc/alpha.light.delegates.out index 86f0c849ccff..87ef3f752b0f 100644 --- a/tezt/_regressions/rpc/alpha.light.delegates.out +++ b/tezt/_regressions/rpc/alpha.light.delegates.out @@ -24,7 +24,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/_regressions/rpc/alpha.proxy.delegates.out b/tezt/_regressions/rpc/alpha.proxy.delegates.out index 172a65ed7b8f..f484c5fe3315 100644 --- a/tezt/_regressions/rpc/alpha.proxy.delegates.out +++ b/tezt/_regressions/rpc/alpha.proxy.delegates.out @@ -24,7 +24,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/_regressions/rpc/alpha.proxy_server_data_dir.delegates.out b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.delegates.out index 82f40f30c09c..8bd81a4eb05a 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_data_dir.delegates.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.delegates.out @@ -22,7 +22,8 @@ rpc/alpha.proxy_server_data_dir.delegates.out "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/_regressions/rpc/alpha.proxy_server_rpc.delegates.out b/tezt/_regressions/rpc/alpha.proxy_server_rpc.delegates.out index bf6ef936d9ad..f2537562625c 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_rpc.delegates.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_rpc.delegates.out @@ -22,7 +22,8 @@ rpc/alpha.proxy_server_rpc.delegates.out "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 d03a9a54dc33c442bdf6fe13f2ce067ba036c9f2 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 23/48] 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 646a1db0cb79..24ff91f2262e 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -1107,6 +1107,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) : @@ -1158,37 +1159,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 @@ -1245,31 +1226,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 9ae091ee04f7..334302db0e33 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -296,12 +296,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 4586aec9670e..2f325bb00673 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -3474,6 +3474,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 = { @@ -3491,6 +3492,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 21b2a26c38b0..87c8782f4519 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 c2af8dd2d839..b99d8cf04053 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/context.ml @@ -460,7 +460,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 = @@ -483,7 +483,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 b7b31721a1cb7acdf8eaf32ea0b4726175ca451e Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 24/48] Proto/Delegate: Capture the consensus key in snapshot --- scripts/yes-wallet/yes_wallet_lib.ml | 7 +- .../lib_client/operation_result.ml | 15 +- src/proto_alpha/lib_delegate/baking_state.ml | 2 +- .../client_baking_denunciation.ml | 8 +- .../test/tenderbrute/lib/tenderbrute.ml | 5 +- src/proto_alpha/lib_plugin/plugin.ml | 258 ++++++++++++------ src/proto_alpha/lib_protocol/alpha_context.ml | 1 + .../lib_protocol/alpha_context.mli | 30 +- src/proto_alpha/lib_protocol/apply.ml | 133 +++++---- src/proto_alpha/lib_protocol/apply.mli | 18 +- src/proto_alpha/lib_protocol/apply_results.ml | 57 ++-- .../lib_protocol/apply_results.mli | 10 +- src/proto_alpha/lib_protocol/baking.ml | 42 ++- src/proto_alpha/lib_protocol/baking.mli | 12 +- .../lib_protocol/delegate_consensus_key.ml | 55 +++- .../lib_protocol/delegate_consensus_key.mli | 29 +- .../lib_protocol/delegate_cycles.ml | 28 ++ .../lib_protocol/delegate_cycles.mli | 4 + .../lib_protocol/delegate_sampler.ml | 27 +- .../lib_protocol/delegate_sampler.mli | 14 +- .../lib_protocol/delegate_services.ml | 4 +- .../lib_protocol/delegate_storage.ml | 15 - .../lib_protocol/delegate_storage.mli | 4 - src/proto_alpha/lib_protocol/init_storage.ml | 2 +- src/proto_alpha/lib_protocol/level_repr.ml | 9 + src/proto_alpha/lib_protocol/level_repr.mli | 2 + src/proto_alpha/lib_protocol/main.ml | 26 +- src/proto_alpha/lib_protocol/main.mli | 12 +- src/proto_alpha/lib_protocol/raw_context.ml | 70 +++-- src/proto_alpha/lib_protocol/raw_context.mli | 48 ++-- src/proto_alpha/lib_protocol/storage.ml | 35 ++- src/proto_alpha/lib_protocol/storage.mli | 12 +- .../lib_protocol/test/helpers/block.ml | 12 +- .../test/unit/test_consensus_key.ml | 135 ++++++--- tezt/_regressions/rpc/alpha.client.others.out | 30 +- tezt/_regressions/rpc/alpha.light.others.out | 30 +- tezt/_regressions/rpc/alpha.proxy.others.out | 30 +- .../alpha.proxy_server_data_dir.others.out | 30 +- .../rpc/alpha.proxy_server_rpc.others.out | 30 +- 39 files changed, 870 insertions(+), 421 deletions(-) diff --git a/scripts/yes-wallet/yes_wallet_lib.ml b/scripts/yes-wallet/yes_wallet_lib.ml index 9c3359aa2f0c..fc2e61059980 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_pk + in Lwt.return @@ Environment.wrap_tzresult r in let*? key_list_acc, staking_balance_acc = acc in diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index ad2d57872ff3..5da8026f2140 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -1066,8 +1066,8 @@ let rec pp_contents_and_result_list : bus | Single_and_result ( Preendorsement {level; _}, - Preendorsement_result {balance_updates; delegate; preendorsement_power} - ) -> + Preendorsement_result + {balance_updates; delegate; consensus_key; preendorsement_power} ) -> Format.fprintf ppf "@[Preendorsement:@,\ @@ -1079,12 +1079,13 @@ let rec pp_contents_and_result_list : level pp_balance_updates balance_updates - Signature.Public_key_hash.pp - delegate + Consensus_key.pp + {delegate; consensus_pkh = consensus_key} preendorsement_power | Single_and_result ( Endorsement {level; _}, - Endorsement_result {balance_updates; delegate; endorsement_power} ) -> + Endorsement_result + {balance_updates; delegate; consensus_key; endorsement_power} ) -> Format.fprintf ppf "@[Endorsement:@,\ @@ -1096,8 +1097,8 @@ let rec pp_contents_and_result_list : level pp_balance_updates balance_updates - Signature.Public_key_hash.pp - delegate + Consensus_key.pp + {delegate; consensus_pkh = consensus_key} endorsement_power | Single_and_result ( Double_endorsement_evidence {op1; op2}, 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_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_delegate/test/tenderbrute/lib/tenderbrute.ml b/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml index fa99d708a0a1..ce3f8bba6380 100644 --- a/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml +++ b/src/proto_alpha/lib_delegate/test/tenderbrute/lib/tenderbrute.ml @@ -102,8 +102,9 @@ let check ctxt ~selection = (fun (level, round) delegate ctxt -> 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 + >>=? fun (ctxt, _, pk) -> + if not (Signature.Public_key_hash.equal delegate pk.delegate) then + raise Exit else return ctxt) selection ctxt diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index a4e87f1dd557..19c540d81296 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -2360,7 +2360,7 @@ module RPC = 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 @@ -3983,7 +3983,8 @@ module RPC = struct 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; } @@ -3991,15 +3992,16 @@ module RPC = 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 @@ -4012,18 +4014,23 @@ module RPC = 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 @@ -4040,9 +4047,10 @@ module RPC = 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\ + the given delegates. Parameter `consensus_key` can be used to \ + restrict the results to the given consensus_keys. 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 \ @@ -4065,8 +4073,9 @@ module RPC = 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.consensus_pkh; delegate}, next)) = + l + in estimated_time round_durations ~current_level @@ -4075,7 +4084,16 @@ module RPC = struct ~level ~round >>?= fun timestamp -> - let acc = {level = level.level; delegate; round; timestamp} :: acc in + let acc = + { + level = level.level; + delegate; + consensus_key = consensus_pkh; + round; + timestamp; + } + :: acc + in next () >>=? fun l -> loop l acc (round + 1) in loop delegates [] 0 @@ -4120,29 +4138,44 @@ module RPC = 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 module Endorsing_rights = struct type delegate_rights = { delegate : Signature.Public_key_hash.t; + consensus_key : Signature.Public_key_hash.t; first_slot : Slot.t; endorsing_power : int; } @@ -4156,14 +4189,15 @@ module RPC = 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 @@ -4186,15 +4220,21 @@ module RPC = 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 = @@ -4210,6 +4250,8 @@ module RPC = struct deprecated because in this case the RPC takes a long time and \ returns an unreasonable amount of data. Parameter `delegate` can \ be used to restrict the results to the given delegates.\n\ + 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 \ @@ -4238,8 +4280,15 @@ module RPC = 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; + consensus_pk = _; + consensus_pkh = consensus_key; + }, + endorsing_power ) + acc -> + {delegate; consensus_key; first_slot; endorsing_power} :: acc) rights [] in @@ -4259,49 +4308,76 @@ module RPC = 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 module Validators = struct type t = { level : Raw_level.t; - delegate : Signature.Public_key_hash.t; + delegate : Signature.public_key_hash; + consensus_key : Signature.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 @@ -4311,14 +4387,20 @@ module RPC = 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 = @@ -4330,7 +4412,8 @@ module RPC = 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" + results 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 @@ -4339,9 +4422,9 @@ module RPC = 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 () = @@ -4355,18 +4438,37 @@ module RPC = 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 diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 242c1d1fe8c9..2292460c7489 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -401,6 +401,7 @@ module Bond_id = struct end module Receipt = Receipt_repr +module Consensus_key = Delegate_consensus_key module Delegate = struct include Delegate_storage diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 2f325bb00673..a454c626e0b7 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2183,6 +2183,25 @@ module Receipt : sig val group_balance_updates : balance_updates -> balance_updates tzresult end +module Consensus_key : sig + type pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; + } + + type t = { + delegate : Signature.Public_key_hash.t; + consensus_pkh : Signature.Public_key_hash.t; + } + + 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 @@ -2272,7 +2291,8 @@ module Delegate : sig Signature.Public_key.t tzresult Lwt.t module Consensus_key : sig - val active_pubkey : context -> public_key_hash -> public_key tzresult Lwt.t + val active_pubkey : + context -> public_key_hash -> Consensus_key.pk tzresult Lwt.t val pending_updates : context -> @@ -3389,13 +3409,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 @@ -3562,6 +3579,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 0511dc1c0c36..aa380ccf8883 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2372,7 +2372,7 @@ let skipped_operation_result : 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 = @@ -2505,7 +2505,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 = @@ -2824,7 +2824,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 = @@ -2850,14 +2850,15 @@ 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 (consensus_pk, voting_power) -> + Delegate.frozen_deposits ctxt consensus_pk.delegate + >>=? fun frozen_deposits -> fail_unless Tez.(frozen_deposits.current_amount > zero) - (Zero_frozen_deposits delegate_pkh) + (Zero_frozen_deposits consensus_pk.delegate) >>=? fun () -> - Operation.check_signature delegate_pk chain_id operation >>?= fun () -> - return (ctxt, delegate_pkh, voting_power) + Operation.check_signature consensus_pk.consensus_pk chain_id operation + >>?= fun () -> return (ctxt, Consensus_key.pkh consensus_pk, voting_power) let apply_manager_contents_list ctxt mode ~payload_producer chain_id prechecked_contents_list = @@ -2900,7 +2901,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) -> @@ -2944,19 +2945,27 @@ let punish_double_endorsement_or_preendorsement (type kind) ctxt ~chain_id 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)) -> + >>=? fun (ctxt, consensus_pk1) -> Stake_distribution.slot_owner ctxt level e2.slot - >>=? fun (ctxt, (_delegate2_pk, delegate2)) -> + >>=? fun (ctxt, consensus_pk2) -> fail_unless - (Signature.Public_key_hash.equal delegate1 delegate2) - (Inconsistent_denunciation {kind; delegate1; delegate2}) + (Signature.Public_key_hash.equal + consensus_pk1.delegate + consensus_pk2.delegate) + (Inconsistent_denunciation + { + kind; + delegate1 = consensus_pk1.delegate; + delegate2 = consensus_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 consensus_pk1.consensus_pk chain_id op1 + >>?= fun () -> + Operation.check_signature consensus_pk2.consensus_pk chain_id op2 + >>?= fun () -> punish_delegate ctxt - delegate + consensus_pk1.delegate level `Double_endorsing mk_result @@ -2986,20 +2995,26 @@ let punish_double_baking ctxt chain_id bh1 bh2 ~payload_producer = 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)) -> + >>=? fun (ctxt, consensus_pk1) -> Round.to_slot round2 ~committee_size >>?= fun slot2 -> Stake_distribution.slot_owner ctxt level slot2 - >>=? fun (ctxt, (_delegate2_pk, delegate2)) -> + >>=? fun (ctxt, consensus_pk2) -> fail_unless - Signature.Public_key_hash.(delegate1 = delegate2) - (Inconsistent_denunciation {kind = Block; delegate1; delegate2}) + Signature.Public_key_hash.(consensus_pk1.delegate = consensus_pk2.delegate) + (Inconsistent_denunciation + { + kind = Block; + delegate1 = consensus_pk1.delegate; + delegate2 = consensus_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 consensus_pk1.consensus_pk + >>?= fun () -> + Block_header.check_signature bh2 chain_id consensus_pk2.consensus_pk + >>?= fun () -> punish_delegate ctxt - delegate + consensus_pk1.delegate level `Double_baking ~payload_producer @@ -3026,16 +3041,19 @@ 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, (delegate_pk, pkh)) -> - Operation.check_signature delegate_pk chain_id op >>?= fun () -> - Consensus.record_grand_parent_endorsement ctxt pkh >>?= fun ctxt -> + >>=? fun (ctxt, consensus_pk) -> + Operation.check_signature consensus_pk.consensus_pk chain_id op + >>?= fun () -> + Consensus.record_grand_parent_endorsement ctxt consensus_pk.delegate + >>?= fun ctxt -> return ( ctxt, Single_result (Endorsement_result { balance_updates = []; - delegate = pkh; + delegate = consensus_pk.delegate; + consensus_key = consensus_pk.consensus_pkh; endorsement_power = 0 (* dummy endorsement power: this will never be used *); }) ) @@ -3058,7 +3076,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_pkh}, voting_power) -> Consensus.record_preendorsement ctxt ~initial_slot:consensus_content.slot @@ -3072,6 +3090,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode { balance_updates = []; delegate; + consensus_key = consensus_pkh; preendorsement_power = voting_power; }) ) | Single (Endorsement consensus_content) -> ( @@ -3093,7 +3112,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_pkh}, voting_power) -> Consensus.record_endorsement ctxt ~initial_slot:consensus_content.slot @@ -3106,13 +3125,16 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode { balance_updates = []; delegate; + consensus_key = consensus_pkh; endorsement_power = voting_power; }) )) | Single (Seed_nonce_revelation {level; nonce}) -> 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)) @@ -3406,8 +3428,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; @@ -3426,17 +3448,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 @@ -3450,8 +3473,8 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level { ctxt; protocol_data; - payload_producer; - block_producer; + 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; @@ -3473,7 +3496,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 @@ -3482,21 +3505,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.consensus_pk ~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 @@ -3511,8 +3535,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, + Consensus_key.pkh payload_producer, + Consensus_key.pkh block_producer, liquidity_baking_operations_results, liquidity_baking_toggle_ema ) @@ -3599,7 +3623,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 @@ -3607,15 +3631,16 @@ let record_endorsing_participation ctxt = in Delegate.record_endorsing_participation ctxt - ~delegate + ~delegate:consensus_pk.delegate ~participation ~endorsing_power:power) validators 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 @@ -3650,7 +3675,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 -> @@ -3661,8 +3686,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 3e3a0688450a..c7a85192d5b3 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -58,8 +58,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; @@ -83,8 +83,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 @@ -118,7 +118,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 @@ -134,8 +134,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 -> @@ -146,7 +146,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 @@ -156,7 +156,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 0eeb36942f7d..d592d0973886 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -1436,13 +1436,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 @@ -1587,10 +1589,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 @@ -1602,12 +1605,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 = @@ -1615,10 +1619,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); @@ -1628,11 +1633,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"] seed_nonce_revelation_case = @@ -3001,8 +3008,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; @@ -3018,8 +3025,9 @@ let block_metadata_encoding = def "block_header.alpha.metadata" @@ conv (fun { - proposer; - baker; + proposer = + {delegate = proposer; consensus_pkh = proposer_active_key}; + baker = {delegate = baker; consensus_pkh = baker_active_key}; level_info; voting_period_info; nonce_hash; @@ -3039,7 +3047,7 @@ let block_metadata_encoding = balance_updates, liquidity_baking_toggle_ema, implicit_operations_results ), - consumed_gas )) + (proposer_active_key, baker_active_key, consumed_gas) )) (fun ( ( proposer, baker, level_info, @@ -3050,10 +3058,10 @@ let block_metadata_encoding = balance_updates, liquidity_baking_toggle_ema, implicit_operations_results ), - _consumed_millgas ) -> + (proposer_active_key, baker_active_key, _consumed_millgas) ) -> { - proposer; - baker; + proposer = {delegate = proposer; consensus_pkh = proposer_active_key}; + baker = {delegate = baker; consensus_pkh = baker_active_key}; level_info; voting_period_info; nonce_hash; @@ -3079,7 +3087,10 @@ let block_metadata_encoding = (req "implicit_operations_results" (list successful_manager_operation_result_encoding))) - (obj1 (req "consumed_milligas" Gas.Arith.n_fp_encoding))) + (obj3 + (req "proposer_consensus_key" Signature.Public_key_hash.encoding) + (req "baker_consensus_key" Signature.Public_key_hash.encoding) + (req "consumed_milligas" Gas.Arith.n_fp_encoding))) type precheck_result = { consumed_gas : Gas.Arith.fp; diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 69822f79d6dd..cdb2c2211103 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 @@ -362,8 +364,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/baking.ml b/src/proto_alpha/lib_protocol/baking.ml index 00bc864d9102..4cf700d66586 100644 --- a/src/proto_alpha/lib_protocol/baking.ml +++ b/src/proto_alpha/lib_protocol/baking.ml @@ -72,12 +72,17 @@ 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, consensus_pk) -> + return + (LCons (Consensus_key.pkh consensus_pk, fun () -> f c (Round.succ round))) 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]. *) @@ -86,11 +91,20 @@ 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, consensus_pk) -> let map = Signature.Public_key_hash.Map.update - pkh - (function None -> Some [slot] | Some slots -> Some (slot :: slots)) + consensus_pk.delegate + (function + | None -> + Some + { + delegate = consensus_pk.delegate; + consensus_key = consensus_pk.consensus_pkh; + slots = [slot]; + } + | Some slots -> Some {slots with slots = slot :: slots.slots}) map in return (ctxt, map)) @@ -103,11 +117,17 @@ let endorsing_rights_by_first_slot ctxt level = Slot.Range.fold_es (fun (ctxt, (delegates_map, slots_map)) slot -> Stake_distribution.slot_owner ctxt level slot - >|=? fun (ctxt, (pk, pkh)) -> + >|=? fun (ctxt, consensus_pk) -> let initial_slot, delegates_map = - match Signature.Public_key_hash.Map.find pkh delegates_map with + match + Signature.Public_key_hash.Map.find consensus_pk.delegate delegates_map + with | None -> - (slot, Signature.Public_key_hash.Map.add pkh slot delegates_map) + ( slot, + Signature.Public_key_hash.Map.add + consensus_pk.delegate + slot + delegates_map ) | Some initial_slot -> (initial_slot, delegates_map) in (* [slots_map]'keys are the minimal slots of delegates because @@ -116,8 +136,8 @@ let endorsing_rights_by_first_slot ctxt level = Slot.Map.update initial_slot (function - | None -> Some (pk, pkh, 1) - | Some (pk, pkh, count) -> Some (pk, pkh, count + 1)) + | None -> Some (consensus_pk, 1) + | Some (consensus_pk, count) -> Some (consensus_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..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. @@ -48,14 +52,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 +67,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/delegate_consensus_key.ml b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml index 2303e0287a1b..37c7e48af185 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml @@ -36,7 +36,7 @@ let () = ~pp:(fun ppf cycle -> Format.fprintf ppf - "Invalid cycle while updating a consensus key (%a)." + "Invalid cycle while updating a consensus key (expected: %a)." Cycle_repr.pp cycle) Data_encoding.(obj1 (req "cycle" Cycle_repr.encoding)) @@ -57,6 +57,35 @@ let () = (function Invalid_consensus_key_update_noop c -> Some c | _ -> None) (fun c -> Invalid_consensus_key_update_noop c) +type pk = Raw_context.consensus_pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +type t = { + delegate : Signature.Public_key_hash.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +let pkh {delegate; consensus_pkh; consensus_pk = _} = {delegate; consensus_pkh} + +let zero = + { + consensus_pkh = Signature.Public_key_hash.zero; + delegate = Signature.Public_key_hash.zero; + } + +let pp ppf {delegate; consensus_pkh} = + Format.fprintf ppf "@[%a" Signature.Public_key_hash.pp delegate ; + if not (Signature.Public_key_hash.equal delegate consensus_pkh) then + Format.fprintf + ppf + "@,Active key: %a" + Signature.Public_key_hash.pp + consensus_pkh ; + Format.fprintf ppf "@]" + let init ctxt delegate pk = Storage.Contract.Consensus_key.init ctxt (Contract_repr.Implicit delegate) pk @@ -65,12 +94,13 @@ let active_pubkey ctxt delegate = let* pk = Storage.Contract.Consensus_key.get ctxt (Contract_repr.Implicit delegate) in - return pk + let pkh = Signature.Public_key.hash pk in + return {consensus_pk = pk; consensus_pkh = pkh; delegate} let active_key ctxt delegate = let open Lwt_tzresult_syntax in let* pk = active_pubkey ctxt delegate in - return (Signature.Public_key.hash pk) + return (pkh pk) let raw_pending_updates ctxt delegate = let open Lwt_tzresult_syntax in @@ -97,23 +127,32 @@ let raw_active_pubkey_for_cycle ctxt delegate 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) + (current_level.cycle, active.consensus_pk) pendings in return active_for_cycle let active_pubkey_for_cycle ctxt delegate cycle = let open Lwt_tzresult_syntax in - let* _, active = raw_active_pubkey_for_cycle ctxt delegate cycle in - return active + let* _, consensus_pk = raw_active_pubkey_for_cycle ctxt delegate cycle in + return + { + consensus_pk; + consensus_pkh = Signature.Public_key.hash consensus_pk; + delegate; + } 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 <= current_level.cycle) - (Invalid_consensus_key_update_cycle cycle) + Cycle_repr.(cycle <> required_cycle) + (Invalid_consensus_key_update_cycle required_cycle) in let* () = let* cycle, active_pubkey = diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli index 8ca12e0beb8b..a8d4ea02aafc 100644 --- a/src/proto_alpha/lib_protocol/delegate_consensus_key.mli +++ b/src/proto_alpha/lib_protocol/delegate_consensus_key.mli @@ -27,6 +27,25 @@ 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 = Raw_context.consensus_pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +(** The public key hash of a consensus key and the associated delegate. *) +type t = { + delegate : Signature.Public_key_hash.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +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 -> @@ -36,22 +55,18 @@ val init : (** Returns the active consensus key for the current cycle. *) val active_pubkey : - Raw_context.t -> - Signature.Public_key_hash.t -> - Signature.Public_key.t tzresult Lwt.t + 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 -> - Signature.Public_key_hash.t tzresult Lwt.t + 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 -> - Signature.Public_key.t tzresult Lwt.t + pk tzresult Lwt.t (** Returns the list of pending consensus-key updates in upcoming cycles. *) val pending_updates : diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index e4cf195b7a21..438d57d7aece 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -279,3 +279,31 @@ 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 + 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_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_sampler.ml b/src/proto_alpha/lib_protocol/delegate_sampler.ml index b2611be04dfd..85240f203e3a 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.ml +++ b/src/proto_alpha/lib_protocol/delegate_sampler.ml @@ -34,8 +34,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" @@ -140,8 +139,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) @@ -225,7 +224,7 @@ let select_distribution_for_cycle ctxt cycle = List.fold_left_es (fun acc (pkh, stake) -> Delegate_consensus_key.active_pubkey_for_cycle ctxt pkh cycle - >|=? fun pk -> ((pk, pkh), Tez_repr.to_mutez stake) :: acc) + >|=? fun pk -> (pk, Tez_repr.to_mutez stake) :: acc) [] stakes >>=? fun stakes_pk -> @@ -247,3 +246,21 @@ let clear_outdated_sampling_data ctxt ~new_cycle = Delegate_sampler_state.remove_existing ctxt outdated_cycle >>=? fun ctxt -> Storage.Seed.For_cycle.remove_existing 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 194c5a50468b..ae3132041a18 100644 --- a/src/proto_alpha/lib_protocol/delegate_sampler.mli +++ b/src/proto_alpha/lib_protocol/delegate_sampler.mli @@ -35,18 +35,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 @@ -63,3 +58,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/delegate_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index ebbc02a7152c..d87b9610b4f8 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -423,7 +423,7 @@ let register () = deactivated; grace_period; voting_info; - active_consensus_key = Signature.Public_key.hash consensus_key; + active_consensus_key = consensus_key.consensus_pkh; pending_consensus_keys = pendings; }) ; register1 ~chunked:false S.full_balance (fun ctxt pkh () () -> @@ -465,7 +465,7 @@ let register () = Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.Consensus_key.active_pubkey ctxt pkh >>=? fun pk -> Delegate.Consensus_key.pending_updates ctxt pkh >>=? fun pendings -> - return (Signature.Public_key.hash pk, pendings)) ; + return (pk.consensus_pkh, pendings)) ; register1 ~chunked:false S.participation (fun ctxt pkh () () -> Delegate.check_registered ctxt pkh >>=? fun () -> Delegate.participation_info ctxt pkh) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 29268f00b595..96aac84dde1e 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -297,18 +297,3 @@ module Contract = struct set_self_delegate c delegate | _ -> set_delegate c contract delegate end - -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_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index bf603fdd3806..4bb421f8a644 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -127,7 +127,3 @@ val manager_pubkey : Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t 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/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index ea7eb7858dbb..81ccb3ba85e6 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -119,7 +119,7 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = Raw_level_repr.of_int32 level >>?= fun level -> Storage.Tenderbake.First_level_of_protocol.update ctxt level >>=? fun ctxt -> - Delegate_storage.Migration_from_Jakarta.update 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 -> 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/main.ml b/src/proto_alpha/lib_protocol/main.ml index 3a1dfce12939..547dae479a32 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; @@ -609,7 +609,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; diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index f1341fb2d2d8..4c0712fd9a92 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -73,6 +73,29 @@ module Sc_rollup_address_map_builder = *) +type consensus_pk = { + delegate : Signature.Public_key_hash.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +let consensus_pk_encoding = + let open Data_encoding in + conv + (fun {delegate; consensus_pk; consensus_pkh} -> + if Signature.Public_key_hash.equal consensus_pkh delegate then + (consensus_pk, None) + else (consensus_pk, Some delegate)) + (fun (consensus_pk, delegate) -> + let consensus_pkh = Signature.Public_key.hash consensus_pk in + let delegate = + match delegate with None -> consensus_pkh | Some del -> del + in + {delegate; consensus_pk; consensus_pkh}) + (obj2 + (req "consensus_pk" Signature.Public_key.encoding) + (opt "delegate" Signature.Public_key_hash.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 @@ -81,16 +104,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 @@ -238,10 +257,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 : @@ -1216,6 +1232,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) @@ -1254,6 +1276,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 @@ -1267,20 +1300,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_endorsements : t -> (consensus_pk * int) slot_map - 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 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 : @@ -1314,7 +1345,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 diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index 913ccadb75d1..2fd0c99bab0d 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -217,14 +217,18 @@ 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.t; + consensus_pk : Signature.Public_key.t; + consensus_pkh : Signature.Public_key_hash.t; +} + +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 @@ -233,19 +237,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. *) @@ -257,6 +252,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 @@ -270,17 +267,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. *) @@ -291,10 +288,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 @@ -356,6 +351,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 : @@ -370,3 +366,7 @@ module Sc_rollup_in_memory_inbox : sig val set_current_messages : t -> Sc_rollup_repr.t -> Context.tree -> t tzresult 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 3ffcddec2f46..6913f64762be 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -997,11 +997,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 @@ -1010,10 +1025,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 = { @@ -1768,3 +1782,8 @@ module Sc_rollup = struct end) (Bitset_and_level) 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 27eec55eb3df..f9310a667565 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -411,8 +411,7 @@ module Total_active_stake : 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 *) @@ -838,3 +837,12 @@ module Sc_rollup : sig and type key = int32 and type value = Raw_level_repr.t * Bitset.t 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 diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 87c8782f4519..51d835047099 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -90,9 +90,12 @@ let get_next_baker_excluding excludes block = let {Plugin.RPC.Baking_rights.delegate = pkh; timestamp; round; _} = WithExceptions.Option.get ~loc:__LOC__ @@ List.find - (fun {Plugin.RPC.Baking_rights.delegate; _} -> + (fun {Plugin.RPC.Baking_rights.consensus_key; _} -> not - (List.mem ~equal:Signature.Public_key_hash.equal delegate excludes)) + (List.mem + ~equal:Signature.Public_key_hash.equal + consensus_key + excludes)) bakers in (pkh, round, WithExceptions.Option.to_exn ~none:(Failure "") timestamp) @@ -187,7 +190,8 @@ module Forge = struct | _ -> assert false in let predecessor_round = Fitness.round pred_fitness in - dispatch_policy policy pred >>=? fun (pkh, round, expected_timestamp) -> + dispatch_policy policy pred + >>=? fun (delegate, round, expected_timestamp) -> let timestamp = Option.value ~default:expected_timestamp timestamp in let level = Int32.succ pred.header.shell.level in Raw_level.of_int32 level |> Environment.wrap_tzresult >>?= fun raw_level -> @@ -234,7 +238,7 @@ module Forge = struct ~payload_round () in - {baker = pkh; shell; contents} + {baker = delegate; shell; contents} (* compatibility only, needed by incremental *) let contents ?(proof_of_work_nonce = default_proof_of_work_nonce) 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 2b66644bcdd0..d1d0de0c7b5f 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 @@ -69,9 +69,7 @@ module Consensus_key = struct >|= Environment.wrap_tzresult let activate ctxt ~new_cycle = - Delegate_consensus_key.activate - ctxt - ~new_cycle:(Cycle_repr.of_int32_exn (Int32.of_int new_cycle)) + Delegate_consensus_key.activate ctxt ~new_cycle >|= Environment.wrap_tzresult end @@ -103,31 +101,63 @@ module Assert = struct let* active_pk = Consensus_key.active_pubkey_for_cycle ctxt delegate c in - equal_pk ~__LOC__ active_pk pk) + equal_pk ~__LOC__ active_pk.consensus_pk 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, delegate = 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 delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh delegate.pkh + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh delegate.pkh in let* () = let* active_pk = Consensus_key.active_pubkey ctxt delegate.pkh in - Assert.equal_pk ~__LOC__ active_pk delegate.pk + Assert.equal_pk ~__LOC__ active_pk.consensus_pk delegate.pk in let* () = let* active_pk = - Consensus_key.active_pubkey_for_cycle ctxt delegate.pkh 5 + Consensus_key.active_pubkey_for_cycle ctxt delegate.pkh 3 in - Assert.equal_pk ~__LOC__ active_pk delegate.pk + Assert.equal_pk ~__LOC__ active_pk.consensus_pk delegate.pk + in + let* () = + let*! err = Consensus_key.register_update ctxt delegate.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 delegate.pkh 4 a1.pk in + let* () = + let*! err = Consensus_key.register_update ctxt delegate.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* () = + let*! err = Consensus_key.register_update ctxt delegate.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* ctxt = Consensus_key.register_update ctxt delegate.pkh 2 a1.pk in - let* ctxt = Consensus_key.register_update ctxt delegate.pkh 5 a2.pk in let* () = Assert.active_keys ~__LOC__ @@ -136,73 +166,94 @@ let test_consensus_key_storage () = [ (0, delegate.pk); (1, delegate.pk); - (2, a1.pk); - (3, a1.pk); + (2, delegate.pk); + (2, delegate.pk); + (3, delegate.pk); (4, a1.pk); - (5, a2.pk); - (6, a2.pk); + (5, a1.pk); ] in + let* ctxt = add_cycles ctxt 1 in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 2 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 2l - | _ -> false) + let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh delegate.pkh in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 3 a1.pk in + let*! err = Consensus_key.register_update ctxt delegate.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 2l + | 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 delegate.pkh 4 a1.pk in + let*! err = Consensus_key.register_update ctxt delegate.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 2l + c = Cycle_repr.of_int32_exn 4l | _ -> false) in + let* ctxt = Consensus_key.register_update ctxt delegate.pkh 5 a2.pk in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 5 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) + Assert.active_keys + ~__LOC__ + ctxt + delegate.pkh + [ + (1, delegate.pk); + (2, delegate.pk); + (2, delegate.pk); + (3, delegate.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 delegate.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh delegate.pkh in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 6 a2.pk in + let*! err = Consensus_key.register_update ctxt delegate.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.activate ctxt ~new_cycle:1 in - let* ctxt = Consensus_key.activate ctxt ~new_cycle:2 in + let* ctxt = Consensus_key.register_update ctxt delegate.pkh 7 a1.pk in let* () = - let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh a1.pkh + Assert.active_keys + ~__LOC__ + ctxt + delegate.pkh + [ + (3, delegate.pk); + (4, a1.pk); + (5, a2.pk); + (6, a2.pk); + (7, a1.pk); + (8, a1.pk); + ] in - let* ctxt = Consensus_key.activate ctxt ~new_cycle:3 in + let* ctxt = add_cycles ctxt 1 in let* () = let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh a1.pkh + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a1.pkh in - let* ctxt = Consensus_key.activate ctxt ~new_cycle:4 in + let* ctxt = add_cycles ctxt 1 in let* () = let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh a1.pkh + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a2.pkh in - let* ctxt = Consensus_key.activate ctxt ~new_cycle:5 in + let* ctxt = add_cycles ctxt 1 in let* () = let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh a2.pkh + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a2.pkh in - let* ctxt = Consensus_key.activate ctxt ~new_cycle:6 in + let* ctxt = add_cycles ctxt 1 in let* () = let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh a2.pkh + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a1.pkh in return () diff --git a/tezt/_regressions/rpc/alpha.client.others.out b/tezt/_regressions/rpc/alpha.client.others.out index 6e692cbcd10a..867b16dcca1a 100644 --- a/tezt/_regressions/rpc/alpha.client.others.out +++ b/tezt/_regressions/rpc/alpha.client.others.out @@ -54,15 +54,20 @@ rpc/alpha.client.others.out ./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, @@ -72,15 +77,20 @@ rpc/alpha.client.others.out [ { "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/_regressions/rpc/alpha.light.others.out b/tezt/_regressions/rpc/alpha.light.others.out index 61402074c195..208d97cc3102 100644 --- a/tezt/_regressions/rpc/alpha.light.others.out +++ b/tezt/_regressions/rpc/alpha.light.others.out @@ -55,15 +55,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' @@ -75,15 +80,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/_regressions/rpc/alpha.proxy.others.out b/tezt/_regressions/rpc/alpha.proxy.others.out index 7d26b7089f03..82d17b80a52e 100644 --- a/tezt/_regressions/rpc/alpha.proxy.others.out +++ b/tezt/_regressions/rpc/alpha.proxy.others.out @@ -55,15 +55,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' @@ -75,15 +80,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/_regressions/rpc/alpha.proxy_server_data_dir.others.out b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out index 12f77d24e987..1f8608a42e78 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out @@ -54,15 +54,20 @@ rpc/alpha.proxy_server_data_dir.others.out ./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, @@ -72,15 +77,20 @@ rpc/alpha.proxy_server_data_dir.others.out [ { "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/_regressions/rpc/alpha.proxy_server_rpc.others.out b/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out index 869343b796cc..f660bc2c4f30 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out @@ -54,15 +54,20 @@ rpc/alpha.proxy_server_rpc.others.out ./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, @@ -72,15 +77,20 @@ rpc/alpha.proxy_server_rpc.others.out [ { "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 3a7f41ace7af6e22657706eb0cf971427a83cc00 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 25/48] Proto: do not allow two delegates to use 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 | 108 ++++++++++-------- 5 files changed, 108 insertions(+), 51 deletions(-) diff --git a/src/proto_alpha/lib_protocol/delegate_consensus_key.ml b/src/proto_alpha/lib_protocol/delegate_consensus_key.ml index 37c7e48af185..53646ff4e493 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 = Raw_context.consensus_pk = { delegate : Signature.Public_key_hash.t; @@ -86,7 +100,20 @@ let pp ppf {delegate; consensus_pkh} = consensus_pkh ; 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 = @@ -162,6 +189,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_pkh = 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 a8d4ea02aafc..f9e89bbae48c 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 = Raw_context.consensus_pk = { diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 6913f64762be..66292f67b43f 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -937,6 +937,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 f9310a667565..6f216f99a6ca 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 d1d0de0c7b5f..8df0ca5fabe3 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 @@ -35,12 +35,14 @@ open Protocol let create () = let open Lwt_result_syntax in - let accounts = Account.generate_accounts 1 in - let account = - match accounts with [(account, _, _)] -> account | _ -> assert false + 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, account) + return (Alpha_context.Internal_for_tests.to_raw ctxt, a1, a2) module Consensus_key = struct let active_key ctxt pkh = @@ -117,42 +119,53 @@ let rec add_cycles ctxt n = let test_consensus_key_storage () = let open Lwt_result_syntax in - let* ctxt, delegate = create () 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 delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh delegate.pkh + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh del1.pkh in let* () = - let* active_pk = Consensus_key.active_pubkey ctxt delegate.pkh in - Assert.equal_pk ~__LOC__ active_pk.consensus_pk delegate.pk + let* active_pk = Consensus_key.active_pubkey ctxt del1.pkh in + Assert.equal_pk ~__LOC__ active_pk.consensus_pk del1.pk in let* () = - let* active_pk = - Consensus_key.active_pubkey_for_cycle ctxt delegate.pkh 3 - in - Assert.equal_pk ~__LOC__ active_pk.consensus_pk delegate.pk + let* active_pk = Consensus_key.active_pubkey_for_cycle ctxt del1.pkh 3 in + Assert.equal_pk ~__LOC__ active_pk.consensus_pk del1.pk in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 3 a1.pk in + 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 | 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 delegate.pkh 4 a1.pk in + let* ctxt = Consensus_key.register_update ctxt del1.pkh 4 a1.pk in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 4 a1.pk in + 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* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 5 a1.pk in + 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 Assert.proto_error ~loc:__LOC__ err (function | Delegate_consensus_key.Invalid_consensus_key_update_cycle c -> c = Cycle_repr.of_int32_exn 4l @@ -162,47 +175,49 @@ let test_consensus_key_storage () = Assert.active_keys ~__LOC__ ctxt - delegate.pkh + del1.pkh [ - (0, delegate.pk); - (1, delegate.pk); - (2, delegate.pk); - (2, delegate.pk); - (3, delegate.pk); + (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 delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh delegate.pkh + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh del1.pkh in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 4 a1.pk in + 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 delegate.pkh 5 a1.pk in + 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 delegate.pkh 5 a2.pk 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 - delegate.pkh + del1.pkh [ - (1, delegate.pk); - (2, delegate.pk); - (2, delegate.pk); - (3, delegate.pk); + (1, del1.pk); + (2, del1.pk); + (2, del1.pk); + (3, del1.pk); (4, a1.pk); (5, a2.pk); (6, a2.pk); @@ -210,49 +225,42 @@ let test_consensus_key_storage () = in let* ctxt = add_cycles ctxt 2 in let* () = - let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in - Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh delegate.pkh + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in + Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh del1.pkh in let* () = - let*! err = Consensus_key.register_update ctxt delegate.pkh 7 a2.pk in + 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 delegate.pkh 7 a1.pk in + let* ctxt = Consensus_key.register_update ctxt del1.pkh 7 a1.pk in let* () = Assert.active_keys ~__LOC__ ctxt - delegate.pkh - [ - (3, delegate.pk); - (4, a1.pk); - (5, a2.pk); - (6, a2.pk); - (7, a1.pk); - (8, a1.pk); - ] + 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 delegate.pkh in + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a1.pkh in let* ctxt = add_cycles ctxt 1 in let* () = - let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a2.pkh in let* ctxt = add_cycles ctxt 1 in let* () = - let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a2.pkh in let* ctxt = add_cycles ctxt 1 in let* () = - let* active_pkh = Consensus_key.active_key ctxt delegate.pkh in + let* active_pkh = Consensus_key.active_key ctxt del1.pkh in Assert.equal_pkh ~__LOC__ active_pkh.consensus_pkh a1.pkh in return () -- GitLab From f083c77306d6901b29290e7b1940280b8c342d9b Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 26/48] 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 7a06c292a8ff41b0653fb0da5940016287622012 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 27/48] Proto: add operation `Update_consensus_key` --- src/proto_alpha/lib_client/injection.ml | 3 + .../lib_client/operation_result.ml | 20 ++ src/proto_alpha/lib_injector/l1_operation.ml | 1 + .../lib_protocol/alpha_context.mli | 12 ++ src/proto_alpha/lib_protocol/apply.ml | 37 +++- 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 +- .../_regressions/rpc/alpha.client.mempool.out | 189 ++++++++++++++++++ tezt/_regressions/rpc/alpha.proxy.mempool.out | 189 ++++++++++++++++++ 12 files changed, 573 insertions(+), 6 deletions(-) diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index 11e8eb18027b..81b87bc7d983 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -315,6 +315,7 @@ let estimated_gas_single (type kind) | Applied (Register_global_constant_result {consumed_gas; _}) -> Ok consumed_gas | Applied (Set_deposits_limit_result {consumed_gas}) -> Ok consumed_gas + | Applied (Update_consensus_key_result {consumed_gas; _}) -> Ok consumed_gas | Applied (Tx_rollup_origination_result {consumed_gas; _}) -> Ok consumed_gas | Applied (Tx_rollup_submit_batch_result {consumed_gas; _}) -> @@ -379,6 +380,7 @@ let estimated_storage_single (type kind) ~tx_rollup_origination_size | Applied (Register_global_constant_result {size_of_constant; _}) -> Ok size_of_constant | Applied (Set_deposits_limit_result _) -> Ok Z.zero + | Applied (Update_consensus_key_result _) -> Ok Z.zero | Applied (Tx_rollup_origination_result _) -> Ok tx_rollup_origination_size | Applied (Tx_rollup_submit_batch_result {paid_storage_size_diff; _}) | Applied (Sc_rollup_atomic_batch_result {paid_storage_size_diff; _}) -> @@ -454,6 +456,7 @@ let originated_contracts_single (type kind) | Applied (Reveal_result _) -> Ok [] | Applied (Delegation_result _) -> Ok [] | Applied (Set_deposits_limit_result _) -> Ok [] + | Applied (Update_consensus_key_result _) -> Ok [] | Applied (Tx_rollup_origination_result _) -> Ok [] | Applied (Tx_rollup_submit_batch_result _) -> Ok [] | Applied (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 5da8026f2140..b5e1d13e44d5 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -205,6 +205,14 @@ let pp_manager_operation_content (type kind) source pp_result 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 = _} -> @@ -744,6 +752,9 @@ let pp_manager_operation_contents_and_result ppf Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas ; pp_balance_updates_opt ppf balance_updates in + let pp_update_consensus_key_op (Update_consensus_key_result {consumed_gas}) = + Format.fprintf ppf "@,Consumed gas: %a" Gas.Arith.pp consumed_gas + in let pp_result (type kind) ppf (result : kind manager_operation_result) = Format.fprintf ppf "@," ; match result with @@ -773,6 +784,15 @@ let pp_manager_operation_contents_and_result ppf ppf "@[This deposits limit modification was BACKTRACKED, its \ expected effects were NOT applied.@]" + | Applied (Update_consensus_key_result _ as op) -> + Format.fprintf ppf "The consensus key was successfully udpated" ; + pp_update_consensus_key_op op + | Backtracked ((Update_consensus_key_result _ as op), _) -> + Format.fprintf + ppf + "@[This consensus key update was BACKTRACKED, its expected \ + effects were NOT applied.@]" ; + pp_update_consensus_key_op op | Applied (Transaction_result tx) -> Format.fprintf ppf "This transaction was successfully applied" ; pp_transaction_result tx diff --git a/src/proto_alpha/lib_injector/l1_operation.ml b/src/proto_alpha/lib_injector/l1_operation.ml index b0aef6cc2142..c4af4a525f21 100644 --- a/src/proto_alpha/lib_injector/l1_operation.ml +++ b/src/proto_alpha/lib_injector/l1_operation.ml @@ -80,6 +80,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 a454c626e0b7..2025e650dc5f 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2893,6 +2893,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 @@ -2936,6 +2938,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 @@ -3070,6 +3073,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; @@ -3289,6 +3295,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 @@ -3354,6 +3362,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 aa380ccf8883..4f9eabd3160d 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -93,6 +93,7 @@ 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} + | 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 @@ -468,6 +469,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" @@ -1498,6 +1514,19 @@ let apply_external_manager_operation_content : Set_deposits_limit_result {consumed_gas = Gas.consumed ~since:before_operation ~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:before_operation ~until:ctxt}, + [] ) | Tx_rollup_origination -> Tx_rollup.originate ctxt >>=? fun (ctxt, originated_tx_rollup) -> let result = @@ -1911,7 +1940,7 @@ let precheck_manager_contents (type kind) ctxt (op : kind Kind.manager contents) @@ (* See comment in the Transaction branch *) ( Script.force_decode_in_context ~consume_deserialization_gas ctxt value >|? fun (_value, ctxt) -> ctxt ) - | 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; _} -> @@ -2117,7 +2146,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) -> @@ -2218,7 +2248,8 @@ let burn_internal_storage_fees : ( ctxt, storage_limit, Register_global_constant_result {payload with balance_updates} ) - | 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 ({balance_updates; _} as 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 d592d0973886..cd8ee1e4dae9 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; @@ -613,6 +617,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 @@ -1429,6 +1453,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; ] @@ -1494,6 +1519,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 @@ -1893,6 +1922,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 @@ -2130,6 +2170,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; @@ -2187,6 +2228,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; @@ -2424,6 +2466,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 cdb2c2211103..d39f0cc35f29 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -207,6 +207,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 a45d1e4a03ad..6ce9b2221580 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -68,6 +68,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 @@ -111,6 +113,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 @@ -307,6 +310,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; @@ -414,6 +420,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 @@ -652,6 +659,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 { @@ -1389,6 +1418,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 @@ -1495,6 +1527,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; @@ -1699,6 +1732,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 63a179cf3944..14ce04ae9add 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -97,6 +97,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 @@ -140,6 +142,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 @@ -348,6 +351,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 @@ -586,6 +594,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 @@ -649,6 +659,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 51d835047099..7502ba0197d5 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -747,9 +747,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 _ @@ -785,6 +785,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/tezt/_regressions/rpc/alpha.client.mempool.out b/tezt/_regressions/rpc/alpha.client.mempool.out index 252bdc0ec972..3686a04f6374 100644 --- a/tezt/_regressions/rpc/alpha.client.mempool.out +++ b/tezt/_regressions/rpc/alpha.client.mempool.out @@ -1683,6 +1683,52 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Update_consensus_key", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "update_consensus_key" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "cycle": { + "type": "integer", + "minimum": -2147483648, + "maximum": 2147483647 + }, + "pk": { + "$ref": "#/definitions/Signature.Public_key" + } + }, + "required": [ + "pk", + "cycle", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", @@ -5075,6 +5121,103 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "name": "Set_deposits_limit" }, + { + "tag": 113, + "fields": [ + { + "name": "Tag", + "layout": { + "size": "Uint8", + "kind": "Int" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "source", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "fee", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "counter", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "gas_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "storage_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "cycle", + "layout": { + "size": "Int32", + "kind": "Int" + }, + "data_kind": { + "size": 4, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "pk", + "layout": { + "name": "public_key", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + } + ], + "name": "Update_consensus_key" + }, { "tag": 150, "fields": [ @@ -12150,6 +12293,52 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Update_consensus_key", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "update_consensus_key" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "cycle": { + "type": "integer", + "minimum": -2147483648, + "maximum": 2147483647 + }, + "pk": { + "$ref": "#/definitions/Signature.Public_key" + } + }, + "required": [ + "pk", + "cycle", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", diff --git a/tezt/_regressions/rpc/alpha.proxy.mempool.out b/tezt/_regressions/rpc/alpha.proxy.mempool.out index c0f381b6079f..e549a5e6107c 100644 --- a/tezt/_regressions/rpc/alpha.proxy.mempool.out +++ b/tezt/_regressions/rpc/alpha.proxy.mempool.out @@ -1704,6 +1704,52 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Update_consensus_key", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "update_consensus_key" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "cycle": { + "type": "integer", + "minimum": -2147483648, + "maximum": 2147483647 + }, + "pk": { + "$ref": "#/definitions/Signature.Public_key" + } + }, + "required": [ + "pk", + "cycle", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", @@ -5096,6 +5142,103 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "name": "Set_deposits_limit" }, + { + "tag": 113, + "fields": [ + { + "name": "Tag", + "layout": { + "size": "Uint8", + "kind": "Int" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "source", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "fee", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "counter", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "gas_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "storage_limit", + "layout": { + "name": "N.t", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + }, + { + "name": "cycle", + "layout": { + "size": "Int32", + "kind": "Int" + }, + "data_kind": { + "size": 4, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "pk", + "layout": { + "name": "public_key", + "kind": "Ref" + }, + "data_kind": { + "kind": "Dynamic" + }, + "kind": "named" + } + ], + "name": "Update_consensus_key" + }, { "tag": 150, "fields": [ @@ -12171,6 +12314,52 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Update_consensus_key", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "update_consensus_key" + ] + }, + "source": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "fee": { + "$ref": "#/definitions/alpha.mutez" + }, + "counter": { + "$ref": "#/definitions/positive_bignum" + }, + "gas_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "storage_limit": { + "$ref": "#/definitions/positive_bignum" + }, + "cycle": { + "type": "integer", + "minimum": -2147483648, + "maximum": 2147483647 + }, + "pk": { + "$ref": "#/definitions/Signature.Public_key" + } + }, + "required": [ + "pk", + "cycle", + "storage_limit", + "gas_limit", + "counter", + "fee", + "source", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", -- GitLab From 47f5ce55684474c289692033b852e11d012d2d73 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 28/48] 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 49111fcc74e3..c319d7aa0573 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -316,6 +316,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 97951466bf00..dc99612f702d 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 0fff31de6b21..01a4c4df8df9 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 @@ -1490,6 +1490,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 8eb4d46156a707b50dfc9aae874cace61f48d791 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 29/48] 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 c319d7aa0573..42afa109f1ff 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -299,35 +299,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 dc99612f702d..73d6cb1e798d 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 01a4c4df8df9..c0c36b3eff9a 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 @@ -1490,6 +1490,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 fcd3a70f1f2667c603ed703ff62c1d7f8426e269 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 30/48] 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 c0c36b3eff9a..00e024799965 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 @@ -1021,7 +1021,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 2d3a8a43fb30..97ef5d74c31b 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -492,7 +492,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 @@ -506,7 +506,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 @@ -795,7 +795,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 @@ -806,7 +806,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 = @@ -826,10 +826,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] @@ -901,6 +902,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 @@ -1836,12 +1848,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 236d049fed5f..bd9c6679b847 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -363,6 +363,7 @@ val bake_for : ?ignore_node_mempool:bool -> ?force:bool -> ?context_path:string -> + ?expect_failure:bool -> t -> unit Lwt.t @@ -628,6 +629,7 @@ val set_delegate : ?fee:Tez.t -> ?fee_cap:Tez.t -> ?force_low_fee:bool -> + ?expect_failure:bool -> src:string -> delegate:string -> t -> @@ -646,7 +648,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 : @@ -729,6 +736,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 @@ -1380,10 +1399,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 16b77d632e1e..eed1452d76c3 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -126,6 +126,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 From f7ac6e284851bfac876e16f3b767f80a7ff96b06 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 31/48] Proto: add operation `Drain_delegate` --- .../lib_client/operation_result.ml | 19 ++ src/proto_alpha/lib_plugin/plugin.ml | 6 +- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 2 +- .../lib_protocol/alpha_context.mli | 16 ++ src/proto_alpha/lib_protocol/apply.ml | 193 +++++++++++++++++- src/proto_alpha/lib_protocol/apply.mli | 12 +- src/proto_alpha/lib_protocol/apply_results.ml | 41 +++- .../lib_protocol/apply_results.mli | 5 + .../lib_protocol/delegate_storage.ml | 47 +++++ .../lib_protocol/delegate_storage.mli | 7 + src/proto_alpha/lib_protocol/dune | 10 +- src/proto_alpha/lib_protocol/main.ml | 8 + src/proto_alpha/lib_protocol/main.mli | 11 + .../lib_protocol/operation_repr.ml | 37 +++- .../lib_protocol/operation_repr.mli | 13 ++ .../_regressions/rpc/alpha.client.mempool.out | 110 ++++++++++ tezt/_regressions/rpc/alpha.proxy.mempool.out | 110 ++++++++++ 17 files changed, 631 insertions(+), 16 deletions(-) diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index b5e1d13e44d5..dee2e1b59e9b 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -1185,6 +1185,25 @@ let rec pp_contents_and_result_list : proposal Data_encoding.Json.pp (Data_encoding.Json.construct Vote.ballot_encoding ballot) + | Single_and_result + ( Drain_delegate {consensus_key; delegate; destination}, + Drain_delegate_result {balance_updates; allocated_destination_contract} + ) -> + Format.fprintf + ppf + "@[Drain delegate:@,\ + Consensus key hash: %a@,\ + Delegate: %a@,\ + Destination: %a%s%a@]" + Signature.Public_key_hash.pp + consensus_key + Signature.Public_key_hash.pp + delegate + Signature.Public_key_hash.pp + destination + (if allocated_destination_contract then " (allocated)" else "") + pp_balance_updates_opt + balance_updates | Single_and_result (Failing_noop _arbitrary, _) -> (* the Failing_noop operation always fails and can't have result *) . diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index 19c540d81296..de9dca51a667 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -1009,7 +1009,8 @@ module Mempool = struct | Single (Double_baking_evidence _) | Single (Activate_account _) | Single (Proposals _) - | Single (Ballot _) -> + | Single (Ballot _) + | Single (Drain_delegate _) -> Lwt.return @@ `Passed_prefilter other_prio | Single (Manager_operation {source; _}) as op -> prefilter_manager_op source op @@ -1288,7 +1289,8 @@ module Mempool = struct | Single_result (Double_baking_evidence_result _) | Single_result (Activate_account_result _) | Single_result Proposals_result - | Single_result Ballot_result -> + | Single_result Ballot_result + | Single_result (Drain_delegate_result _) -> Lwt.return (`Passed_postfilter filter_state) | Single_result (Manager_operation_result _) as result -> Lwt.return (post_filter_manager ctxt filter_state result config) diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 07845e66f02d..104ed3a178a0 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -111,6 +111,7 @@ "Stake_storage", "Contract_storage", "Token", + "Fees_storage", "Delegate_consensus_key", "Delegate_storage", "Delegate_missed_endorsements_storage", @@ -120,7 +121,6 @@ "Bootstrap_storage", "Vote_storage", - "Fees_storage", "Ticket_storage", "Liquidity_baking_storage", "Liquidity_baking_cpmm", diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 2025e650dc5f..3871697f2768 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2220,6 +2220,12 @@ module Delegate : sig val check_registered : context -> public_key_hash -> unit tzresult Lwt.t + val drain : + context -> + delegate:public_key_hash -> + destination:public_key_hash -> + (context * bool * Tez.t * Receipt.balance_updates) tzresult Lwt.t + type participation_info = { expected_cycle_activity : int; minimal_cycle_activity : int; @@ -2895,6 +2901,8 @@ module Kind : sig type update_consensus_key = Update_consensus_key_kind + type drain_delegate = Drain_delegate_kind + type failing_noop = Failing_noop_kind type register_global_constant = Register_global_constant_kind @@ -3044,6 +3052,12 @@ and _ contents = ballot : Vote.ballot; } -> Kind.ballot contents + | Drain_delegate : { + consensus_key : Signature.Public_key_hash.t; + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + } + -> Kind.drain_delegate contents | Failing_noop : string -> Kind.failing_noop contents | Manager_operation : { source : public_key_hash; @@ -3285,6 +3299,8 @@ module Operation : sig val ballot_case : Kind.ballot case + val drain_delegate_case : Kind.drain_delegate case + val failing_noop_case : Kind.failing_noop case val reveal_case : Kind.reveal Kind.manager case diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 4f9eabd3160d..ba302df68c1e 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -94,6 +94,19 @@ 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} | Update_consensus_key_on_unregistered_delegate of Signature.Public_key_hash.t + | Drain_delegate_on_unregistered_delegate of Signature.Public_key_hash.t + | Invalid_drain_delegate_inactive_key of { + delegate : Signature.Public_key_hash.t; + consensus_key : Signature.Public_key_hash.t; + active_consensus_key : Signature.Public_key_hash.t; + } + | Invalid_drain_delegate_no_consensus_key of Signature.Public_key_hash.t + | Invalid_drain_delegate_noop of Signature.Public_key_hash.t + | Invalid_drain_delegate_no_allocation_burn of { + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + } + | Unauthorized_key_for_drain of Signature.Public_key_hash.t | Empty_transaction of Contract.t | Tx_rollup_feature_disabled | Tx_rollup_invalid_transaction_ticket_amount @@ -484,6 +497,118 @@ let () = (function | Update_consensus_key_on_unregistered_delegate c -> Some c | _ -> None) (fun c -> Update_consensus_key_on_unregistered_delegate c) ; + register_error_kind + `Temporary + ~id:"operation.drain_delegate_key_on_unregistered_delegate" + ~title:"Drain delegate key on an unregistered delegate" + ~description:"Cannot drain an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot drain an unregistered delegate %a." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Drain_delegate_on_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Drain_delegate_on_unregistered_delegate c) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.inactive_key" + ~title:"Drain delegate with an inactive consensus key" + ~description:"Cannot drain with an inactive consensus key." + ~pp:(fun ppf (delegate, consensus_key, active_consensus_key) -> + Format.fprintf + ppf + "Consensus key %a is not active consensus key for delegate %a. The \ + active consensus key is %a." + Signature.Public_key_hash.pp + consensus_key + Signature.Public_key_hash.pp + delegate + Signature.Public_key_hash.pp + active_consensus_key) + Data_encoding.( + obj3 + (req "delegate" Signature.Public_key_hash.encoding) + (req "consensus_key" Signature.Public_key_hash.encoding) + (req "active_consensus_key" Signature.Public_key_hash.encoding)) + (function + | Invalid_drain_delegate_inactive_key + {delegate; consensus_key; active_consensus_key} -> + Some (delegate, consensus_key, active_consensus_key) + | _ -> None) + (fun (delegate, consensus_key, active_consensus_key) -> + Invalid_drain_delegate_inactive_key + {delegate; consensus_key; active_consensus_key}) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.no_consensus_key" + ~title:"Drain a delegate without consensus key" + ~description:"Cannot drain a delegate without consensus key." + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "There is no active consensus key for delegate %a." + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Invalid_drain_delegate_no_consensus_key c -> Some c | _ -> None) + (fun c -> Invalid_drain_delegate_no_consensus_key c) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.noop" + ~title:"Invalid drain delegate: noop" + ~description:"Cannot drain a delegate to itself." + ~pp:(fun ppf delegate -> + Format.fprintf + ppf + "The destination of a drain operation cannot be the delegate itself \ + (%a)." + Signature.Public_key_hash.pp + delegate) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Invalid_drain_delegate_noop c -> Some c | _ -> None) + (fun c -> Invalid_drain_delegate_noop c) ; + register_error_kind + `Temporary + ~id:"operation.unauthorized_key_for_drain" + ~title:"Unauthorized key for draining a delegate" + ~description:"Unauthorized key for draining a delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "The source key (%a) is not an active consensus key. It cannot be used \ + for draining a delegate." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Unauthorized_key_for_drain c -> Some c | _ -> None) + (fun c -> Unauthorized_key_for_drain c) ; + register_error_kind + `Temporary + ~id:"operation.invalid_drain.no_allocation_burn" + ~title:"Drain delegate without enough balance for allocation burn" + ~description:"Cannot drain without enough allocation burn." + ~pp:(fun ppf (delegate, destination) -> + Format.fprintf + ppf + "Cannot drain delegate %a to %a. The destination is not allocated and \ + there is not enough funds in the delegate account to pay for the \ + allocation burn." + Signature.Public_key_hash.pp + delegate + Signature.Public_key_hash.pp + destination) + Data_encoding.( + obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "destination" Signature.Public_key_hash.encoding)) + (function + | Invalid_drain_delegate_no_allocation_burn {delegate; destination} -> + Some (delegate, destination) + | _ -> None) + (fun (delegate, destination) -> + Invalid_drain_delegate_no_allocation_burn {delegate; destination}) ; register_error_kind `Branch ~id:"contract.empty_transaction" @@ -1940,7 +2065,7 @@ let precheck_manager_contents (type kind) ctxt (op : kind Kind.manager contents) @@ (* See comment in the Transaction branch *) ( Script.force_decode_in_context ~consume_deserialization_gas ctxt value >|? fun (_value, ctxt) -> ctxt ) - | Delegation _ | Set_deposits_limit _ | Update_consensus_key _ -> return ctxt + | Delegation _ | Set_deposits_limit _ | Update_consensus_key _ | Tx_rollup_origination -> assert_tx_rollup_feature_enabled ctxt >|=? fun () -> ctxt | Tx_rollup_submit_batch {content; _} -> @@ -2532,6 +2657,49 @@ let check_manager_signature ctxt chain_id (op : _ Kind.manager contents_list) find_manager_public_key ctxt op >>=? fun public_key -> Lwt.return (Operation.check_signature public_key chain_id raw_operation) +let check_drain ctxt + (Single (Drain_delegate {delegate; destination; consensus_key})) = + Delegate.registered ctxt delegate >>= fun is_registered -> + error_unless is_registered (Drain_delegate_on_unregistered_delegate delegate) + >>?= fun () -> + Delegate.Consensus_key.active_pubkey ctxt delegate >>=? fun active_pk -> + if not (Signature.Public_key_hash.equal active_pk.consensus_pkh consensus_key) + then + fail + (Invalid_drain_delegate_inactive_key + { + delegate; + consensus_key; + active_consensus_key = active_pk.consensus_pkh; + }) + else if Signature.Public_key_hash.equal active_pk.consensus_pkh delegate then + fail (Invalid_drain_delegate_no_consensus_key delegate) + else if Signature.Public_key_hash.equal destination delegate then + fail (Invalid_drain_delegate_noop delegate) + else return active_pk.consensus_pk + +let precheck_drain ctxt + (Single (Drain_delegate {delegate; destination; _}) as op) = + check_drain ctxt op >>=? fun _active_pk -> + Contract.allocated ctxt (Contract.Implicit destination) + >>= fun is_destination_allocated -> + (if is_destination_allocated then ok Tez.zero + else + let cost_per_byte = Constants.cost_per_byte ctxt in + let origination_size = Constants.origination_size ctxt in + Tez.(cost_per_byte *? Int64.of_int origination_size)) + >>?= fun min_balance -> + Contract.get_balance ctxt (Contract.Implicit delegate) >>=? fun balance -> + if Tez.(balance < min_balance) then + fail (Invalid_drain_delegate_no_allocation_burn {delegate; destination}) + else return_unit + +let check_drain_signature ctxt chain_id (Single (Drain_delegate {delegate; _})) + raw_operation = + Delegate.Consensus_key.active_pubkey ctxt delegate >>=? fun active_pk -> + Lwt.return + (Operation.check_signature active_pk.consensus_pk chain_id raw_operation) + let rec apply_manager_contents_list_rec : type kind. context -> @@ -2675,7 +2843,8 @@ let record_operation (type kind) ctxt (operation : kind operation) : context = | Single ( Failing_noop _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ | Double_endorsement_evidence _ | Double_preendorsement_evidence _ - | Double_baking_evidence _ | Activate_account _ | Manager_operation _ ) + | Double_baking_evidence _ | Activate_account _ | Drain_delegate _ + | Manager_operation _ ) | Cons (Manager_operation _, _) -> let hash = Operation.hash operation in record_non_consensus_operation_hash ctxt hash @@ -3219,6 +3388,26 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode >>?= fun () -> Amendment.record_ballot ctxt source proposal ballot >|=? fun ctxt -> (ctxt, Single_result Ballot_result) + | Single (Drain_delegate {delegate; destination; consensus_key = _}) as op -> + check_drain ctxt op >>=? fun active_pk -> + Operation.check_signature active_pk chain_id operation >>?= fun () -> + Delegate.drain ctxt ~delegate ~destination + >>=? fun ( ctxt, + allocated_destination_contract, + fees, + drain_balance_updates ) -> + Token.transfer + ctxt + (`Delegate_balance delegate) + (`Contract (Contract.Implicit payload_producer.Consensus_key.delegate)) + fees + >>=? fun (ctxt, fees_balance_updates) -> + let balance_updates = drain_balance_updates @ fees_balance_updates in + return + ( ctxt, + Single_result + (Drain_delegate_result + {balance_updates; allocated_destination_contract}) ) | Single (Failing_noop _) -> (* Failing_noop _ always fails *) fail Failing_noop_error diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index c7a85192d5b3..beacfae230e7 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -210,4 +210,14 @@ val check_manager_signature : Chain_id.t -> 'a Kind.manager contents_list -> 'b operation -> - (unit, error trace) result Lwt.t + unit tzresult Lwt.t + +val precheck_drain : + context -> Kind.drain_delegate contents_list -> unit tzresult Lwt.t + +val check_drain_signature : + context -> + Chain_id.t -> + Kind.drain_delegate contents_list -> + Kind.drain_delegate operation -> + unit tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index cd8ee1e4dae9..fe097547cd6f 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -1490,6 +1490,11 @@ type 'kind contents_result = -> Kind.activate_account contents_result | Proposals_result : Kind.proposals contents_result | Ballot_result : Kind.ballot contents_result + | Drain_delegate_result : { + balance_updates : Receipt.balance_updates; + allocated_destination_contract : bool; + } + -> Kind.drain_delegate contents_result | Manager_operation_result : { balance_updates : Receipt.balance_updates; operation_result : 'kind manager_operation_result; @@ -1523,9 +1528,6 @@ let equal_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 | Kind.Register_global_constant_manager_kind, _ -> None | Kind.Set_deposits_limit_manager_kind, Kind.Set_deposits_limit_manager_kind -> @@ -1801,6 +1803,34 @@ module Encoding = struct inj = (fun () -> Ballot_result); } + let drain_delegate_case = + Case + { + op_case = Operation.Encoding.drain_delegate_case; + encoding = + Data_encoding.( + obj2 + (dft "balance_updates" Receipt.balance_updates_encoding []) + (dft "allocated_destination_contract" bool false)); + select = + (function + | Contents_result (Drain_delegate_result _ as op) -> Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Drain_delegate _ as op), res) -> Some (op, res) + | _ -> None); + proj = + (function + | Drain_delegate_result + {balance_updates; allocated_destination_contract} -> + (balance_updates, allocated_destination_contract)); + inj = + (fun (balance_updates, allocated_destination_contract) -> + Drain_delegate_result + {balance_updates; allocated_destination_contract}); + } + let[@coq_axiom_with_reason "gadt"] make_manager_case (type kind) (Operation.Encoding.Case op_case : kind Kind.manager Operation.Encoding.case) @@ -1862,6 +1892,7 @@ module Encoding = struct | Contents_result (Double_preendorsement_evidence_result _) -> None | Contents_result (Double_baking_evidence_result _) -> None | Contents_result (Activate_account_result _) -> None + | Contents_result (Drain_delegate_result _) -> None | Contents_result Proposals_result -> None); mselect; proj = @@ -2164,6 +2195,7 @@ let contents_result_encoding = make activate_account_case; make proposals_case; make ballot_case; + make drain_delegate_case; make reveal_case; make transaction_case; make origination_case; @@ -2229,6 +2261,7 @@ let contents_and_result_encoding = make register_global_constant_case; make set_deposits_limit_case; make update_consensus_key_case; + make drain_delegate_case; make tx_rollup_origination_case; make tx_rollup_submit_batch_case; make tx_rollup_commit_case; @@ -2370,6 +2403,8 @@ let kind_equal : | Proposals _, _ -> None | Ballot _, Ballot_result -> Some Eq | Ballot _, _ -> None + | Drain_delegate _, Drain_delegate_result _ -> Some Eq + | Drain_delegate _, _ -> None | Failing_noop _, _ -> (* the Failing_noop operation always fails and can't have result *) None diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index d39f0cc35f29..71a57aabb3f3 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -118,6 +118,11 @@ and 'kind contents_result = -> Kind.activate_account contents_result | Proposals_result : Kind.proposals contents_result | Ballot_result : Kind.ballot contents_result + | Drain_delegate_result : { + balance_updates : Receipt.balance_updates; + allocated_destination_contract : bool; + } + -> Kind.drain_delegate contents_result | Manager_operation_result : { balance_updates : Receipt.balance_updates; operation_result : 'kind manager_operation_result; diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 96aac84dde1e..38c2270529a0 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -297,3 +297,50 @@ module Contract = struct set_self_delegate c delegate | _ -> set_delegate c contract delegate end + +type error += (* `Temporary *) Invalid_drain + +let () = + register_error_kind + `Temporary + ~id:"delegate.invalid_drain" + ~title:"Invalid Drain operation" + ~description: + "The drain operation is not signed by the active consensus key." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "The drain operation is invalid: not signed by the active consensus key") + Data_encoding.empty + (function Invalid_drain -> Some () | _ -> None) + (fun () -> Invalid_drain) + +let drain ctxt ~delegate ~destination = + let open Lwt_tzresult_syntax in + let*! is_destination_allocated = + Contract_storage.allocated ctxt (Contract_repr.Implicit destination) + in + let* ctxt, _, balance_updates1 = + if not is_destination_allocated then + Fees_storage.burn_origination_fees + ctxt + ~storage_limit:(Z.of_int (Constants_storage.origination_size ctxt)) + ~payer:(`Delegate_balance delegate) + else return (ctxt, Z.zero, []) + in + let* manager_balance = balance ctxt delegate in + let*? one_percent = Tez_repr.(manager_balance /? 100L) in + let fees = Tez_repr.(min one one_percent) in + let*? transfered = Tez_repr.(manager_balance -? fees) in + let* ctxt, balance_updates2 = + Token.transfer + ctxt + (`Delegate_balance delegate) + (`Contract (Contract_repr.Implicit destination)) + transfered + in + return + ( ctxt, + not is_destination_allocated, + fees, + balance_updates1 @ balance_updates2 ) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 4bb421f8a644..3478986218b4 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -127,3 +127,10 @@ val manager_pubkey : Raw_context.t -> Signature.Public_key_hash.t -> Signature.Public_key.t tzresult Lwt.t + +val drain : + Raw_context.t -> + delegate:Signature.Public_key_hash.t -> + destination:Signature.Public_key_hash.t -> + (Raw_context.t * bool * Tez_repr.t * Receipt_repr.balance_updates) tzresult + Lwt.t diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 5f889852a9dd..81a2f61ddd78 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -138,6 +138,7 @@ Stake_storage Contract_storage Token + Fees_storage Delegate_consensus_key Delegate_storage Delegate_missed_endorsements_storage @@ -146,7 +147,6 @@ Delegate_cycles Bootstrap_storage Vote_storage - Fees_storage Ticket_storage Liquidity_baking_storage Liquidity_baking_cpmm @@ -356,6 +356,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + fees_storage.ml fees_storage.mli delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml @@ -365,7 +366,6 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli - fees_storage.ml fees_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml @@ -561,6 +561,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + fees_storage.ml fees_storage.mli delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml @@ -570,7 +571,6 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli - fees_storage.ml fees_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml @@ -786,6 +786,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + fees_storage.ml fees_storage.mli delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml @@ -795,7 +796,6 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli - fees_storage.ml fees_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml @@ -1007,6 +1007,7 @@ stake_storage.ml stake_storage.mli contract_storage.ml contract_storage.mli token.ml token.mli + fees_storage.ml fees_storage.mli delegate_consensus_key.ml delegate_consensus_key.mli delegate_storage.ml delegate_storage.mli delegate_missed_endorsements_storage.ml @@ -1016,7 +1017,6 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli - fees_storage.ml fees_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index 547dae479a32..d763dab346c2 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -715,6 +715,9 @@ let relative_position_within_block op1 op2 = | Single (Ballot _), Single (Ballot _) -> 0 | _, Single (Ballot _) -> 1 | Single (Ballot _), _ -> -1 + | Single (Drain_delegate _), Single (Drain_delegate _) -> 0 + | _, Single (Drain_delegate _) -> 1 + | Single (Drain_delegate _), _ -> -1 | Single (Failing_noop _), Single (Failing_noop _) -> 0 | _, Single (Failing_noop _) -> 1 | Single (Failing_noop _), _ -> -1 @@ -812,4 +815,9 @@ let precheck_manager {ctxt; _} op = * 'kind Alpha_context.Kind.manager Apply_results.prechecked_contents_list) -> () +let precheck_drain {ctxt; _} op = Apply.precheck_drain ctxt op + +let check_drain_signature {chain_id; ctxt; _} op raw_op = + Apply.check_drain_signature ctxt chain_id op raw_op + (* Vanity nonce: TBD *) diff --git a/src/proto_alpha/lib_protocol/main.mli b/src/proto_alpha/lib_protocol/main.mli index ad796cee7971..2cbb0aff5b23 100644 --- a/src/proto_alpha/lib_protocol/main.mli +++ b/src/proto_alpha/lib_protocol/main.mli @@ -148,6 +148,17 @@ val precheck_manager : 'a Alpha_context.Kind.manager Alpha_context.contents_list -> unit tzresult Lwt.t +val check_drain_signature : + validation_state -> + Alpha_context.Kind.drain_delegate Alpha_context.contents_list -> + Alpha_context.Kind.drain_delegate Alpha_context.operation -> + unit tzresult Lwt.t + +val precheck_drain : + validation_state -> + Alpha_context.Kind.drain_delegate Alpha_context.contents_list -> + unit tzresult Lwt.t + include Updater.PROTOCOL with type block_header_data = Alpha_context.Block_header.protocol_data diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 6ce9b2221580..d761d7caf7b6 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 update_consensus_key = Update_consensus_key_kind + type drain_delegate = Drain_delegate_kind + type failing_noop = Failing_noop_kind type register_global_constant = Register_global_constant_kind @@ -279,6 +281,12 @@ and _ contents = ballot : Vote_repr.ballot; } -> Kind.ballot contents + | Drain_delegate : { + consensus_key : Signature.Public_key_hash.t; + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + } + -> Kind.drain_delegate contents | Failing_noop : string -> Kind.failing_noop contents | Manager_operation : { source : Signature.public_key_hash; @@ -1350,6 +1358,27 @@ module Encoding = struct Ballot {source; period; proposal; ballot}); } + let[@coq_axiom_with_reason "gadt"] drain_delegate_case = + Case + { + tag = 8; + name = "drain_delegate"; + encoding = + obj3 + (req "consensus_key" Signature.Public_key_hash.encoding) + (req "delegate" Signature.Public_key_hash.encoding) + (req "destination" Signature.Public_key_hash.encoding); + select = + (function Contents (Drain_delegate _ as op) -> Some op | _ -> None); + proj = + (function + | Drain_delegate {consensus_key; delegate; destination} -> + (consensus_key, delegate, destination)); + inj = + (fun (consensus_key, delegate, destination) -> + Drain_delegate {consensus_key; delegate; destination}); + } + let failing_noop_case = Case { @@ -1528,6 +1557,7 @@ module Encoding = struct make delegation_case; make set_deposits_limit_case; make update_consensus_key_case; + make drain_delegate_case; make failing_noop_case; make register_global_constant_case; make tx_rollup_origination_case; @@ -1612,6 +1642,7 @@ let acceptable_passes (op : packed_operation) = | Single (Double_preendorsement_evidence _) -> [2] | Single (Double_baking_evidence _) -> [2] | Single (Activate_account _) -> [2] + | Single (Drain_delegate _) -> [2] | Single (Manager_operation _) -> [3] | Cons (Manager_operation _, _ops) -> [3] @@ -1686,8 +1717,8 @@ let check_signature (type kind) key chain_id | Single ( Failing_noop _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ | Double_endorsement_evidence _ | Double_preendorsement_evidence _ - | Double_baking_evidence _ | Activate_account _ | Manager_operation _ - ) -> + | Double_baking_evidence _ | Activate_account _ | Drain_delegate _ + | Manager_operation _ ) -> check ~watermark:Generic_operation (Contents_list protocol_data.contents) @@ -1790,6 +1821,8 @@ let equal_contents_kind : type a b. a contents -> b contents -> (a, b) eq option | Proposals _, _ -> None | Ballot _, Ballot _ -> Some Eq | Ballot _, _ -> None + | Drain_delegate _, Drain_delegate _ -> Some Eq + | Drain_delegate _, _ -> None | Failing_noop _, Failing_noop _ -> Some Eq | Failing_noop _, _ -> None | Manager_operation op1, Manager_operation op2 -> ( diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index 14ce04ae9add..33177956f4e2 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 update_consensus_key = Update_consensus_key_kind + type drain_delegate = Drain_delegate_kind + type failing_noop = Failing_noop_kind type register_global_constant = Register_global_constant_kind @@ -295,6 +297,15 @@ and _ contents = ballot : Vote_repr.ballot; } -> Kind.ballot contents + (* [Drain_delegate { consensus_key ; delegate ; destination }] + transfers the spendable balance of the [delegate] to [destination] + when [consensus_key] is the active consensus key of [delegate].. *) + | Drain_delegate : { + consensus_key : Signature.Public_key_hash.t; + delegate : Signature.Public_key_hash.t; + destination : Signature.Public_key_hash.t; + } + -> Kind.drain_delegate contents (* Failing_noop: An operation never considered by the state machine and which will always fail at [apply]. This allows end-users to sign arbitrary messages which have no computational semantics. *) @@ -584,6 +595,8 @@ module Encoding : sig val ballot_case : Kind.ballot case + val drain_delegate_case : Kind.drain_delegate case + val failing_noop_case : Kind.failing_noop case val reveal_case : Kind.reveal Kind.manager case diff --git a/tezt/_regressions/rpc/alpha.client.mempool.out b/tezt/_regressions/rpc/alpha.client.mempool.out index 3686a04f6374..934e1b034237 100644 --- a/tezt/_regressions/rpc/alpha.client.mempool.out +++ b/tezt/_regressions/rpc/alpha.client.mempool.out @@ -1729,6 +1729,34 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Drain_delegate", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "drain_delegate" + ] + }, + "consensus_key": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "delegate": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "destination": { + "$ref": "#/definitions/Signature.Public_key_hash" + } + }, + "required": [ + "destination", + "delegate", + "consensus_key", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", @@ -4381,6 +4409,60 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "name": "Double_preendorsement_evidence" }, + { + "tag": 8, + "fields": [ + { + "name": "Tag", + "layout": { + "size": "Uint8", + "kind": "Int" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "consensus_key", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "delegate", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "destination", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + } + ], + "name": "Drain_delegate" + }, { "tag": 17, "fields": [ @@ -12339,6 +12421,34 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Drain_delegate", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "drain_delegate" + ] + }, + "consensus_key": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "delegate": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "destination": { + "$ref": "#/definitions/Signature.Public_key_hash" + } + }, + "required": [ + "destination", + "delegate", + "consensus_key", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", diff --git a/tezt/_regressions/rpc/alpha.proxy.mempool.out b/tezt/_regressions/rpc/alpha.proxy.mempool.out index e549a5e6107c..fd3289f9b28f 100644 --- a/tezt/_regressions/rpc/alpha.proxy.mempool.out +++ b/tezt/_regressions/rpc/alpha.proxy.mempool.out @@ -1750,6 +1750,34 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Drain_delegate", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "drain_delegate" + ] + }, + "consensus_key": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "delegate": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "destination": { + "$ref": "#/definitions/Signature.Public_key_hash" + } + }, + "required": [ + "destination", + "delegate", + "consensus_key", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", @@ -4402,6 +4430,60 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "name": "Double_preendorsement_evidence" }, + { + "tag": 8, + "fields": [ + { + "name": "Tag", + "layout": { + "size": "Uint8", + "kind": "Int" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "consensus_key", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "delegate", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + }, + { + "name": "destination", + "layout": { + "name": "public_key_hash", + "kind": "Ref" + }, + "data_kind": { + "size": 21, + "kind": "Float" + }, + "kind": "named" + } + ], + "name": "Drain_delegate" + }, { "tag": 17, "fields": [ @@ -12360,6 +12442,34 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + { + "title": "Drain_delegate", + "type": "object", + "properties": { + "kind": { + "type": "string", + "enum": [ + "drain_delegate" + ] + }, + "consensus_key": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "delegate": { + "$ref": "#/definitions/Signature.Public_key_hash" + }, + "destination": { + "$ref": "#/definitions/Signature.Public_key_hash" + } + }, + "required": [ + "destination", + "delegate", + "consensus_key", + "kind" + ], + "additionalProperties": false + }, { "title": "Failing_noop", "type": "object", -- GitLab From 1eb52a1f7ee24aecd0b1be2cf6a2cf6f40ee1a0a Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 32/48] Proto/Client: add `tezos-client drain delegate to ` --- .../lib_client/client_proto_context.ml | 22 +++++++ .../lib_client/client_proto_context.mli | 15 +++++ .../client_proto_context_commands.ml | 59 +++++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/src/proto_alpha/lib_client/client_proto_context.ml b/src/proto_alpha/lib_client/client_proto_context.ml index 42afa109f1ff..0ad62e66205c 100644 --- a/src/proto_alpha/lib_client/client_proto_context.ml +++ b/src/proto_alpha/lib_client/client_proto_context.ml @@ -400,6 +400,28 @@ let update_consensus_key cctxt ~chain ~block ?confirmations ?dry_run | Apply_results.Single_and_result ((Manager_operation _ as op), result) -> return (oph, op, result) +let drain_delegate cctxt ~chain ~block ?confirmations ?dry_run ?verbose_signing + ?simulation ~consensus_sk ~consensus_pkh ?(destination = consensus_pkh) + ~delegate () = + let operation = + Single + (Drain_delegate {consensus_key = consensus_pkh; delegate; destination}) + in + Injection.inject_operation + cctxt + ~chain + ~block + ?confirmations + ?dry_run + ?verbose_signing + ?simulation + ~src_sk:consensus_sk + operation + >>=? fun (oph, op, result) -> + match Apply_results.pack_contents_list op result with + | Apply_results.Single_and_result ((Drain_delegate _ 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 73d6cb1e798d..4c13216cd894 100644 --- a/src/proto_alpha/lib_client/client_proto_context.mli +++ b/src/proto_alpha/lib_client/client_proto_context.mli @@ -147,6 +147,21 @@ val update_consensus_key : Signature.public_key -> Kind.update_consensus_key Kind.manager Injection.result tzresult Lwt.t +val drain_delegate : + #Protocol_client_context.full -> + chain:Shell_services.chain -> + block:Shell_services.block -> + ?confirmations:int -> + ?dry_run:bool -> + ?verbose_signing:bool -> + ?simulation:bool -> + consensus_sk:Client_keys.sk_uri -> + consensus_pkh:Signature.public_key_hash -> + ?destination:Signature.public_key_hash -> + delegate:Signature.public_key_hash -> + unit -> + Kind.drain_delegate 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 00e024799965..14fdbc765d87 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 @@ -1570,6 +1570,65 @@ let commands_rw () = >>= function | Ok _ -> return_unit | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Drain all funds from a delegate." + (args2 dry_run_switch verbose_signing_switch) + (prefixes ["drain"; "delegate"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["to"] + @@ Public_key_hash.source_param ~name:"key" ~desc:"the consensus key" + @@ stop) + (fun (dry_run, verbose_signing) delegate_pkh consensus_pkh cctxt -> + Client_keys.get_key cctxt consensus_pkh + >>=? fun (_, _consensus_pk, consensus_sk) -> + drain_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~consensus_pkh + ~consensus_sk + ~delegate:delegate_pkh + () + >>= function + | Ok _ -> return_unit + | Error el -> Lwt.return_error el); + command + ~group + ~desc:"Drain all funds from a delegate." + (args2 dry_run_switch verbose_signing_switch) + (prefixes ["drain"; "delegate"] + @@ Public_key_hash.source_param ~name:"mgr" ~desc:"the delegate key" + @@ prefixes ["to"] + @@ Public_key_hash.source_param ~name:"key" ~desc:"the destination key" + @@ prefixes ["with"] + @@ Public_key_hash.source_param ~name:"key" ~desc:"the consensus key" + @@ stop) + (fun (dry_run, verbose_signing) + delegate_pkh + destination_pkh + consensus_pkh + cctxt -> + Client_keys.get_key cctxt consensus_pkh + >>=? fun (_, _consensus_pk, consensus_sk) -> + drain_delegate + cctxt + ~chain:cctxt#chain + ~block:cctxt#block + ?confirmations:cctxt#confirmations + ~dry_run + ~verbose_signing + ~consensus_pkh + ~consensus_sk + ~destination:destination_pkh + ~delegate:delegate_pkh + () + >>= function + | Ok _ -> return_unit + | Error el -> Lwt.return_error el); command ~desc:"Wait until an operation is included in a block" (args3 -- GitLab From e42bae60aedf9434bae6b94a120690d2b06933ef Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Sun, 8 May 2022 19:46:31 +0200 Subject: [PATCH 33/48] Proto/Plugin: prioritize `Drain_delegate` over any manager op --- src/proto_alpha/lib_plugin/plugin.ml | 139 ++++++++++++++++-- src/proto_alpha/lib_plugin/test/generators.ml | 2 +- .../lib_plugin/test/test_filter_state.ml | 4 +- src/proto_alpha/lib_plugin/test/test_utils.ml | 57 ++++--- 4 files changed, 170 insertions(+), 32 deletions(-) diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index de9dca51a667..613a05a152b1 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -225,6 +225,8 @@ module Mempool = struct weight : Q.t; } + type op_info = Manager_op of manager_op_info | Drained of Operation_hash.t + type manager_op_weight = {operation_hash : Operation_hash.t; weight : Q.t} let op_weight_of_info (info : manager_op_info) : manager_op_weight = @@ -243,7 +245,7 @@ module Mempool = struct type state = { grandparent_level_start : Timestamp.t option; round_zero_duration : Period.t option; - op_prechecked_managers : manager_op_info Signature.Public_key_hash.Map.t; + op_prechecked_managers : op_info Signature.Public_key_hash.Map.t; (** All managers that are the source of manager operations prechecked in the mempool. Each manager in the map is associated to a record of type [manager_op_info] (See for record details above). @@ -363,7 +365,8 @@ module Mempool = struct let ops_prechecked = match !removed_op with | None -> filter_state.ops_prechecked - | Some op -> + | Some (Drained _) -> filter_state.ops_prechecked + | Some (Manager_op op) -> ManagerOpWeightSet.remove (op_weight_of_info op) filter_state.ops_prechecked @@ -417,6 +420,7 @@ module Mempool = struct type Environment.Error_monad.error += | Manager_restriction of {oph : Operation_hash.t; fee : Tez.t} + | Manager_drained of {oph : Operation_hash.t} let () = Environment.Error_monad.register_error_kind @@ -439,7 +443,24 @@ module Mempool = struct (req "operation_hash" Operation_hash.encoding) (req "operation_fee" Tez.encoding)) (function Manager_restriction {oph; fee} -> Some (oph, fee) | _ -> None) - (fun (oph, fee) -> Manager_restriction {oph; fee}) + (fun (oph, fee) -> Manager_restriction {oph; fee}) ; + Environment.Error_monad.register_error_kind + `Temporary + ~id:"prefilter.manager_drained" + ~title: + "Only one manager operation per manager per block allowed (drained)" + ~description: + "Only one manager operation per manager per block allowed (drained)" + ~pp:(fun ppf oph -> + Format.fprintf + ppf + "Only one manager operation per manager per block allowed (found \ + Drain_delegate operation %a which takes precedence)" + Operation_hash.pp + oph) + Data_encoding.(obj1 (req "operation_hash" Operation_hash.encoding)) + (function Manager_drained {oph} -> Some oph | _ -> None) + (fun oph -> Manager_drained {oph}) type Environment.Error_monad.error += | Manager_operation_replaced of { @@ -543,13 +564,18 @@ module Mempool = struct filter_state.op_prechecked_managers with | None -> `Fresh + | Some (Drained old_hash) -> + `Fail + (`Branch_delayed + [Environment.wrap_tzerror (Manager_drained {oph = old_hash})]) | Some - { - operation_hash = old_hash; - gas_limit = old_gas; - fee = old_fee; - weight = _; - } -> + (Manager_op + { + operation_hash = old_hash; + gas_limit = old_gas; + fee = old_fee; + weight = _; + }) -> (* Manager already seen: one manager per block limitation triggered. Can replace old operation if new operation's fees are better *) if @@ -1133,7 +1159,7 @@ module Mempool = struct (* Manager not seen yet, record it for next ops *) Signature.Public_key_hash.Map.add source - info + (Manager_op info) filter_state.op_prechecked_managers; operation_hash_to_manager = Operation_hash.Map.add oph source filter_state.operation_hash_to_manager @@ -1144,6 +1170,78 @@ module Mempool = struct min_prechecked_op_weight; } + let precheck_drain filter_state validation_state oph shell + ({contents; _} as protocol_data : Kind.drain_delegate protocol_data) + delegate ~nb_successful_prechecks = + let precheck_drain_and_check_signature ~on_success = + ( Main.precheck_drain validation_state contents >>=? fun () -> + let (raw_operation : Kind.drain_delegate operation) = + Alpha_context.{shell; protocol_data} + in + if Compare.Int.(nb_successful_prechecks > 0) then + (* Signature succesfully checked at least once. *) + return_unit + else + (* Signature probably never checked. *) + Main.check_drain_signature validation_state contents raw_operation ) + >|= function + | Ok () -> on_success + | Error err -> ( + let err = Environment.wrap_tztrace err in + match classify_trace err with + | Branch -> `Branch_refused err + | Permanent -> `Refused err + | Temporary -> `Branch_delayed err + | Outdated -> `Outdated err) + in + match + Signature.Public_key_hash.Map.find + delegate + filter_state.op_prechecked_managers + with + | None -> + let on_success = `Prechecked_drain `No_replace in + precheck_drain_and_check_signature ~on_success + | Some (Drained old_hash) -> + Lwt.return + (`Branch_delayed + [Environment.wrap_tzerror (Manager_drained {oph = old_hash})]) + | Some (Manager_op {operation_hash = old_oph; _}) -> + let err = + Environment.wrap_tzerror + @@ Manager_operation_replaced {old_hash = old_oph; new_hash = oph} + in + precheck_drain_and_check_signature + ~on_success:(`Prechecked_drain (`Replace (old_oph, `Outdated [err]))) + + let add_drain_restriction filter_state oph delegate replacement = + let filter_state = + match replacement with + | `No_replace -> filter_state + | `Replace (oph, _class) -> remove ~filter_state oph + in + let prechecked_operations_count = + if Operation_hash.Map.mem oph filter_state.operation_hash_to_manager then + filter_state.prechecked_operations_count + else filter_state.prechecked_operations_count + 1 + in + { + filter_state with + op_prechecked_managers = + (* Manager not seen yet, record it for next ops *) + Signature.Public_key_hash.Map.add + delegate + (Drained oph) + filter_state.op_prechecked_managers; + operation_hash_to_manager = + Operation_hash.Map.add + oph + delegate + filter_state.operation_hash_to_manager + (* Record which manager is used for the operation hash. *); + prechecked_operations_count; + } + let precheck : config -> filter_state:state -> @@ -1163,6 +1261,25 @@ module Mempool = struct oph {shell = shell_header; protocol_data = Operation_data protocol_data} ~nb_successful_prechecks -> + let precheck_drain protocol_data delegate = + precheck_drain + filter_state + validation_state + oph + shell_header + protocol_data + delegate + ~nb_successful_prechecks + >|= function + | `Prechecked_drain replacement -> + let filter_state = + add_drain_restriction filter_state oph delegate replacement + in + `Passed_precheck (filter_state, replacement) + | (`Refused _ | `Branch_delayed _ | `Branch_refused _ | `Outdated _) as + errs -> + errs + in let precheck_manager protocol_data source op = match get_manager_operation_gas_and_fee op with | Error err -> Lwt.return (`Refused (Environment.wrap_tztrace err)) @@ -1198,6 +1315,8 @@ module Mempool = struct errs) in match protocol_data.contents with + | Single (Drain_delegate {delegate; _}) -> + precheck_drain protocol_data delegate | Single (Manager_operation {source; _}) as op -> precheck_manager protocol_data source op | Cons (Manager_operation {source; _}, _) as op -> diff --git a/src/proto_alpha/lib_plugin/test/generators.ml b/src/proto_alpha/lib_plugin/test/generators.ml index 38d6e4e13509..367822582621 100644 --- a/src/proto_alpha/lib_plugin/test/generators.ml +++ b/src/proto_alpha/lib_plugin/test/generators.ml @@ -80,7 +80,7 @@ let filter_state_gen : Plugin.Mempool.state QCheck2.Gen.t = op_prechecked_managers = Signature.Public_key_hash.Map.add pkh - info + (Manager_op info) state.op_prechecked_managers; operation_hash_to_manager = Operation_hash.Map.add oph pkh state.operation_hash_to_manager; diff --git a/src/proto_alpha/lib_plugin/test/test_filter_state.ml b/src/proto_alpha/lib_plugin/test/test_filter_state.ml index 1a06a6762e87..f28f180505ee 100644 --- a/src/proto_alpha/lib_plugin/test/test_filter_state.ml +++ b/src/proto_alpha/lib_plugin/test/test_filter_state.ml @@ -95,7 +95,7 @@ let test_check_manager_restriction_fail = op_prechecked_managers = Signature.Public_key_hash.Map.add pkh - {op_info with fee = Alpha_context.Tez.one} + (Manager_op {op_info with fee = Alpha_context.Tez.one}) (* We force higher fee than below: [one > zero]. *) filter_state.op_prechecked_managers; } @@ -150,7 +150,7 @@ let test_check_manager_restriction_replace = op_prechecked_managers = Signature.Public_key_hash.Map.add pkh - op_info + (Manager_op op_info) filter_state.op_prechecked_managers; } in diff --git a/src/proto_alpha/lib_plugin/test/test_utils.ml b/src/proto_alpha/lib_plugin/test/test_utils.ml index cf25d367381e..d26e76f16cc6 100644 --- a/src/proto_alpha/lib_plugin/test/test_utils.ml +++ b/src/proto_alpha/lib_plugin/test/test_utils.ml @@ -40,18 +40,28 @@ let pp_prechecked_managers fmt set = Format.fprintf fmt "[%a]" - (Format.pp_print_list (fun ppf (pkh, (op_info : manager_op_info)) -> - Format.fprintf - ppf - "(%a -> (hash:%a,gas:%a,fee:%a))" - Signature.Public_key_hash.pp - pkh - Operation_hash.pp - op_info.operation_hash - Alpha_context.Gas.Arith.pp - op_info.gas_limit - Alpha_context.Tez.pp - op_info.fee)) + (Format.pp_print_list (fun ppf (pkh, info) -> + match info with + | Drained oph -> + Format.fprintf + ppf + "(%a -> (hash:%a,drained))" + Signature.Public_key_hash.pp + pkh + Operation_hash.pp + oph + | Manager_op op_info -> + Format.fprintf + ppf + "(%a -> (hash:%a,gas:%a,fee:%a))" + Signature.Public_key_hash.pp + pkh + Operation_hash.pp + op_info.operation_hash + Alpha_context.Gas.Arith.pp + op_info.gas_limit + Alpha_context.Tez.pp + op_info.fee)) (Signature.Public_key_hash.Map.bindings set) let pp_operation_hash_manager fmt map = @@ -113,13 +123,22 @@ let pp_state fmt state = state.min_prechecked_op_weight let eq_prechecked_managers = - Signature.Public_key_hash.Map.equal - (fun - ({operation_hash = oph1; gas_limit = _; fee = _; weight = _} : - manager_op_info) - ({operation_hash = oph2; gas_limit = _; fee = _; weight = _} : - manager_op_info) - -> Operation_hash.equal oph1 oph2) + Signature.Public_key_hash.Map.equal (fun op1 op2 -> + let oph1 = + match op1 with + | Drained oph1 + | Manager_op {operation_hash = oph1; gas_limit = _; fee = _; weight = _} + -> + oph1 + in + let oph2 = + match op2 with + | Drained oph2 + | Manager_op {operation_hash = oph2; gas_limit = _; fee = _; weight = _} + -> + oph2 + in + Operation_hash.equal oph1 oph2) (* This function needs to be updated if the filter state is extended *) let eq_state s1 s2 = -- GitLab From 6f8019376b1524d533dea6c9a56701a0e2e1d7ba Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Fri, 20 May 2022 17:46:00 +0200 Subject: [PATCH 34/48] Proto/Plugin: filter out `Drain_delegate` without enough fees --- src/proto_alpha/lib_plugin/plugin.ml | 24 ++++++++++++-- .../lib_protocol/alpha_context.mli | 2 ++ src/proto_alpha/lib_protocol/apply.ml | 9 ++--- src/proto_alpha/lib_protocol/apply.mli | 4 ++- .../lib_protocol/delegate_storage.ml | 8 +++-- .../lib_protocol/delegate_storage.mli | 2 ++ src/proto_alpha/lib_protocol/main.mli | 13 +++++++- .../_regressions/rpc/alpha.client.mempool.out | 33 ++++++++++++------- tezt/_regressions/rpc/alpha.proxy.mempool.out | 33 ++++++++++++------- 9 files changed, 95 insertions(+), 33 deletions(-) diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index 613a05a152b1..671409179316 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -104,6 +104,7 @@ module Mempool = struct minimal_fees : Tez.t; minimal_nanotez_per_gas_unit : nanotez; minimal_nanotez_per_byte : nanotez; + minimal_drain_fees : Tez.t; allow_script_failure : bool; (** If [true], this makes [post_filter_manager] unconditionally return [`Passed_postfilter filter_state], no matter the operation's @@ -125,6 +126,9 @@ module Mempool = struct let default_minimal_fees = match Tez.of_mutez 100L with None -> assert false | Some t -> t + let default_minimal_drain_fees = + match Tez.of_mutez 100L with None -> assert false | Some t -> t + let default_minimal_nanotez_per_gas_unit = Q.of_int 100 let default_minimal_nanotez_per_byte = Q.of_int 1000 @@ -146,6 +150,7 @@ module Mempool = struct minimal_fees = default_minimal_fees; minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit; minimal_nanotez_per_byte = default_minimal_nanotez_per_byte; + minimal_drain_fees = default_minimal_drain_fees; allow_script_failure = true; clock_drift = None; replace_by_fee_factor = @@ -159,6 +164,7 @@ module Mempool = struct conv (fun { minimal_fees; + minimal_drain_fees; minimal_nanotez_per_gas_unit; minimal_nanotez_per_byte; allow_script_failure; @@ -167,6 +173,7 @@ module Mempool = struct max_prechecked_manager_operations; } -> ( minimal_fees, + minimal_drain_fees, minimal_nanotez_per_gas_unit, minimal_nanotez_per_byte, allow_script_failure, @@ -174,6 +181,7 @@ module Mempool = struct replace_by_fee_factor, max_prechecked_manager_operations )) (fun ( minimal_fees, + minimal_drain_fees, minimal_nanotez_per_gas_unit, minimal_nanotez_per_byte, allow_script_failure, @@ -182,6 +190,7 @@ module Mempool = struct max_prechecked_manager_operations ) -> { minimal_fees; + minimal_drain_fees; minimal_nanotez_per_gas_unit; minimal_nanotez_per_byte; allow_script_failure; @@ -189,8 +198,12 @@ module Mempool = struct replace_by_fee_factor; max_prechecked_manager_operations; }) - (obj7 + (obj8 (dft "minimal_fees" Tez.encoding default_config.minimal_fees) + (dft + "minimal_drain_fees" + Tez.encoding + default_config.minimal_drain_fees) (dft "minimal_nanotez_per_gas_unit" nanotez_enc @@ -1170,11 +1183,15 @@ module Mempool = struct min_prechecked_op_weight; } - let precheck_drain filter_state validation_state oph shell + let precheck_drain config filter_state validation_state oph shell ({contents; _} as protocol_data : Kind.drain_delegate protocol_data) delegate ~nb_successful_prechecks = let precheck_drain_and_check_signature ~on_success = - ( Main.precheck_drain validation_state contents >>=? fun () -> + ( Main.precheck_drain validation_state contents >>=? fun fees -> + Environment.Error_monad.fail_when + Tez.(fees < config.minimal_drain_fees) + Fees_too_low + >>=? fun () -> let (raw_operation : Kind.drain_delegate operation) = Alpha_context.{shell; protocol_data} in @@ -1263,6 +1280,7 @@ module Mempool = struct ~nb_successful_prechecks -> let precheck_drain protocol_data delegate = precheck_drain + config filter_state validation_state oph diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 3871697f2768..a419c7d4a53c 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2226,6 +2226,8 @@ module Delegate : sig destination:public_key_hash -> (context * bool * Tez.t * Receipt.balance_updates) tzresult Lwt.t + val drain_fees : Tez.t -> Tez.t tzresult + type participation_info = { expected_cycle_activity : int; minimal_cycle_activity : int; diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index ba302df68c1e..2fd5a2d8eaf8 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2688,11 +2688,12 @@ let precheck_drain ctxt let cost_per_byte = Constants.cost_per_byte ctxt in let origination_size = Constants.origination_size ctxt in Tez.(cost_per_byte *? Int64.of_int origination_size)) - >>?= fun min_balance -> + >>?= fun allocation_burn -> Contract.get_balance ctxt (Contract.Implicit delegate) >>=? fun balance -> - if Tez.(balance < min_balance) then - fail (Invalid_drain_delegate_no_allocation_burn {delegate; destination}) - else return_unit + match Tez.(balance -? allocation_burn) with + | Error _ -> + fail (Invalid_drain_delegate_no_allocation_burn {delegate; destination}) + | Ok balance -> Lwt.return (Delegate.drain_fees balance) let check_drain_signature ctxt chain_id (Single (Drain_delegate {delegate; _})) raw_operation = diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index beacfae230e7..43403c38a898 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -212,9 +212,11 @@ val check_manager_signature : 'b operation -> unit tzresult Lwt.t +(** See [Main.precheck_drain] *) val precheck_drain : - context -> Kind.drain_delegate contents_list -> unit tzresult Lwt.t + context -> Kind.drain_delegate contents_list -> Tez.t tzresult Lwt.t +(** See [Main.check_drain_signature] *) val check_drain_signature : context -> Chain_id.t -> diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 38c2270529a0..c323433c11ca 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -315,6 +315,11 @@ let () = (function Invalid_drain -> Some () | _ -> None) (fun () -> Invalid_drain) +let drain_fees manager_balance = + let open Result_syntax in + let* one_percent = Tez_repr.(manager_balance /? 100L) in + return Tez_repr.(min one one_percent) + let drain ctxt ~delegate ~destination = let open Lwt_tzresult_syntax in let*! is_destination_allocated = @@ -329,8 +334,7 @@ let drain ctxt ~delegate ~destination = else return (ctxt, Z.zero, []) in let* manager_balance = balance ctxt delegate in - let*? one_percent = Tez_repr.(manager_balance /? 100L) in - let fees = Tez_repr.(min one one_percent) in + let*? fees = drain_fees manager_balance in let*? transfered = Tez_repr.(manager_balance -? fees) in let* ctxt, balance_updates2 = Token.transfer diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 3478986218b4..2b84244ce947 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -134,3 +134,5 @@ val drain : destination:Signature.Public_key_hash.t -> (Raw_context.t * bool * Tez_repr.t * Receipt_repr.balance_updates) tzresult Lwt.t + +val drain_fees : Tez_repr.t -> Tez_repr.t tzresult diff --git a/src/proto_alpha/lib_protocol/main.mli b/src/proto_alpha/lib_protocol/main.mli index 2cbb0aff5b23..59a051e9b23b 100644 --- a/src/proto_alpha/lib_protocol/main.mli +++ b/src/proto_alpha/lib_protocol/main.mli @@ -148,16 +148,27 @@ val precheck_manager : 'a Alpha_context.Kind.manager Alpha_context.contents_list -> unit tzresult Lwt.t +(** [check_drain_signature validation_state op raw_operation] + The function starts by retrieving the active consensus public key [pk] + of the delegate. + + @return [Error Invalid_signature] if the signature check fails +*) val check_drain_signature : validation_state -> Alpha_context.Kind.drain_delegate Alpha_context.contents_list -> Alpha_context.Kind.drain_delegate Alpha_context.operation -> unit tzresult Lwt.t +(** [precheck_drain validation_state op] returns the fees that will be + credited to the baker if the operation [op] is solveable, returns + an error otherwise. A drain operation is solveable if it is + well-formed and can pay for the potential allocation burn of the + destination account. This function uses [Apply.precheck_drain]. *) val precheck_drain : validation_state -> Alpha_context.Kind.drain_delegate Alpha_context.contents_list -> - unit tzresult Lwt.t + Alpha_context.Tez.t tzresult Lwt.t include Updater.PROTOCOL diff --git a/tezt/_regressions/rpc/alpha.client.mempool.out b/tezt/_regressions/rpc/alpha.client.mempool.out index 934e1b034237..e7c7756202cf 100644 --- a/tezt/_regressions/rpc/alpha.client.mempool.out +++ b/tezt/_regressions/rpc/alpha.client.mempool.out @@ -154,13 +154,15 @@ curl -s 'http://localhost:[PORT]/chains/main/mempool/monitor_operations?applied= [{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"},{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"0","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"permanent","id":"proto.alpha.prefilter.fees_too_low"}]},{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"branch","id":"proto.alpha.contract.counter_in_the_past","contract":"[PUBLIC_KEY_HASH]","expected":"2","found":"1"}]},{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"5","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"temporary","id":"proto.alpha.contract.counter_in_the_future","contract":"[PUBLIC_KEY_HASH]","expected":"1","found":"5"}]}] ./tezos-client rpc get /chains/main/mempool/filter -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } ./tezos-client rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } @@ -180,19 +182,22 @@ curl -s 'http://localhost:[PORT]/chains/main/mempool/monitor_operations?applied= ], "allow_script_failure": false }' -{ "minimal_fees": "50", "minimal_nanotez_per_gas_unit": [ "201", "5" ], +{ "minimal_fees": "50", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "201", "5" ], "minimal_nanotez_per_byte": [ "56", "3" ], "allow_script_failure": false, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } ./tezos-client rpc get /chains/main/mempool/filter -{ "minimal_fees": "50", "minimal_nanotez_per_gas_unit": [ "201", "5" ], +{ "minimal_fees": "50", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "201", "5" ], "minimal_nanotez_per_byte": [ "56", "3" ], "allow_script_failure": false, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } ./tezos-client rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "50", "minimal_nanotez_per_gas_unit": [ "201", "5" ], +{ "minimal_fees": "50", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "201", "5" ], "minimal_nanotez_per_byte": [ "56", "3" ], "allow_script_failure": false, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } @@ -205,19 +210,22 @@ curl -s 'http://localhost:[PORT]/chains/main/mempool/monitor_operations?applied= "minimal_fees": "200", "allow_script_failure": true }' -{ "minimal_fees": "200", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "200", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } ./tezos-client rpc get /chains/main/mempool/filter -{ "minimal_fees": "200", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "200", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } ./tezos-client rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "200", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "200", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } @@ -226,19 +234,22 @@ curl -s 'http://localhost:[PORT]/chains/main/mempool/monitor_operations?applied= { "minimal_fees": "200" } ./tezos-client rpc post /chains/main/mempool/filter with '{}' -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } ./tezos-client rpc get /chains/main/mempool/filter -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } ./tezos-client rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } diff --git a/tezt/_regressions/rpc/alpha.proxy.mempool.out b/tezt/_regressions/rpc/alpha.proxy.mempool.out index fd3289f9b28f..6ebc9200d13f 100644 --- a/tezt/_regressions/rpc/alpha.proxy.mempool.out +++ b/tezt/_regressions/rpc/alpha.proxy.mempool.out @@ -160,14 +160,16 @@ curl -s 'http://localhost:[PORT]/chains/main/mempool/monitor_operations?applied= [{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]"},{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"0","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"permanent","id":"proto.alpha.prefilter.fees_too_low"}]},{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"1","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"branch","id":"proto.alpha.contract.counter_in_the_past","contract":"[PUBLIC_KEY_HASH]","expected":"2","found":"1"}]},{"hash":"[OPERATION_HASH]","protocol":"ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK","branch":"[BRANCH_HASH]","contents":[{"kind":"transaction","source":"[PUBLIC_KEY_HASH]","fee":"1000","counter":"5","gas_limit":"1040","storage_limit":"257","amount":"1000000","destination":"[PUBLIC_KEY_HASH]"}],"signature":"[SIGNATURE]","error":[{"kind":"temporary","id":"proto.alpha.contract.counter_in_the_future","contract":"[PUBLIC_KEY_HASH]","expected":"1","found":"5"}]}] ./tezos-client --mode proxy rpc get /chains/main/mempool/filter -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } @@ -189,21 +191,24 @@ protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaAL ], "allow_script_failure": false }' -{ "minimal_fees": "50", "minimal_nanotez_per_gas_unit": [ "201", "5" ], +{ "minimal_fees": "50", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "201", "5" ], "minimal_nanotez_per_byte": [ "56", "3" ], "allow_script_failure": false, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc get /chains/main/mempool/filter -{ "minimal_fees": "50", "minimal_nanotez_per_gas_unit": [ "201", "5" ], +{ "minimal_fees": "50", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "201", "5" ], "minimal_nanotez_per_byte": [ "56", "3" ], "allow_script_failure": false, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "50", "minimal_nanotez_per_gas_unit": [ "201", "5" ], +{ "minimal_fees": "50", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "201", "5" ], "minimal_nanotez_per_byte": [ "56", "3" ], "allow_script_failure": false, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } @@ -218,21 +223,24 @@ protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaAL "minimal_fees": "200", "allow_script_failure": true }' -{ "minimal_fees": "200", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "200", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc get /chains/main/mempool/filter -{ "minimal_fees": "200", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "200", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "200", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "200", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } @@ -243,21 +251,24 @@ protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaAL protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc post /chains/main/mempool/filter with '{}' -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc get /chains/main/mempool/filter -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } protocol of proxy unspecified, using the node's protocol: ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK ./tezos-client --mode proxy rpc get '/chains/main/mempool/filter?include_default=true' -{ "minimal_fees": "100", "minimal_nanotez_per_gas_unit": [ "100", "1" ], +{ "minimal_fees": "100", "minimal_drain_fees": "100", + "minimal_nanotez_per_gas_unit": [ "100", "1" ], "minimal_nanotez_per_byte": [ "1000", "1" ], "allow_script_failure": true, "replace_by_fee_factor": [ "21", "20" ], "max_prechecked_manager_operations": 5000 } -- GitLab From f60da9c4c7d9b8494f0f23997873a31035f2679d Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 35/48] Proto: add a minimal `tezt` scenario for `Drain_delegate` --- tezt/lib_tezos/client.ml | 16 +++++ tezt/lib_tezos/client.mli | 12 ++++ tezt/tests/consensus_key.ml | 136 ++++++++++++++++++++++++------------ 3 files changed, 120 insertions(+), 44 deletions(-) diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 97ef5d74c31b..d045a6348f7f 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -913,6 +913,22 @@ let update_consensus_key ?hooks ?endpoint ?(wait = "none") ?burn_cap @ optional_arg "burn-cap" Tez.to_string burn_cap) |> Process.check ?expect_failure +let drain_delegate ?hooks ?endpoint ?(wait = "none") ?expect_failure ~delegate + ~consensus_key ?destination client = + let destination = + match destination with + | None -> [] + | Some destination -> [destination; "with"] + in + spawn_command + ?hooks + ?endpoint + client + (["--wait"; wait] + @ ["drain"; "delegate"; delegate; "to"] + @ destination @ [consensus_key]) + |> Process.check ?expect_failure + let spawn_originate_contract ?hooks ?log_output ?endpoint ?(wait = "none") ?init ?burn_cap ~alias ~amount ~src ~prg client = spawn_command diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index bd9c6679b847..7abaf1ec7bc1 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -748,6 +748,18 @@ val update_consensus_key : t -> unit Lwt.t +(** Run [tezos-client drain delegate with consensus key ] *) +val drain_delegate : + ?hooks:Process.hooks -> + ?endpoint:endpoint -> + ?wait:string -> + ?expect_failure:bool -> + delegate:string -> + consensus_key:string -> + ?destination: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 diff --git a/tezt/tests/consensus_key.ml b/tezt/tests/consensus_key.ml index 34576df6a454..6ee1ffc51045 100644 --- a/tezt/tests/consensus_key.ml +++ b/tezt/tests/consensus_key.ml @@ -98,6 +98,7 @@ let test_update_consensus_key = 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* destination = Client.gen_and_show_keys client in let* () = Client.transfer @@ -107,6 +108,22 @@ let test_update_consensus_key = ~receiver:key_b.alias client in + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:(Tez.of_int 1_000_000) + ~giver:Constant.bootstrap2.alias + ~receiver:key_c.alias + client + in + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:(Tez.of_int 1) + ~giver:Constant.bootstrap4.alias + ~receiver:destination.alias + client + in let* () = Client.bake_for_and_wait client in (* Trying multiple invalid updates: @@ -217,19 +234,6 @@ let test_update_consensus_key = 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 @@ -239,15 +243,10 @@ let test_update_consensus_key = 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 + ~pk:key_c.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 @@ -263,52 +262,101 @@ let test_update_consensus_key = } in - (* Bootstrap's accounts should not be able to bake anymore... *) + (* Invalid drain: unregistered delegate. *) let* () = - Client.bake_for + Client.drain_delegate ~expect_failure:true - ~keys:[Constant.bootstrap1.alias] + ~delegate:destination.alias + ~consensus_key:destination.alias + ~destination:destination.alias client in + + (* Invalid drain: bootstrap2 is has no custom consensus key. *) let* () = - Client.bake_for + Client.drain_delegate ~expect_failure:true - ~keys:[Constant.bootstrap2.alias] + ~delegate:Constant.bootstrap2.alias + ~consensus_key:Constant.bootstrap2.alias + ~destination:destination.alias client in + + (* Invalid drain: bootstrap2 is not the consensus key for bootstrap1. *) let* () = - Client.bake_for + Client.drain_delegate ~expect_failure:true - ~keys:[Constant.bootstrap3.alias] + ~delegate:Constant.bootstrap1.alias + ~consensus_key:Constant.bootstrap2.alias + ~destination:destination.alias client in + + (* Invalid drain: cannot drain to itself. *) let* () = - Client.bake_for + Client.drain_delegate ~expect_failure:true - ~keys:[Constant.bootstrap4.alias] + ~delegate:Constant.bootstrap4.alias + ~consensus_key:key_c.alias + ~destination:Constant.bootstrap4.alias client in + + let* old_balance = Client.get_balance_for ~account:destination.alias client in let* () = - Client.bake_for - ~expect_failure:true - ~keys:[Constant.bootstrap5.alias] + Client.drain_delegate + ~delegate:Constant.bootstrap4.alias + ~consensus_key:key_c.alias + ~destination:destination.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* () = Client.bake_for_and_wait ~keys:[Constant.bootstrap1.alias] client in + + (* The manager account has been drained... *) + let* b = Client.get_balance_for ~account:Constant.bootstrap4.alias client in + Check.((Tez.to_mutez b = 0) int) ~error_msg:"Manager balance is not empty" ; + + let* new_balance = Client.get_balance_for ~account:destination.alias client in + Check.((Tez.to_mutez old_balance < Tez.to_mutez new_balance) int) + ~error_msg:"Destination account has not been credited" ; + + (* Check if drain is prefered over a operation from the delegate... *) + let* old_balance5 = + Client.get_balance_for ~account:Constant.bootstrap5.alias client + in let* () = - check_current_level + Client.transfer + ~burn_cap:Tez.one + ~amount:(Tez.of_int 1) + ~giver:Constant.bootstrap3.alias + ~receiver:Constant.bootstrap5.alias client - { - level = 16; - level_position = 15; - cycle = 3; - cycle_position = 3; - expected_commitment = true; - } in + + let* old_balance = Client.get_balance_for ~account:destination.alias client in + let* () = + Client.drain_delegate + ~delegate:Constant.bootstrap3.alias + ~consensus_key:key_a.alias + ~destination:destination.alias + client + in + let* () = Client.bake_for_and_wait ~keys:[Constant.bootstrap1.alias] client in + + (* The manager account has been drained... *) + let* b = Client.get_balance_for ~account:Constant.bootstrap3.alias client in + Check.((Tez.to_mutez b = 0) int) ~error_msg:"Manager balance is not empty" ; + + let* new_balance5 = + Client.get_balance_for ~account:Constant.bootstrap5.alias client + in + Check.((Tez.to_mutez new_balance5 = Tez.to_mutez old_balance5) int) + ~error_msg:"Manager operation was included" ; + + let* new_balance = Client.get_balance_for ~account:destination.alias client in + Check.((Tez.to_mutez old_balance < Tez.to_mutez new_balance) int) + ~error_msg:"Destination account has not been credited" ; + unit let register ~protocols = test_update_consensus_key protocols -- GitLab From 13409d3449a83209174dbd0e6766a2d36f3eaa92 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 15:49:26 +0200 Subject: [PATCH 36/48] Proto/Per_block_vote: introduce `Toggle_vote_repr` --- src/lib_store/test/alpha_utils.ml | 4 +- src/proto_alpha/lib_client/mockup.ml | 2 +- .../lib_delegate/baking_commands.ml | 8 +-- .../lib_delegate/baking_configuration.ml | 7 +-- .../lib_delegate/baking_configuration.mli | 12 ++-- src/proto_alpha/lib_delegate/baking_events.ml | 8 +-- src/proto_alpha/lib_delegate/block_forge.mli | 4 +- .../lib_delegate/client_daemon.mli | 3 +- .../liquidity_baking_vote_file.ml | 6 +- src/proto_alpha/lib_plugin/plugin.ml | 9 ++- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 4 ++ .../lib_protocol/alpha_context.mli | 22 ++++--- src/proto_alpha/lib_protocol/apply.mli | 2 +- .../lib_protocol/block_header_repr.ml | 9 +-- .../lib_protocol/block_header_repr.mli | 3 +- src/proto_alpha/lib_protocol/dune | 5 ++ .../lib_protocol/liquidity_baking_repr.ml | 26 ++------ .../lib_protocol/liquidity_baking_repr.mli | 9 +-- .../lib_protocol/liquidity_baking_storage.mli | 2 +- src/proto_alpha/lib_protocol/main.ml | 4 +- .../lib_protocol/test/helpers/block.ml | 9 ++- .../lib_protocol/test/helpers/block.mli | 12 ++-- .../test/integration/test_liquidity_baking.ml | 60 ++++++++++--------- .../test/unit/test_liquidity_baking_repr.ml | 36 ++++++----- .../lib_protocol/toggle_vote_repr.ml | 39 ++++++++++++ .../lib_protocol/toggle_vote_repr.mli | 32 ++++++++++ 27 files changed, 191 insertions(+), 147 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_repr.ml create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_repr.mli diff --git a/src/lib_store/test/alpha_utils.ml b/src/lib_store/test/alpha_utils.ml index 31a14e77165b..0acb15307815 100644 --- a/src/lib_store/test/alpha_utils.ml +++ b/src/lib_store/test/alpha_utils.ml @@ -259,8 +259,8 @@ module Forge = struct let make_contents ~payload_hash ~payload_round ?(proof_of_work_nonce = default_proof_of_work_nonce) - ?(liquidity_baking_toggle_vote = Liquidity_baking.LB_pass) - ~seed_nonce_hash () = + ?(liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass) ~seed_nonce_hash + () = Block_header. { payload_hash; diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml index 24ff91f2262e..4a397e938ffd 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -1455,7 +1455,7 @@ let mem_init : seed_nonce_hash = None; proof_of_work_nonce; (* following Baking_configuration.toggle_votes in lib_delegate *) - liquidity_baking_toggle_vote = Liquidity_baking.LB_pass; + liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass; } in let unsigned_bytes = diff --git a/src/proto_alpha/lib_delegate/baking_commands.ml b/src/proto_alpha/lib_delegate/baking_commands.ml index eae0f2d4beda..c54c117c30b3 100644 --- a/src/proto_alpha/lib_delegate/baking_commands.ml +++ b/src/proto_alpha/lib_delegate/baking_commands.ml @@ -144,11 +144,11 @@ let keep_alive_arg = let liquidity_baking_toggle_vote_parameter = Clic.parameter ~autocomplete:(fun _ctxt -> return ["on"; "off"; "pass"]) - (let open Protocol.Alpha_context.Liquidity_baking in + (let open Protocol.Alpha_context.Toggle_vote in fun _ctxt -> function - | "on" -> return LB_on - | "off" -> return LB_off - | "pass" -> return LB_pass + | "on" -> return Toggle_on + | "off" -> return Toggle_off + | "pass" -> return Toggle_pass | s -> failwith "unexpected vote: %s, expected either \"on\", \"off\", or \"pass\"." diff --git a/src/proto_alpha/lib_delegate/baking_configuration.ml b/src/proto_alpha/lib_delegate/baking_configuration.ml index d7b24e86ddc7..0d1b9862cdd7 100644 --- a/src/proto_alpha/lib_delegate/baking_configuration.ml +++ b/src/proto_alpha/lib_delegate/baking_configuration.ml @@ -82,8 +82,7 @@ type t = { validation : validation_config; retries_on_failure : int; user_activated_upgrades : (int32 * Protocol_hash.t) list; - liquidity_baking_toggle_vote : - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote; + liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t; per_block_vote_file : string option; force : bool; state_recorder : state_recorder_config; @@ -109,7 +108,7 @@ let default_retries_on_failure_config = 5 let default_user_activated_upgrades = [] let default_liquidity_baking_toggle_vote = - Protocol.Alpha_context.Liquidity_baking.LB_pass + Protocol.Alpha_context.Toggle_vote.Toggle_pass let default_force = false @@ -224,7 +223,7 @@ let user_activate_upgrades_config_encoding = list (tup2 int32 Protocol_hash.encoding) let liquidity_baking_toggle_vote_config_encoding = - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote_encoding + Protocol.Alpha_context.Toggle_vote.encoding let force_config_encoding = Data_encoding.bool diff --git a/src/proto_alpha/lib_delegate/baking_configuration.mli b/src/proto_alpha/lib_delegate/baking_configuration.mli index bb90f6f5cf4a..1cbb0030fc51 100644 --- a/src/proto_alpha/lib_delegate/baking_configuration.mli +++ b/src/proto_alpha/lib_delegate/baking_configuration.mli @@ -57,8 +57,7 @@ type t = { validation : validation_config; retries_on_failure : int; user_activated_upgrades : (int32 * Protocol_hash.t) list; - liquidity_baking_toggle_vote : - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote; + liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t; per_block_vote_file : string option; force : bool; state_recorder : state_recorder_config; @@ -75,8 +74,7 @@ val default_retries_on_failure_config : int val default_user_activated_upgrades : (int32 * Protocol_hash.t) list -val default_liquidity_baking_toggle_vote : - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote +val default_liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t val default_force : bool @@ -96,8 +94,7 @@ val make : ?context_path:string -> ?retries_on_failure:int -> ?user_activated_upgrades:(int32 * Protocol_hash.t) list -> - ?liquidity_baking_toggle_vote: - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote -> + ?liquidity_baking_toggle_vote:Protocol.Alpha_context.Toggle_vote.t -> ?per_block_vote_file:string -> ?force:bool -> ?state_recorder:state_recorder_config -> @@ -117,8 +114,7 @@ val user_activate_upgrades_config_encoding : (int32 * Protocol_hash.t) list Data_encoding.t val liquidity_baking_toggle_vote_config_encoding : - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote - Data_encoding.t + Protocol.Alpha_context.Toggle_vote.t Data_encoding.t val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_delegate/baking_events.ml b/src/proto_alpha/lib_delegate/baking_events.ml index dd8506d8c7fc..c264f54f96f0 100644 --- a/src/proto_alpha/lib_delegate/baking_events.ml +++ b/src/proto_alpha/lib_delegate/baking_events.ml @@ -658,9 +658,7 @@ module Actions = struct ~name:"vote_for_liquidity_baking_toggle" ~level:Notice ~msg:"Voting {value} for liquidity baking toggle vote" - ( "value", - Protocol.Alpha_context.Liquidity_baking - .liquidity_baking_toggle_vote_encoding ) + ("value", Protocol.Alpha_context.Toggle_vote.encoding) end module Nonces = struct @@ -821,9 +819,7 @@ module Liquidity_baking = struct ~name:"liquidity_baking_toggle_vote" ~level:Notice ~msg:"liquidity baking toggle vote = {value}" - ( "value", - Protocol.Alpha_context.Liquidity_baking - .liquidity_baking_toggle_vote_encoding ) + ("value", Protocol.Alpha_context.Toggle_vote.encoding) let per_block_vote_file_fail = declare_1 diff --git a/src/proto_alpha/lib_delegate/block_forge.mli b/src/proto_alpha/lib_delegate/block_forge.mli index b111e27b417c..c1f65d222237 100644 --- a/src/proto_alpha/lib_delegate/block_forge.mli +++ b/src/proto_alpha/lib_delegate/block_forge.mli @@ -44,7 +44,7 @@ val forge_faked_protocol_data : ?payload_hash:Block_payload_hash.t -> payload_round:Round.t -> seed_nonce_hash:Nonce_hash.t option -> - liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + liquidity_baking_toggle_vote:Toggle_vote.t -> unit -> block_header_data @@ -53,7 +53,7 @@ val forge : chain_id:Chain_id.t -> pred_info:Baking_state.block_info -> timestamp:Time.Protocol.t -> - liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + liquidity_baking_toggle_vote:Toggle_vote.t -> user_activated_upgrades:User_activated.upgrades -> Baking_configuration.fees_config -> seed_nonce_hash:Nonce_hash.t option -> diff --git a/src/proto_alpha/lib_delegate/client_daemon.mli b/src/proto_alpha/lib_delegate/client_daemon.mli index 790d03cee1c2..91f26041d68e 100644 --- a/src/proto_alpha/lib_delegate/client_daemon.mli +++ b/src/proto_alpha/lib_delegate/client_daemon.mli @@ -32,8 +32,7 @@ module Baker : sig ?minimal_fees:Protocol.Alpha_context.Tez.t -> ?minimal_nanotez_per_gas_unit:Q.t -> ?minimal_nanotez_per_byte:Q.t -> - liquidity_baking_toggle_vote: - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote -> + liquidity_baking_toggle_vote:Protocol.Alpha_context.Toggle_vote.t -> ?per_block_vote_file:string -> ?extra_operations:Baking_configuration.Operations_source.t -> chain:Shell_services.chain -> diff --git a/src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml b/src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml index da49a169c1b0..d2b325558a52 100644 --- a/src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml +++ b/src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml @@ -27,8 +27,7 @@ open Protocol_client_context module Events = Baking_events.Liquidity_baking type per_block_votes = { - liquidity_baking_toggle_vote : - Protocol.Alpha_context.Liquidity_baking.liquidity_baking_toggle_vote option; + liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t option; } let per_block_votes_encoding = @@ -40,8 +39,7 @@ let per_block_votes_encoding = (obj1 (opt "liquidity_baking_toggle_vote" - Protocol.Alpha_context.Liquidity_baking - .liquidity_baking_toggle_vote_encoding)) + Protocol.Alpha_context.Toggle_vote.encoding)) type error += Block_vote_file_not_found of string diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index 671409179316..8be85e55d1e2 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -3684,11 +3684,10 @@ module RPC = struct "proof_of_work_nonce" (Fixed.bytes Alpha_context.Constants.proof_of_work_nonce_size) empty_proof_of_work_nonce) - Liquidity_baking.( - dft - "liquidity_baking_toggle_vote" - liquidity_baking_toggle_vote_encoding - LB_pass)) + (dft + "liquidity_baking_toggle_vote" + Toggle_vote.encoding + Toggle_pass)) ~output:(obj1 (req "protocol_data" bytes)) RPC_path.(path / "protocol_data") diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 104ed3a178a0..820a561857cb 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -28,6 +28,7 @@ "Fixed_point_repr", "Saturation_repr", "Gas_limit_repr", + "Toggle_vote_repr", "Constants_parametric_repr", "Constants_parametric_previous_repr", "Constants_repr", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 2292460c7489..c1a42e59c61d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -96,6 +96,10 @@ module Vote = struct include Vote_storage end +module Toggle_vote = struct + include Toggle_vote_repr +end + module Block_payload = struct include Block_payload_repr end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index a419c7d4a53c..cd57a976c91e 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -701,6 +701,14 @@ module Script : sig val strip_annotations : node -> node end +module Toggle_vote : sig + type t = Toggle_on | Toggle_off | Toggle_pass + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t +end + module Constants : sig (** Fixed constants *) type fixed @@ -2764,8 +2772,7 @@ module Block_header : sig payload_round : Round.t; seed_nonce_hash : Nonce_hash.t option; proof_of_work_nonce : bytes; - liquidity_baking_toggle_vote : - Liquidity_baking_repr.liquidity_baking_toggle_vote; + liquidity_baking_toggle_vote : Toggle_vote.t; } type protocol_data = {contents : contents; signature : signature} @@ -3545,15 +3552,6 @@ module Parameters : sig end module Liquidity_baking : sig - type liquidity_baking_toggle_vote = - Liquidity_baking_repr.liquidity_baking_toggle_vote = - | LB_on - | LB_off - | LB_pass - - val liquidity_baking_toggle_vote_encoding : - liquidity_baking_toggle_vote Data_encoding.encoding - val get_cpmm_address : context -> Contract_hash.t tzresult Lwt.t module Toggle_EMA : sig @@ -3568,7 +3566,7 @@ module Liquidity_baking : sig val on_subsidy_allowed : context -> - toggle_vote:liquidity_baking_toggle_vote -> + toggle_vote:Toggle_vote.t -> (context -> Contract_hash.t -> (context * 'a list) tzresult Lwt.t) -> (context * 'a list * Toggle_EMA.t) tzresult Lwt.t end diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index 43403c38a898..760f443ab459 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -48,7 +48,7 @@ type error += val begin_partial_construction : context -> predecessor_level:Level.t -> - toggle_vote:Liquidity_baking_repr.liquidity_baking_toggle_vote -> + toggle_vote:Toggle_vote.t -> (t * packed_successful_manager_operation_result list * Liquidity_baking.Toggle_EMA.t) diff --git a/src/proto_alpha/lib_protocol/block_header_repr.ml b/src/proto_alpha/lib_protocol/block_header_repr.ml index 39b6375d1afd..2d4a5b90ce9e 100644 --- a/src/proto_alpha/lib_protocol/block_header_repr.ml +++ b/src/proto_alpha/lib_protocol/block_header_repr.ml @@ -30,8 +30,7 @@ type contents = { payload_round : Round_repr.t; seed_nonce_hash : Nonce_hash.t option; proof_of_work_nonce : bytes; - liquidity_baking_toggle_vote : - Liquidity_baking_repr.liquidity_baking_toggle_vote; + liquidity_baking_toggle_vote : Toggle_vote_repr.t; } type protocol_data = {contents : contents; signature : Signature.t} @@ -103,9 +102,7 @@ let contents_encoding = "proof_of_work_nonce" (Fixed.bytes Constants_repr.proof_of_work_nonce_size)) (opt "seed_nonce_hash" Nonce_hash.encoding) - (req - "liquidity_baking_toggle_vote" - Liquidity_baking_repr.liquidity_baking_toggle_vote_encoding)) + (req "liquidity_baking_toggle_vote" Toggle_vote_repr.encoding)) let protocol_data_encoding = let open Data_encoding in @@ -164,7 +161,7 @@ let max_header_length = proof_of_work_nonce = Bytes.make Constants_repr.proof_of_work_nonce_size '0'; seed_nonce_hash = Some Nonce_hash.zero; - liquidity_baking_toggle_vote = LB_pass; + liquidity_baking_toggle_vote = Toggle_pass; } in Data_encoding.Binary.length diff --git a/src/proto_alpha/lib_protocol/block_header_repr.mli b/src/proto_alpha/lib_protocol/block_header_repr.mli index a84761403288..d79972b756a7 100644 --- a/src/proto_alpha/lib_protocol/block_header_repr.mli +++ b/src/proto_alpha/lib_protocol/block_header_repr.mli @@ -30,8 +30,7 @@ type contents = { payload_round : Round_repr.t; seed_nonce_hash : Nonce_hash.t option; proof_of_work_nonce : bytes; - liquidity_baking_toggle_vote : - Liquidity_baking_repr.liquidity_baking_toggle_vote; + liquidity_baking_toggle_vote : Toggle_vote_repr.t; } type protocol_data = {contents : contents; signature : Signature.t} diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 81a2f61ddd78..3975aee131be 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -59,6 +59,7 @@ Fixed_point_repr Saturation_repr Gas_limit_repr + Toggle_vote_repr Constants_parametric_repr Constants_parametric_previous_repr Constants_repr @@ -275,6 +276,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_repr.ml toggle_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -480,6 +482,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_repr.ml toggle_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -705,6 +708,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_repr.ml toggle_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -926,6 +930,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_repr.ml toggle_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml b/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml index 7a15716270cc..9b4e7800825d 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml @@ -24,25 +24,6 @@ (* *) (*****************************************************************************) -(** Options available for the Liquidity Baking per-block vote *) - -type liquidity_baking_toggle_vote = LB_on | LB_off | LB_pass - -let liquidity_baking_toggle_vote_encoding = - let of_int8 = function - | 0 -> Ok LB_on - | 1 -> Ok LB_off - | 2 -> Ok LB_pass - | _ -> Error "liquidity_baking_toggle_vote_of_int8" - in - let to_int8 = function LB_on -> 0 | LB_off -> 1 | LB_pass -> 2 in - let open Data_encoding in - (* union *) - def "liquidity_baking_toggle_vote" - @@ splitted - ~binary:(conv_with_guard to_int8 of_int8 int8) - ~json:(string_enum [("on", LB_on); ("off", LB_off); ("pass", LB_pass)]) - module Toggle_EMA : sig (* The exponential moving average is represented as an Int32 between 0l and 2_000_000_000l *) @@ -116,7 +97,8 @@ end (* Invariant: 0 <= ema <= 2_000_000 *) let compute_new_ema ~toggle_vote ema = + let open Toggle_vote_repr in match toggle_vote with - | LB_pass -> ema - | LB_off -> Toggle_EMA.update_ema_off ema - | LB_on -> Toggle_EMA.update_ema_on ema + | Toggle_pass -> ema + | Toggle_off -> Toggle_EMA.update_ema_off ema + | Toggle_on -> Toggle_EMA.update_ema_on ema diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli b/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli index a41f80d5835b..09b9a1e55469 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli @@ -24,13 +24,6 @@ (* *) (*****************************************************************************) -(** Options available for the Liquidity Baking per-block vote *) - -type liquidity_baking_toggle_vote = LB_on | LB_off | LB_pass - -val liquidity_baking_toggle_vote_encoding : - liquidity_baking_toggle_vote Data_encoding.encoding - (** Exponential moving average of toggle votes. Represented as an int32 between 0 and 2,000,000. It is an exponential moving average of the [LB_off] votes over a window of the most recent 2000 blocks that did not vote [LB_pass]. *) @@ -61,4 +54,4 @@ end rounded toward 1,000,000,000 (the middle of the interval). *) val compute_new_ema : - toggle_vote:liquidity_baking_toggle_vote -> Toggle_EMA.t -> Toggle_EMA.t + toggle_vote:Toggle_vote_repr.t -> Toggle_EMA.t -> Toggle_EMA.t diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli index 4db50c0a2536..ab2784be76f9 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli @@ -39,6 +39,6 @@ val get_cpmm_address : Raw_context.t -> Contract_hash.t tzresult Lwt.t see [apply_liquidity_baking_subsidy] in [apply.ml]. *) val on_subsidy_allowed : Raw_context.t -> - toggle_vote:Liquidity_baking_repr.liquidity_baking_toggle_vote -> + toggle_vote:Toggle_vote_repr.t -> (Raw_context.t -> Contract_hash.t -> (Raw_context.t * 'a list) tzresult Lwt.t) -> (Raw_context.t * 'a list * Liquidity_baking_repr.Toggle_EMA.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index d763dab346c2..d45949b43654 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -262,7 +262,7 @@ let begin_construction ~chain_id ~predecessor_context:ctxt | None -> Alpha_context.Fitness.round_from_raw predecessor_fitness >>?= fun predecessor_round -> - let toggle_vote = Alpha_context.Liquidity_baking.LB_pass in + let toggle_vote = Alpha_context.Toggle_vote.Toggle_pass in Apply.begin_partial_construction ctxt ~predecessor_level ~toggle_vote >>=? fun ( ctxt, liquidity_baking_operations_results, @@ -784,7 +784,7 @@ let init chain_id ctxt block_header = { payload_hash = Block_payload_hash.zero; payload_round = Alpha_context.Round.zero; - liquidity_baking_toggle_vote = Alpha_context.Liquidity_baking.LB_pass; + liquidity_baking_toggle_vote = Alpha_context.Toggle_vote.Toggle_pass; seed_nonce_hash = None; proof_of_work_nonce = Bytes.make Constants_repr.proof_of_work_nonce_size '0'; diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 7502ba0197d5..30d8cc1d355c 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -124,8 +124,8 @@ module Forge = struct let make_contents ?(proof_of_work_nonce = default_proof_of_work_nonce) ~payload_hash ~payload_round - ?(liquidity_baking_toggle_vote = Liquidity_baking.LB_pass) - ~seed_nonce_hash () = + ?(liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass) ~seed_nonce_hash + () = Block_header. { payload_hash; @@ -242,9 +242,8 @@ module Forge = struct (* compatibility only, needed by incremental *) let contents ?(proof_of_work_nonce = default_proof_of_work_nonce) - ?seed_nonce_hash - ?(liquidity_baking_toggle_vote = Liquidity_baking.LB_pass) ~payload_hash - ~payload_round () = + ?seed_nonce_hash ?(liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass) + ~payload_hash ~payload_round () = { Block_header.proof_of_work_nonce; seed_nonce_hash; diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index d19bece55353..def8cef48857 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -68,7 +68,7 @@ module Forge : sig val contents : ?proof_of_work_nonce:Bytes.t -> ?seed_nonce_hash:Nonce_hash.t -> - ?liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + ?liquidity_baking_toggle_vote:Toggle_vote.t -> payload_hash:Block_payload_hash.t -> payload_round:Round.t -> unit -> @@ -86,7 +86,7 @@ module Forge : sig ?policy:baker_policy -> ?timestamp:Timestamp.time -> ?operations:Operation.packed list -> - ?liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + ?liquidity_baking_toggle_vote:Toggle_vote.t -> t -> header tzresult Lwt.t @@ -189,7 +189,7 @@ val bake : ?timestamp:Timestamp.time -> ?operation:Operation.packed -> ?operations:Operation.packed list -> - ?liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + ?liquidity_baking_toggle_vote:Toggle_vote.t -> ?check_size:bool -> t -> t tzresult Lwt.t @@ -198,7 +198,7 @@ val bake : val bake_n : ?baking_mode:baking_mode -> ?policy:baker_policy -> - ?liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + ?liquidity_baking_toggle_vote:Toggle_vote.t -> int -> t -> block tzresult Lwt.t @@ -208,7 +208,7 @@ val bake_n : val bake_n_with_all_balance_updates : ?baking_mode:baking_mode -> ?policy:baker_policy -> - ?liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + ?liquidity_baking_toggle_vote:Toggle_vote.t -> int -> t -> (block * Alpha_context.Receipt.balance_updates) tzresult Lwt.t @@ -231,7 +231,7 @@ val bake_n_with_origination_results : val bake_n_with_liquidity_baking_toggle_ema : ?baking_mode:baking_mode -> ?policy:baker_policy -> - ?liquidity_baking_toggle_vote:Liquidity_baking.liquidity_baking_toggle_vote -> + ?liquidity_baking_toggle_vote:Toggle_vote.t -> int -> t -> (block * Alpha_context.Liquidity_baking.Toggle_EMA.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml index 78c42d5fce1b..765f70b8ae4e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml @@ -160,18 +160,18 @@ let liquidity_baking_toggle ~n_vote_on ~n_vote_off ~n_vote_pass expected_level >>=? fun liquidity_baking_subsidy -> let rec bake_stopping blk i = if i < expected_level then - Block.bake_n ~liquidity_baking_toggle_vote:LB_on n_vote_on blk + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_on n_vote_on blk >>=? fun blk -> - Block.bake_n ~liquidity_baking_toggle_vote:LB_off n_vote_off blk + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_off n_vote_off blk >>=? fun blk -> - Block.bake_n ~liquidity_baking_toggle_vote:LB_pass n_vote_pass blk + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass n_vote_pass blk >>=? fun blk -> bake_stopping blk (i + n_vote_on + n_vote_off + n_vote_pass) else return blk in bake_stopping blk 0 >>=? fun blk -> Context.Contract.balance (B blk) liquidity_baking >>=? fun balance -> - Block.bake_n ~liquidity_baking_toggle_vote:LB_pass bake_after blk + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass bake_after blk >>=? fun blk -> Assert.balance_is ~loc:__LOC__ (B blk) liquidity_baking balance >>=? fun () -> liquidity_baking_subsidy *? Int64.of_int (expected_level - 1) @@ -184,19 +184,19 @@ let liquidity_baking_toggle ~n_vote_on ~n_vote_off ~n_vote_pass expected_level expected_final_balance >>=? fun () -> return_unit -(* 100% of blocks have liquidity_baking_toggle_vote = LB_off *) +(* 100% of blocks have liquidity_baking_toggle_vote = Toggle_off *) let liquidity_baking_toggle_100 n () = liquidity_baking_toggle ~n_vote_on:0 ~n_vote_off:1 ~n_vote_pass:0 1386 n () -(* 80% of blocks have liquidity_baking_toggle_vote = LB_off *) +(* 80% of blocks have liquidity_baking_toggle_vote = Toggle_off *) let liquidity_baking_toggle_80 n () = liquidity_baking_toggle ~n_vote_on:1 ~n_vote_off:4 ~n_vote_pass:0 1963 n () -(* 60% of blocks have liquidity_baking_toggle_vote = LB_off *) +(* 60% of blocks have liquidity_baking_toggle_vote = Toggle_off *) let liquidity_baking_toggle_60 n () = liquidity_baking_toggle ~n_vote_on:2 ~n_vote_off:3 ~n_vote_pass:0 3583 n () -(* 50% of blocks have liquidity_baking_toggle_vote = LB_off. +(* 50% of blocks have liquidity_baking_toggle_vote = Toggle_off. Subsidy should not be stopped. *) let liquidity_baking_toggle_50 n () = Context.init1 ~consensus_threshold:0 () >>=? fun (blk, _contract) -> @@ -207,8 +207,8 @@ let liquidity_baking_toggle_50 n () = Context.Contract.balance (B blk) liquidity_baking >>=? fun old_balance -> let rec bake_50_percent_escaping blk i = if i < Int32.to_int sunset + n then - Block.bake ~liquidity_baking_toggle_vote:LB_on blk >>=? fun blk -> - Block.bake ~liquidity_baking_toggle_vote:LB_off blk >>=? fun blk -> + Block.bake ~liquidity_baking_toggle_vote:Toggle_on blk >>=? fun blk -> + Block.bake ~liquidity_baking_toggle_vote:Toggle_off blk >>=? fun blk -> bake_50_percent_escaping blk (i + 2) else return blk in @@ -225,24 +225,26 @@ let liquidity_baking_toggle_50 n () = expected_balance >>=? fun () -> return_unit -(* Test that the subsidy can restart if LB_on votes regain majority. - Bake n_votes with LB_off, check that the subsidy is paused, bake - n_votes with LB_on, check that the subsidy flows. +(* Test that the subsidy can restart if Toggle_on votes regain majority. + Bake n_votes with Toggle_off, check that the subsidy is paused, bake + n_votes with Toggle_on, check that the subsidy flows. *) let liquidity_baking_restart n_votes n () = Context.init1 ~consensus_threshold:0 () >>=? fun (blk, _contract) -> Context.get_liquidity_baking_cpmm_address (B blk) >>=? fun liquidity_baking -> let liquidity_baking = Alpha_context.Contract.Originated liquidity_baking in - Block.bake_n ~liquidity_baking_toggle_vote:LB_off n_votes blk >>=? fun blk -> + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_off n_votes blk + >>=? fun blk -> Context.Contract.balance (B blk) liquidity_baking >>=? fun balance_when_paused -> - Block.bake_n ~liquidity_baking_toggle_vote:LB_pass n blk >>=? fun blk -> + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass n blk >>=? fun blk -> Assert.balance_is ~loc:__LOC__ (B blk) liquidity_baking balance_when_paused >>=? fun () -> - Block.bake_n ~liquidity_baking_toggle_vote:LB_on n_votes blk >>=? fun blk -> + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_on n_votes blk + >>=? fun blk -> Context.Contract.balance (B blk) liquidity_baking >>=? fun balance_when_restarted -> - Block.bake_n ~liquidity_baking_toggle_vote:LB_pass n blk >>=? fun blk -> + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass n blk >>=? fun blk -> Context.get_liquidity_baking_subsidy (B blk) >>=? fun liquidity_baking_subsidy -> liquidity_baking_subsidy *? Int64.of_int n >>?= fun expected_balance -> @@ -260,9 +262,9 @@ let liquidity_baking_toggle_ema n_vote_on n_vote_off level bake_after Context.init1 ~consensus_threshold:0 () >>=? fun (blk, _contract) -> let rec bake_escaping blk i = if i < level then - Block.bake_n ~liquidity_baking_toggle_vote:LB_on n_vote_on blk + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_on n_vote_on blk >>=? fun blk -> - Block.bake_n ~liquidity_baking_toggle_vote:LB_off n_vote_off blk + Block.bake_n ~liquidity_baking_toggle_vote:Toggle_off n_vote_off blk >>=? fun blk -> bake_escaping blk (i + n_vote_on + n_vote_off) else return blk in @@ -481,47 +483,47 @@ let tests = `Quick (liquidity_baking_sunset_level 100); Tztest.tztest - "test liquidity baking toggle vote with 100% of bakers voting LB_off \ + "test liquidity baking toggle vote with 100% of bakers voting Toggle_off \ baking one block longer" `Quick (liquidity_baking_toggle_100 1); Tztest.tztest - "test liquidity baking toggle vote with 100% of bakers voting LB_off \ + "test liquidity baking toggle vote with 100% of bakers voting Toggle_off \ baking two blocks longer" `Quick (liquidity_baking_toggle_100 2); Tztest.tztest - "test liquidity baking toggle vote with 100% of bakers voting LB_off \ + "test liquidity baking toggle vote with 100% of bakers voting Toggle_off \ baking 100 blocks longer" `Quick (liquidity_baking_toggle_100 100); Tztest.tztest - "test liquidity baking toggle vote with 80% of bakers voting LB_off \ + "test liquidity baking toggle vote with 80% of bakers voting Toggle_off \ baking one block longer" `Quick (liquidity_baking_toggle_80 1); Tztest.tztest - "test liquidity baking toggle vote with 80% of bakers voting LB_off \ + "test liquidity baking toggle vote with 80% of bakers voting Toggle_off \ baking two blocks longer" `Quick (liquidity_baking_toggle_80 2); Tztest.tztest - "test liquidity baking toggle vote with 80% of bakers voting LB_off \ + "test liquidity baking toggle vote with 80% of bakers voting Toggle_off \ baking 100 blocks longer" `Quick (liquidity_baking_toggle_80 100); Tztest.tztest - "test liquidity baking toggle vote with 60% of bakers voting LB_off \ + "test liquidity baking toggle vote with 60% of bakers voting Toggle_off \ baking one block longer" `Quick (liquidity_baking_toggle_60 1); Tztest.tztest - "test liquidity baking toggle vote with 60% of bakers voting LB_off \ + "test liquidity baking toggle vote with 60% of bakers voting Toggle_off \ baking two blocks longer" `Quick (liquidity_baking_toggle_60 2); Tztest.tztest - "test liquidity baking toggle vote with 60% of bakers voting LB_off \ + "test liquidity baking toggle vote with 60% of bakers voting Toggle_off \ baking 100 blocks longer" `Quick (liquidity_baking_toggle_60 100); @@ -547,7 +549,7 @@ let tests = (liquidity_baking_restart 2000 1); Tztest.tztest "test liquidity baking toggle ema in block metadata is zero with no \ - bakers voting LB_off." + bakers voting Toggle_off." `Quick liquidity_baking_toggle_ema_zero; Tztest.tztest diff --git a/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml b/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml index ac40fa0600e8..a62d670461ac 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml @@ -98,7 +98,7 @@ let test_ema_pass () = ema_of_int32 old_ema >>=? fun ema -> Assert.equal_int32 ~loc:__LOC__ - (compute_new_ema ~toggle_vote:LB_pass ema) + (compute_new_ema ~toggle_vote:Toggle_pass ema) old_ema) ema_range @@ -107,7 +107,7 @@ let test_ema_in_bound_off () = List.iter_es (fun old_ema -> ema_of_int32 old_ema >>=? fun ema -> - let new_ema = compute_new_ema ~toggle_vote:LB_off ema in + let new_ema = compute_new_ema ~toggle_vote:Toggle_off ema in Assert.leq_int32 ~loc:__LOC__ 0l new_ema >>=? fun () -> Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) ema_range @@ -121,7 +121,7 @@ let test_ema_increases_off () = Assert.lt_int32 ~loc:__LOC__ old_ema - (compute_new_ema ~toggle_vote:LB_off ema)) + (compute_new_ema ~toggle_vote:Toggle_off ema)) (List.filter (fun ema -> Compare.Int32.(ema < 1_999_999_000l)) ema_range) (* Test that the increase in EMA caused by an Off vote is bounded by 1,000,000 *) @@ -131,7 +131,7 @@ let test_ema_increases_off_bound () = ema_of_int32 old_ema >>=? fun ema -> Assert.leq_int32 ~loc:__LOC__ - (Int32.sub (compute_new_ema ~toggle_vote:LB_off ema) old_ema) + (Int32.sub (compute_new_ema ~toggle_vote:Toggle_off ema) old_ema) 1_000_000l) ema_range @@ -140,7 +140,7 @@ let test_ema_in_bound_on () = List.iter_es (fun old_ema -> ema_of_int32 old_ema >>=? fun ema -> - let new_ema = compute_new_ema ~toggle_vote:LB_on ema in + let new_ema = compute_new_ema ~toggle_vote:Toggle_on ema in Assert.leq_int32 ~loc:__LOC__ 0l new_ema >>=? fun () -> Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) ema_range @@ -153,7 +153,7 @@ let test_ema_decreases_on () = ema_of_int32 old_ema >>=? fun ema -> Assert.lt_int32 ~loc:__LOC__ - (compute_new_ema ~toggle_vote:LB_on ema) + (compute_new_ema ~toggle_vote:Toggle_on ema) old_ema) (List.filter (fun ema -> Compare.Int32.(ema > 1000l)) ema_range) @@ -164,36 +164,40 @@ let test_ema_decreases_on_bound () = ema_of_int32 old_ema >>=? fun ema -> Assert.leq_int32 ~loc:__LOC__ - (Int32.sub (compute_new_ema ~toggle_vote:LB_on ema) old_ema) + (Int32.sub (compute_new_ema ~toggle_vote:Toggle_on ema) old_ema) 1_000_000l) ema_range (* Test that 1385 Off votes are needed to reach the threshold from 0. *) let test_ema_many_off () = - let open Liquidity_baking_repr in + let open Toggle_vote_repr in ema_of_int32 0l >>=? fun initial_ema -> Assert.leq_int32 ~loc:__LOC__ - (compute_new_ema_n (Stdlib.List.init 1385 (fun _ -> LB_off)) initial_ema) + (compute_new_ema_n + (Stdlib.List.init 1385 (fun _ -> Toggle_off)) + initial_ema) 1_000_000_000l >>=? fun () -> Assert.leq_int32 ~loc:__LOC__ 1_000_000_000l - (compute_new_ema_n (Stdlib.List.init 1386 (fun _ -> LB_off)) initial_ema) + (compute_new_ema_n + (Stdlib.List.init 1386 (fun _ -> Toggle_off)) + initial_ema) (* Test that 1385 On votes are needed to reach the threshold from the max value of the EMA (2,000,000,000). *) let test_ema_many_on () = - let open Liquidity_baking_repr in + let open Toggle_vote_repr in ema_of_int32 2_000_000_000l >>=? fun initial_ema -> Assert.leq_int32 ~loc:__LOC__ 1_000_000_000l - (compute_new_ema_n (Stdlib.List.init 1385 (fun _ -> LB_on)) initial_ema) + (compute_new_ema_n (Stdlib.List.init 1385 (fun _ -> Toggle_on)) initial_ema) >>=? fun () -> Assert.leq_int32 ~loc:__LOC__ - (compute_new_ema_n (Stdlib.List.init 1386 (fun _ -> LB_on)) initial_ema) + (compute_new_ema_n (Stdlib.List.init 1386 (fun _ -> Toggle_on)) initial_ema) 1_000_000_000l (* Test that the EMA update function is symmetric: @@ -207,8 +211,10 @@ let test_ema_symmetry () = let opposite_ema = Int32.(sub 2_000_000_000l ema) in ema_of_int32 ema >>=? fun ema -> ema_of_int32 opposite_ema >>=? fun opposite_ema -> - let new_ema = compute_new_ema ~toggle_vote:LB_on ema in - let new_opposite_ema = compute_new_ema ~toggle_vote:LB_off opposite_ema in + let new_ema = compute_new_ema ~toggle_vote:Toggle_on ema in + let new_opposite_ema = + compute_new_ema ~toggle_vote:Toggle_off opposite_ema + in Assert.equal_int32 ~loc:__LOC__ Int32.(add new_ema new_opposite_ema) diff --git a/src/proto_alpha/lib_protocol/toggle_vote_repr.ml b/src/proto_alpha/lib_protocol/toggle_vote_repr.ml new file mode 100644 index 000000000000..0f2cc2483005 --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_repr.ml @@ -0,0 +1,39 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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 t = Toggle_on | Toggle_off | Toggle_pass + +let encoding = + let open Data_encoding in + def "toggle_vote" + @@ string_enum [("on", Toggle_on); ("off", Toggle_off); ("pass", Toggle_pass)] + +let to_string = function + | Toggle_pass -> "pass" + | Toggle_off -> "off" + | Toggle_on -> "on" + +let pp ppf v = Format.pp_print_string ppf (to_string v) diff --git a/src/proto_alpha/lib_protocol/toggle_vote_repr.mli b/src/proto_alpha/lib_protocol/toggle_vote_repr.mli new file mode 100644 index 000000000000..a66b22df06df --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_repr.mli @@ -0,0 +1,32 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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. *) +(* *) +(*****************************************************************************) + +(** Options available for toggle votes *) +type t = Toggle_on | Toggle_off | Toggle_pass + +val pp : Format.formatter -> t -> unit + +val encoding : t Data_encoding.t -- GitLab From 8f33b892fc1d59d4c80f3c8b6e9b954321047f4b Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 15:52:48 +0200 Subject: [PATCH 37/48] Proto/Per_block_vote: introduce `Toggle_vote_ema_repr` --- src/proto_alpha/lib_client/mockup.ml | 8 +- .../lib_parameters/default_parameters.ml | 3 +- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 1 + .../lib_protocol/alpha_context.mli | 45 +++- src/proto_alpha/lib_protocol/apply.ml | 2 +- src/proto_alpha/lib_protocol/apply.mli | 10 +- src/proto_alpha/lib_protocol/apply_results.ml | 6 +- .../lib_protocol/apply_results.mli | 2 +- .../constants_parametric_previous_repr.ml | 6 +- .../constants_parametric_previous_repr.mli | 2 +- .../lib_protocol/constants_parametric_repr.ml | 6 +- .../constants_parametric_repr.mli | 2 +- .../lib_protocol/constants_storage.mli | 3 +- src/proto_alpha/lib_protocol/dune | 5 + .../liquidity_baking_migration.ml | 5 +- .../lib_protocol/liquidity_baking_repr.ml | 80 +------ .../lib_protocol/liquidity_baking_repr.mli | 22 +- .../lib_protocol/liquidity_baking_storage.ml | 10 +- .../lib_protocol/liquidity_baking_storage.mli | 2 +- src/proto_alpha/lib_protocol/main.ml | 2 +- src/proto_alpha/lib_protocol/main.mli | 2 +- src/proto_alpha/lib_protocol/storage.ml | 2 +- src/proto_alpha/lib_protocol/storage.mli | 4 +- .../lib_protocol/test/helpers/block.ml | 2 +- .../lib_protocol/test/helpers/block.mli | 2 +- .../test/integration/test_liquidity_baking.ml | 2 +- .../lib_protocol/test/unit/main.ml | 2 +- ...g_repr.ml => test_toggle_vote_ema_repr.ml} | 226 ++++++++---------- .../lib_protocol/toggle_vote_ema_repr.ml | 114 +++++++++ .../lib_protocol/toggle_vote_ema_repr.mli | 84 +++++++ 31 files changed, 395 insertions(+), 268 deletions(-) rename src/proto_alpha/lib_protocol/test/unit/{test_liquidity_baking_repr.ml => test_toggle_vote_ema_repr.ml} (56%) create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_ema_repr.ml create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_ema_repr.mli diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml index 4a397e938ffd..9891f4b7006b 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -57,7 +57,7 @@ module Protocol_constants_overrides = struct min_proposal_quorum : int32 option; liquidity_baking_subsidy : Tez.t option; liquidity_baking_sunset_level : int32 option; - liquidity_baking_toggle_ema_threshold : int32 option; + liquidity_baking_toggle_ema_threshold : Toggle_vote.Ema.t option; max_operations_time_to_live : int option; minimal_block_delay : Period.t option; delay_increment_per_round : Period.t option; @@ -325,7 +325,9 @@ module Protocol_constants_overrides = struct (opt "min_proposal_quorum" int32) (opt "liquidity_baking_subsidy" Tez.encoding) (opt "liquidity_baking_sunset_level" int32) - (opt "liquidity_baking_toggle_ema_threshold" int32) + (opt + "liquidity_baking_toggle_ema_threshold" + Toggle_vote.Ema.encoding) (opt "max_operations_time_to_live" int16) (opt "minimal_block_delay" Period.encoding) (opt "delay_increment_per_round" Period.encoding) @@ -712,7 +714,7 @@ module Protocol_constants_overrides = struct { name = "liquidity_baking_toggle_ema_threshold"; override_value = o.liquidity_baking_toggle_ema_threshold; - pp = pp_print_int32; + pp = Toggle_vote.Ema.pp; }; O { diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 334302db0e33..da725b9b7b1f 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -90,7 +90,8 @@ let constants_mainnet = liquidity_baking_sunset_level = 3_063_809l; (* 1/2 window size of 2000 blocks with precision of 1_000_000 for integer computation *) - liquidity_baking_toggle_ema_threshold = 1_000_000_000l; + liquidity_baking_toggle_ema_threshold = + Toggle_vote.Ema.Config.simple_off.default_threshold; (* The rationale behind the value of this constant is that an operation should be considered alive for about one hour: diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 820a561857cb..4b1aa47ae835 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -29,6 +29,7 @@ "Saturation_repr", "Gas_limit_repr", "Toggle_vote_repr", + "Toggle_vote_ema_repr", "Constants_parametric_repr", "Constants_parametric_previous_repr", "Constants_repr", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index c1a42e59c61d..e95c8e779cc6 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -97,6 +97,7 @@ module Vote = struct end module Toggle_vote = struct + module Ema = Toggle_vote_ema_repr include Toggle_vote_repr end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index cd57a976c91e..874d44d0d3c7 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -702,6 +702,35 @@ module Script : sig end module Toggle_vote : sig + module Ema : sig + include BASIC_DATA + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + + val min_value : t + + val max_value : t + + module Config : sig + type nonrec t = { + initial : t; + default_threshold : t; + update_ema_on : t -> t; + update_ema_off : t -> t; + } + + val simple_off : t + end + + module Internal_for_tests : sig + val to_int32 : t -> Int32.t + + val of_int32_exn : Int32.t -> t + end + end + type t = Toggle_on | Toggle_off | Toggle_pass val pp : Format.formatter -> t -> unit @@ -751,7 +780,7 @@ module Constants : sig min_proposal_quorum : int32; liquidity_baking_subsidy : Tez.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : int32; + liquidity_baking_toggle_ema_threshold : Toggle_vote.Ema.t; max_operations_time_to_live : int; minimal_block_delay : Period.t; delay_increment_per_round : Period.t; @@ -852,7 +881,7 @@ module Constants : sig val liquidity_baking_sunset_level : context -> int32 - val liquidity_baking_toggle_ema_threshold : context -> int32 + val liquidity_baking_toggle_ema_threshold : context -> Toggle_vote.Ema.t val minimal_block_delay : context -> Period.t @@ -3554,21 +3583,11 @@ end module Liquidity_baking : sig val get_cpmm_address : context -> Contract_hash.t tzresult Lwt.t - module Toggle_EMA : sig - type t - - val zero : t - - val to_int32 : t -> Int32.t - - val encoding : t Data_encoding.t - end - val on_subsidy_allowed : context -> toggle_vote:Toggle_vote.t -> (context -> Contract_hash.t -> (context * 'a list) tzresult Lwt.t) -> - (context * 'a list * Toggle_EMA.t) tzresult Lwt.t + (context * 'a list * Toggle_vote.Ema.t) tzresult Lwt.t end (** This module re-exports functions from [Ticket_storage]. See diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 2fd5a2d8eaf8..5ef5030f7747 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -3653,7 +3653,7 @@ type 'a full_construction = { 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; + liquidity_baking_toggle_ema : Toggle_vote.Ema.t; } let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index 760f443ab459..b60e6ef75827 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -49,9 +49,7 @@ val begin_partial_construction : context -> predecessor_level:Level.t -> toggle_vote:Toggle_vote.t -> - (t - * packed_successful_manager_operation_result list - * Liquidity_baking.Toggle_EMA.t) + (t * packed_successful_manager_operation_result list * Toggle_vote.Ema.t) tzresult Lwt.t @@ -62,7 +60,7 @@ type 'a full_construction = { 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; + liquidity_baking_toggle_ema : Toggle_vote.Ema.t; } val begin_full_construction : @@ -86,7 +84,7 @@ val begin_application : * Consensus_key.t * Consensus_key.t * packed_successful_manager_operation_result list - * Liquidity_baking.Toggle_EMA.t) + * Toggle_vote.Ema.t) tzresult Lwt.t @@ -136,7 +134,7 @@ val finalize_application : Block_header.contents -> payload_producer:Consensus_key.t -> block_producer:Consensus_key.t -> - Liquidity_baking.Toggle_EMA.t -> + Toggle_vote.Ema.t -> packed_successful_manager_operation_result list -> round:Round.t -> predecessor:Block_hash.t -> diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index fe097547cd6f..c3ac41813a36 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -3119,7 +3119,7 @@ type block_metadata = { consumed_gas : Gas.Arith.fp; deactivated : Signature.Public_key_hash.t list; balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Liquidity_baking.Toggle_EMA.t; + liquidity_baking_toggle_ema : Toggle_vote.Ema.t; implicit_operations_results : packed_successful_manager_operation_result list; } @@ -3184,9 +3184,7 @@ let block_metadata_encoding = (req "consumed_gas" Gas.Arith.n_fp_encoding) (req "deactivated" (list Signature.Public_key_hash.encoding)) (dft "balance_updates" Receipt.balance_updates_encoding []) - (req - "liquidity_baking_toggle_ema" - Liquidity_baking.Toggle_EMA.encoding) + (req "liquidity_baking_toggle_ema" Toggle_vote.Ema.encoding) (req "implicit_operations_results" (list successful_manager_operation_result_encoding))) diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 71a57aabb3f3..69dafba4f014 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -381,7 +381,7 @@ type block_metadata = { consumed_gas : Gas.Arith.fp; deactivated : Signature.Public_key_hash.t list; balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Liquidity_baking.Toggle_EMA.t; + liquidity_baking_toggle_ema : Toggle_vote.Ema.t; implicit_operations_results : packed_successful_manager_operation_result list; } diff --git a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml index 1cdbd9b2d5ac..fd1ce6f31e33 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.ml @@ -47,7 +47,7 @@ type t = { min_proposal_quorum : int32; liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : int32; + liquidity_baking_toggle_ema_threshold : Toggle_vote_ema_repr.t; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; delay_increment_per_round : Period_repr.t; @@ -285,7 +285,9 @@ let encoding = (req "min_proposal_quorum" int32) (req "liquidity_baking_subsidy" Tez_repr.encoding) (req "liquidity_baking_sunset_level" int32) - (req "liquidity_baking_toggle_ema_threshold" int32) + (req + "liquidity_baking_toggle_ema_threshold" + Toggle_vote_ema_repr.encoding) (req "max_operations_time_to_live" int16) (req "minimal_block_delay" Period_repr.encoding) (req "delay_increment_per_round" Period_repr.encoding) diff --git a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli index aa70452999d5..9849527eece7 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_previous_repr.mli @@ -47,7 +47,7 @@ type t = { min_proposal_quorum : int32; liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : int32; + liquidity_baking_toggle_ema_threshold : Toggle_vote_ema_repr.t; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; delay_increment_per_round : Period_repr.t; diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml index 4742a32eb545..a0878abca5bb 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -55,7 +55,7 @@ type t = { min_proposal_quorum : int32; liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : int32; + liquidity_baking_toggle_ema_threshold : Toggle_vote_ema_repr.t; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; delay_increment_per_round : Period_repr.t; @@ -319,7 +319,9 @@ let encoding = (req "min_proposal_quorum" int32) (req "liquidity_baking_subsidy" Tez_repr.encoding) (req "liquidity_baking_sunset_level" int32) - (req "liquidity_baking_toggle_ema_threshold" int32) + (req + "liquidity_baking_toggle_ema_threshold" + Toggle_vote_ema_repr.encoding) (req "max_operations_time_to_live" int16) (req "minimal_block_delay" Period_repr.encoding) (req "delay_increment_per_round" Period_repr.encoding) diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli index ee6722acc7c1..8dbb556fed7b 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -48,7 +48,7 @@ type t = { min_proposal_quorum : int32; liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : int32; + liquidity_baking_toggle_ema_threshold : Toggle_vote_ema_repr.t; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; delay_increment_per_round : Period_repr.t; diff --git a/src/proto_alpha/lib_protocol/constants_storage.mli b/src/proto_alpha/lib_protocol/constants_storage.mli index bcabda7717f0..df5c0a211554 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.mli +++ b/src/proto_alpha/lib_protocol/constants_storage.mli @@ -72,7 +72,8 @@ val liquidity_baking_subsidy : Raw_context.t -> Tez_repr.t val liquidity_baking_sunset_level : Raw_context.t -> int32 -val liquidity_baking_toggle_ema_threshold : Raw_context.t -> int32 +val liquidity_baking_toggle_ema_threshold : + Raw_context.t -> Toggle_vote_ema_repr.t val parametric : Raw_context.t -> Constants_parametric_repr.t diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 3975aee131be..dcf1c3222be9 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -60,6 +60,7 @@ Saturation_repr Gas_limit_repr Toggle_vote_repr + Toggle_vote_ema_repr Constants_parametric_repr Constants_parametric_previous_repr Constants_repr @@ -277,6 +278,7 @@ saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli + toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -483,6 +485,7 @@ saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli + toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -709,6 +712,7 @@ saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli + toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -931,6 +935,7 @@ saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli + toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml b/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml index 4f4d13dfa38e..79a63925c5a7 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml @@ -198,7 +198,10 @@ let init ctxt ~typecheck = (* We use a custom origination nonce because it is unset when stitching from 009 *) let nonce = Operation_hash.hash_string ["Drip, drip, drip."] in let ctxt = Raw_context.init_origination_nonce ctxt nonce in - Storage.Liquidity_baking.Toggle_ema.init ctxt 0l >>=? fun ctxt -> + Storage.Liquidity_baking.Toggle_ema.init + ctxt + Toggle_vote_ema_repr.Config.simple_off.initial + >>=? fun ctxt -> let current_level = Raw_level_repr.to_int32 (Level_storage.current ctxt).level in diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml b/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml index 9b4e7800825d..faf6d89a9883 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml @@ -24,81 +24,9 @@ (* *) (*****************************************************************************) -module Toggle_EMA : sig - (* The exponential moving average is represented as an Int32 between 0l and 2_000_000_000l *) - - type t - - val zero : t - - val of_int32 : Int32.t -> t tzresult Lwt.t - - val to_int32 : t -> Int32.t - - val update_ema_off : t -> t - - val update_ema_on : t -> t - - val ( < ) : t -> Int32.t -> bool - - val encoding : t Data_encoding.t -end = struct - type t = Int32.t (* Invariant 0 <= ema <= 2_000_000_000l *) - - (* This error is not registered because we don't expect it to be - raised. *) - type error += Liquidity_baking_toggle_ema_out_of_bound of Int32.t - - let check_bounds x = Compare.Int32.(0l <= x && x <= 2_000_000_000l) - - let of_int32 x = - if check_bounds x then return x - else fail @@ Liquidity_baking_toggle_ema_out_of_bound x - - let zero = Int32.zero - - (* The conv_with_guard combinator of Data_encoding expects a (_, string) result. *) - let of_int32_for_encoding x = - if check_bounds x then Ok x else Error "out of bounds" - - let to_int32 ema = ema - - (* We perform the computations in Z to avoid overflows. *) - - let z_1999 = Z.of_int 1999 - - let z_2000 = Z.of_int 2000 - - let attenuate z = Z.(div (mul z_1999 z) z_2000) - - let z_1_000_000_000 = Z.of_int 1_000_000_000 - - (* Outside of this module, the EMA is always between 0 and 2,000,000,000. - This [recenter] wrappers, puts it in between -1,000,000,000 and 1,000,000,000. - The goal of this recentering around zero is to make [update_ema_off] and - [update_ema_on] behave symmetrically with respect to rounding. *) - let recenter f ema = Z.(add z_1_000_000_000 (f (sub ema z_1_000_000_000))) - - let z_500_000 = Z.of_int 500_000 - - let update_ema_off ema = - let ema = Z.of_int32 ema in - recenter (fun ema -> Z.add (attenuate ema) z_500_000) ema |> Z.to_int32 - - let update_ema_on ema = - let ema = Z.of_int32 ema in - recenter (fun ema -> Z.sub (attenuate ema) z_500_000) ema |> Z.to_int32 - - let ( < ) = Compare.Int32.( < ) - - let encoding = - Data_encoding.(conv_with_guard to_int32 of_int32_for_encoding int32) -end - (* Invariant: 0 <= ema <= 2_000_000 *) let compute_new_ema ~toggle_vote ema = - let open Toggle_vote_repr in - match toggle_vote with - | Toggle_pass -> ema - | Toggle_off -> Toggle_EMA.update_ema_off ema - | Toggle_on -> Toggle_EMA.update_ema_on ema + Toggle_vote_ema_repr.update + Toggle_vote_ema_repr.Config.simple_off + toggle_vote + ema diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli b/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli index 09b9a1e55469..6f3676b3824d 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli @@ -24,24 +24,6 @@ (* *) (*****************************************************************************) -(** Exponential moving average of toggle votes. Represented as an int32 between - 0 and 2,000,000. It is an exponential moving average of the [LB_off] votes - over a window of the most recent 2000 blocks that did not vote [LB_pass]. *) - -module Toggle_EMA : sig - type t - - val of_int32 : Int32.t -> t tzresult Lwt.t - - val zero : t - - val to_int32 : t -> Int32.t - - val encoding : t Data_encoding.t - - val ( < ) : t -> Int32.t -> bool -end - (** [compute_new_ema ~toggle_vote old_ema] returns the value [new_ema] of the exponential moving average [old_ema] updated by the vote [toggle_vote]. @@ -54,4 +36,6 @@ end rounded toward 1,000,000,000 (the middle of the interval). *) val compute_new_ema : - toggle_vote:Toggle_vote_repr.t -> Toggle_EMA.t -> Toggle_EMA.t + toggle_vote:Toggle_vote_repr.t -> + Toggle_vote_ema_repr.t -> + Toggle_vote_ema_repr.t diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml index 0202241484b9..8b4b0d907018 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml @@ -28,9 +28,7 @@ open Liquidity_baking_repr let get_cpmm_address = Storage.Liquidity_baking.Cpmm_address.get -let get_toggle_ema ctxt = - Storage.Liquidity_baking.Toggle_ema.get ctxt >>=? fun ema -> - Toggle_EMA.of_int32 ema +let get_toggle_ema ctxt = Storage.Liquidity_baking.Toggle_ema.get ctxt let on_cpmm_exists ctxt f = get_cpmm_address ctxt >>=? fun cpmm_contract -> @@ -49,11 +47,11 @@ let check_below_sunset ctxt = let update_toggle_ema ctxt ~toggle_vote = get_toggle_ema ctxt >>=? fun old_ema -> let new_ema = compute_new_ema ~toggle_vote old_ema in - Storage.Liquidity_baking.Toggle_ema.update ctxt (Toggle_EMA.to_int32 new_ema) - >|=? fun ctxt -> (ctxt, new_ema) + Storage.Liquidity_baking.Toggle_ema.update ctxt new_ema >|=? fun ctxt -> + (ctxt, new_ema) let check_ema_below_threshold ctxt ema = - Toggle_EMA.( + Toggle_vote_ema_repr.( ema < Constants_storage.liquidity_baking_toggle_ema_threshold ctxt) let on_subsidy_allowed ctxt ~toggle_vote f = diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli index ab2784be76f9..0c5a288389e0 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli @@ -41,4 +41,4 @@ val on_subsidy_allowed : Raw_context.t -> toggle_vote:Toggle_vote_repr.t -> (Raw_context.t -> Contract_hash.t -> (Raw_context.t * 'a list) tzresult Lwt.t) -> - (Raw_context.t * 'a list * Liquidity_baking_repr.Toggle_EMA.t) tzresult Lwt.t + (Raw_context.t * 'a list * Toggle_vote_ema_repr.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index d45949b43654..571ac12c8264 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -132,7 +132,7 @@ type validation_state = { ctxt : Alpha_context.t; op_count : int; migration_balance_updates : Alpha_context.Receipt.balance_updates; - liquidity_baking_toggle_ema : Alpha_context.Liquidity_baking.Toggle_EMA.t; + liquidity_baking_toggle_ema : Alpha_context.Toggle_vote.Ema.t; implicit_operations_results : Apply_results.packed_successful_manager_operation_result list; } diff --git a/src/proto_alpha/lib_protocol/main.mli b/src/proto_alpha/lib_protocol/main.mli index 59a051e9b23b..da2a30c7094c 100644 --- a/src/proto_alpha/lib_protocol/main.mli +++ b/src/proto_alpha/lib_protocol/main.mli @@ -104,7 +104,7 @@ type validation_state = { ctxt : Alpha_context.t; op_count : int; migration_balance_updates : Alpha_context.Receipt.balance_updates; - liquidity_baking_toggle_ema : Alpha_context.Liquidity_baking.Toggle_EMA.t; + liquidity_baking_toggle_ema : Alpha_context.Toggle_vote.Ema.t; implicit_operations_results : Apply_results.packed_successful_manager_operation_result list; } diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 66292f67b43f..ece71e4f66fa 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1417,7 +1417,7 @@ module Liquidity_baking = struct (* The old "escape" name is kept here to avoid migrating this. *) let name = ["liquidity_baking_escape_ema"] end) - (Encoding.Int32) + (Toggle_vote_ema_repr) module Cpmm_address = Make_single_data_storage (Registered) (Raw_context) diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 6f216f99a6ca..01718440bace 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -561,7 +561,9 @@ module Liquidity_baking : sig The liquidity baking subsidy is not sent to the CPMM if this EMA is above the threshold set in constants. **) module Toggle_ema : - Single_data_storage with type t := Raw_context.t and type value = Int32.t + Single_data_storage + with type t := Raw_context.t + and type value = Toggle_vote_ema_repr.t (** Constant product market maker contract that receives liquidity baking subsidy. **) module Cpmm_address : diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 30d8cc1d355c..8969ebec24c2 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -817,7 +817,7 @@ let bake_n_with_origination_results ?(baking_mode = Application) ?policy n b = let bake_n_with_liquidity_baking_toggle_ema ?(baking_mode = Application) ?policy ?liquidity_baking_toggle_vote n b = - let initial_ema = Liquidity_baking.Toggle_EMA.zero in + let initial_ema = Toggle_vote.Ema.Internal_for_tests.of_int32_exn 0l in List.fold_left_es (fun (b, _toggle_ema) _ -> bake_with_metadata ~baking_mode ?policy ?liquidity_baking_toggle_vote b diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index def8cef48857..9919b6dc363f 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -234,7 +234,7 @@ val bake_n_with_liquidity_baking_toggle_ema : ?liquidity_baking_toggle_vote:Toggle_vote.t -> int -> t -> - (block * Alpha_context.Liquidity_baking.Toggle_EMA.t) tzresult Lwt.t + (block * Alpha_context.Toggle_vote.Ema.t) tzresult Lwt.t val current_cycle : t -> Cycle.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml index 765f70b8ae4e..ff1ae71a9f4e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml @@ -274,7 +274,7 @@ let liquidity_baking_toggle_ema n_vote_on n_vote_off level bake_after >>=? fun (_blk, toggle_ema) -> Assert.leq_int ~loc:__LOC__ - (toggle_ema |> Alpha_context.Liquidity_baking.Toggle_EMA.to_int32 + (toggle_ema |> Alpha_context.Toggle_vote.Ema.Internal_for_tests.to_int32 |> Int32.to_int) expected_toggle_ema >>=? fun () -> return_unit diff --git a/src/proto_alpha/lib_protocol/test/unit/main.ml b/src/proto_alpha/lib_protocol/test/unit/main.ml index 42bc5a90aa75..8bf22188ff12 100644 --- a/src/proto_alpha/lib_protocol/test/unit/main.ml +++ b/src/proto_alpha/lib_protocol/test/unit/main.ml @@ -71,7 +71,7 @@ let () = Unit_test.spec "Sc_rollup_storage.ml" Test_sc_rollup_storage.tests; Unit_test.spec "tx rollup l2" Test_tx_rollup_l2.tests; Unit_test.spec "tx rollup l2 apply" Test_tx_rollup_l2_apply.tests; - Unit_test.spec "liquidity baking" Test_liquidity_baking_repr.tests; + Unit_test.spec "toggle vote ema" Test_toggle_vote_ema_repr.tests; Unit_test.spec "sc rollup arith" Test_sc_rollup_arith.tests; Unit_test.spec "merkle list" Test_merkle_list.tests; Unit_test.spec "sc rollup inbox" Test_sc_rollup_inbox.tests; diff --git a/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml b/src/proto_alpha/lib_protocol/test/unit/test_toggle_vote_ema_repr.ml similarity index 56% rename from src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml rename to src/proto_alpha/lib_protocol/test/unit/test_toggle_vote_ema_repr.ml index a62d670461ac..8cc1cef81f36 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_liquidity_baking_repr.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_toggle_vote_ema_repr.ml @@ -25,180 +25,165 @@ (** Testing ------- - Component: Protocol Liquidity_baking_repr module + Component: Protocol Toggle_vote_ema_repr module Invocation: dune exec src/proto_alpha/lib_protocol/test/unit/main.exe \ - -- test "^\[Unit\] liquidity baking$" - Subject: Tests for the Liquidity_baking_repr module + -- test "^\[Unit\] toggle vote ema" + Subject: Tests for the Toggle_vote_ema_repr module *) open Protocol +open Toggle_vote_repr -let ema_of_int32 ema = - Liquidity_baking_repr.Toggle_EMA.of_int32 ema >|= Environment.wrap_tzresult +module Ema = struct + include Toggle_vote_ema_repr + include Internal_for_tests +end -let ema_to_int32 = Liquidity_baking_repr.Toggle_EMA.to_int32 +let update = Ema.(update Config.simple_off) -let compute_new_ema ~toggle_vote ema = - Liquidity_baking_repr.compute_new_ema ~toggle_vote ema |> ema_to_int32 - -(* Folds compute_new_ema on a list of votes *) -let compute_new_ema_n toggle_votes initial_ema = +(* Folds [update] on a list of votes *) +let update_n toggle_votes initial_ema = List.fold_left - (fun ema toggle_vote -> - Liquidity_baking_repr.compute_new_ema ~toggle_vote ema) + (fun ema toggle_vote -> update toggle_vote ema) initial_ema toggle_votes - |> ema_to_int32 let ema_range = - [ - 0l; - 1l; - 10l; - 100l; - 1000l; - 10_000l; - 100_000l; - 1_000_000l; - 10_000_000l; - 100_000_000l; - 200_000_000l; - 300_000_000l; - 400_000_000l; - 500_000_000l; - 600_000_000l; - 760_000_000l; - 800_000_000l; - 900_000_000l; - 1_000_000_000l; - 1_100_000_000l; - 1_200_000_000l; - 1_300_000_000l; - 1_400_000_000l; - 1_500_000_000l; - 1_600_000_000l; - 1_700_000_000l; - 1_800_000_000l; - 1_900_000_000l; - 1_990_000_000l; - 1_999_000_000l; - 1_999_900_000l; - 1_999_990_000l; - 1_999_999_000l; - 1_999_999_900l; - 1_999_999_990l; - 1_999_999_999l; - 2_000_000_000l; - ] + List.map + Ema.Internal_for_tests.of_int32_exn + [ + 0l; + 1l; + 10l; + 100l; + 1000l; + 10_000l; + 100_000l; + 1_000_000l; + 10_000_000l; + 100_000_000l; + 200_000_000l; + 300_000_000l; + 400_000_000l; + 500_000_000l; + 600_000_000l; + 760_000_000l; + 800_000_000l; + 900_000_000l; + 1_000_000_000l; + 1_100_000_000l; + 1_200_000_000l; + 1_300_000_000l; + 1_400_000_000l; + 1_500_000_000l; + 1_600_000_000l; + 1_700_000_000l; + 1_800_000_000l; + 1_900_000_000l; + 1_990_000_000l; + 1_999_000_000l; + 1_999_900_000l; + 1_999_990_000l; + 1_999_999_000l; + 1_999_999_900l; + 1_999_999_990l; + 1_999_999_999l; + 2_000_000_000l; + ] + +module Assert = struct + include Assert + + let equal_ema ~__LOC__ ?(msg = "") a b = + equal ~loc:__LOC__ Ema.equal (msg ^ "EMA aren't equal") Ema.pp a b + + let leq_ema ~__LOC__ ?(msg = "") a b = + leq ~loc:__LOC__ Ema.compare (msg ^ "EMA comparison") Ema.pp a b + + let lt_ema ~__LOC__ ?(msg = "") a b = + lt ~loc:__LOC__ Ema.compare (msg ^ "EMA comparison") Ema.pp a b + + let in_range_ema ~__LOC__ ?(msg = "") a = + leq ~loc:__LOC__ Ema.compare (msg ^ "EMA comparison") Ema.pp Ema.min_value a + >>=? fun () -> + leq ~loc:__LOC__ Ema.compare (msg ^ "EMA comparison") Ema.pp a Ema.max_value +end (* Test that new_ema = old_ema when voting Pass. *) let test_ema_pass () = List.iter_es - (fun old_ema -> - ema_of_int32 old_ema >>=? fun ema -> - Assert.equal_int32 - ~loc:__LOC__ - (compute_new_ema ~toggle_vote:Toggle_pass ema) - old_ema) + (fun ema -> Assert.equal_ema ~__LOC__ (update Toggle_pass ema) ema) ema_range (* Test that new_ema is still between 0 and 2,000,000,000 after an Off vote. *) let test_ema_in_bound_off () = List.iter_es - (fun old_ema -> - ema_of_int32 old_ema >>=? fun ema -> - let new_ema = compute_new_ema ~toggle_vote:Toggle_off ema in - Assert.leq_int32 ~loc:__LOC__ 0l new_ema >>=? fun () -> - Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) + (fun ema -> Assert.in_range_ema ~__LOC__ (update Toggle_off ema)) ema_range (* Test that new_ema > old_ema when voting Off, except if old_ema is already very close to the upper bound. *) let test_ema_increases_off () = List.iter_es - (fun old_ema -> - ema_of_int32 old_ema >>=? fun ema -> - Assert.lt_int32 - ~loc:__LOC__ - old_ema - (compute_new_ema ~toggle_vote:Toggle_off ema)) - (List.filter (fun ema -> Compare.Int32.(ema < 1_999_999_000l)) ema_range) + (fun ema -> Assert.lt_ema ~__LOC__ ema (update Toggle_off ema)) + (List.filter (fun ema -> Ema.(ema < of_int32_exn 1_999_999_000l)) ema_range) (* Test that the increase in EMA caused by an Off vote is bounded by 1,000,000 *) let test_ema_increases_off_bound () = List.iter_es - (fun old_ema -> - ema_of_int32 old_ema >>=? fun ema -> + (fun ema -> Assert.leq_int32 ~loc:__LOC__ - (Int32.sub (compute_new_ema ~toggle_vote:Toggle_off ema) old_ema) + (Int32.sub (Ema.to_int32 (update Toggle_off ema)) (Ema.to_int32 ema)) 1_000_000l) ema_range (* Test that new_ema is still between 0 and 2,000,000,000 after an Off vote. *) let test_ema_in_bound_on () = List.iter_es - (fun old_ema -> - ema_of_int32 old_ema >>=? fun ema -> - let new_ema = compute_new_ema ~toggle_vote:Toggle_on ema in - Assert.leq_int32 ~loc:__LOC__ 0l new_ema >>=? fun () -> - Assert.leq_int32 ~loc:__LOC__ new_ema 2_000_000_000l) + (fun ema -> Assert.in_range_ema ~__LOC__ (update Toggle_on ema)) ema_range (* Test that new_ema < old_ema when voting On, except if old_ema is already very close to the lower bound. *) let test_ema_decreases_on () = List.iter_es - (fun old_ema -> - ema_of_int32 old_ema >>=? fun ema -> - Assert.lt_int32 - ~loc:__LOC__ - (compute_new_ema ~toggle_vote:Toggle_on ema) - old_ema) - (List.filter (fun ema -> Compare.Int32.(ema > 1000l)) ema_range) + (fun ema -> Assert.lt_ema ~__LOC__ (update Toggle_on ema) ema) + (List.filter (fun ema -> Ema.(of_int32_exn 1000l < ema)) ema_range) (* Test that the decrease in EMA caused by an On vote is bounded by 1,000,000 *) let test_ema_decreases_on_bound () = List.iter_es - (fun old_ema -> - ema_of_int32 old_ema >>=? fun ema -> + (fun ema -> Assert.leq_int32 ~loc:__LOC__ - (Int32.sub (compute_new_ema ~toggle_vote:Toggle_on ema) old_ema) + (Int32.sub (Ema.to_int32 ema) (Ema.to_int32 (update Toggle_on ema))) 1_000_000l) ema_range (* Test that 1385 Off votes are needed to reach the threshold from 0. *) let test_ema_many_off () = - let open Toggle_vote_repr in - ema_of_int32 0l >>=? fun initial_ema -> - Assert.leq_int32 - ~loc:__LOC__ - (compute_new_ema_n - (Stdlib.List.init 1385 (fun _ -> Toggle_off)) - initial_ema) - 1_000_000_000l + let ema = + update_n + (Stdlib.List.init 1385 (fun _ -> Toggle_off)) + Ema.Config.simple_off.initial + in + Assert.leq_ema ~__LOC__ ema Ema.Config.simple_off.default_threshold >>=? fun () -> - Assert.leq_int32 - ~loc:__LOC__ - 1_000_000_000l - (compute_new_ema_n - (Stdlib.List.init 1386 (fun _ -> Toggle_off)) - initial_ema) + let ema = update Toggle_off ema in + Assert.leq_ema ~__LOC__ Ema.Config.simple_off.default_threshold ema + >>=? fun () -> return_unit (* Test that 1385 On votes are needed to reach the threshold from the max value of the EMA (2,000,000,000). *) let test_ema_many_on () = - let open Toggle_vote_repr in - ema_of_int32 2_000_000_000l >>=? fun initial_ema -> - Assert.leq_int32 - ~loc:__LOC__ - 1_000_000_000l - (compute_new_ema_n (Stdlib.List.init 1385 (fun _ -> Toggle_on)) initial_ema) + let ema = + update_n (Stdlib.List.init 1385 (fun _ -> Toggle_on)) Ema.max_value + in + Assert.leq_ema ~__LOC__ Ema.Config.simple_off.default_threshold ema >>=? fun () -> - Assert.leq_int32 - ~loc:__LOC__ - (compute_new_ema_n (Stdlib.List.init 1386 (fun _ -> Toggle_on)) initial_ema) - 1_000_000_000l + let ema = update Toggle_on ema in + Assert.leq_ema ~__LOC__ ema Ema.Config.simple_off.default_threshold + >>=? fun () -> return_unit (* Test that the EMA update function is symmetric: from two dual values of the EMA (that is, two values x and y such that @@ -208,17 +193,16 @@ let test_ema_many_on () = let test_ema_symmetry () = List.iter_es (fun ema -> - let opposite_ema = Int32.(sub 2_000_000_000l ema) in - ema_of_int32 ema >>=? fun ema -> - ema_of_int32 opposite_ema >>=? fun opposite_ema -> - let new_ema = compute_new_ema ~toggle_vote:Toggle_on ema in - let new_opposite_ema = - compute_new_ema ~toggle_vote:Toggle_off opposite_ema + let opposite_ema = + Ema.of_int32_exn + Int32.(sub (Ema.to_int32 Ema.max_value) (Ema.to_int32 ema)) in Assert.equal_int32 ~loc:__LOC__ - Int32.(add new_ema new_opposite_ema) - 2_000_000_000l) + (Int32.add + (Ema.to_int32 (update Toggle_on ema)) + (Ema.to_int32 (update Toggle_off opposite_ema))) + (Ema.to_int32 Ema.max_value)) ema_range let tests = diff --git a/src/proto_alpha/lib_protocol/toggle_vote_ema_repr.ml b/src/proto_alpha/lib_protocol/toggle_vote_ema_repr.ml new file mode 100644 index 000000000000..31bc2ffbbd0a --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_ema_repr.ml @@ -0,0 +1,114 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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. *) +(* *) +(*****************************************************************************) + +include Compare.Int32 (* Invariant 0 <= ema <= 2_000_000_000l *) + +let pp ppf = Format.fprintf ppf "%ld" + +let min_value = 0l + +let max_value = 2_000_000_000l + +let check_bounds x = min_value <= x && x <= max_value + +let of_int32_exn x = if check_bounds x then x else assert false + +let of_int32_err x = + if check_bounds x then Ok x + else Error "Toggle_vote.EMA.of_int32: out of bounds" + +let to_int32 ema = ema + +(* We perform the computations in Z to avoid overflows. *) + +let z_1_000_000_000 = Z.of_int 1_000_000_000 + +(* Outside of this module, the EMA is always between 0 and 2,000,000,000. + This [centered_z_update f ema] wrappers, puts it in between + -1,000,000,000 and 1,000,000,000 before calling [f] and + shifting the result back into 0 and 2,000,000,000. + The goal of this recentering around zero is to make + [update_ema_off] and [update_ema_on] behave symmetrically + with respect to rounding. *) +let centered_z_update f ema = + let res = + Z.( + to_int32 (add z_1_000_000_000 (f (sub (Z.of_int32 ema) z_1_000_000_000)))) + in + (* As a safeguard, we force the returned value inside the expected range. + However, the current single usage, i.e see [simple_off] below, will + always return a value in the expected range *) + max min_value (min res max_value) + +let encoding = Data_encoding.(conv_with_guard to_int32 of_int32_err int32) + +module Config = struct + type nonrec t = { + initial : t; + default_threshold : t; + update_ema_on : t -> t; + update_ema_off : t -> t; + } + + let z_1999 = Z.of_int 1999 + + let z_2000 = Z.of_int 2000 + + let attenuate z = Z.(div (mul z_1999 z) z_2000) + + module Simple_off = struct + let z_500_000 = Z.of_int 500_000 + + let update_ema_off = + centered_z_update (fun ema -> Z.add (attenuate ema) z_500_000) + + let update_ema_on = + centered_z_update (fun ema -> Z.sub (attenuate ema) z_500_000) + + let config = + { + initial = of_int32_exn 0l; + default_threshold = of_int32_exn 1_000_000_000l; + update_ema_on; + update_ema_off; + } + end + + let simple_off = Simple_off.config +end + +let update config vote ema = + let open Toggle_vote_repr in + match vote with + | Toggle_pass -> ema + | Toggle_off -> config.Config.update_ema_off ema + | Toggle_on -> config.update_ema_on ema + +module Internal_for_tests = struct + let of_int32_exn = of_int32_exn + + let to_int32 = to_int32 +end diff --git a/src/proto_alpha/lib_protocol/toggle_vote_ema_repr.mli b/src/proto_alpha/lib_protocol/toggle_vote_ema_repr.mli new file mode 100644 index 000000000000..48e18259c494 --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_ema_repr.mli @@ -0,0 +1,84 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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. *) +(* *) +(*****************************************************************************) + +(** Exponential moving average of toggle votes. Represented as int32 + between 0 and 2,000,000,000. *) +type t + +include Compare.S with type t := t + +(** Lowest bound for [t]. Currently 0. *) +val min_value : t + +(** Upper bound for [t]. Currently 2,000,000,000. *) +val max_value : t + +val pp : Format.formatter -> t -> unit + +val encoding : t Data_encoding.t + +module Config : sig + type nonrec t = { + initial : t; + default_threshold : t; + update_ema_on : t -> t; + update_ema_off : t -> t; + } + + (** A simple configuration where: + + - initial value is 0; + + - default_threshold is 1,000,000,000; + + - when used with the function [update]: + + - if [toggle_vote] is [Toggle_pass], then + + [new_ema] = [old_ema], + + - if [toggle_vote] is [Toggle_off], then + + [new_ema] = (1999 * old_ema // 2000) + 1,000,000, + + - if [toggle_vote] is [Toggle_on], then: + + [new_ema] = (1999 * old_ema // 2000). + + The multiplication is performed in [Z.t] to avoid overflows, + division is rounded toward 1,000,000,000 (the middle of the + interval). *) + val simple_off : t +end + +(** Compute the next EMA for a given vote and a given configuration. *) +val update : Config.t -> Toggle_vote_repr.t -> t -> t + +module Internal_for_tests : sig + val of_int32_exn : Int32.t -> t + + val to_int32 : t -> Int32.t +end -- GitLab From 9c388494f4deed505ec18bf8ec767506ea5dbf7e Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 16:51:34 +0200 Subject: [PATCH 38/48] Proto/Per_block_vote: prepare storage for multiple vote --- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 1 + .../lib_protocol/alpha_context.mli | 10 +++ src/proto_alpha/lib_protocol/dune | 5 ++ src/proto_alpha/lib_protocol/init_storage.ml | 1 + .../liquidity_baking_migration.ml | 16 ++++- .../liquidity_baking_migration.mli | 4 ++ .../lib_protocol/liquidity_baking_storage.ml | 4 +- src/proto_alpha/lib_protocol/storage.ml | 25 ++++++-- src/proto_alpha/lib_protocol/storage.mli | 20 ++++-- .../lib_protocol/toggle_vote_name_repr.ml | 64 +++++++++++++++++++ .../lib_protocol/toggle_vote_name_repr.mli | 34 ++++++++++ 12 files changed, 168 insertions(+), 17 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 4b1aa47ae835..dfce8d967140 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -28,6 +28,7 @@ "Fixed_point_repr", "Saturation_repr", "Gas_limit_repr", + "Toggle_vote_name_repr", "Toggle_vote_repr", "Toggle_vote_ema_repr", "Constants_parametric_repr", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index e95c8e779cc6..f438eb9ea700 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -97,6 +97,7 @@ module Vote = struct end module Toggle_vote = struct + module Name = Toggle_vote_name_repr module Ema = Toggle_vote_ema_repr include Toggle_vote_repr end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 874d44d0d3c7..ab6a875e7767 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -702,6 +702,16 @@ module Script : sig end module Toggle_vote : sig + module Name : sig + type t = Liquidity_baking + + val pp : Format.formatter -> t -> unit + + val encoding : t Data_encoding.t + + val all : t list + end + module Ema : sig include BASIC_DATA diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index dcf1c3222be9..4ae8e4e9e1fb 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -59,6 +59,7 @@ Fixed_point_repr Saturation_repr Gas_limit_repr + Toggle_vote_name_repr Toggle_vote_repr Toggle_vote_ema_repr Constants_parametric_repr @@ -277,6 +278,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli @@ -484,6 +486,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli @@ -711,6 +714,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli @@ -934,6 +938,7 @@ fixed_point_repr.ml fixed_point_repr.mli saturation_repr.ml saturation_repr.mli gas_limit_repr.ml gas_limit_repr.mli + toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 81ccb3ba85e6..d499e337fd92 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -120,6 +120,7 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = Storage.Tenderbake.First_level_of_protocol.update ctxt level >>=? fun ctxt -> Delegate_cycles.Migration_from_Jakarta.update ctxt >>=? fun ctxt -> + Liquidity_baking_migration.From_Jakarta.update ctxt >>=? fun ctxt -> return (ctxt, [])) >>=? fun (ctxt, balance_updates) -> Receipt_repr.group_balance_updates balance_updates >>?= fun balance_updates -> diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml b/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml index 79a63925c5a7..9736fc2c38d3 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml @@ -198,8 +198,9 @@ let init ctxt ~typecheck = (* We use a custom origination nonce because it is unset when stitching from 009 *) let nonce = Operation_hash.hash_string ["Drip, drip, drip."] in let ctxt = Raw_context.init_origination_nonce ctxt nonce in - Storage.Liquidity_baking.Toggle_ema.init + Storage.Toggle_vote_ema.init ctxt + Liquidity_baking Toggle_vote_ema_repr.Config.simple_off.initial >>=? fun ctxt -> let current_level = @@ -245,3 +246,16 @@ let init ctxt ~typecheck = (* Unsets the origination nonce, which is okay because this is called after other originations in stitching. *) let ctxt = Raw_context.unset_origination_nonce ctxt in (ctxt, [cpmm_result; lqt_result] @ token_result)) + +module From_Jakarta = struct + let update ctxt = + let open Lwt_tzresult_syntax in + let* lb_ema = + Storage.Liquidity_baking.Migration_from_Jakarta.Toggle_ema.get ctxt + in + let*! ctxt = + Storage.Liquidity_baking.Migration_from_Jakarta.Toggle_ema.remove ctxt + in + let* ctxt = Storage.Toggle_vote_ema.init ctxt Liquidity_baking lb_ema in + return ctxt +end diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli b/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli index 27059e493d50..16a3ff5da48c 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli @@ -31,3 +31,7 @@ val init : ((Script_repr.t * Lazy_storage_diff.diffs option) * Raw_context.t) tzresult Lwt.t) -> (Raw_context.t * Migration_repr.origination_result list) tzresult Lwt.t + +module From_Jakarta : sig + val update : Raw_context.t -> Raw_context.t tzresult Lwt.t +end diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml index 8b4b0d907018..04800681d90b 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml @@ -28,7 +28,7 @@ open Liquidity_baking_repr let get_cpmm_address = Storage.Liquidity_baking.Cpmm_address.get -let get_toggle_ema ctxt = Storage.Liquidity_baking.Toggle_ema.get ctxt +let get_toggle_ema ctxt = Storage.Toggle_vote_ema.get ctxt Liquidity_baking let on_cpmm_exists ctxt f = get_cpmm_address ctxt >>=? fun cpmm_contract -> @@ -47,7 +47,7 @@ let check_below_sunset ctxt = let update_toggle_ema ctxt ~toggle_vote = get_toggle_ema ctxt >>=? fun old_ema -> let new_ema = compute_new_ema ~toggle_vote old_ema in - Storage.Liquidity_baking.Toggle_ema.update ctxt new_ema >|=? fun ctxt -> + Storage.Toggle_vote_ema.update ctxt Liquidity_baking new_ema >|=? fun ctxt -> (ctxt, new_ema) let check_ema_below_threshold ctxt ema = diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index ece71e4f66fa..6d4474994505 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -1410,14 +1410,25 @@ module Pending_migration = struct return (ctxt, balance_updates, operation_results) end +module Toggle_vote_ema = + Make_indexed_data_storage + (Make_subcontext (Registered) (Raw_context) + (struct + let name = ["toggle_vote_emas"] + end)) + (Make_index (Toggle_vote_name_repr)) + (Toggle_vote_ema_repr) + module Liquidity_baking = struct - module Toggle_ema = - Make_single_data_storage (Registered) (Raw_context) - (struct - (* The old "escape" name is kept here to avoid migrating this. *) - let name = ["liquidity_baking_escape_ema"] - end) - (Toggle_vote_ema_repr) + module Migration_from_Jakarta = struct + module Toggle_ema = + Make_single_data_storage (Ghost) (Raw_context) + (struct + (* The old "escape" name is kept here to avoid migrating this. *) + let name = ["liquidity_baking_escape_ema"] + end) + (Toggle_vote_ema_repr) + end module Cpmm_address = Make_single_data_storage (Registered) (Raw_context) diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 01718440bace..3863a548d53c 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -556,14 +556,20 @@ module Pending_migration : sig Lwt.t end +(** Exponential moving average (ema) of flags set in protocol_data.contents. **) +module Toggle_vote_ema : + Indexed_data_storage + with type t := Raw_context.t + and type key = Toggle_vote_name_repr.t + and type value = Toggle_vote_ema_repr.t + module Liquidity_baking : sig - (** Exponential moving average (ema) of flags set in protocol_data.contents. - The liquidity baking subsidy is not sent to the CPMM if this EMA is above - the threshold set in constants. **) - module Toggle_ema : - Single_data_storage - with type t := Raw_context.t - and type value = Toggle_vote_ema_repr.t + module Migration_from_Jakarta : sig + module Toggle_ema : + Single_data_storage + with type t := Raw_context.t + and type value = Toggle_vote_ema_repr.t + end (** Constant product market maker contract that receives liquidity baking subsidy. **) module Cpmm_address : diff --git a/src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml new file mode 100644 index 000000000000..0a63f3a97a7c --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml @@ -0,0 +1,64 @@ +(*****************************************************************************) +(* *) +(* 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 t = Liquidity_baking + +let to_string = function Liquidity_baking -> "liquidity_baking" + +let of_string_opt = function + | "liquidity_baking" -> Some Liquidity_baking + | _ -> None + +let of_string_err name = + match of_string_opt name with + | Some vote -> Ok vote + | None -> Error "invalid name of toggle vote" + +let pp ppf v = Format.pp_print_string ppf (to_string v) + +let all = [Liquidity_baking] + +let encoding = + let open Data_encoding in + def "toggle_vote_name" + @@ conv + (fun Liquidity_baking -> ()) + (fun () -> Liquidity_baking) + (constant "liquidity_baking") + +let path_length = 1 + +let to_path v l = to_string v :: l + +let of_path = function [] | _ :: _ :: _ -> None | [c] -> of_string_opt c + +let rpc_arg = + RPC_arg.make + ~name:"toggle_vote" + ~destruct:of_string_err + ~construct:to_string + () + +let compare a b = match (a, b) with Liquidity_baking, Liquidity_baking -> 0 diff --git a/src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli new file mode 100644 index 000000000000..ef3bad1c89f3 --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli @@ -0,0 +1,34 @@ +(*****************************************************************************) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(** The per-block toggle votes. *) +type t = Liquidity_baking + +val pp : Format.formatter -> t -> unit + +include Storage_description.INDEX with type t := t + +(** The list of all per-block toggle votes. *) +val all : t list -- GitLab From ecf2ff5274f1341585a0cead59e560472ba2f3a2 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 17:39:44 +0200 Subject: [PATCH 39/48] Proto/Per_block_vote: prepare block metadata for multiple vote --- src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 1 + src/proto_alpha/lib_protocol/alpha_context.ml | 1 + .../lib_protocol/alpha_context.mli | 19 ++++++- src/proto_alpha/lib_protocol/apply.ml | 36 ++++++------ src/proto_alpha/lib_protocol/apply.mli | 8 +-- src/proto_alpha/lib_protocol/apply_results.ml | 27 +++++---- .../lib_protocol/apply_results.mli | 2 +- src/proto_alpha/lib_protocol/dune | 5 ++ .../lib_protocol/liquidity_baking_storage.ml | 16 ++++-- .../lib_protocol/liquidity_baking_storage.mli | 9 ++- src/proto_alpha/lib_protocol/main.ml | 50 +++++++---------- src/proto_alpha/lib_protocol/main.mli | 2 +- .../lib_protocol/test/helpers/block.ml | 6 +- .../lib_protocol/test/helpers/block.mli | 2 +- .../test/integration/test_liquidity_baking.ml | 5 +- .../lib_protocol/toggle_vote_emas_repr.ml | 56 +++++++++++++++++++ .../lib_protocol/toggle_vote_emas_repr.mli | 41 ++++++++++++++ 17 files changed, 205 insertions(+), 81 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml create mode 100644 src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index dfce8d967140..927736c13d07 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -31,6 +31,7 @@ "Toggle_vote_name_repr", "Toggle_vote_repr", "Toggle_vote_ema_repr", + "Toggle_vote_emas_repr", "Constants_parametric_repr", "Constants_parametric_previous_repr", "Constants_repr", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index f438eb9ea700..bb578c88e7c0 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -99,6 +99,7 @@ end module Toggle_vote = struct module Name = Toggle_vote_name_repr module Ema = Toggle_vote_ema_repr + module Emas = Toggle_vote_emas_repr include Toggle_vote_repr end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index ab6a875e7767..157d9463d258 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -741,6 +741,16 @@ module Toggle_vote : sig end end + module Emas : sig + type t = {liquidity_baking : Ema.t} + + val encoding : t Data_encoding.t + + val initial : t + + val default_thresholds : t + end + type t = Toggle_on | Toggle_off | Toggle_pass val pp : Format.formatter -> t -> unit @@ -3593,11 +3603,16 @@ end module Liquidity_baking : sig val get_cpmm_address : context -> Contract_hash.t tzresult Lwt.t - val on_subsidy_allowed : + val update_toggle_ema : context -> toggle_vote:Toggle_vote.t -> + (context * Toggle_vote.Emas.t) tzresult Lwt.t + + val on_subsidy_allowed : + context -> + Toggle_vote.Emas.t -> (context -> Contract_hash.t -> (context * 'a list) tzresult Lwt.t) -> - (context * 'a list * Toggle_vote.Ema.t) tzresult Lwt.t + (context * 'a list) tzresult Lwt.t end (** This module re-exports functions from [Ticket_storage]. See diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 5ef5030f7747..96f4760ff625 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -3490,10 +3490,10 @@ let init_allowed_consensus_operations ctxt ~endorsement_level ~allowed_endorsements ~allowed_preendorsements) -let apply_liquidity_baking_subsidy ctxt ~toggle_vote = +let apply_liquidity_baking_subsidy ctxt toggle_vote_emas = Liquidity_baking.on_subsidy_allowed ctxt - ~toggle_vote + toggle_vote_emas (fun ctxt liquidity_baking_cpmm_contract_hash -> let liquidity_baking_cpmm_contract = Contract.Originated liquidity_baking_cpmm_contract_hash @@ -3653,7 +3653,7 @@ type 'a full_construction = { block_producer : Consensus_key.t; round : Round.t; implicit_operations_results : packed_successful_manager_operation_result list; - liquidity_baking_toggle_ema : Toggle_vote.Ema.t; + toggle_vote_emas : Toggle_vote.Emas.t; } let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level @@ -3687,10 +3687,10 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level ~preendorsement_level:current_level >>=? fun ctxt -> let toggle_vote = protocol_data.liquidity_baking_toggle_vote in - apply_liquidity_baking_subsidy ctxt ~toggle_vote - >|=? fun ( ctxt, - liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) -> + Liquidity_baking.update_toggle_ema ctxt ~toggle_vote + >>=? fun (ctxt, toggle_vote_emas) -> + apply_liquidity_baking_subsidy ctxt toggle_vote_emas + >|=? fun (ctxt, liquidity_baking_operations_results) -> { ctxt; protocol_data; @@ -3698,7 +3698,7 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level block_producer = Consensus_key.pkh block_producer; round; implicit_operations_results = liquidity_baking_operations_results; - liquidity_baking_toggle_ema; + toggle_vote_emas; } let begin_partial_construction ctxt ~predecessor_level ~toggle_vote = @@ -3710,7 +3710,11 @@ let begin_partial_construction ctxt ~predecessor_level ~toggle_vote = ctxt ~endorsement_level:predecessor_level ~preendorsement_level:predecessor_level - >>=? fun ctxt -> apply_liquidity_baking_subsidy ctxt ~toggle_vote + >>=? fun ctxt -> + Liquidity_baking.update_toggle_ema ctxt ~toggle_vote + >>=? fun (ctxt, toggle_vote_emas) -> + apply_liquidity_baking_subsidy ctxt toggle_vote_emas >>=? fun (ctxt, res) -> + return (ctxt, res, toggle_vote_emas) let begin_application ctxt chain_id (block_header : Block_header.t) fitness ~predecessor_timestamp ~predecessor_level ~predecessor_round = @@ -3751,15 +3755,15 @@ let begin_application ctxt chain_id (block_header : Block_header.t) fitness block_header.Block_header.protocol_data.contents .liquidity_baking_toggle_vote in - apply_liquidity_baking_subsidy ctxt ~toggle_vote - >|=? fun ( ctxt, - liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) -> + Liquidity_baking.update_toggle_ema ctxt ~toggle_vote + >>=? fun (ctxt, toggle_vote_emas) -> + apply_liquidity_baking_subsidy ctxt toggle_vote_emas + >|=? fun (ctxt, liquidity_baking_operations_results) -> ( ctxt, Consensus_key.pkh payload_producer, Consensus_key.pkh block_producer, liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) + toggle_vote_emas ) type finalize_application_mode = | Finalize_full_construction of { @@ -3860,7 +3864,7 @@ let record_endorsing_participation ctxt = let finalize_application ctxt (mode : finalize_application_mode) protocol_data ~(payload_producer : Consensus_key.t) ~(block_producer : Consensus_key.t) - liquidity_baking_toggle_ema implicit_operations_results ~round ~predecessor + toggle_vote_emas implicit_operations_results ~round ~predecessor ~migration_balance_updates = (* Then we finalize the consensus. *) let level = Level.current ctxt in @@ -3939,7 +3943,7 @@ let finalize_application ctxt (mode : finalize_application_mode) protocol_data consumed_gas; deactivated; balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results; } in diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index b60e6ef75827..1a3357094201 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -49,7 +49,7 @@ val begin_partial_construction : context -> predecessor_level:Level.t -> toggle_vote:Toggle_vote.t -> - (t * packed_successful_manager_operation_result list * Toggle_vote.Ema.t) + (t * packed_successful_manager_operation_result list * Toggle_vote.Emas.t) tzresult Lwt.t @@ -60,7 +60,7 @@ type 'a full_construction = { block_producer : Consensus_key.t; round : Round.t; implicit_operations_results : packed_successful_manager_operation_result list; - liquidity_baking_toggle_ema : Toggle_vote.Ema.t; + toggle_vote_emas : Toggle_vote.Emas.t; } val begin_full_construction : @@ -84,7 +84,7 @@ val begin_application : * Consensus_key.t * Consensus_key.t * packed_successful_manager_operation_result list - * Toggle_vote.Ema.t) + * Toggle_vote.Emas.t) tzresult Lwt.t @@ -134,7 +134,7 @@ val finalize_application : Block_header.contents -> payload_producer:Consensus_key.t -> block_producer:Consensus_key.t -> - Toggle_vote.Ema.t -> + Toggle_vote.Emas.t -> packed_successful_manager_operation_result list -> round:Round.t -> predecessor:Block_hash.t -> diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index c3ac41813a36..1e2306cf49c3 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -3119,7 +3119,7 @@ type block_metadata = { consumed_gas : Gas.Arith.fp; deactivated : Signature.Public_key_hash.t list; balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Toggle_vote.Ema.t; + toggle_vote_emas : Toggle_vote.Emas.t; implicit_operations_results : packed_successful_manager_operation_result list; } @@ -3137,7 +3137,7 @@ let block_metadata_encoding = consumed_gas; deactivated; balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results; } -> ( ( proposer, @@ -3146,22 +3146,22 @@ let block_metadata_encoding = voting_period_info, nonce_hash, consumed_gas, + consumed_gas, deactivated, balance_updates, - liquidity_baking_toggle_ema, implicit_operations_results ), - (proposer_active_key, baker_active_key, consumed_gas) )) + ((proposer_active_key, baker_active_key), toggle_vote_emas) )) (fun ( ( proposer, baker, level_info, voting_period_info, nonce_hash, consumed_gas, + _consumed_millgas, deactivated, balance_updates, - liquidity_baking_toggle_ema, implicit_operations_results ), - (proposer_active_key, baker_active_key, _consumed_millgas) ) -> + ((proposer_active_key, baker_active_key), toggle_vote_emas) ) -> { proposer = {delegate = proposer; consensus_pkh = proposer_active_key}; baker = {delegate = baker; consensus_pkh = baker_active_key}; @@ -3171,7 +3171,7 @@ let block_metadata_encoding = consumed_gas; deactivated; balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results; }) (merge_objs @@ -3182,16 +3182,19 @@ let block_metadata_encoding = (req "voting_period_info" Voting_period.info_encoding) (req "nonce_hash" (option Nonce_hash.encoding)) (req "consumed_gas" Gas.Arith.n_fp_encoding) + (req "consumed_milligas" Gas.Arith.n_fp_encoding) (req "deactivated" (list Signature.Public_key_hash.encoding)) (dft "balance_updates" Receipt.balance_updates_encoding []) - (req "liquidity_baking_toggle_ema" Toggle_vote.Ema.encoding) (req "implicit_operations_results" (list successful_manager_operation_result_encoding))) - (obj3 - (req "proposer_consensus_key" Signature.Public_key_hash.encoding) - (req "baker_consensus_key" Signature.Public_key_hash.encoding) - (req "consumed_milligas" Gas.Arith.n_fp_encoding))) + (merge_objs + (obj2 + (req + "proposer_consensus_key" + Signature.Public_key_hash.encoding) + (req "baker_consensus_key" Signature.Public_key_hash.encoding)) + Toggle_vote.Emas.encoding)) type precheck_result = { consumed_gas : Gas.Arith.fp; diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 69dafba4f014..9fe3502eacf5 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -381,7 +381,7 @@ type block_metadata = { consumed_gas : Gas.Arith.fp; deactivated : Signature.Public_key_hash.t list; balance_updates : Receipt.balance_updates; - liquidity_baking_toggle_ema : Toggle_vote.Ema.t; + toggle_vote_emas : Toggle_vote.Emas.t; implicit_operations_results : packed_successful_manager_operation_result list; } diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 4ae8e4e9e1fb..4309e84fc15f 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -62,6 +62,7 @@ Toggle_vote_name_repr Toggle_vote_repr Toggle_vote_ema_repr + Toggle_vote_emas_repr Constants_parametric_repr Constants_parametric_previous_repr Constants_repr @@ -281,6 +282,7 @@ toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli + toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -489,6 +491,7 @@ toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli + toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -717,6 +720,7 @@ toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli + toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -941,6 +945,7 @@ toggle_vote_name_repr.ml toggle_vote_name_repr.mli toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli + toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml index 04800681d90b..18f584cdc821 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml @@ -45,18 +45,22 @@ let check_below_sunset ctxt = Compare.Int32.(level < sunset_level) let update_toggle_ema ctxt ~toggle_vote = + let open Toggle_vote_emas_repr in get_toggle_ema ctxt >>=? fun old_ema -> let new_ema = compute_new_ema ~toggle_vote old_ema in Storage.Toggle_vote_ema.update ctxt Liquidity_baking new_ema >|=? fun ctxt -> - (ctxt, new_ema) + (ctxt, {liquidity_baking = new_ema}) let check_ema_below_threshold ctxt ema = Toggle_vote_ema_repr.( ema < Constants_storage.liquidity_baking_toggle_ema_threshold ctxt) -let on_subsidy_allowed ctxt ~toggle_vote f = - update_toggle_ema ctxt ~toggle_vote >>=? fun (ctxt, toggle_ema) -> - if check_ema_below_threshold ctxt toggle_ema && check_below_sunset ctxt then +let on_subsidy_allowed ctxt toggle_vote_emas f = + let open Toggle_vote_emas_repr in + if + check_ema_below_threshold ctxt toggle_vote_emas.liquidity_baking + && check_below_sunset ctxt + then on_cpmm_exists ctxt f >|=? fun (ctxt, operation_results) -> - (ctxt, operation_results, toggle_ema) - else return (ctxt, [], toggle_ema) + (ctxt, operation_results) + else return (ctxt, []) diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli index 0c5a288389e0..f4c105ee6ceb 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli @@ -28,6 +28,11 @@ Liquidity Baking subsidy *) val get_cpmm_address : Raw_context.t -> Contract_hash.t tzresult Lwt.t +val update_toggle_ema : + Raw_context.t -> + toggle_vote:Toggle_vote_repr.t -> + (Raw_context.t * Toggle_vote_emas_repr.t) tzresult Lwt.t + (** [on_subsidy_allowed ctxt ~toggle_vote f] updates the toggle EMA according to [toggle_vote]. Then the callback function [f] is called if the following conditions are met: @@ -39,6 +44,6 @@ val get_cpmm_address : Raw_context.t -> Contract_hash.t tzresult Lwt.t see [apply_liquidity_baking_subsidy] in [apply.ml]. *) val on_subsidy_allowed : Raw_context.t -> - toggle_vote:Toggle_vote_repr.t -> + Toggle_vote_emas_repr.t -> (Raw_context.t -> Contract_hash.t -> (Raw_context.t * 'a list) tzresult Lwt.t) -> - (Raw_context.t * 'a list * Toggle_vote_ema_repr.t) tzresult Lwt.t + (Raw_context.t * 'a list) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index 571ac12c8264..aac64e47f749 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -132,7 +132,7 @@ type validation_state = { ctxt : Alpha_context.t; op_count : int; migration_balance_updates : Alpha_context.Receipt.balance_updates; - liquidity_baking_toggle_ema : Alpha_context.Toggle_vote.Ema.t; + toggle_vote_emas : Alpha_context.Toggle_vote.Emas.t; implicit_operations_results : Apply_results.packed_successful_manager_operation_result list; } @@ -165,7 +165,7 @@ let begin_partial_application ~chain_id ~ancestor_context:ctxt payload_producer, block_producer, liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) -> + toggle_vote_emas ) -> let mode = Partial_application { @@ -184,7 +184,7 @@ let begin_partial_application ~chain_id ~ancestor_context:ctxt ctxt; op_count = 0; migration_balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results = Apply_results.pack_migration_operation_results migration_operation_results @@ -221,7 +221,7 @@ let begin_application ~chain_id ~predecessor_context:ctxt ~predecessor_timestamp payload_producer, block_producer, liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) -> + toggle_vote_emas ) -> let mode = Application { @@ -240,7 +240,7 @@ let begin_application ~chain_id ~predecessor_context:ctxt ~predecessor_timestamp ctxt; op_count = 0; migration_balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results = Apply_results.pack_migration_operation_results migration_operation_results @@ -264,9 +264,7 @@ let begin_construction ~chain_id ~predecessor_context:ctxt >>?= fun predecessor_round -> let toggle_vote = Alpha_context.Toggle_vote.Toggle_pass in Apply.begin_partial_construction ctxt ~predecessor_level ~toggle_vote - >>=? fun ( ctxt, - liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) -> + >>=? fun (ctxt, liquidity_baking_operations_results, toggle_vote_emas) -> let mode = Partial_construction { @@ -276,11 +274,7 @@ let begin_construction ~chain_id ~predecessor_context:ctxt predecessor_round; } in - return - ( mode, - ctxt, - liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) + return (mode, ctxt, liquidity_baking_operations_results, toggle_vote_emas) | Some proto_header -> Alpha_context.Fitness.round_from_raw predecessor_fitness >>?= fun predecessor_round -> @@ -306,7 +300,7 @@ let begin_construction ~chain_id ~predecessor_context:ctxt payload_producer; block_producer; round; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results = liquidity_baking_operations_results; } -> @@ -323,22 +317,16 @@ let begin_construction ~chain_id ~predecessor_context:ctxt predecessor_level; } in - return - ( mode, - ctxt, - liquidity_baking_operations_results, - liquidity_baking_toggle_ema )) - >|=? fun ( mode, - ctxt, - liquidity_baking_operations_results, - liquidity_baking_toggle_ema ) -> + return (mode, ctxt, liquidity_baking_operations_results, toggle_vote_emas)) + >|=? fun (mode, ctxt, liquidity_baking_operations_results, toggle_vote_emas) + -> { mode; chain_id; ctxt; op_count = 0; migration_balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results = Apply_results.pack_migration_operation_results migration_operation_results @ liquidity_baking_operations_results; @@ -498,7 +486,7 @@ let cache_nonce_from_block_header shell contents = Block_hash.to_bytes (hash x) let finalize_block_application ctxt round ~cache_nonce finalize_application_mode - protocol_data payload_producer block_producer liquidity_baking_toggle_ema + protocol_data payload_producer block_producer toggle_vote_emas implicit_operations_results predecessor migration_balance_updates op_count = Apply.finalize_application ctxt @@ -506,7 +494,7 @@ let finalize_block_application ctxt round ~cache_nonce finalize_application_mode protocol_data ~payload_producer ~block_producer - liquidity_baking_toggle_ema + toggle_vote_emas implicit_operations_results ~round ~predecessor @@ -558,7 +546,7 @@ let finalize_block ctxt; op_count; migration_balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results; _; } shell_header = @@ -581,7 +569,7 @@ let finalize_block consumed_gas = Alpha_context.Gas.Arith.zero; deactivated = []; balance_updates = migration_balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results; } ) | Partial_application {fitness; block_producer; _} -> @@ -620,7 +608,7 @@ let finalize_block consumed_gas = Alpha_context.Gas.Arith.zero; deactivated = []; balance_updates = migration_balance_updates; - liquidity_baking_toggle_ema; + toggle_vote_emas; implicit_operations_results; } ) | Application @@ -641,7 +629,7 @@ let finalize_block protocol_data payload_producer block_producer - liquidity_baking_toggle_ema + toggle_vote_emas implicit_operations_results shell.predecessor migration_balance_updates @@ -673,7 +661,7 @@ let finalize_block protocol_data_contents payload_producer block_producer - liquidity_baking_toggle_ema + toggle_vote_emas implicit_operations_results predecessor migration_balance_updates diff --git a/src/proto_alpha/lib_protocol/main.mli b/src/proto_alpha/lib_protocol/main.mli index da2a30c7094c..52dadecfe9bc 100644 --- a/src/proto_alpha/lib_protocol/main.mli +++ b/src/proto_alpha/lib_protocol/main.mli @@ -104,7 +104,7 @@ type validation_state = { ctxt : Alpha_context.t; op_count : int; migration_balance_updates : Alpha_context.Receipt.balance_updates; - liquidity_baking_toggle_ema : Alpha_context.Toggle_vote.Ema.t; + toggle_vote_emas : Alpha_context.Toggle_vote.Emas.t; implicit_operations_results : Apply_results.packed_successful_manager_operation_result list; } diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 8969ebec24c2..f94a51f4c3ee 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -817,12 +817,12 @@ let bake_n_with_origination_results ?(baking_mode = Application) ?policy n b = let bake_n_with_liquidity_baking_toggle_ema ?(baking_mode = Application) ?policy ?liquidity_baking_toggle_vote n b = - let initial_ema = Toggle_vote.Ema.Internal_for_tests.of_int32_exn 0l in + let initial_emas = Toggle_vote.Emas.initial in List.fold_left_es (fun (b, _toggle_ema) _ -> bake_with_metadata ~baking_mode ?policy ?liquidity_baking_toggle_vote b - >|=? fun (b, metadata) -> (b, metadata.liquidity_baking_toggle_ema)) - (b, initial_ema) + >|=? fun (b, metadata) -> (b, metadata.toggle_vote_emas)) + (b, initial_emas) (1 -- n) let bake_until_cycle_end ?policy b = diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index 9919b6dc363f..d8c5a8077eb1 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -234,7 +234,7 @@ val bake_n_with_liquidity_baking_toggle_ema : ?liquidity_baking_toggle_vote:Toggle_vote.t -> int -> t -> - (block * Alpha_context.Toggle_vote.Ema.t) tzresult Lwt.t + (block * Alpha_context.Toggle_vote.Emas.t) tzresult Lwt.t val current_cycle : t -> Cycle.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml index ff1ae71a9f4e..e99b6e4b6ed4 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml @@ -274,8 +274,9 @@ let liquidity_baking_toggle_ema n_vote_on n_vote_off level bake_after >>=? fun (_blk, toggle_ema) -> Assert.leq_int ~loc:__LOC__ - (toggle_ema |> Alpha_context.Toggle_vote.Ema.Internal_for_tests.to_int32 - |> Int32.to_int) + (toggle_ema.liquidity_baking + |> Alpha_context.Toggle_vote.Ema.Internal_for_tests.to_int32 |> Int32.to_int + ) expected_toggle_ema >>=? fun () -> return_unit diff --git a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml new file mode 100644 index 000000000000..3ce376b226b4 --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml @@ -0,0 +1,56 @@ +(*****************************************************************************) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Toggle_vote_name_repr + +type t = {liquidity_baking : Toggle_vote_ema_repr.t} + +let encoding = + let open Data_encoding in + conv + (fun {liquidity_baking} -> liquidity_baking) + (fun liquidity_baking -> {liquidity_baking}) + (obj1 (req "liquidity_baking_toggle_ema" Toggle_vote_ema_repr.encoding)) + +let threshold_encoding = + let open Data_encoding in + conv + (fun {liquidity_baking} -> liquidity_baking) + (fun liquidity_baking -> {liquidity_baking}) + (obj1 + (req + "liquidity_baking_toggle_ema_threshold" + Toggle_vote_ema_repr.encoding)) + +let get_config = function + | Liquidity_baking -> Toggle_vote_ema_repr.Config.simple_off + +let initial = + let get name = (get_config name).initial in + {liquidity_baking = get Liquidity_baking} + +let default_thresholds = + let get name = (get_config name).default_threshold in + {liquidity_baking = get Liquidity_baking} diff --git a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli new file mode 100644 index 000000000000..3ca325dc28db --- /dev/null +++ b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli @@ -0,0 +1,41 @@ +(*****************************************************************************) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +(** The EMAs for all pending toggle votes. *) +type t = {liquidity_baking : Toggle_vote_ema_repr.t} + +(** Encoding for current EMAs of all pending toggle vote. *) +val encoding : t Data_encoding.t + +(** Alternate encoding for EMA's threshold of all pending toggle vote. + Compared to the default [encoding], the field names in JSON are + suffixed with `_threshold`. *) +val threshold_encoding : t Data_encoding.t + +(** Initial EMA for all pending toggle votes. *) +val initial : t + +(** Default EMA's threshold for all pending toggle vote. *) +val default_thresholds : t -- GitLab From 5d461144bb33b5928cc2368807ecb89f851fe0b0 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 17:16:46 +0200 Subject: [PATCH 40/48] Proto/Per_block_vote: prepare constants for multiple vote --- src/proto_alpha/lib_client/mockup.ml | 111 +++++++++++------- .../lib_parameters/default_parameters.ml | 5 +- .../lib_protocol/alpha_context.mli | 4 +- .../lib_protocol/constants_parametric_repr.ml | 69 ++++++----- .../constants_parametric_repr.mli | 2 +- .../lib_protocol/constants_storage.ml | 4 +- .../lib_protocol/constants_storage.mli | 3 +- .../lib_protocol/liquidity_baking_storage.ml | 2 +- src/proto_alpha/lib_protocol/raw_context.ml | 4 +- 9 files changed, 111 insertions(+), 93 deletions(-) diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml index 9891f4b7006b..199cd0e347d6 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -30,6 +30,33 @@ open Alpha_context (* ------------------------------------------------------------------------- *) (* Mockup protocol parameters *) +module Emas = struct + module Opt = struct + type t = {liquidity_baking : Toggle_vote.Ema.t option} + + let threshold_encoding = + let open Data_encoding in + conv + (fun {liquidity_baking} -> liquidity_baking) + (fun liquidity_baking -> {liquidity_baking}) + (obj1 + (opt + "liquidity_baking_toggle_ema_threshold" + Toggle_vote.Ema.encoding)) + end + + let some (p : Toggle_vote.Emas.t) : Opt.t = + {Opt.liquidity_baking = Some p.liquidity_baking} + + let none : Opt.t = {liquidity_baking = None} + + let merge (c : Toggle_vote.Emas.t) (o : Opt.t) : Toggle_vote.Emas.t = + { + liquidity_baking = + Option.value ~default:c.liquidity_baking o.liquidity_baking; + } +end + (** Protocol constants overriding logic. *) module Protocol_constants_overrides = struct (** Equivalent of [Constants.parametric] with additionally [chain_id] and [timestamp] but each field is wrapped in an [option]. @@ -57,7 +84,7 @@ module Protocol_constants_overrides = struct min_proposal_quorum : int32 option; liquidity_baking_subsidy : Tez.t option; liquidity_baking_sunset_level : int32 option; - liquidity_baking_toggle_ema_threshold : Toggle_vote.Ema.t option; + toggle_vote_ema_thresholds : Emas.Opt.t; max_operations_time_to_live : int option; minimal_block_delay : Period.t option; delay_increment_per_round : Period.t option; @@ -124,16 +151,16 @@ module Protocol_constants_overrides = struct c.cost_per_byte, c.hard_storage_limit_per_operation, c.quorum_min ), - ( ( c.quorum_max, - c.min_proposal_quorum, - c.liquidity_baking_subsidy, - c.liquidity_baking_sunset_level, - c.liquidity_baking_toggle_ema_threshold, - c.max_operations_time_to_live, - c.minimal_block_delay, - c.delay_increment_per_round, - c.consensus_committee_size, - c.consensus_threshold ), + ( ( ( c.quorum_max, + c.min_proposal_quorum, + c.liquidity_baking_subsidy, + c.liquidity_baking_sunset_level, + c.max_operations_time_to_live, + c.minimal_block_delay, + c.delay_increment_per_round, + c.consensus_committee_size, + c.consensus_threshold ), + c.toggle_vote_ema_thresholds ), ( ( c.minimal_participation_ratio, c.max_slashing_period, c.frozen_deposits_percentage, @@ -187,16 +214,16 @@ module Protocol_constants_overrides = struct cost_per_byte, hard_storage_limit_per_operation, quorum_min ), - ( ( quorum_max, - min_proposal_quorum, - liquidity_baking_subsidy, - liquidity_baking_sunset_level, - liquidity_baking_toggle_ema_threshold, - max_operations_time_to_live, - minimal_block_delay, - delay_increment_per_round, - consensus_committee_size, - consensus_threshold ), + ( ( ( quorum_max, + min_proposal_quorum, + liquidity_baking_subsidy, + liquidity_baking_sunset_level, + max_operations_time_to_live, + minimal_block_delay, + delay_increment_per_round, + consensus_committee_size, + consensus_threshold ), + toggle_vote_ema_thresholds ), ( ( minimal_participation_ratio, max_slashing_period, frozen_deposits_percentage, @@ -255,7 +282,7 @@ module Protocol_constants_overrides = struct min_proposal_quorum; liquidity_baking_subsidy; liquidity_baking_sunset_level; - liquidity_baking_toggle_ema_threshold; + toggle_vote_ema_thresholds; max_operations_time_to_live; minimal_block_delay; delay_increment_per_round; @@ -320,19 +347,18 @@ module Protocol_constants_overrides = struct (opt "hard_storage_limit_per_operation" z) (opt "quorum_min" int32)) (merge_objs - (obj10 - (opt "quorum_max" int32) - (opt "min_proposal_quorum" int32) - (opt "liquidity_baking_subsidy" Tez.encoding) - (opt "liquidity_baking_sunset_level" int32) - (opt - "liquidity_baking_toggle_ema_threshold" - Toggle_vote.Ema.encoding) - (opt "max_operations_time_to_live" int16) - (opt "minimal_block_delay" Period.encoding) - (opt "delay_increment_per_round" Period.encoding) - (opt "consensus_committee_size" int31) - (opt "consensus_threshold" int31)) + (merge_objs + (obj9 + (opt "quorum_max" int32) + (opt "min_proposal_quorum" int32) + (opt "liquidity_baking_subsidy" Tez.encoding) + (opt "liquidity_baking_sunset_level" int32) + (opt "max_operations_time_to_live" int16) + (opt "minimal_block_delay" Period.encoding) + (opt "delay_increment_per_round" Period.encoding) + (opt "consensus_committee_size" int31) + (opt "consensus_threshold" int31)) + Emas.Opt.threshold_encoding) (merge_objs (obj8 (opt "minimal_participation_ratio" Ratio.encoding) @@ -425,8 +451,8 @@ module Protocol_constants_overrides = struct liquidity_baking_subsidy = Some parametric.liquidity_baking_subsidy; liquidity_baking_sunset_level = Some parametric.liquidity_baking_sunset_level; - liquidity_baking_toggle_ema_threshold = - Some parametric.liquidity_baking_toggle_ema_threshold; + toggle_vote_ema_thresholds = + Emas.some parametric.toggle_vote_ema_thresholds; max_operations_time_to_live = Some parametric.max_operations_time_to_live; minimal_block_delay = Some parametric.minimal_block_delay; @@ -517,7 +543,7 @@ module Protocol_constants_overrides = struct min_proposal_quorum = None; liquidity_baking_subsidy = None; liquidity_baking_sunset_level = None; - liquidity_baking_toggle_ema_threshold = None; + toggle_vote_ema_thresholds = Emas.none; max_operations_time_to_live = None; minimal_block_delay = None; delay_increment_per_round = None; @@ -713,7 +739,7 @@ module Protocol_constants_overrides = struct O { name = "liquidity_baking_toggle_ema_threshold"; - override_value = o.liquidity_baking_toggle_ema_threshold; + override_value = o.toggle_vote_ema_thresholds.liquidity_baking; pp = Toggle_vote.Ema.pp; }; O @@ -936,10 +962,8 @@ module Protocol_constants_overrides = struct Option.value ~default:c.liquidity_baking_sunset_level o.liquidity_baking_sunset_level; - liquidity_baking_toggle_ema_threshold = - Option.value - ~default:c.liquidity_baking_toggle_ema_threshold - o.liquidity_baking_toggle_ema_threshold; + toggle_vote_ema_thresholds = + Emas.merge c.toggle_vote_ema_thresholds o.toggle_vote_ema_thresholds; max_operations_time_to_live = Option.value ~default:c.max_operations_time_to_live @@ -1456,7 +1480,6 @@ let mem_init : payload_hash; seed_nonce_hash = None; proof_of_work_nonce; - (* following Baking_configuration.toggle_votes in lib_delegate *) liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass; } in diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index da725b9b7b1f..d821ede779a6 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -88,10 +88,7 @@ let constants_mainnet = (* level after protocol activation when liquidity baking shuts off: about 6 months after first activation on mainnet *) liquidity_baking_sunset_level = 3_063_809l; - (* 1/2 window size of 2000 blocks with precision of 1_000_000 - for integer computation *) - liquidity_baking_toggle_ema_threshold = - Toggle_vote.Ema.Config.simple_off.default_threshold; + toggle_vote_ema_thresholds = Toggle_vote.Emas.default_thresholds; (* The rationale behind the value of this constant is that an operation should be considered alive for about one hour: diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 157d9463d258..b7e17662055e 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -800,7 +800,7 @@ module Constants : sig min_proposal_quorum : int32; liquidity_baking_subsidy : Tez.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : Toggle_vote.Ema.t; + toggle_vote_ema_thresholds : Toggle_vote.Emas.t; max_operations_time_to_live : int; minimal_block_delay : Period.t; delay_increment_per_round : Period.t; @@ -901,7 +901,7 @@ module Constants : sig val liquidity_baking_sunset_level : context -> int32 - val liquidity_baking_toggle_ema_threshold : context -> Toggle_vote.Ema.t + val toggle_vote_ema_thresholds : context -> Toggle_vote.Emas.t val minimal_block_delay : context -> Period.t diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml index a0878abca5bb..105b8020d984 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.ml @@ -55,7 +55,7 @@ type t = { min_proposal_quorum : int32; liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : Toggle_vote_ema_repr.t; + toggle_vote_ema_thresholds : Toggle_vote_emas_repr.t; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; delay_increment_per_round : Period_repr.t; @@ -120,16 +120,16 @@ let encoding = c.cost_per_byte, c.hard_storage_limit_per_operation, c.quorum_min ), - ( ( c.quorum_max, - c.min_proposal_quorum, - c.liquidity_baking_subsidy, - c.liquidity_baking_sunset_level, - c.liquidity_baking_toggle_ema_threshold, - c.max_operations_time_to_live, - c.minimal_block_delay, - c.delay_increment_per_round, - c.consensus_committee_size, - c.consensus_threshold ), + ( ( ( c.quorum_max, + c.min_proposal_quorum, + c.liquidity_baking_subsidy, + c.liquidity_baking_sunset_level, + c.max_operations_time_to_live, + c.minimal_block_delay, + c.delay_increment_per_round, + c.consensus_committee_size, + c.consensus_threshold ), + c.toggle_vote_ema_thresholds ), ( ( c.minimal_participation_ratio, c.max_slashing_period, c.frozen_deposits_percentage, @@ -181,16 +181,16 @@ let encoding = cost_per_byte, hard_storage_limit_per_operation, quorum_min ), - ( ( quorum_max, - min_proposal_quorum, - liquidity_baking_subsidy, - liquidity_baking_sunset_level, - liquidity_baking_toggle_ema_threshold, - max_operations_time_to_live, - minimal_block_delay, - delay_increment_per_round, - consensus_committee_size, - consensus_threshold ), + ( ( ( quorum_max, + min_proposal_quorum, + liquidity_baking_subsidy, + liquidity_baking_sunset_level, + max_operations_time_to_live, + minimal_block_delay, + delay_increment_per_round, + consensus_committee_size, + consensus_threshold ), + toggle_vote_ema_thresholds ), ( ( minimal_participation_ratio, max_slashing_period, frozen_deposits_percentage, @@ -247,7 +247,7 @@ let encoding = min_proposal_quorum; liquidity_baking_subsidy; liquidity_baking_sunset_level; - liquidity_baking_toggle_ema_threshold; + toggle_vote_ema_thresholds; max_operations_time_to_live; minimal_block_delay; delay_increment_per_round; @@ -314,19 +314,18 @@ let encoding = (req "hard_storage_limit_per_operation" z) (req "quorum_min" int32)) (merge_objs - (obj10 - (req "quorum_max" int32) - (req "min_proposal_quorum" int32) - (req "liquidity_baking_subsidy" Tez_repr.encoding) - (req "liquidity_baking_sunset_level" int32) - (req - "liquidity_baking_toggle_ema_threshold" - Toggle_vote_ema_repr.encoding) - (req "max_operations_time_to_live" int16) - (req "minimal_block_delay" Period_repr.encoding) - (req "delay_increment_per_round" Period_repr.encoding) - (req "consensus_committee_size" int31) - (req "consensus_threshold" int31)) + (merge_objs + (obj9 + (req "quorum_max" int32) + (req "min_proposal_quorum" int32) + (req "liquidity_baking_subsidy" Tez_repr.encoding) + (req "liquidity_baking_sunset_level" int32) + (req "max_operations_time_to_live" int16) + (req "minimal_block_delay" Period_repr.encoding) + (req "delay_increment_per_round" Period_repr.encoding) + (req "consensus_committee_size" int31) + (req "consensus_threshold" int31)) + Toggle_vote_emas_repr.threshold_encoding) (merge_objs (obj6 (req "minimal_participation_ratio" Ratio_repr.encoding) diff --git a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli index 8dbb556fed7b..0ccbd3face76 100644 --- a/src/proto_alpha/lib_protocol/constants_parametric_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_parametric_repr.mli @@ -48,7 +48,7 @@ type t = { min_proposal_quorum : int32; liquidity_baking_subsidy : Tez_repr.t; liquidity_baking_sunset_level : int32; - liquidity_baking_toggle_ema_threshold : Toggle_vote_ema_repr.t; + toggle_vote_ema_thresholds : Toggle_vote_emas_repr.t; max_operations_time_to_live : int; minimal_block_delay : Period_repr.t; delay_increment_per_round : Period_repr.t; diff --git a/src/proto_alpha/lib_protocol/constants_storage.ml b/src/proto_alpha/lib_protocol/constants_storage.ml index a6bb076a4844..0966b7056b32 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.ml +++ b/src/proto_alpha/lib_protocol/constants_storage.ml @@ -108,9 +108,9 @@ let liquidity_baking_sunset_level c = let constants = Raw_context.constants c in constants.liquidity_baking_sunset_level -let liquidity_baking_toggle_ema_threshold c = +let toggle_vote_ema_thresholds c = let constants = Raw_context.constants c in - constants.liquidity_baking_toggle_ema_threshold + constants.toggle_vote_ema_thresholds let parametric c = Raw_context.constants c diff --git a/src/proto_alpha/lib_protocol/constants_storage.mli b/src/proto_alpha/lib_protocol/constants_storage.mli index df5c0a211554..28d723b62f8e 100644 --- a/src/proto_alpha/lib_protocol/constants_storage.mli +++ b/src/proto_alpha/lib_protocol/constants_storage.mli @@ -72,8 +72,7 @@ val liquidity_baking_subsidy : Raw_context.t -> Tez_repr.t val liquidity_baking_sunset_level : Raw_context.t -> int32 -val liquidity_baking_toggle_ema_threshold : - Raw_context.t -> Toggle_vote_ema_repr.t +val toggle_vote_ema_thresholds : Raw_context.t -> Toggle_vote_emas_repr.t val parametric : Raw_context.t -> Constants_parametric_repr.t diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml index 18f584cdc821..11ea09ef7d84 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml @@ -53,7 +53,7 @@ let update_toggle_ema ctxt ~toggle_vote = let check_ema_below_threshold ctxt ema = Toggle_vote_ema_repr.( - ema < Constants_storage.liquidity_baking_toggle_ema_threshold ctxt) + ema < (Constants_storage.toggle_vote_ema_thresholds ctxt).liquidity_baking) let on_subsidy_allowed ctxt toggle_vote_emas f = let open Toggle_vote_emas_repr in diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index 4c0712fd9a92..b15133c2a3fb 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -927,8 +927,8 @@ let prepare_first_block ~level ~timestamp ctxt = min_proposal_quorum = c.min_proposal_quorum; liquidity_baking_subsidy = c.liquidity_baking_subsidy; liquidity_baking_sunset_level = c.liquidity_baking_sunset_level; - liquidity_baking_toggle_ema_threshold = - c.liquidity_baking_toggle_ema_threshold; + toggle_vote_ema_thresholds = + {liquidity_baking = c.liquidity_baking_toggle_ema_threshold}; minimal_block_delay = c.minimal_block_delay; delay_increment_per_round = c.delay_increment_per_round; consensus_committee_size = c.consensus_committee_size; -- GitLab From cc2ff011152f077daf99bf9b4840cbc9d4971e85 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 17:17:05 +0200 Subject: [PATCH 41/48] Proto/Per_block_vote: prepare block header for multiple vote --- src/lib_store/test/alpha_utils.ml | 5 +- src/proto_alpha/lib_client/mockup.ml | 2 +- src/proto_alpha/lib_delegate/block_forge.ml | 4 +- .../test/mockup_simulator/mockup_simulator.ml | 7 +- src/proto_alpha/lib_plugin/plugin.ml | 42 +++++------ src/proto_alpha/lib_protocol/TEZOS_PROTOCOL | 3 +- src/proto_alpha/lib_protocol/alpha_context.ml | 6 +- .../lib_protocol/alpha_context.mli | 24 ++++-- src/proto_alpha/lib_protocol/apply.ml | 21 +++--- src/proto_alpha/lib_protocol/apply.mli | 2 +- .../lib_protocol/block_header_repr.ml | 39 +++++----- .../lib_protocol/block_header_repr.mli | 2 +- src/proto_alpha/lib_protocol/dune | 15 ++-- src/proto_alpha/lib_protocol/init_storage.ml | 3 +- .../liquidity_baking_migration.ml | 18 ----- .../liquidity_baking_migration.mli | 4 - .../lib_protocol/liquidity_baking_storage.ml | 20 +---- .../lib_protocol/liquidity_baking_storage.mli | 12 +-- src/proto_alpha/lib_protocol/main.ml | 6 +- .../lib_protocol/per_block_vote_repr.ml | 59 +++++++++++++++ ...baking_repr.ml => per_block_vote_repr.mli} | 25 +++++-- .../lib_protocol/per_block_vote_storage.ml | 74 +++++++++++++++++++ ...ng_repr.mli => per_block_vote_storage.mli} | 34 +++++---- .../lib_protocol/test/helpers/block.ml | 43 +++++------ .../lib_protocol/test/helpers/block.mli | 14 ++-- .../test/integration/test_liquidity_baking.ml | 42 +++++------ .../lib_protocol/toggle_vote_emas_repr.ml | 2 + .../lib_protocol/toggle_vote_emas_repr.mli | 6 ++ 28 files changed, 323 insertions(+), 211 deletions(-) create mode 100644 src/proto_alpha/lib_protocol/per_block_vote_repr.ml rename src/proto_alpha/lib_protocol/{liquidity_baking_repr.ml => per_block_vote_repr.mli} (73%) create mode 100644 src/proto_alpha/lib_protocol/per_block_vote_storage.ml rename src/proto_alpha/lib_protocol/{liquidity_baking_repr.mli => per_block_vote_storage.mli} (68%) diff --git a/src/lib_store/test/alpha_utils.ml b/src/lib_store/test/alpha_utils.ml index 0acb15307815..13620a233d96 100644 --- a/src/lib_store/test/alpha_utils.ml +++ b/src/lib_store/test/alpha_utils.ml @@ -259,15 +259,14 @@ module Forge = struct let make_contents ~payload_hash ~payload_round ?(proof_of_work_nonce = default_proof_of_work_nonce) - ?(liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass) ~seed_nonce_hash - () = + ?(per_block_vote = Per_block_vote.all_pass) ~seed_nonce_hash () = Block_header. { payload_hash; payload_round; proof_of_work_nonce; seed_nonce_hash; - liquidity_baking_toggle_vote; + per_block_vote; } let make_shell ~level ~predecessor ~timestamp ~fitness ~operations_hash diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml index 199cd0e347d6..d4da7daf7395 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -1480,7 +1480,7 @@ let mem_init : payload_hash; seed_nonce_hash = None; proof_of_work_nonce; - liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass; + per_block_vote = Per_block_vote.all_pass; } in let unsigned_bytes = diff --git a/src/proto_alpha/lib_delegate/block_forge.ml b/src/proto_alpha/lib_delegate/block_forge.ml index 8efc10394526..9970a0ba855f 100644 --- a/src/proto_alpha/lib_delegate/block_forge.ml +++ b/src/proto_alpha/lib_delegate/block_forge.ml @@ -50,7 +50,7 @@ let forge_faked_protocol_data ?(payload_hash = Block_payload_hash.zero) payload_round; seed_nonce_hash; proof_of_work_nonce = Baking_pow.empty_proof_of_work_nonce; - liquidity_baking_toggle_vote; + per_block_vote = {liquidity_baking = liquidity_baking_toggle_vote}; }; signature = Signature.zero; } @@ -378,7 +378,7 @@ let forge (cctxt : #Protocol_client_context.full) ~chain_id ~pred_info payload_round; seed_nonce_hash; proof_of_work_nonce; - liquidity_baking_toggle_vote; + per_block_vote = {liquidity_baking = liquidity_baking_toggle_vote}; }) >>=? fun contents -> let unsigned_block_header = 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 001336b30a94..c8e54388d813 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 @@ -823,8 +823,11 @@ let genesis_protocol_data (baker_sk : Signature.secret_key) payload_round = Alpha_context.Round.zero; proof_of_work_nonce; seed_nonce_hash = None; - liquidity_baking_toggle_vote = - Baking_configuration.default_liquidity_baking_toggle_vote; + per_block_vote = + { + liquidity_baking = + Baking_configuration.default_liquidity_baking_toggle_vote; + }; } in let unsigned_header = diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index 8be85e55d1e2..8f7fda80114a 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -3676,18 +3676,17 @@ module RPC = struct ~description:"Forge the protocol-specific part of a block header" ~query:RPC_query.empty ~input: - (obj5 - (req "payload_hash" Block_payload_hash.encoding) - (req "payload_round" Round.encoding) - (opt "nonce_hash" Nonce_hash.encoding) - (dft - "proof_of_work_nonce" - (Fixed.bytes Alpha_context.Constants.proof_of_work_nonce_size) - empty_proof_of_work_nonce) - (dft - "liquidity_baking_toggle_vote" - Toggle_vote.encoding - Toggle_pass)) + (merge_objs + (obj4 + (req "payload_hash" Block_payload_hash.encoding) + (req "payload_round" Round.encoding) + (opt "nonce_hash" Nonce_hash.encoding) + (dft + "proof_of_work_nonce" + (Fixed.bytes + Alpha_context.Constants.proof_of_work_nonce_size) + empty_proof_of_work_nonce)) + Per_block_vote.dft_encoding) ~output:(obj1 (req "protocol_data" bytes)) RPC_path.(path / "protocol_data") @@ -3799,11 +3798,8 @@ module RPC = struct S.protocol_data (fun () - ( payload_hash, - payload_round, - seed_nonce_hash, - proof_of_work_nonce, - liquidity_baking_toggle_vote ) + ( (payload_hash, payload_round, seed_nonce_hash, proof_of_work_nonce), + per_block_vote ) -> return (Data_encoding.Binary.to_bytes_exn @@ -3813,7 +3809,7 @@ module RPC = struct payload_round; seed_nonce_hash; proof_of_work_nonce; - liquidity_baking_toggle_vote; + per_block_vote; })) ; Registration.register0_noctxt ~chunked:true @@ -4002,18 +3998,14 @@ module RPC = struct let protocol_data ctxt block ?(payload_hash = Block_payload_hash.zero) ?(payload_round = Round.zero) ?seed_nonce_hash - ?(proof_of_work_nonce = empty_proof_of_work_nonce) - ~liquidity_baking_toggle_vote () = + ?(proof_of_work_nonce = empty_proof_of_work_nonce) ~toggle_vote () = RPC_context.make_call0 S.protocol_data ctxt block () - ( payload_hash, - payload_round, - seed_nonce_hash, - proof_of_work_nonce, - liquidity_baking_toggle_vote ) + ( (payload_hash, payload_round, seed_nonce_hash, proof_of_work_nonce), + toggle_vote ) end module Parse = struct diff --git a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL index 927736c13d07..5c12a4d2a9c4 100644 --- a/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL +++ b/src/proto_alpha/lib_protocol/TEZOS_PROTOCOL @@ -32,6 +32,7 @@ "Toggle_vote_repr", "Toggle_vote_ema_repr", "Toggle_vote_emas_repr", + "Per_block_vote_repr", "Constants_parametric_repr", "Constants_parametric_previous_repr", "Constants_repr", @@ -73,7 +74,6 @@ "Tx_rollup_state_repr", "Bond_id_repr", "Vote_repr", - "Liquidity_baking_repr", "Block_header_repr", "Destination_repr", "Operation_repr", @@ -125,6 +125,7 @@ "Bootstrap_storage", "Vote_storage", + "Per_block_vote_storage", "Ticket_storage", "Liquidity_baking_storage", "Liquidity_baking_cpmm", diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index bb578c88e7c0..3198aaa7da6b 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -103,6 +103,11 @@ module Toggle_vote = struct include Toggle_vote_repr end +module Per_block_vote = struct + include Per_block_vote_repr + include Per_block_vote_storage +end + module Block_payload = struct include Block_payload_repr end @@ -536,7 +541,6 @@ let description = Raw_context.description module Parameters = Parameters_repr module Liquidity_baking = struct - include Liquidity_baking_repr include Liquidity_baking_storage end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index b7e17662055e..0cc2d5c544b7 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -736,8 +736,6 @@ module Toggle_vote : sig module Internal_for_tests : sig val to_int32 : t -> Int32.t - - val of_int32_exn : Int32.t -> t end end @@ -758,6 +756,21 @@ module Toggle_vote : sig val encoding : t Data_encoding.t end +module Per_block_vote : sig + type t = {liquidity_baking : Toggle_vote.t} + + val encoding : t Data_encoding.t + + val dft_encoding : t Data_encoding.t + + val all_pass : t + + val update : context -> t -> (context * Toggle_vote.Emas.t) tzresult Lwt.t + + val below_threshold : + context -> Toggle_vote.Emas.t -> Toggle_vote.Name.t -> bool +end + module Constants : sig (** Fixed constants *) type fixed @@ -2821,7 +2834,7 @@ module Block_header : sig payload_round : Round.t; seed_nonce_hash : Nonce_hash.t option; proof_of_work_nonce : bytes; - liquidity_baking_toggle_vote : Toggle_vote.t; + per_block_vote : Per_block_vote.t; } type protocol_data = {contents : contents; signature : signature} @@ -3603,11 +3616,6 @@ end module Liquidity_baking : sig val get_cpmm_address : context -> Contract_hash.t tzresult Lwt.t - val update_toggle_ema : - context -> - toggle_vote:Toggle_vote.t -> - (context * Toggle_vote.Emas.t) tzresult Lwt.t - val on_subsidy_allowed : context -> Toggle_vote.Emas.t -> diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 96f4760ff625..2a01c4956492 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -3686,8 +3686,7 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level ~endorsement_level:predecessor_level ~preendorsement_level:current_level >>=? fun ctxt -> - let toggle_vote = protocol_data.liquidity_baking_toggle_vote in - Liquidity_baking.update_toggle_ema ctxt ~toggle_vote + Per_block_vote.update ctxt protocol_data.per_block_vote >>=? fun (ctxt, toggle_vote_emas) -> apply_liquidity_baking_subsidy ctxt toggle_vote_emas >|=? fun (ctxt, liquidity_baking_operations_results) -> @@ -3701,7 +3700,7 @@ let begin_full_construction ctxt ~predecessor_timestamp ~predecessor_level toggle_vote_emas; } -let begin_partial_construction ctxt ~predecessor_level ~toggle_vote = +let begin_partial_construction ctxt ~predecessor_level ~per_block_vote = (* In the mempool, only consensus operations for [predecessor_level] (that is, head's level) are allowed, contrary to block validation where endorsements are for the previous level and @@ -3711,10 +3710,10 @@ let begin_partial_construction ctxt ~predecessor_level ~toggle_vote = ~endorsement_level:predecessor_level ~preendorsement_level:predecessor_level >>=? fun ctxt -> - Liquidity_baking.update_toggle_ema ctxt ~toggle_vote - >>=? fun (ctxt, toggle_vote_emas) -> - apply_liquidity_baking_subsidy ctxt toggle_vote_emas >>=? fun (ctxt, res) -> - return (ctxt, res, toggle_vote_emas) + Per_block_vote.update ctxt per_block_vote >>=? fun (ctxt, toggle_vote_emas) -> + apply_liquidity_baking_subsidy ctxt toggle_vote_emas + >|=? fun (ctxt, liquidity_baking_operations_results) -> + (ctxt, liquidity_baking_operations_results, toggle_vote_emas) let begin_application ctxt chain_id (block_header : Block_header.t) fitness ~predecessor_timestamp ~predecessor_level ~predecessor_round = @@ -3751,12 +3750,10 @@ let begin_application ctxt chain_id (block_header : Block_header.t) fitness ~endorsement_level:predecessor_level ~preendorsement_level:current_level >>=? fun ctxt -> - let toggle_vote = - block_header.Block_header.protocol_data.contents - .liquidity_baking_toggle_vote + let per_block_vote = + block_header.Block_header.protocol_data.contents.per_block_vote in - Liquidity_baking.update_toggle_ema ctxt ~toggle_vote - >>=? fun (ctxt, toggle_vote_emas) -> + Per_block_vote.update ctxt per_block_vote >>=? fun (ctxt, toggle_vote_emas) -> apply_liquidity_baking_subsidy ctxt toggle_vote_emas >|=? fun (ctxt, liquidity_baking_operations_results) -> ( ctxt, diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index 1a3357094201..2feda8443aa3 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -48,7 +48,7 @@ type error += val begin_partial_construction : context -> predecessor_level:Level.t -> - toggle_vote:Toggle_vote.t -> + per_block_vote:Per_block_vote.t -> (t * packed_successful_manager_operation_result list * Toggle_vote.Emas.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/block_header_repr.ml b/src/proto_alpha/lib_protocol/block_header_repr.ml index 2d4a5b90ce9e..0ed260094f70 100644 --- a/src/proto_alpha/lib_protocol/block_header_repr.ml +++ b/src/proto_alpha/lib_protocol/block_header_repr.ml @@ -30,7 +30,7 @@ type contents = { payload_round : Round_repr.t; seed_nonce_hash : Nonce_hash.t option; proof_of_work_nonce : bytes; - liquidity_baking_toggle_vote : Toggle_vote_repr.t; + per_block_vote : Per_block_vote_repr.t; } type protocol_data = {contents : contents; signature : Signature.t} @@ -76,33 +76,28 @@ let contents_encoding = payload_round; seed_nonce_hash; proof_of_work_nonce; - liquidity_baking_toggle_vote; + per_block_vote; } -> - ( payload_hash, - payload_round, - proof_of_work_nonce, - seed_nonce_hash, - liquidity_baking_toggle_vote )) - (fun ( payload_hash, - payload_round, - proof_of_work_nonce, - seed_nonce_hash, - liquidity_baking_toggle_vote ) -> + ( (payload_hash, payload_round, proof_of_work_nonce, seed_nonce_hash), + per_block_vote )) + (fun ( (payload_hash, payload_round, proof_of_work_nonce, seed_nonce_hash), + per_block_vote ) -> { payload_hash; payload_round; seed_nonce_hash; proof_of_work_nonce; - liquidity_baking_toggle_vote; + per_block_vote; }) - (obj5 - (req "payload_hash" Block_payload_hash.encoding) - (req "payload_round" Round_repr.encoding) - (req - "proof_of_work_nonce" - (Fixed.bytes Constants_repr.proof_of_work_nonce_size)) - (opt "seed_nonce_hash" Nonce_hash.encoding) - (req "liquidity_baking_toggle_vote" Toggle_vote_repr.encoding)) + (merge_objs + (obj4 + (req "payload_hash" Block_payload_hash.encoding) + (req "payload_round" Round_repr.encoding) + (req + "proof_of_work_nonce" + (Fixed.bytes Constants_repr.proof_of_work_nonce_size)) + (opt "seed_nonce_hash" Nonce_hash.encoding)) + Per_block_vote_repr.encoding) let protocol_data_encoding = let open Data_encoding in @@ -161,7 +156,7 @@ let max_header_length = proof_of_work_nonce = Bytes.make Constants_repr.proof_of_work_nonce_size '0'; seed_nonce_hash = Some Nonce_hash.zero; - liquidity_baking_toggle_vote = Toggle_pass; + per_block_vote = Per_block_vote_repr.all_pass; } in Data_encoding.Binary.length diff --git a/src/proto_alpha/lib_protocol/block_header_repr.mli b/src/proto_alpha/lib_protocol/block_header_repr.mli index d79972b756a7..bcfb81a241f2 100644 --- a/src/proto_alpha/lib_protocol/block_header_repr.mli +++ b/src/proto_alpha/lib_protocol/block_header_repr.mli @@ -30,7 +30,7 @@ type contents = { payload_round : Round_repr.t; seed_nonce_hash : Nonce_hash.t option; proof_of_work_nonce : bytes; - liquidity_baking_toggle_vote : Toggle_vote_repr.t; + per_block_vote : Per_block_vote_repr.t; } type protocol_data = {contents : contents; signature : Signature.t} diff --git a/src/proto_alpha/lib_protocol/dune b/src/proto_alpha/lib_protocol/dune index 4309e84fc15f..0a270c5b93a8 100644 --- a/src/proto_alpha/lib_protocol/dune +++ b/src/proto_alpha/lib_protocol/dune @@ -63,6 +63,7 @@ Toggle_vote_repr Toggle_vote_ema_repr Toggle_vote_emas_repr + Per_block_vote_repr Constants_parametric_repr Constants_parametric_previous_repr Constants_repr @@ -104,7 +105,6 @@ Tx_rollup_state_repr Bond_id_repr Vote_repr - Liquidity_baking_repr Block_header_repr Destination_repr Operation_repr @@ -151,6 +151,7 @@ Delegate_cycles Bootstrap_storage Vote_storage + Per_block_vote_storage Ticket_storage Liquidity_baking_storage Liquidity_baking_cpmm @@ -283,6 +284,7 @@ toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli + per_block_vote_repr.ml per_block_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -326,7 +328,6 @@ tx_rollup_state_repr.ml tx_rollup_state_repr.mli bond_id_repr.ml bond_id_repr.mli vote_repr.ml vote_repr.mli - liquidity_baking_repr.ml liquidity_baking_repr.mli block_header_repr.ml block_header_repr.mli destination_repr.ml destination_repr.mli operation_repr.ml operation_repr.mli @@ -374,6 +375,7 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli + per_block_vote_storage.ml per_block_vote_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml @@ -492,6 +494,7 @@ toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli + per_block_vote_repr.ml per_block_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -535,7 +538,6 @@ tx_rollup_state_repr.ml tx_rollup_state_repr.mli bond_id_repr.ml bond_id_repr.mli vote_repr.ml vote_repr.mli - liquidity_baking_repr.ml liquidity_baking_repr.mli block_header_repr.ml block_header_repr.mli destination_repr.ml destination_repr.mli operation_repr.ml operation_repr.mli @@ -583,6 +585,7 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli + per_block_vote_storage.ml per_block_vote_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml @@ -721,6 +724,7 @@ toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli + per_block_vote_repr.ml per_block_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -764,7 +768,6 @@ tx_rollup_state_repr.ml tx_rollup_state_repr.mli bond_id_repr.ml bond_id_repr.mli vote_repr.ml vote_repr.mli - liquidity_baking_repr.ml liquidity_baking_repr.mli block_header_repr.ml block_header_repr.mli destination_repr.ml destination_repr.mli operation_repr.ml operation_repr.mli @@ -812,6 +815,7 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli + per_block_vote_storage.ml per_block_vote_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml @@ -946,6 +950,7 @@ toggle_vote_repr.ml toggle_vote_repr.mli toggle_vote_ema_repr.ml toggle_vote_ema_repr.mli toggle_vote_emas_repr.ml toggle_vote_emas_repr.mli + per_block_vote_repr.ml per_block_vote_repr.mli constants_parametric_repr.ml constants_parametric_repr.mli constants_parametric_previous_repr.ml constants_parametric_previous_repr.mli @@ -989,7 +994,6 @@ tx_rollup_state_repr.ml tx_rollup_state_repr.mli bond_id_repr.ml bond_id_repr.mli vote_repr.ml vote_repr.mli - liquidity_baking_repr.ml liquidity_baking_repr.mli block_header_repr.ml block_header_repr.mli destination_repr.ml destination_repr.mli operation_repr.ml operation_repr.mli @@ -1037,6 +1041,7 @@ delegate_cycles.ml delegate_cycles.mli bootstrap_storage.ml bootstrap_storage.mli vote_storage.ml vote_storage.mli + per_block_vote_storage.ml per_block_vote_storage.mli ticket_storage.ml ticket_storage.mli liquidity_baking_storage.ml liquidity_baking_storage.mli liquidity_baking_cpmm.ml diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index d499e337fd92..07df4f632a74 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -109,6 +109,7 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = >>=? fun (ctxt, operation_results) -> Storage.Pending_migration.Operation_results.init ctxt operation_results >>=? fun ctxt -> + Per_block_vote_storage.init ctxt >>= fun ctxt -> return ( ctxt, commitments_balance_updates @ bootstrap_balance_updates @@ -120,7 +121,7 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = Storage.Tenderbake.First_level_of_protocol.update ctxt level >>=? fun ctxt -> Delegate_cycles.Migration_from_Jakarta.update ctxt >>=? fun ctxt -> - Liquidity_baking_migration.From_Jakarta.update ctxt >>=? fun ctxt -> + Per_block_vote_storage.Migration_from_Jakarta.update ctxt >>=? fun ctxt -> return (ctxt, [])) >>=? fun (ctxt, balance_updates) -> Receipt_repr.group_balance_updates balance_updates >>?= fun balance_updates -> diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml b/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml index 9736fc2c38d3..f3d77311b4a8 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_migration.ml @@ -198,11 +198,6 @@ let init ctxt ~typecheck = (* We use a custom origination nonce because it is unset when stitching from 009 *) let nonce = Operation_hash.hash_string ["Drip, drip, drip."] in let ctxt = Raw_context.init_origination_nonce ctxt nonce in - Storage.Toggle_vote_ema.init - ctxt - Liquidity_baking - Toggle_vote_ema_repr.Config.simple_off.initial - >>=? fun ctxt -> let current_level = Raw_level_repr.to_int32 (Level_storage.current ctxt).level in @@ -246,16 +241,3 @@ let init ctxt ~typecheck = (* Unsets the origination nonce, which is okay because this is called after other originations in stitching. *) let ctxt = Raw_context.unset_origination_nonce ctxt in (ctxt, [cpmm_result; lqt_result] @ token_result)) - -module From_Jakarta = struct - let update ctxt = - let open Lwt_tzresult_syntax in - let* lb_ema = - Storage.Liquidity_baking.Migration_from_Jakarta.Toggle_ema.get ctxt - in - let*! ctxt = - Storage.Liquidity_baking.Migration_from_Jakarta.Toggle_ema.remove ctxt - in - let* ctxt = Storage.Toggle_vote_ema.init ctxt Liquidity_baking lb_ema in - return ctxt -end diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli b/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli index 16a3ff5da48c..27059e493d50 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_migration.mli @@ -31,7 +31,3 @@ val init : ((Script_repr.t * Lazy_storage_diff.diffs option) * Raw_context.t) tzresult Lwt.t) -> (Raw_context.t * Migration_repr.origination_result list) tzresult Lwt.t - -module From_Jakarta : sig - val update : Raw_context.t -> Raw_context.t tzresult Lwt.t -end diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml index 11ea09ef7d84..3bebd14e68f1 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.ml @@ -24,12 +24,8 @@ (* *) (*****************************************************************************) -open Liquidity_baking_repr - let get_cpmm_address = Storage.Liquidity_baking.Cpmm_address.get -let get_toggle_ema ctxt = Storage.Toggle_vote_ema.get ctxt Liquidity_baking - let on_cpmm_exists ctxt f = get_cpmm_address ctxt >>=? fun cpmm_contract -> Contract_storage.exists ctxt (Contract_repr.Originated cpmm_contract) @@ -44,21 +40,9 @@ let check_below_sunset ctxt = let level = Raw_level_repr.to_int32 (Level_storage.current ctxt).level in Compare.Int32.(level < sunset_level) -let update_toggle_ema ctxt ~toggle_vote = - let open Toggle_vote_emas_repr in - get_toggle_ema ctxt >>=? fun old_ema -> - let new_ema = compute_new_ema ~toggle_vote old_ema in - Storage.Toggle_vote_ema.update ctxt Liquidity_baking new_ema >|=? fun ctxt -> - (ctxt, {liquidity_baking = new_ema}) - -let check_ema_below_threshold ctxt ema = - Toggle_vote_ema_repr.( - ema < (Constants_storage.toggle_vote_ema_thresholds ctxt).liquidity_baking) - -let on_subsidy_allowed ctxt toggle_vote_emas f = - let open Toggle_vote_emas_repr in +let on_subsidy_allowed ctxt emas f = if - check_ema_below_threshold ctxt toggle_vote_emas.liquidity_baking + Per_block_vote_storage.below_threshold ctxt emas Liquidity_baking && check_below_sunset ctxt then on_cpmm_exists ctxt f >|=? fun (ctxt, operation_results) -> diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli index f4c105ee6ceb..76163467c29d 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli +++ b/src/proto_alpha/lib_protocol/liquidity_baking_storage.mli @@ -24,19 +24,13 @@ (* *) (*****************************************************************************) -(** Get the address of the Constant-Product Market Maker receiving the +(** Get the address of the Constant-Product Market Maker receiving the Liquidity Baking subsidy *) val get_cpmm_address : Raw_context.t -> Contract_hash.t tzresult Lwt.t -val update_toggle_ema : - Raw_context.t -> - toggle_vote:Toggle_vote_repr.t -> - (Raw_context.t * Toggle_vote_emas_repr.t) tzresult Lwt.t - -(** [on_subsidy_allowed ctxt ~toggle_vote f] updates the toggle EMA according to - [toggle_vote]. Then the callback function [f] is called if the following +(** [on_subsidy_allowed ctxt emas f]. The callback function [f] is called if the following conditions are met: - - the updated EMA is below the threshold, + - the liquidity baking toggle vote EMA is below the threshold, - the current level is below the sunset level, - the CPMM contract exists. diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index aac64e47f749..35e78d70b486 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -262,8 +262,8 @@ let begin_construction ~chain_id ~predecessor_context:ctxt | None -> Alpha_context.Fitness.round_from_raw predecessor_fitness >>?= fun predecessor_round -> - let toggle_vote = Alpha_context.Toggle_vote.Toggle_pass in - Apply.begin_partial_construction ctxt ~predecessor_level ~toggle_vote + let per_block_vote = Alpha_context.Per_block_vote.all_pass in + Apply.begin_partial_construction ctxt ~predecessor_level ~per_block_vote >>=? fun (ctxt, liquidity_baking_operations_results, toggle_vote_emas) -> let mode = Partial_construction @@ -772,7 +772,7 @@ let init chain_id ctxt block_header = { payload_hash = Block_payload_hash.zero; payload_round = Alpha_context.Round.zero; - liquidity_baking_toggle_vote = Alpha_context.Toggle_vote.Toggle_pass; + per_block_vote = Alpha_context.Per_block_vote.all_pass; seed_nonce_hash = None; proof_of_work_nonce = Bytes.make Constants_repr.proof_of_work_nonce_size '0'; diff --git a/src/proto_alpha/lib_protocol/per_block_vote_repr.ml b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml new file mode 100644 index 000000000000..12705c370725 --- /dev/null +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml @@ -0,0 +1,59 @@ +(*****************************************************************************) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Toggle_vote_name_repr +open Toggle_vote_repr + +type t = {liquidity_baking : Toggle_vote_repr.t} + +let encoding = + (* Warning: when adding a second vote, please use compact encodings. *) + let open Data_encoding in + conv + (fun {liquidity_baking} -> liquidity_baking) + (fun liquidity_baking -> {liquidity_baking}) + (obj1 (req "liquidity_baking_toggle_vote" Toggle_vote_repr.encoding)) + +let dft_encoding = + let open Data_encoding in + conv + (fun {liquidity_baking} -> liquidity_baking) + (fun liquidity_baking -> {liquidity_baking}) + (obj1 + (dft + "liquidity_baking_toggle_vote" + Toggle_vote_repr.encoding + Toggle_pass)) + +let all_pass = {liquidity_baking = Toggle_pass} + +let update ballot (emas : Toggle_vote_emas_repr.t) : Toggle_vote_emas_repr.t = + { + liquidity_baking = + Toggle_vote_ema_repr.update + (Toggle_vote_emas_repr.get_config Liquidity_baking) + ballot.liquidity_baking + emas.liquidity_baking; + } diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli similarity index 73% rename from src/proto_alpha/lib_protocol/liquidity_baking_repr.ml rename to src/proto_alpha/lib_protocol/per_block_vote_repr.mli index faf6d89a9883..423ba19885ad 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_repr.ml +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli @@ -1,8 +1,7 @@ (*****************************************************************************) (* *) (* Open Source License *) -(* Copyright (c) 2021 Tocqueville Group, Inc. *) -(* Copyright (c) 2022 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,9 +23,19 @@ (* *) (*****************************************************************************) -(* Invariant: 0 <= ema <= 2_000_000 *) -let compute_new_ema ~toggle_vote ema = - Toggle_vote_ema_repr.update - Toggle_vote_ema_repr.Config.simple_off - toggle_vote - ema +(** A per-block ballot. *) +type t = {liquidity_baking : Toggle_vote_repr.t} + +(** Encoding for a per-block ballot where all toggle-vote fields are required. *) +val encoding : t Data_encoding.t + +(** Encoding for a per-block ballot where all toggle-vote fields have + [Toggle_pass] as default value . *) +val dft_encoding : t Data_encoding.t + +(** A per block ballot where all toggle-votes are [Toggle_pass]. *) +val all_pass : t + +(** Given a ballot and the old EMAs, compute the new EMAs. + See [Toggle_vote_ema_repr] for the computation details. *) +val update : t -> Toggle_vote_emas_repr.t -> Toggle_vote_emas_repr.t diff --git a/src/proto_alpha/lib_protocol/per_block_vote_storage.ml b/src/proto_alpha/lib_protocol/per_block_vote_storage.ml new file mode 100644 index 000000000000..3a60f380e24d --- /dev/null +++ b/src/proto_alpha/lib_protocol/per_block_vote_storage.ml @@ -0,0 +1,74 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2022 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 get_ema ctxt vote = + let open Lwt_tzresult_syntax in + let* ema = Storage.Toggle_vote_ema.find ctxt vote in + match ema with + | None -> return (Toggle_vote_emas_repr.get_config vote).initial + | Some ema -> return ema + +let set_ema = Storage.Toggle_vote_ema.add + +let get_emas ctxt = + let open Lwt_tzresult_syntax in + let* liquidity_baking = get_ema ctxt Liquidity_baking in + return {Toggle_vote_emas_repr.liquidity_baking} + +let set_all ctxt emas = + let open Lwt_result_syntax in + let {Toggle_vote_emas_repr.liquidity_baking} = emas in + let*! ctxt = set_ema ctxt Liquidity_baking liquidity_baking in + Lwt.return ctxt + +let update ctxt ballots = + let open Lwt_tzresult_syntax in + let* emas = get_emas ctxt in + let emas = Per_block_vote_repr.update ballots emas in + let*! ctxt = set_all ctxt emas in + return (ctxt, emas) + +let below_threshold ctxt emas vote = + let current = Toggle_vote_emas_repr.get vote emas in + let thresholds = Constants_storage.toggle_vote_ema_thresholds ctxt in + let threshold = Toggle_vote_emas_repr.get vote thresholds in + Toggle_vote_ema_repr.(current < threshold) + +let init ctxt = set_all ctxt Toggle_vote_emas_repr.initial + +module Migration_from_Jakarta = struct + let update ctxt = + let open Lwt_tzresult_syntax in + let*! ctxt = init ctxt in + let* lb_ema = + Storage.Liquidity_baking.Migration_from_Jakarta.Toggle_ema.get ctxt + in + let*! ctxt = + Storage.Liquidity_baking.Migration_from_Jakarta.Toggle_ema.remove ctxt + in + let*! ctxt = set_ema ctxt Liquidity_baking lb_ema in + return ctxt +end diff --git a/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli b/src/proto_alpha/lib_protocol/per_block_vote_storage.mli similarity index 68% rename from src/proto_alpha/lib_protocol/liquidity_baking_repr.mli rename to src/proto_alpha/lib_protocol/per_block_vote_storage.mli index 6f3676b3824d..0a781ef8069e 100644 --- a/src/proto_alpha/lib_protocol/liquidity_baking_repr.mli +++ b/src/proto_alpha/lib_protocol/per_block_vote_storage.mli @@ -1,8 +1,8 @@ (*****************************************************************************) (* *) (* Open Source License *) -(* Copyright (c) 2021 Tocqueville Group, Inc. *) (* Copyright (c) 2022 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,18 +24,24 @@ (* *) (*****************************************************************************) -(** [compute_new_ema ~toggle_vote old_ema] returns the value [new_ema] of the - exponential moving average [old_ema] updated by the vote [toggle_vote]. +(** Reads the current EMA value for all pending toggle votes. *) +val get_emas : Raw_context.t -> Toggle_vote_emas_repr.t tzresult Lwt.t - It is updated as follows: - - if [toggle_vote] is [LB_pass] then [new_ema] = [old_ema], - - if [toggle_vote] is [LB_off], then [new_ema] = (1999 * ema[n] // 2000) + 1,000,000, - - if [toggle_vote] is [LB_on], then [new_ema] = (1999 * ema[n] // 2000). +(** Updates in the context the current EMA value of each pending + toggle votes, and return the new values. *) +val update : + Raw_context.t -> + Per_block_vote_repr.t -> + (Raw_context.t * Toggle_vote_emas_repr.t) tzresult Lwt.t - The multiplication is performed in [Z.t] to avoid overflows, division is - rounded toward 1,000,000,000 (the middle of the interval). - *) -val compute_new_ema : - toggle_vote:Toggle_vote_repr.t -> - Toggle_vote_ema_repr.t -> - Toggle_vote_ema_repr.t +(** Checks that the current EMA value of a given toggle vote + is below the expected threshold. *) +val below_threshold : + Raw_context.t -> Toggle_vote_emas_repr.t -> Toggle_vote_name_repr.t -> bool + +(** Initializes the context with the initial EMA value for all toggle votes. *) +val init : Raw_context.t -> Raw_context.t 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/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index f94a51f4c3ee..cb887e14bf01 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -123,16 +123,15 @@ module Forge = struct Bytes.create Constants.proof_of_work_nonce_size let make_contents ?(proof_of_work_nonce = default_proof_of_work_nonce) - ~payload_hash ~payload_round - ?(liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass) ~seed_nonce_hash - () = + ~payload_hash ~payload_round ?(per_block_vote = Per_block_vote.all_pass) + ~seed_nonce_hash () = Block_header. { payload_hash; payload_round; proof_of_work_nonce; seed_nonce_hash; - liquidity_baking_toggle_vote; + per_block_vote; } let make_shell ~level ~predecessor ~timestamp ~fitness ~operations_hash = @@ -182,8 +181,8 @@ module Forge = struct Array.to_list t let forge_header ?(locked_round = None) ?(payload_round = None) - ?(policy = By_round 0) ?timestamp ?(operations = []) - ?liquidity_baking_toggle_vote pred = + ?(policy = By_round 0) ?timestamp ?(operations = []) ?per_block_vote pred + = let pred_fitness = match Fitness.from_raw pred.header.shell.fitness with | Ok pred_fitness -> pred_fitness @@ -233,7 +232,7 @@ module Forge = struct let contents = make_contents ~seed_nonce_hash - ?liquidity_baking_toggle_vote + ?per_block_vote ~payload_hash ~payload_round () @@ -242,12 +241,12 @@ module Forge = struct (* compatibility only, needed by incremental *) let contents ?(proof_of_work_nonce = default_proof_of_work_nonce) - ?seed_nonce_hash ?(liquidity_baking_toggle_vote = Toggle_vote.Toggle_pass) - ~payload_hash ~payload_round () = + ?seed_nonce_hash ?(per_block_vote = Per_block_vote.all_pass) ~payload_hash + ~payload_round () = { Block_header.proof_of_work_nonce; seed_nonce_hash; - liquidity_baking_toggle_vote; + per_block_vote; payload_hash; payload_round; } @@ -682,7 +681,7 @@ let apply header ?(operations = []) pred = >>=? fun (t, _metadata) -> return t let bake_with_metadata ?locked_round ?policy ?timestamp ?operation ?operations - ?payload_round ?check_size ~baking_mode ?liquidity_baking_toggle_vote pred = + ?payload_round ?check_size ~baking_mode ?per_block_vote pred = let operations = match (operation, operations) with | Some op, Some ops -> Some (op :: ops) @@ -696,15 +695,14 @@ let bake_with_metadata ?locked_round ?policy ?timestamp ?operation ?operations ?timestamp ?policy ?operations - ?liquidity_baking_toggle_vote + ?per_block_vote pred >>=? fun header -> Forge.sign_header header >>=? fun header -> apply_with_metadata ?policy ?check_size ~baking_mode header ?operations pred let bake ?(baking_mode = Application) ?payload_round ?locked_round ?policy - ?timestamp ?operation ?operations ?liquidity_baking_toggle_vote ?check_size - pred = + ?timestamp ?operation ?operations ?per_block_vote ?check_size pred = bake_with_metadata ?payload_round ~baking_mode @@ -713,7 +711,7 @@ let bake ?(baking_mode = Application) ?payload_round ?locked_round ?policy ?timestamp ?operation ?operations - ?liquidity_baking_toggle_vote + ?per_block_vote ?check_size pred >>=? fun (t, (_metadata : block_header_metadata)) -> return t @@ -723,18 +721,17 @@ let bake ?(baking_mode = Application) ?payload_round ?locked_round ?policy (* This function is duplicated from Context to avoid a cyclic dependency *) let get_constants b = Alpha_services.Constants.all rpc_ctxt b -let bake_n ?(baking_mode = Application) ?policy ?liquidity_baking_toggle_vote n - b = +let bake_n ?(baking_mode = Application) ?policy ?per_block_vote n b = List.fold_left_es - (fun b _ -> bake ~baking_mode ?policy ?liquidity_baking_toggle_vote b) + (fun b _ -> bake ~baking_mode ?policy ?per_block_vote b) b (1 -- n) let bake_n_with_all_balance_updates ?(baking_mode = Application) ?policy - ?liquidity_baking_toggle_vote n b = + ?per_block_vote n b = List.fold_left_es (fun (b, balance_updates_rev) _ -> - bake_with_metadata ~baking_mode ?policy ?liquidity_baking_toggle_vote b + bake_with_metadata ~baking_mode ?policy ?per_block_vote b >>=? fun (b, metadata) -> let balance_updates_rev = List.rev_append metadata.balance_updates balance_updates_rev @@ -815,12 +812,12 @@ let bake_n_with_origination_results ?(baking_mode = Application) ?policy n b = (1 -- n) >|=? fun (b, origination_results_rev) -> (b, List.rev origination_results_rev) -let bake_n_with_liquidity_baking_toggle_ema ?(baking_mode = Application) ?policy - ?liquidity_baking_toggle_vote n b = +let bake_n_with_toggle_ema ?(baking_mode = Application) ?policy ?per_block_vote + n b = let initial_emas = Toggle_vote.Emas.initial in List.fold_left_es (fun (b, _toggle_ema) _ -> - bake_with_metadata ~baking_mode ?policy ?liquidity_baking_toggle_vote b + bake_with_metadata ~baking_mode ?policy ?per_block_vote b >|=? fun (b, metadata) -> (b, metadata.toggle_vote_emas)) (b, initial_emas) (1 -- n) diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index d8c5a8077eb1..c4cb629a45e2 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -68,7 +68,7 @@ module Forge : sig val contents : ?proof_of_work_nonce:Bytes.t -> ?seed_nonce_hash:Nonce_hash.t -> - ?liquidity_baking_toggle_vote:Toggle_vote.t -> + ?per_block_vote:Per_block_vote.t -> payload_hash:Block_payload_hash.t -> payload_round:Round.t -> unit -> @@ -86,7 +86,7 @@ module Forge : sig ?policy:baker_policy -> ?timestamp:Timestamp.time -> ?operations:Operation.packed list -> - ?liquidity_baking_toggle_vote:Toggle_vote.t -> + ?per_block_vote:Per_block_vote.t -> t -> header tzresult Lwt.t @@ -189,7 +189,7 @@ val bake : ?timestamp:Timestamp.time -> ?operation:Operation.packed -> ?operations:Operation.packed list -> - ?liquidity_baking_toggle_vote:Toggle_vote.t -> + ?per_block_vote:Per_block_vote.t -> ?check_size:bool -> t -> t tzresult Lwt.t @@ -198,7 +198,7 @@ val bake : val bake_n : ?baking_mode:baking_mode -> ?policy:baker_policy -> - ?liquidity_baking_toggle_vote:Toggle_vote.t -> + ?per_block_vote:Per_block_vote.t -> int -> t -> block tzresult Lwt.t @@ -208,7 +208,7 @@ val bake_n : val bake_n_with_all_balance_updates : ?baking_mode:baking_mode -> ?policy:baker_policy -> - ?liquidity_baking_toggle_vote:Toggle_vote.t -> + ?per_block_vote:Per_block_vote.t -> int -> t -> (block * Alpha_context.Receipt.balance_updates) tzresult Lwt.t @@ -228,10 +228,10 @@ val bake_n_with_origination_results : Lwt.t (** Version of bake_n that returns the liquidity baking toggle EMA after [n] blocks. **) -val bake_n_with_liquidity_baking_toggle_ema : +val bake_n_with_toggle_ema : ?baking_mode:baking_mode -> ?policy:baker_policy -> - ?liquidity_baking_toggle_vote:Toggle_vote.t -> + ?per_block_vote:Per_block_vote.t -> int -> t -> (block * Alpha_context.Toggle_vote.Emas.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml index e99b6e4b6ed4..586de3f8205a 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml @@ -147,6 +147,12 @@ let liquidity_baking_sunset_level n () = expected_credit >>=? fun () -> return_unit +let lb_pass = Alpha_context.Per_block_vote.all_pass + +let lb_off = {Alpha_context.Per_block_vote.liquidity_baking = Toggle_off} + +let lb_on = {Alpha_context.Per_block_vote.liquidity_baking = Toggle_on} + (* Test that subsidy shuts off at correct level alternating baking blocks with liquidity_baking_toggle_vote set to [LB_on], [LB_off], and [LB_pass] followed by [bake_after_toggle] blocks with it set to [LB_pass]. *) (* Expected level is roughly 2*(log(1-1/(2*p)) / log(0.999)) where [p] is the proportion [LB_off / (LB_on + LB_off)]. *) @@ -160,19 +166,15 @@ let liquidity_baking_toggle ~n_vote_on ~n_vote_off ~n_vote_pass expected_level >>=? fun liquidity_baking_subsidy -> let rec bake_stopping blk i = if i < expected_level then - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_on n_vote_on blk - >>=? fun blk -> - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_off n_vote_off blk - >>=? fun blk -> - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass n_vote_pass blk - >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_on n_vote_on blk >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_off n_vote_off blk >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_pass n_vote_pass blk >>=? fun blk -> bake_stopping blk (i + n_vote_on + n_vote_off + n_vote_pass) else return blk in bake_stopping blk 0 >>=? fun blk -> Context.Contract.balance (B blk) liquidity_baking >>=? fun balance -> - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass bake_after blk - >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_pass bake_after blk >>=? fun blk -> Assert.balance_is ~loc:__LOC__ (B blk) liquidity_baking balance >>=? fun () -> liquidity_baking_subsidy *? Int64.of_int (expected_level - 1) >>?= fun expected_final_balance -> @@ -207,8 +209,8 @@ let liquidity_baking_toggle_50 n () = Context.Contract.balance (B blk) liquidity_baking >>=? fun old_balance -> let rec bake_50_percent_escaping blk i = if i < Int32.to_int sunset + n then - Block.bake ~liquidity_baking_toggle_vote:Toggle_on blk >>=? fun blk -> - Block.bake ~liquidity_baking_toggle_vote:Toggle_off blk >>=? fun blk -> + Block.bake ~per_block_vote:lb_on blk >>=? fun blk -> + Block.bake ~per_block_vote:lb_off blk >>=? fun blk -> bake_50_percent_escaping blk (i + 2) else return blk in @@ -233,18 +235,16 @@ let liquidity_baking_restart n_votes n () = Context.init1 ~consensus_threshold:0 () >>=? fun (blk, _contract) -> Context.get_liquidity_baking_cpmm_address (B blk) >>=? fun liquidity_baking -> let liquidity_baking = Alpha_context.Contract.Originated liquidity_baking in - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_off n_votes blk - >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_off n_votes blk >>=? fun blk -> Context.Contract.balance (B blk) liquidity_baking >>=? fun balance_when_paused -> - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass n blk >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_pass n blk >>=? fun blk -> Assert.balance_is ~loc:__LOC__ (B blk) liquidity_baking balance_when_paused >>=? fun () -> - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_on n_votes blk - >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_on n_votes blk >>=? fun blk -> Context.Contract.balance (B blk) liquidity_baking >>=? fun balance_when_restarted -> - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_pass n blk >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_pass n blk >>=? fun blk -> Context.get_liquidity_baking_subsidy (B blk) >>=? fun liquidity_baking_subsidy -> liquidity_baking_subsidy *? Int64.of_int n >>?= fun expected_balance -> @@ -262,16 +262,14 @@ let liquidity_baking_toggle_ema n_vote_on n_vote_off level bake_after Context.init1 ~consensus_threshold:0 () >>=? fun (blk, _contract) -> let rec bake_escaping blk i = if i < level then - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_on n_vote_on blk - >>=? fun blk -> - Block.bake_n ~liquidity_baking_toggle_vote:Toggle_off n_vote_off blk - >>=? fun blk -> bake_escaping blk (i + n_vote_on + n_vote_off) + Block.bake_n ~per_block_vote:lb_on n_vote_on blk >>=? fun blk -> + Block.bake_n ~per_block_vote:lb_off n_vote_off blk >>=? fun blk -> + bake_escaping blk (i + n_vote_on + n_vote_off) else return blk in bake_escaping blk 0 >>=? fun blk -> (* We only need to return the toggle EMA at the end. *) - Block.bake_n_with_liquidity_baking_toggle_ema bake_after blk - >>=? fun (_blk, toggle_ema) -> + Block.bake_n_with_toggle_ema bake_after blk >>=? fun (_blk, toggle_ema) -> Assert.leq_int ~loc:__LOC__ (toggle_ema.liquidity_baking diff --git a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml index 3ce376b226b4..5566420050f5 100644 --- a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml +++ b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml @@ -44,6 +44,8 @@ let threshold_encoding = "liquidity_baking_toggle_ema_threshold" Toggle_vote_ema_repr.encoding)) +let get = function Liquidity_baking -> fun emas -> emas.liquidity_baking + let get_config = function | Liquidity_baking -> Toggle_vote_ema_repr.Config.simple_off diff --git a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli index 3ca325dc28db..2d2312160612 100644 --- a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli +++ b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli @@ -39,3 +39,9 @@ val initial : t (** Default EMA's threshold for all pending toggle vote. *) val default_thresholds : t + +(** Extracts the EMA of a given toggle vote. *) +val get : Toggle_vote_name_repr.t -> t -> Toggle_vote_ema_repr.t + +(** Returns the EMA's configuration of a given toggle vote. *) +val get_config : Toggle_vote_name_repr.t -> Toggle_vote_ema_repr.Config.t -- GitLab From a1087f1bbccf0ad47ac116761c3c387ba36e17dd Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 16:53:10 +0200 Subject: [PATCH 42/48] Proto/Per_block_vote: update testsuite --- .../tests_alpha/test_per_block_votes.py | 6 +- .../_regressions/rpc/alpha.client.mempool.out | 63 +++++++++++++------ tezt/_regressions/rpc/alpha.client.others.out | 7 +-- tezt/_regressions/rpc/alpha.light.others.out | 7 +-- tezt/_regressions/rpc/alpha.proxy.mempool.out | 63 +++++++++++++------ tezt/_regressions/rpc/alpha.proxy.others.out | 7 +-- .../alpha.proxy_server_data_dir.others.out | 7 +-- .../rpc/alpha.proxy_server_rpc.others.out | 7 +-- ...nt_of_rollup_node_commitment_is_stored.out | 7 +-- ...nt_of_rollup_node_handles_chain_reorgs.out | 7 +-- ...mmitment_of_rollup_node_messages_reset.out | 7 +-- ...mitment_of_rollup_node_non_final_level.out | 7 +-- 12 files changed, 116 insertions(+), 79 deletions(-) diff --git a/tests_python/tests_alpha/test_per_block_votes.py b/tests_python/tests_alpha/test_per_block_votes.py index 97493c6023a1..cebe7d64cc03 100644 --- a/tests_python/tests_alpha/test_per_block_votes.py +++ b/tests_python/tests_alpha/test_per_block_votes.py @@ -45,15 +45,15 @@ def check_baker_logs(sandbox: Sandbox, pattern: str) -> bool: def get_what_the_baker_votes_from_its_logs(sandbox: Sandbox) -> str: if not check_baker_logs( - sandbox, 'Voting on for liquidity baking toggle vote' + sandbox, 'Voting on for liquidity_baking toggle vote' ): return 'on' if not check_baker_logs( - sandbox, 'Voting off for liquidity baking toggle vote' + sandbox, 'Voting off for liquidity_baking toggle vote' ): return 'off' if not check_baker_logs( - sandbox, 'Voting pass for liquidity baking toggle vote' + sandbox, 'Voting pass for liquidity_baking toggle vote' ): return 'pass' return 'error' diff --git a/tezt/_regressions/rpc/alpha.client.mempool.out b/tezt/_regressions/rpc/alpha.client.mempool.out index e7c7756202cf..95487877d313 100644 --- a/tezt/_regressions/rpc/alpha.client.mempool.out +++ b/tezt/_regressions/rpc/alpha.client.mempool.out @@ -757,7 +757,7 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "$ref": "#/definitions/cycle_nonce" }, "liquidity_baking_toggle_vote": { - "$ref": "#/definitions/alpha.liquidity_baking_toggle_vote" + "$ref": "#/definitions/alpha.toggle_vote" }, "signature": { "$ref": "#/definitions/Signature" @@ -954,14 +954,6 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' } ] }, - "alpha.liquidity_baking_toggle_vote": { - "type": "string", - "enum": [ - "off", - "on", - "pass" - ] - }, "alpha.michelson.v1.primitives": { "type": "string", "enum": [ @@ -3783,6 +3775,14 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + "alpha.toggle_vote": { + "type": "string", + "enum": [ + "off", + "on", + "pass" + ] + }, "alpha.tx_rollup_id": { "title": "A tx rollup handle", "description": "A tx rollup notation as given to an RPC or inside scripts, is a base58 tx rollup hash", @@ -7452,8 +7452,9 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' { "name": "liquidity_baking_toggle_vote", "layout": { - "size": "Int8", - "kind": "Int" + "size": "Uint8", + "reference": "alpha.toggle_vote", + "kind": "Enum" }, "data_kind": { "size": 1, @@ -7475,6 +7476,28 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ] } }, + { + "description": { + "title": "alpha.toggle_vote" + }, + "encoding": { + "size": "Uint8", + "cases": [ + [ + 0, + "on" + ], + [ + 1, + "off" + ], + [ + 2, + "pass" + ] + ] + } + }, { "description": { "title": "fitness.elem" @@ -11449,7 +11472,7 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "$ref": "#/definitions/cycle_nonce" }, "liquidity_baking_toggle_vote": { - "$ref": "#/definitions/alpha.liquidity_baking_toggle_vote" + "$ref": "#/definitions/alpha.toggle_vote" }, "signature": { "$ref": "#/definitions/Signature" @@ -11646,14 +11669,6 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' } ] }, - "alpha.liquidity_baking_toggle_vote": { - "type": "string", - "enum": [ - "off", - "on", - "pass" - ] - }, "alpha.michelson.v1.primitives": { "type": "string", "enum": [ @@ -14475,6 +14490,14 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + "alpha.toggle_vote": { + "type": "string", + "enum": [ + "off", + "on", + "pass" + ] + }, "alpha.tx_rollup_id": { "title": "A tx rollup handle", "description": "A tx rollup notation as given to an RPC or inside scripts, is a base58 tx rollup hash", diff --git a/tezt/_regressions/rpc/alpha.client.others.out b/tezt/_regressions/rpc/alpha.client.others.out index 867b16dcca1a..0e73684ce95a 100644 --- a/tezt/_regressions/rpc/alpha.client.others.out +++ b/tezt/_regressions/rpc/alpha.client.others.out @@ -18,11 +18,10 @@ rpc/alpha.client.others.out "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.light.others.out b/tezt/_regressions/rpc/alpha.light.others.out index 208d97cc3102..a6cf4a2bba8b 100644 --- a/tezt/_regressions/rpc/alpha.light.others.out +++ b/tezt/_regressions/rpc/alpha.light.others.out @@ -18,11 +18,10 @@ rpc/alpha.light.others.out "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.proxy.mempool.out b/tezt/_regressions/rpc/alpha.proxy.mempool.out index 6ebc9200d13f..ecefe615f3f1 100644 --- a/tezt/_regressions/rpc/alpha.proxy.mempool.out +++ b/tezt/_regressions/rpc/alpha.proxy.mempool.out @@ -778,7 +778,7 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "$ref": "#/definitions/cycle_nonce" }, "liquidity_baking_toggle_vote": { - "$ref": "#/definitions/alpha.liquidity_baking_toggle_vote" + "$ref": "#/definitions/alpha.toggle_vote" }, "signature": { "$ref": "#/definitions/Signature" @@ -975,14 +975,6 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' } ] }, - "alpha.liquidity_baking_toggle_vote": { - "type": "string", - "enum": [ - "off", - "on", - "pass" - ] - }, "alpha.michelson.v1.primitives": { "type": "string", "enum": [ @@ -3804,6 +3796,14 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + "alpha.toggle_vote": { + "type": "string", + "enum": [ + "off", + "on", + "pass" + ] + }, "alpha.tx_rollup_id": { "title": "A tx rollup handle", "description": "A tx rollup notation as given to an RPC or inside scripts, is a base58 tx rollup hash", @@ -7473,8 +7473,9 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' { "name": "liquidity_baking_toggle_vote", "layout": { - "size": "Int8", - "kind": "Int" + "size": "Uint8", + "reference": "alpha.toggle_vote", + "kind": "Enum" }, "data_kind": { "size": 1, @@ -7496,6 +7497,28 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ] } }, + { + "description": { + "title": "alpha.toggle_vote" + }, + "encoding": { + "size": "Uint8", + "cases": [ + [ + 0, + "on" + ], + [ + 1, + "off" + ], + [ + 2, + "pass" + ] + ] + } + }, { "description": { "title": "fitness.elem" @@ -11470,7 +11493,7 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "$ref": "#/definitions/cycle_nonce" }, "liquidity_baking_toggle_vote": { - "$ref": "#/definitions/alpha.liquidity_baking_toggle_vote" + "$ref": "#/definitions/alpha.toggle_vote" }, "signature": { "$ref": "#/definitions/Signature" @@ -11667,14 +11690,6 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' } ] }, - "alpha.liquidity_baking_toggle_vote": { - "type": "string", - "enum": [ - "off", - "on", - "pass" - ] - }, "alpha.michelson.v1.primitives": { "type": "string", "enum": [ @@ -14496,6 +14511,14 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' ], "additionalProperties": false }, + "alpha.toggle_vote": { + "type": "string", + "enum": [ + "off", + "on", + "pass" + ] + }, "alpha.tx_rollup_id": { "title": "A tx rollup handle", "description": "A tx rollup notation as given to an RPC or inside scripts, is a base58 tx rollup hash", diff --git a/tezt/_regressions/rpc/alpha.proxy.others.out b/tezt/_regressions/rpc/alpha.proxy.others.out index 82d17b80a52e..2560171bfaa3 100644 --- a/tezt/_regressions/rpc/alpha.proxy.others.out +++ b/tezt/_regressions/rpc/alpha.proxy.others.out @@ -18,11 +18,10 @@ rpc/alpha.proxy.others.out "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out index 1f8608a42e78..e0e18022e40c 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out @@ -18,11 +18,10 @@ rpc/alpha.proxy_server_data_dir.others.out "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out b/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out index f660bc2c4f30..2f694b9a08b3 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out @@ -18,11 +18,10 @@ rpc/alpha.proxy_server_rpc.others.out "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out index c1bff044a65f..7dd882836fbd 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out @@ -51,11 +51,10 @@ This sequence of operations was run: "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out index 87771e9297da..fa6a8f38466f 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out @@ -51,11 +51,10 @@ This sequence of operations was run: "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out index 561e028b4673..61af31c70a17 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out @@ -51,11 +51,10 @@ This sequence of operations was run: "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out index 8d75efad20d8..677f63d3a276 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out @@ -51,11 +51,10 @@ This sequence of operations was run: "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", -- GitLab From 0301db6ccdaa3aef981252d25f7feca39d03750d Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 2 May 2022 12:26:13 +0200 Subject: [PATCH 43/48] Tests/Python: share toggle vote arguments --- tests_python/examples/example.py | 2 +- tests_python/examples/test_example.py | 2 +- tests_python/scripts/run_node_baker.py | 2 +- tests_python/scripts/run_testnet.py | 2 +- tests_python/tests_alpha/test_baker_endorser.py | 2 +- .../tests_alpha/test_baker_operations_cli_options.py | 5 ++--- tests_python/tests_alpha/test_bootstrap.py | 9 +++++---- tests_python/tests_alpha/test_many_bakers.py | 2 +- tests_python/tests_alpha/test_many_nodes.py | 2 +- tests_python/tests_alpha/test_nonce_seed_revelation.py | 2 +- tests_python/tests_alpha/test_per_block_votes.py | 2 +- tests_python/tests_alpha/test_tenderbake.py | 2 +- .../tests_alpha/test_tenderbake_bakers_restart.py | 4 ++-- .../tests_alpha/test_tenderbake_incremental_start.py | 4 ++-- .../tests_alpha/test_tenderbake_long_dynamic_bake.py | 4 ++-- tests_python/tests_alpha/test_voting_full.py | 6 +++--- tests_python/tools/constants.py | 2 ++ 17 files changed, 28 insertions(+), 26 deletions(-) diff --git a/tests_python/examples/example.py b/tests_python/examples/example.py index 82f3dc8cc9d9..883aa9c71ede 100644 --- a/tests_python/examples/example.py +++ b/tests_python/examples/example.py @@ -18,7 +18,7 @@ def scenario(): 0, ['bootstrap5'], proto=constants.ALPHA_DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) # Wait for second node to update its protocol to alpha, if not # it may not know yet the `wait_for_inclusion` operation which is diff --git a/tests_python/examples/test_example.py b/tests_python/examples/test_example.py index 7331a0666187..93713d2595b3 100644 --- a/tests_python/examples/test_example.py +++ b/tests_python/examples/test_example.py @@ -16,7 +16,7 @@ def sandbox() -> Iterator[Sandbox]: 0, [], proto=constants.ALPHA_DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) yield sandbox assert sandbox.are_daemons_alive() diff --git a/tests_python/scripts/run_node_baker.py b/tests_python/scripts/run_node_baker.py index b3cd6a702861..88f18cc57983 100755 --- a/tests_python/scripts/run_node_baker.py +++ b/tests_python/scripts/run_node_baker.py @@ -29,7 +29,7 @@ def scenario(contract, storage, round_duration, proto): 1, accounts, proto=proto_daemon, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) client = sandbox.client(1) if contract: diff --git a/tests_python/scripts/run_testnet.py b/tests_python/scripts/run_testnet.py index 190ce4c9cbd7..03931a963a8d 100755 --- a/tests_python/scripts/run_testnet.py +++ b/tests_python/scripts/run_testnet.py @@ -448,7 +448,7 @@ def scenario(round_duration, num_nodes, log_dir): accounts(i, num_nodes), proto=constants.ALPHA_DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) while 1: diff --git a/tests_python/tests_alpha/test_baker_endorser.py b/tests_python/tests_alpha/test_baker_endorser.py index 0a49d475ad5e..c30fb21a3234 100644 --- a/tests_python/tests_alpha/test_baker_endorser.py +++ b/tests_python/tests_alpha/test_baker_endorser.py @@ -48,7 +48,7 @@ class TestAllDaemonsWithOperations: i, [f'bootstrap{5 - i}'], protocol.DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_wait_for_protocol(self, sandbox: Sandbox): diff --git a/tests_python/tests_alpha/test_baker_operations_cli_options.py b/tests_python/tests_alpha/test_baker_operations_cli_options.py index 907e32f544e6..82cd56aa7628 100644 --- a/tests_python/tests_alpha/test_baker_operations_cli_options.py +++ b/tests_python/tests_alpha/test_baker_operations_cli_options.py @@ -339,9 +339,8 @@ class TestBakerExternalOperations: run_params=[ '--operations-pool', session['operations_file'], - '--liquidity-baking-toggle-vote', - 'pass', - ], + ] + + constants.TOGGLE_VOTE_BAKER_PARAMS, ) @pytest.mark.timeout(30) diff --git a/tests_python/tests_alpha/test_bootstrap.py b/tests_python/tests_alpha/test_bootstrap.py index 87b50aea9318..724289dc4497 100644 --- a/tests_python/tests_alpha/test_bootstrap.py +++ b/tests_python/tests_alpha/test_bootstrap.py @@ -1,6 +1,7 @@ import time import pytest +from tools import constants from launchers.sandbox import Sandbox from . import protocol @@ -24,7 +25,7 @@ def add_fully_delegated_baker(sandbox: Sandbox, node: int, protocol: str): node, [], proto=protocol, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) @@ -39,7 +40,7 @@ class TestThresholdZero: 0, ['bootstrap5'], proto=protocol.DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_bootstrap(self, sandbox: Sandbox): @@ -60,7 +61,7 @@ class TestThresholdOne: 0, ['bootstrap5'], proto=protocol.DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_bootstrap(self, sandbox: Sandbox): @@ -86,7 +87,7 @@ class TestThresholdTwo: 0, ['bootstrap5'], proto=protocol.DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_add_nodes(self, sandbox: Sandbox): diff --git a/tests_python/tests_alpha/test_many_bakers.py b/tests_python/tests_alpha/test_many_bakers.py index b08bc4e2ecdb..a01a59d57ede 100644 --- a/tests_python/tests_alpha/test_many_bakers.py +++ b/tests_python/tests_alpha/test_many_bakers.py @@ -25,7 +25,7 @@ class TestManyBakers: i, [f'bootstrap{i + 1}'], proto=protocol.DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_wait(self): diff --git a/tests_python/tests_alpha/test_many_nodes.py b/tests_python/tests_alpha/test_many_nodes.py index e6a9eed2f7b1..6b371487db5d 100644 --- a/tests_python/tests_alpha/test_many_nodes.py +++ b/tests_python/tests_alpha/test_many_nodes.py @@ -34,7 +34,7 @@ class TestManyNodesBootstrap: i, [f'bootstrap{i + 1}'], proto=protocol.DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_add_nodes(self, sandbox: Sandbox): diff --git a/tests_python/tests_alpha/test_nonce_seed_revelation.py b/tests_python/tests_alpha/test_nonce_seed_revelation.py index 44ac88f405cc..da9f820eff44 100644 --- a/tests_python/tests_alpha/test_nonce_seed_revelation.py +++ b/tests_python/tests_alpha/test_nonce_seed_revelation.py @@ -55,7 +55,7 @@ class TestNonceSeedRevelation: [f"bootstrap{i + 1}"], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) @pytest.mark.timeout(2 * TEST_DURATION) diff --git a/tests_python/tests_alpha/test_per_block_votes.py b/tests_python/tests_alpha/test_per_block_votes.py index cebe7d64cc03..51a12a439ee1 100644 --- a/tests_python/tests_alpha/test_per_block_votes.py +++ b/tests_python/tests_alpha/test_per_block_votes.py @@ -136,7 +136,7 @@ class TestAllPerBlockVotes: 0, ['bootstrap1'], proto=protocol.DAEMON, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_wait_for_protocol(self, sandbox: Sandbox): diff --git a/tests_python/tests_alpha/test_tenderbake.py b/tests_python/tests_alpha/test_tenderbake.py index 4f6d414d5345..33988d38f00f 100644 --- a/tests_python/tests_alpha/test_tenderbake.py +++ b/tests_python/tests_alpha/test_tenderbake.py @@ -41,7 +41,7 @@ class TestProtoTenderbake: [f'bootstrap{i + 1}'], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_wait(self): diff --git a/tests_python/tests_alpha/test_tenderbake_bakers_restart.py b/tests_python/tests_alpha/test_tenderbake_bakers_restart.py index 37c5b8a45590..a29543685600 100644 --- a/tests_python/tests_alpha/test_tenderbake_bakers_restart.py +++ b/tests_python/tests_alpha/test_tenderbake_bakers_restart.py @@ -48,7 +48,7 @@ class TestProtoTenderbake: [f'bootstrap{i + 1}'], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_restart(self, sandbox): @@ -69,7 +69,7 @@ class TestProtoTenderbake: [f'bootstrap{dead_baker + 1}'], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) # the CYCLE_DUR is long enough for bakers to take a decision time.sleep(CYCLE_DUR) diff --git a/tests_python/tests_alpha/test_tenderbake_incremental_start.py b/tests_python/tests_alpha/test_tenderbake_incremental_start.py index df8d5db846e0..41c81c265faf 100644 --- a/tests_python/tests_alpha/test_tenderbake_incremental_start.py +++ b/tests_python/tests_alpha/test_tenderbake_incremental_start.py @@ -38,7 +38,7 @@ class TestProtoTenderbakeIncrementalStart: [account], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) def test_activate(self, sandbox): @@ -64,7 +64,7 @@ class TestProtoTenderbakeIncrementalStart: [account], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) time.sleep(MINIMAL_BLOCK_DELAY) diff --git a/tests_python/tests_alpha/test_tenderbake_long_dynamic_bake.py b/tests_python/tests_alpha/test_tenderbake_long_dynamic_bake.py index b64008511772..25454068165a 100644 --- a/tests_python/tests_alpha/test_tenderbake_long_dynamic_bake.py +++ b/tests_python/tests_alpha/test_tenderbake_long_dynamic_bake.py @@ -77,7 +77,7 @@ def add_bakers(sandbox: Sandbox, nodes: Iterable[int]) -> None: [account], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) @@ -155,7 +155,7 @@ class TestAllDaemonsWithOperations: [f'bootstrap{dead_baker+1}'], proto=protocol.DAEMON, log_levels=constants.TENDERBAKE_BAKER_LOG_LEVELS, - run_params=['--liquidity-baking-toggle-vote', 'pass'], + run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, ) # set the next baker to die dead_baker = baker diff --git a/tests_python/tests_alpha/test_voting_full.py b/tests_python/tests_alpha/test_voting_full.py index 9203fb194174..801f6f9df26c 100644 --- a/tests_python/tests_alpha/test_voting_full.py +++ b/tests_python/tests_alpha/test_voting_full.py @@ -110,7 +110,7 @@ class TestVotingFull: # """Add a baker per node""" # sandbox.add_baker( # 1, [f"bootstrap{i}" for i in range(1, 6)], proto=PROTO_B_DAEMON, - # run_params=['--liquidity-baking-toggle-vote', 'pass'], + # run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, # ) def test_client_knows_proto_b(self, sandbox: Sandbox): @@ -181,12 +181,12 @@ class TestVotingFull: # we let a PROTO_A baker bake the last blocks of PROTO_A # sandbox.add_baker( # 0, [f"bootstrap{i}" for i in range(1, 6)], proto=PROTO_A_DAEMON, - # run_params=['--liquidity-baking-toggle-vote', 'pass'], + # run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, # ) # for i in range(1,NUM_NODES): # sandbox.add_baker( # i, [f"bootstrap{i}"], proto=PROTO_B_DAEMON, - # run_params=['--liquidity-baking-toggle-vote', 'pass'], + # run_params=constants.TOGGLE_VOTE_BAKER_PARAMS, # ) clients = sandbox.all_clients() client = clients[0] diff --git a/tests_python/tools/constants.py b/tests_python/tools/constants.py index 0c53cc8ca5b3..902056a70734 100644 --- a/tests_python/tools/constants.py +++ b/tests_python/tools/constants.py @@ -264,3 +264,5 @@ TENDERBAKE_NODE_LOG_LEVELS = { "validator.block": "debug", "validator.chain": "debug", } + +TOGGLE_VOTE_BAKER_PARAMS = ['--liquidity-baking-toggle-vote', 'pass'] -- GitLab From bf34f95c272690ffce8c7214d81f8295a317ac3a Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Tue, 10 May 2022 12:10:46 +0200 Subject: [PATCH 44/48] Baker: prepare `Per_block_vote_file` for multiple votes --- .../lib_delegate/baking_actions.ml | 17 +- .../lib_delegate/baking_commands.ml | 2 +- .../lib_delegate/baking_configuration.ml | 90 +++++----- .../lib_delegate/baking_configuration.mli | 16 +- src/proto_alpha/lib_delegate/baking_events.ml | 49 +++-- src/proto_alpha/lib_delegate/baking_lib.ml | 5 +- src/proto_alpha/lib_delegate/baking_lib.mli | 2 + src/proto_alpha/lib_delegate/block_forge.ml | 19 +- src/proto_alpha/lib_delegate/block_forge.mli | 4 +- src/proto_alpha/lib_delegate/client_daemon.ml | 8 +- .../lib_delegate/client_daemon.mli | 2 +- .../liquidity_baking_vote_file.ml | 169 ------------------ .../lib_delegate/per_block_vote_file.ml | 160 +++++++++++++++++ .../lib_delegate/per_block_vote_file.mli | 40 +++++ .../test/mockup_simulator/mockup_simulator.ml | 6 +- .../lib_protocol/alpha_context.mli | 2 + .../lib_protocol/per_block_vote_repr.ml | 3 + .../lib_protocol/per_block_vote_repr.mli | 3 + 18 files changed, 315 insertions(+), 282 deletions(-) delete mode 100644 src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml create mode 100644 src/proto_alpha/lib_delegate/per_block_vote_file.ml create mode 100644 src/proto_alpha/lib_delegate/per_block_vote_file.mli diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 5ac946621647..09109b4def37 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -269,17 +269,10 @@ let inject_block ~state_recorder state block_to_bake ~updated_state = let user_activated_upgrades = state.global_state.config.user_activated_upgrades in - (* Set liquidity_baking_toggle_vote for this block *) - let default = state.global_state.config.liquidity_baking_toggle_vote in - (match state.global_state.config.per_block_vote_file with - | None -> Lwt.return default - | Some per_block_vote_file -> - Liquidity_baking_vote_file.read_liquidity_baking_toggle_vote_no_fail - ~default - ~per_block_vote_file) - >>= fun liquidity_baking_toggle_vote -> - Events.(emit vote_for_liquidity_baking_toggle) liquidity_baking_toggle_vote - >>= fun () -> + Per_block_vote_file.may_read_with_default + state.global_state.config.per_block_vote + state.global_state.config.per_block_vote_file + >>= fun per_block_vote -> Block_forge.forge cctxt ~chain_id @@ -287,7 +280,7 @@ let inject_block ~state_recorder state block_to_bake ~updated_state = ~timestamp ~seed_nonce_hash ~payload_round - ~liquidity_baking_toggle_vote + ~per_block_vote ~user_activated_upgrades state.global_state.config.fees simulation_mode diff --git a/src/proto_alpha/lib_delegate/baking_commands.ml b/src/proto_alpha/lib_delegate/baking_commands.ml index c54c117c30b3..3bdc022eb7b9 100644 --- a/src/proto_alpha/lib_delegate/baking_commands.ml +++ b/src/proto_alpha/lib_delegate/baking_commands.ml @@ -364,7 +364,7 @@ let baker_commands () : Protocol_client_context.full Clic.command list = ~minimal_fees ~minimal_nanotez_per_gas_unit ~minimal_nanotez_per_byte - ~liquidity_baking_toggle_vote + ~per_block_vote:{liquidity_baking = liquidity_baking_toggle_vote} ?per_block_vote_file ?extra_operations ~chain:cctxt#chain diff --git a/src/proto_alpha/lib_delegate/baking_configuration.ml b/src/proto_alpha/lib_delegate/baking_configuration.ml index 0d1b9862cdd7..e35257dcf412 100644 --- a/src/proto_alpha/lib_delegate/baking_configuration.ml +++ b/src/proto_alpha/lib_delegate/baking_configuration.ml @@ -82,7 +82,7 @@ type t = { validation : validation_config; retries_on_failure : int; user_activated_upgrades : (int32 * Protocol_hash.t) list; - liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t; + per_block_vote : Protocol.Alpha_context.Per_block_vote.t; per_block_vote_file : string option; force : bool; state_recorder : state_recorder_config; @@ -107,8 +107,7 @@ let default_retries_on_failure_config = 5 let default_user_activated_upgrades = [] -let default_liquidity_baking_toggle_vote = - Protocol.Alpha_context.Toggle_vote.Toggle_pass +let default_per_block_vote = Protocol.Alpha_context.Per_block_vote.all_pass let default_force = false @@ -125,7 +124,7 @@ let default_config = validation = default_validation_config; retries_on_failure = default_retries_on_failure_config; user_activated_upgrades = default_user_activated_upgrades; - liquidity_baking_toggle_vote = default_liquidity_baking_toggle_vote; + per_block_vote = default_per_block_vote; force = default_force; state_recorder = default_state_recorder_config; extra_operations = default_extra_operations; @@ -139,9 +138,9 @@ let make ?(minimal_fees = default_fees_config.minimal_fees) ?(nonce = default_nonce_config) ?context_path ?(retries_on_failure = default_retries_on_failure_config) ?(user_activated_upgrades = default_user_activated_upgrades) - ?(liquidity_baking_toggle_vote = default_liquidity_baking_toggle_vote) - ?per_block_vote_file ?(force = default_force) - ?(state_recorder = default_state_recorder_config) ?extra_operations () = + ?(per_block_vote = default_per_block_vote) ?per_block_vote_file + ?(force = default_force) ?(state_recorder = default_state_recorder_config) + ?extra_operations () = let fees = {minimal_fees; minimal_nanotez_per_gas_unit; minimal_nanotez_per_byte} in @@ -156,7 +155,7 @@ let make ?(minimal_fees = default_fees_config.minimal_fees) nonce; retries_on_failure; user_activated_upgrades; - liquidity_baking_toggle_vote; + per_block_vote; per_block_vote_file; force; state_recorder; @@ -222,8 +221,8 @@ let user_activate_upgrades_config_encoding = let open Data_encoding in list (tup2 int32 Protocol_hash.encoding) -let liquidity_baking_toggle_vote_config_encoding = - Protocol.Alpha_context.Toggle_vote.encoding +let per_block_vote_config_encoding = + Protocol.Alpha_context.Per_block_vote.dft_encoding let force_config_encoding = Data_encoding.bool @@ -259,57 +258,58 @@ let encoding : t Data_encoding.t = nonce; retries_on_failure; user_activated_upgrades; - liquidity_baking_toggle_vote; + per_block_vote; per_block_vote_file; force; state_recorder; extra_operations; } -> - ( fees, - validation, - nonce, - retries_on_failure, - user_activated_upgrades, - liquidity_baking_toggle_vote, - per_block_vote_file, - force, - state_recorder, - extra_operations )) - (fun ( fees, - validation, - nonce, - retries_on_failure, - user_activated_upgrades, - liquidity_baking_toggle_vote, - per_block_vote_file, - force, - state_recorder, - extra_operations ) -> + ( ( fees, + validation, + nonce, + retries_on_failure, + user_activated_upgrades, + per_block_vote_file, + force, + state_recorder, + extra_operations ), + per_block_vote )) + (fun ( ( fees, + validation, + nonce, + retries_on_failure, + user_activated_upgrades, + per_block_vote_file, + force, + state_recorder, + extra_operations ), + per_block_vote ) -> { fees; validation; nonce; retries_on_failure; user_activated_upgrades; - liquidity_baking_toggle_vote; + per_block_vote; per_block_vote_file; force; state_recorder; extra_operations; }) - (obj10 - (req "fees" fees_config_encoding) - (req "validation" validation_config_encoding) - (req "nonce" nonce_config_encoding) - (req "retries_on_failure" retries_on_failure_config_encoding) - (req "user_activated_upgrades" user_activate_upgrades_config_encoding) - (req - "liquidity_baking_toggle_vote" - liquidity_baking_toggle_vote_config_encoding) - (opt "per_block_vote_file" Data_encoding.string) - (req "force" force_config_encoding) - (req "state_recorder" state_recorder_config_encoding) - (opt "extra_operations" Operations_source.encoding)) + (merge_objs + (obj9 + (req "fees" fees_config_encoding) + (req "validation" validation_config_encoding) + (req "nonce" nonce_config_encoding) + (req "retries_on_failure" retries_on_failure_config_encoding) + (req + "user_activated_upgrades" + user_activate_upgrades_config_encoding) + (opt "per_block_vote_file" Data_encoding.string) + (req "force" force_config_encoding) + (req "state_recorder" state_recorder_config_encoding) + (opt "extra_operations" Operations_source.encoding)) + per_block_vote_config_encoding) let pp fmt t = let json = Data_encoding.Json.construct encoding t in diff --git a/src/proto_alpha/lib_delegate/baking_configuration.mli b/src/proto_alpha/lib_delegate/baking_configuration.mli index 1cbb0030fc51..62f9368abb8b 100644 --- a/src/proto_alpha/lib_delegate/baking_configuration.mli +++ b/src/proto_alpha/lib_delegate/baking_configuration.mli @@ -22,6 +22,9 @@ (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) + +open Protocol.Alpha_context + (** {1 Operations_source abstraction} *) module Operations_source : sig type t = @@ -37,7 +40,7 @@ module Operations_source : sig end type fees_config = { - minimal_fees : Protocol.Alpha_context.Tez.t; + minimal_fees : Tez.t; minimal_nanotez_per_gas_unit : Q.t; minimal_nanotez_per_byte : Q.t; } @@ -57,7 +60,7 @@ type t = { validation : validation_config; retries_on_failure : int; user_activated_upgrades : (int32 * Protocol_hash.t) list; - liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t; + per_block_vote : Per_block_vote.t; per_block_vote_file : string option; force : bool; state_recorder : state_recorder_config; @@ -74,7 +77,7 @@ val default_retries_on_failure_config : int val default_user_activated_upgrades : (int32 * Protocol_hash.t) list -val default_liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t +val default_per_block_vote : Per_block_vote.t val default_force : bool @@ -87,14 +90,14 @@ val default_per_block_vote_file : string option val default_config : t val make : - ?minimal_fees:Protocol.Alpha_context.Tez.t -> + ?minimal_fees:Tez.t -> ?minimal_nanotez_per_gas_unit:Q.t -> ?minimal_nanotez_per_byte:Q.t -> ?nonce:nonce_config -> ?context_path:string -> ?retries_on_failure:int -> ?user_activated_upgrades:(int32 * Protocol_hash.t) list -> - ?liquidity_baking_toggle_vote:Protocol.Alpha_context.Toggle_vote.t -> + ?per_block_vote:Per_block_vote.t -> ?per_block_vote_file:string -> ?force:bool -> ?state_recorder:state_recorder_config -> @@ -113,8 +116,7 @@ val retries_on_failure_config_encoding : int Data_encoding.t val user_activate_upgrades_config_encoding : (int32 * Protocol_hash.t) list Data_encoding.t -val liquidity_baking_toggle_vote_config_encoding : - Protocol.Alpha_context.Toggle_vote.t Data_encoding.t +val per_block_vote_config_encoding : Per_block_vote.t Data_encoding.t val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_delegate/baking_events.ml b/src/proto_alpha/lib_delegate/baking_events.ml index c264f54f96f0..c9f51d6675d7 100644 --- a/src/proto_alpha/lib_delegate/baking_events.ml +++ b/src/proto_alpha/lib_delegate/baking_events.ml @@ -651,14 +651,6 @@ module Actions = struct ~level:Error ~msg:"cannot fetch operations: {errs}" ("errs", Error_monad.(TzTrace.encoding error_encoding)) - - let vote_for_liquidity_baking_toggle = - declare_1 - ~section - ~name:"vote_for_liquidity_baking_toggle" - ~level:Notice - ~msg:"Voting {value} for liquidity baking toggle vote" - ("value", Protocol.Alpha_context.Toggle_vote.encoding) end module Nonces = struct @@ -786,7 +778,7 @@ module Nonces = struct () end -module Liquidity_baking = struct +module Block_vote = struct include Internal_event.Simple let reading_per_block = @@ -805,22 +797,6 @@ module Liquidity_baking = struct ~msg:"per block vote file {event}" ("event", Data_encoding.string) - let reading_liquidity_baking = - declare_0 - ~section - ~name:"reading_liquidity_baking" - ~level:Notice - ~msg:"reading liquidity baking toggle vote" - () - - let liquidity_baking_toggle_vote = - declare_1 - ~section - ~name:"liquidity_baking_toggle_vote" - ~level:Notice - ~msg:"liquidity baking toggle vote = {value}" - ("value", Protocol.Alpha_context.Toggle_vote.encoding) - let per_block_vote_file_fail = declare_1 ~section @@ -830,6 +806,29 @@ module Liquidity_baking = struct ~pp1:pp_print_top_error_of_trace ("errors", Error_monad.(TzTrace.encoding error_encoding)) + let using_default_vote = + declare_2 + ~section + ~name:"per_block_vote_default" + ~level:Notice + ~msg:"Voting {vote} for {name} toggle vote" + ("vote", Toggle_vote.encoding) + ("name", Toggle_vote.Name.encoding) + + let using_file_vote = + declare_3 + ~section + ~name:"per_block_vote_file" + ~level:Notice + ~msg:"Voting {vote} for {name} toggle vote (file vote over {default})" + ("vote", Toggle_vote.encoding) + ("default", Toggle_vote.encoding) + ("name", Toggle_vote.Name.encoding) +end + +module Liquidity_baking = struct + include Internal_event.Simple + let liquidity_baking_off = declare_0 ~section diff --git a/src/proto_alpha/lib_delegate/baking_lib.ml b/src/proto_alpha/lib_delegate/baking_lib.ml index 7ec3ae000cd5..cb50f6540b2f 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.ml +++ b/src/proto_alpha/lib_delegate/baking_lib.ml @@ -509,7 +509,8 @@ let baking_minimal_timestamp state = let bake (cctxt : Protocol_client_context.full) ?minimal_fees ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ?force ?(minimal_timestamp = false) ?extra_operations - ?(monitor_node_mempool = true) ?context_path delegates = + ?(monitor_node_mempool = true) ?per_block_vote ?per_block_vote_file + ?context_path delegates = let open Lwt_result_syntax in let config = Baking_configuration.make @@ -519,6 +520,8 @@ let bake (cctxt : Protocol_client_context.full) ?minimal_fees ?context_path ?force ?extra_operations + ?per_block_vote + ?per_block_vote_file () in let* block_stream, current_proposal = get_current_proposal cctxt in diff --git a/src/proto_alpha/lib_delegate/baking_lib.mli b/src/proto_alpha/lib_delegate/baking_lib.mli index e37f01ac7bb5..9d50b10ed5af 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.mli +++ b/src/proto_alpha/lib_delegate/baking_lib.mli @@ -36,6 +36,8 @@ val bake : ?minimal_timestamp:bool -> ?extra_operations:Baking_configuration.Operations_source.t -> ?monitor_node_mempool:bool -> + ?per_block_vote:Per_block_vote.t -> + ?per_block_vote_file:string -> ?context_path:string -> Baking_state.consensus_key list -> unit tzresult Lwt.t diff --git a/src/proto_alpha/lib_delegate/block_forge.ml b/src/proto_alpha/lib_delegate/block_forge.ml index 9970a0ba855f..6c20edc911d1 100644 --- a/src/proto_alpha/lib_delegate/block_forge.ml +++ b/src/proto_alpha/lib_delegate/block_forge.ml @@ -41,7 +41,7 @@ type simulation_kind = type simulation_mode = Local of Context.index | Node let forge_faked_protocol_data ?(payload_hash = Block_payload_hash.zero) - ~payload_round ~seed_nonce_hash ~liquidity_baking_toggle_vote () = + ~payload_round ~seed_nonce_hash ~per_block_vote () = Block_header. { contents = @@ -50,7 +50,7 @@ let forge_faked_protocol_data ?(payload_hash = Block_payload_hash.zero) payload_round; seed_nonce_hash; proof_of_work_nonce = Baking_pow.empty_proof_of_work_nonce; - per_block_vote = {liquidity_baking = liquidity_baking_toggle_vote}; + per_block_vote; }; signature = Signature.zero; } @@ -116,9 +116,8 @@ let retain_live_operations_only ~live_blocks operation_pool = operation_pool let forge (cctxt : #Protocol_client_context.full) ~chain_id ~pred_info - ~timestamp ~liquidity_baking_toggle_vote ~user_activated_upgrades - fees_config ~seed_nonce_hash ~payload_round simulation_mode simulation_kind - constants = + ~timestamp ~per_block_vote ~user_activated_upgrades fees_config + ~seed_nonce_hash ~payload_round simulation_mode simulation_kind constants = let predecessor_block = (pred_info : Baking_state.block_info) in let hard_gas_limit_per_block = constants.Constants.Parametric.hard_gas_limit_per_block @@ -149,7 +148,7 @@ let forge (cctxt : #Protocol_client_context.full) ~chain_id ~pred_info forge_faked_protocol_data ~payload_round ~seed_nonce_hash - ~liquidity_baking_toggle_vote + ~per_block_vote () in Node_rpc.preapply_block @@ -182,7 +181,7 @@ let forge (cctxt : #Protocol_client_context.full) ~chain_id ~pred_info forge_faked_protocol_data ~payload_round ~seed_nonce_hash - ~liquidity_baking_toggle_vote + ~per_block_vote () in Baking_simulator.begin_construction @@ -256,7 +255,7 @@ let forge (cctxt : #Protocol_client_context.full) ~chain_id ~pred_info let faked_protocol_data = forge_faked_protocol_data ~seed_nonce_hash - ~liquidity_baking_toggle_vote + ~per_block_vote ~payload_hash ~payload_round () @@ -276,7 +275,7 @@ let forge (cctxt : #Protocol_client_context.full) ~chain_id ~pred_info let faked_protocol_data = forge_faked_protocol_data ~seed_nonce_hash - ~liquidity_baking_toggle_vote + ~per_block_vote ~payload_hash ~payload_round () @@ -378,7 +377,7 @@ let forge (cctxt : #Protocol_client_context.full) ~chain_id ~pred_info payload_round; seed_nonce_hash; proof_of_work_nonce; - per_block_vote = {liquidity_baking = liquidity_baking_toggle_vote}; + per_block_vote; }) >>=? fun contents -> let unsigned_block_header = diff --git a/src/proto_alpha/lib_delegate/block_forge.mli b/src/proto_alpha/lib_delegate/block_forge.mli index c1f65d222237..22912cf00863 100644 --- a/src/proto_alpha/lib_delegate/block_forge.mli +++ b/src/proto_alpha/lib_delegate/block_forge.mli @@ -44,7 +44,7 @@ val forge_faked_protocol_data : ?payload_hash:Block_payload_hash.t -> payload_round:Round.t -> seed_nonce_hash:Nonce_hash.t option -> - liquidity_baking_toggle_vote:Toggle_vote.t -> + per_block_vote:Per_block_vote.t -> unit -> block_header_data @@ -53,7 +53,7 @@ val forge : chain_id:Chain_id.t -> pred_info:Baking_state.block_info -> timestamp:Time.Protocol.t -> - liquidity_baking_toggle_vote:Toggle_vote.t -> + per_block_vote:Per_block_vote.t -> user_activated_upgrades:User_activated.upgrades -> Baking_configuration.fees_config -> seed_nonce_hash:Nonce_hash.t option -> diff --git a/src/proto_alpha/lib_delegate/client_daemon.ml b/src/proto_alpha/lib_delegate/client_daemon.ml index cb5d92e4b6bc..89a8e4189d83 100644 --- a/src/proto_alpha/lib_delegate/client_daemon.ml +++ b/src/proto_alpha/lib_delegate/client_daemon.ml @@ -68,9 +68,9 @@ let rec retry_on_disconnection (cctxt : #Protocol_client_context.full) f = module Baker = struct let run (cctxt : Protocol_client_context.full) ?minimal_fees - ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte - ~liquidity_baking_toggle_vote ?per_block_vote_file ?extra_operations - ~chain ~context_path ~keep_alive delegates = + ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte ~per_block_vote + ?per_block_vote_file ?extra_operations ~chain ~context_path ~keep_alive + delegates = let process () = Config_services.user_activated_upgrades cctxt >>=? fun user_activated_upgrades -> @@ -79,7 +79,7 @@ module Baker = struct ?minimal_fees ?minimal_nanotez_per_gas_unit ?minimal_nanotez_per_byte - ~liquidity_baking_toggle_vote + ~per_block_vote ?per_block_vote_file ?extra_operations ~context_path diff --git a/src/proto_alpha/lib_delegate/client_daemon.mli b/src/proto_alpha/lib_delegate/client_daemon.mli index 91f26041d68e..25009c8e5f8f 100644 --- a/src/proto_alpha/lib_delegate/client_daemon.mli +++ b/src/proto_alpha/lib_delegate/client_daemon.mli @@ -32,7 +32,7 @@ module Baker : sig ?minimal_fees:Protocol.Alpha_context.Tez.t -> ?minimal_nanotez_per_gas_unit:Q.t -> ?minimal_nanotez_per_byte:Q.t -> - liquidity_baking_toggle_vote:Protocol.Alpha_context.Toggle_vote.t -> + per_block_vote:Protocol.Alpha_context.Per_block_vote.t -> ?per_block_vote_file:string -> ?extra_operations:Baking_configuration.Operations_source.t -> chain:Shell_services.chain -> diff --git a/src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml b/src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml deleted file mode 100644 index d2b325558a52..000000000000 --- a/src/proto_alpha/lib_delegate/liquidity_baking_vote_file.ml +++ /dev/null @@ -1,169 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2021 Nomadic Labs *) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -open Protocol_client_context -module Events = Baking_events.Liquidity_baking - -type per_block_votes = { - liquidity_baking_toggle_vote : Protocol.Alpha_context.Toggle_vote.t option; -} - -let per_block_votes_encoding = - let open Data_encoding in - def "per_block_votes.alpha" - @@ conv - (fun {liquidity_baking_toggle_vote} -> liquidity_baking_toggle_vote) - (fun liquidity_baking_toggle_vote -> {liquidity_baking_toggle_vote}) - (obj1 - (opt - "liquidity_baking_toggle_vote" - Protocol.Alpha_context.Toggle_vote.encoding)) - -type error += Block_vote_file_not_found of string - -type error += Block_vote_file_invalid of string - -type error += Block_vote_file_wrong_content of string - -type error += Block_vote_file_missing_liquidity_baking_toggle_vote of string - -let () = - register_error_kind - `Permanent - ~id:"Client_baking_forge.block_vote_file_not_found" - ~title: - "The provided block vote file path does not point to an existing file." - ~description: - "A block vote file path was provided on the command line but the path \ - does not point to an existing file." - ~pp:(fun ppf file_path -> - Format.fprintf - ppf - "@[The provided block vote file path \"%s\" does not point to an \ - existing file.@]" - file_path) - Data_encoding.(obj1 (req "file_path" string)) - (function - | Block_vote_file_not_found file_path -> Some file_path | _ -> None) - (fun file_path -> Block_vote_file_not_found file_path) ; - register_error_kind - `Permanent - ~id:"Client_baking_forge.block_vote_file_invalid" - ~title: - "The provided block vote file path does not point to a valid JSON file." - ~description: - "A block vote file path was provided on the command line but the path \ - does not point to a valid JSON file." - ~pp:(fun ppf file_path -> - Format.fprintf - ppf - "@[The provided block vote file path \"%s\" does not point to a valid \ - JSON file. The file exists but its content is not valid JSON.@]" - file_path) - Data_encoding.(obj1 (req "file_path" string)) - (function Block_vote_file_invalid file_path -> Some file_path | _ -> None) - (fun file_path -> Block_vote_file_invalid file_path) ; - register_error_kind - `Permanent - ~id:"Client_baking_forge.block_vote_file_wrong_content" - ~title:"The content of the provided block vote file is unexpected." - ~description: - "The block vote file is valid JSON but its content is not the expected \ - one." - ~pp:(fun ppf file_path -> - Format.fprintf - ppf - "@[The provided block vote file \"%s\" is a valid JSON file but its \ - content is unexpected. Expecting a JSON file containing either \ - '{\"liquidity_baking_toggle_vote\": \"on\"}', or \ - '{\"liquidity_baking_toggle_vote\": \"off\"}', or \ - '{\"liquidity_baking_toggle_vote\": \"pass\"}'.@]" - file_path) - Data_encoding.(obj1 (req "file_path" string)) - (function - | Block_vote_file_wrong_content file_path -> Some file_path | _ -> None) - (fun file_path -> Block_vote_file_wrong_content file_path) ; - register_error_kind - `Permanent - ~id: - "Client_baking_forge.block_vote_file_missing_liquidity_baking_toggle_vote" - ~title: - "In the provided block vote file, no entry for liquidity baking toggle \ - vote was found" - ~description: - "In the provided block vote file, no entry for liquidity baking toggle \ - vote was found." - ~pp:(fun ppf file_path -> - Format.fprintf - ppf - "@[In the provided block vote file \"%s\", the \ - \"liquidity_baking_toggle_vote\" boolean field is missing. Expecting \ - a JSON file containing either '{\"liquidity_baking_toggle_vote\": \ - \"on\"}', or '{\"liquidity_baking_toggle_vote\": \"off\"}', or \ - '{\"liquidity_baking_toggle_vote\": \"pass\"}'.@]" - file_path) - Data_encoding.(obj1 (req "file_path" string)) - (function - | Block_vote_file_missing_liquidity_baking_toggle_vote file_path -> - Some file_path - | _ -> None) - (fun file_path -> - Block_vote_file_missing_liquidity_baking_toggle_vote file_path) - -let traced_option_to_result ~error = - Option.fold ~some:ok ~none:(Result_syntax.tzfail error) - -let check_file_exists file = - if Sys.file_exists file then Result.return_unit - else error (Block_vote_file_not_found file) - -let read_liquidity_baking_toggle_vote ~per_block_vote_file = - Events.(emit reading_per_block) per_block_vote_file >>= fun () -> - check_file_exists per_block_vote_file >>?= fun () -> - trace (Block_vote_file_invalid per_block_vote_file) - @@ Lwt_utils_unix.Json.read_file per_block_vote_file - >>=? fun votes_json -> - Events.(emit per_block_vote_file_notice) "found" >>= fun () -> - trace (Block_vote_file_wrong_content per_block_vote_file) - @@ Error_monad.protect (fun () -> - return - @@ Data_encoding.Json.destruct per_block_votes_encoding votes_json) - >>=? fun votes -> - Events.(emit per_block_vote_file_notice) "JSON decoded" >>= fun () -> - traced_option_to_result - ~error: - (Block_vote_file_missing_liquidity_baking_toggle_vote per_block_vote_file) - votes.liquidity_baking_toggle_vote - >>?= fun liquidity_baking_toggle_vote -> - Events.(emit reading_liquidity_baking) () >>= fun () -> - Events.(emit liquidity_baking_toggle_vote) liquidity_baking_toggle_vote - >>= fun () -> return liquidity_baking_toggle_vote - -let read_liquidity_baking_toggle_vote_no_fail ~default ~per_block_vote_file = - read_liquidity_baking_toggle_vote ~per_block_vote_file >>= function - | Ok vote -> Lwt.return vote - | Error errs -> - Events.(emit per_block_vote_file_fail) errs >>= fun () -> - Lwt.return default diff --git a/src/proto_alpha/lib_delegate/per_block_vote_file.ml b/src/proto_alpha/lib_delegate/per_block_vote_file.ml new file mode 100644 index 000000000000..61460084b725 --- /dev/null +++ b/src/proto_alpha/lib_delegate/per_block_vote_file.ml @@ -0,0 +1,160 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context +module Events = Baking_events.Block_vote + +type error += + | Not_found of string + | Malformed_json of string + | Unexpected_content of string + +let () = + register_error_kind + `Permanent + ~id:"toggle_vote_file.not_found" + ~title: + "The provided block toggle vote file path does not point to an existing \ + file." + ~description: + "A toggle vote file path was provided on the command line but the path \ + does not point to an existing file." + ~pp:(fun ppf file_path -> + Format.fprintf + ppf + "The provided block vote file path \"%s\" does not point to an \ + existing file." + file_path) + Data_encoding.(obj1 (req "file_path" string)) + (function Not_found file_path -> Some file_path | _ -> None) + (fun file_path -> Not_found file_path) ; + register_error_kind + `Permanent + ~id:"toggle_vote_file.malformed_json" + ~title: + "The provided block vote file path does not point to a valid JSON file." + ~description: + "A block vote file path was provided on the command line but the path \ + does not point to a valid JSON file." + ~pp:(fun ppf file_path -> + Format.fprintf + ppf + "The provided block vote file path \"%s\" does not point to a valid \ + JSON file. The file exists but its content is not valid JSON." + file_path) + Data_encoding.(obj1 (req "file_path" string)) + (function Malformed_json file_path -> Some file_path | _ -> None) + (fun file_path -> Malformed_json file_path) ; + register_error_kind + `Permanent + ~id:"toggle_vote_file.unexpected_content" + ~title:"The content of the provided block vote file is unexpected." + ~description: + "The block vote file is valid JSON but its content is not the expected \ + one." + ~pp:(fun ppf file_path -> + Format.fprintf + ppf + "@[The provided block vote file \"%s\" is a valid JSON file but its \ + content is unexpected. Expecting a JSON file containing either \ + '{\"liquidity_baking_toggle_vote\": \"on\"}', or \ + '{\"liquidity_baking_toggle_vote\": \"off\"}', or \ + '{\"liquidity_baking_toggle_vote\": \"pass\"}'.@]" + file_path) + Data_encoding.(obj1 (req "file_path" string)) + (function Unexpected_content file_path -> Some file_path | _ -> None) + (fun file_path -> Unexpected_content file_path) + +type t = {liquidity_baking : Toggle_vote.t option} + +let encoding = + let open Data_encoding in + conv + (fun {liquidity_baking} -> liquidity_baking) + (fun liquidity_baking -> {liquidity_baking}) + (obj1 (opt "liquidity_baking_toggle_vote" Toggle_vote.encoding)) + +let check_file_exists file = + if Sys.file_exists file then Result.return_unit else error (Not_found file) + +let read file = + let open Lwt_result_syntax in + let*! () = Events.(emit reading_per_block) file in + let*? () = check_file_exists file in + let* votes_json = + trace (Malformed_json file) @@ Lwt_utils_unix.Json.read_file file + in + let*! () = Events.(emit per_block_vote_file_notice) "found" in + let* votes = + trace (Unexpected_content file) + @@ Error_monad.protect (fun () -> + return @@ Data_encoding.Json.destruct encoding votes_json) + in + let*! () = Events.(emit per_block_vote_file_notice) "JSON decoded" in + return votes + +let merge_vote default file name = + let open Lwt_result_syntax in + match file with + | Some v -> + let*! () = Events.(emit using_file_vote (v, default, name)) in + Lwt.return v + | None -> + let*! () = Events.(emit using_default_vote (default, name)) in + Lwt.return default + +let merge (default : Per_block_vote.t) (vote : t) = + let open Lwt_result_syntax in + let*! liquidity_baking = + merge_vote default.liquidity_baking vote.liquidity_baking Liquidity_baking + in + Lwt.return {Per_block_vote.liquidity_baking} + +let emit_default_vote default = + List.iter_s + (fun name -> + Events.( + emit + using_default_vote + (Per_block_vote.get_toggle_vote name default, name))) + Toggle_vote.Name.all + +let read_with_default default file = + let open Lwt_result_syntax in + let*! content = read file in + match content with + | Ok vote -> merge default vote + | Error errs -> + let*! () = Events.(emit per_block_vote_file_fail) errs in + let*! () = emit_default_vote default in + Lwt.return default + +let may_read_with_default default file = + let open Lwt_result_syntax in + match file with + | None -> + let*! () = emit_default_vote default in + Lwt.return default + | Some file -> read_with_default default file diff --git a/src/proto_alpha/lib_delegate/per_block_vote_file.mli b/src/proto_alpha/lib_delegate/per_block_vote_file.mli new file mode 100644 index 000000000000..2c381d5cac4a --- /dev/null +++ b/src/proto_alpha/lib_delegate/per_block_vote_file.mli @@ -0,0 +1,40 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs *) +(* *) +(* 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. *) +(* *) +(*****************************************************************************) + +open Protocol.Alpha_context + +val read_with_default : Per_block_vote.t -> string -> Per_block_vote.t Lwt.t + +val may_read_with_default : + Per_block_vote.t -> string option -> Per_block_vote.t Lwt.t + +type error += + | Not_found of string + | Malformed_json of string + | Unexpected_content of string + +type t = {liquidity_baking : Toggle_vote.t option} + +val read : string -> t tzresult Lwt.t 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 c8e54388d813..8511b0a610b6 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 @@ -823,11 +823,7 @@ let genesis_protocol_data (baker_sk : Signature.secret_key) payload_round = Alpha_context.Round.zero; proof_of_work_nonce; seed_nonce_hash = None; - per_block_vote = - { - liquidity_baking = - Baking_configuration.default_liquidity_baking_toggle_vote; - }; + per_block_vote = Baking_configuration.default_per_block_vote; } in let unsigned_header = diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 0cc2d5c544b7..efaf6e65d5c5 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -765,6 +765,8 @@ module Per_block_vote : sig val all_pass : t + val get_toggle_vote : Toggle_vote.Name.t -> t -> Toggle_vote.t + val update : context -> t -> (context * Toggle_vote.Emas.t) tzresult Lwt.t val below_threshold : diff --git a/src/proto_alpha/lib_protocol/per_block_vote_repr.ml b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml index 12705c370725..2684d659f92d 100644 --- a/src/proto_alpha/lib_protocol/per_block_vote_repr.ml +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml @@ -49,6 +49,9 @@ let dft_encoding = let all_pass = {liquidity_baking = Toggle_pass} +let get_toggle_vote = function + | Liquidity_baking -> fun ballot -> ballot.liquidity_baking + let update ballot (emas : Toggle_vote_emas_repr.t) : Toggle_vote_emas_repr.t = { liquidity_baking = diff --git a/src/proto_alpha/lib_protocol/per_block_vote_repr.mli b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli index 423ba19885ad..ed899f5c0f00 100644 --- a/src/proto_alpha/lib_protocol/per_block_vote_repr.mli +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli @@ -36,6 +36,9 @@ val dft_encoding : t Data_encoding.t (** A per block ballot where all toggle-votes are [Toggle_pass]. *) val all_pass : t +(** Extracts a given toggle vote from a ballot. *) +val get_toggle_vote : Toggle_vote_name_repr.t -> t -> Toggle_vote_repr.t + (** Given a ballot and the old EMAs, compute the new EMAs. See [Toggle_vote_ema_repr] for the computation details. *) val update : t -> Toggle_vote_emas_repr.t -> Toggle_vote_emas_repr.t -- GitLab From bba6f5d8f2269369812f2116daa5e4494b619d71 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Tue, 10 May 2022 12:17:37 +0200 Subject: [PATCH 45/48] Baker: prepare CLI for multiple votes --- .../lib_delegate/baking_commands.ml | 60 +++++++++++++------ .../lib_protocol/alpha_context.mli | 2 + .../lib_protocol/per_block_vote_repr.ml | 5 ++ .../lib_protocol/per_block_vote_repr.mli | 3 + 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_commands.ml b/src/proto_alpha/lib_delegate/baking_commands.ml index 3bdc022eb7b9..57d845d8619f 100644 --- a/src/proto_alpha/lib_delegate/baking_commands.ml +++ b/src/proto_alpha/lib_delegate/baking_commands.ml @@ -141,7 +141,7 @@ let keep_alive_arg = ~long:"keep-alive" () -let liquidity_baking_toggle_vote_parameter = +let toggle_vote_parameter = Clic.parameter ~autocomplete:(fun _ctxt -> return ["on"; "off"; "pass"]) (let open Protocol.Alpha_context.Toggle_vote in @@ -154,14 +154,43 @@ let liquidity_baking_toggle_vote_parameter = "unexpected vote: %s, expected either \"on\", \"off\", or \"pass\"." s) -let liquidity_baking_toggle_vote_arg = - Clic.arg - ~doc: - "Vote to continue (option \"on\") or end (option \"off\") the liquidity \ - baking subsidy. Or choose to pass (option \"pass\")." - ~long:"liquidity-baking-toggle-vote" - ~placeholder:"vote" - liquidity_baking_toggle_vote_parameter +let per_block_vote_arg = + let open Protocol.Alpha_context in + let open Toggle_vote.Name in + let to_name = function Liquidity_baking -> "liquidity baking" in + let to_option_name = function + | Liquidity_baking -> "liquidity-baking-toggle-vote" + in + let to_option_doc = function + | Liquidity_baking -> + "Vote to continue (option \"on\") or end (option \"off\") the \ + liquidity baking subsidy. Or choose to pass (option \"pass\")." + in + let rec generate arg = function + | [] -> arg + | name :: names -> + generate + (Clic.map_arg + ~f:(fun _ctx (vote, ballot) -> + match vote with + | Some vote -> + return (Per_block_vote.set_toggle_vote name ballot vote) + | None -> + failwith + "Missing %s vote, please use the --%s option" + (to_name name) + (to_option_name name)) + (Clic.aggregate + (Clic.args2 + (Clic.arg + ~doc:(to_option_doc name) + ~long:(to_option_name name) + ~placeholder:"vote" + toggle_vote_parameter) + arg))) + names + in + generate (Clic.constant Per_block_vote.all_pass) Toggle_vote.Name.all let get_delegates (cctxt : Protocol_client_context.full) (pkhs : Signature.public_key_hash list) = @@ -329,7 +358,7 @@ let baker_commands () : Protocol_client_context.full Clic.command list = minimal_nanotez_per_gas_unit_arg minimal_nanotez_per_byte_arg keep_alive_arg - liquidity_baking_toggle_vote_arg + per_block_vote_arg per_block_vote_file_arg operations_arg) (prefixes ["run"; "with"; "local"; "node"] @@ -343,19 +372,12 @@ let baker_commands () : Protocol_client_context.full Clic.command list = minimal_nanotez_per_gas_unit, minimal_nanotez_per_byte, keep_alive, - liquidity_baking_toggle_vote, + per_block_vote, per_block_vote_file, extra_operations ) node_data_path sources cctxt -> - (match liquidity_baking_toggle_vote with - | None -> - failwith - "Missing liquidity baking toggle vote, please use the \ - --liquidity-baking-toggle-vote option" - | Some vote -> return vote) - >>=? fun liquidity_baking_toggle_vote -> may_lock_pidfile pidfile @@ fun () -> get_delegates cctxt sources >>=? fun delegates -> let context_path = Filename.Infix.(node_data_path // "context") in @@ -364,7 +386,7 @@ let baker_commands () : Protocol_client_context.full Clic.command list = ~minimal_fees ~minimal_nanotez_per_gas_unit ~minimal_nanotez_per_byte - ~per_block_vote:{liquidity_baking = liquidity_baking_toggle_vote} + ~per_block_vote ?per_block_vote_file ?extra_operations ~chain:cctxt#chain diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index efaf6e65d5c5..af64c23b1d5b 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -767,6 +767,8 @@ module Per_block_vote : sig val get_toggle_vote : Toggle_vote.Name.t -> t -> Toggle_vote.t + val set_toggle_vote : Toggle_vote.Name.t -> t -> Toggle_vote.t -> t + val update : context -> t -> (context * Toggle_vote.Emas.t) tzresult Lwt.t val below_threshold : diff --git a/src/proto_alpha/lib_protocol/per_block_vote_repr.ml b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml index 2684d659f92d..f390effb9d13 100644 --- a/src/proto_alpha/lib_protocol/per_block_vote_repr.ml +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml @@ -52,6 +52,11 @@ let all_pass = {liquidity_baking = Toggle_pass} let get_toggle_vote = function | Liquidity_baking -> fun ballot -> ballot.liquidity_baking +let set_toggle_vote name = + match name with + | Liquidity_baking -> + fun {liquidity_baking = _} vote -> {liquidity_baking = vote} + let update ballot (emas : Toggle_vote_emas_repr.t) : Toggle_vote_emas_repr.t = { liquidity_baking = diff --git a/src/proto_alpha/lib_protocol/per_block_vote_repr.mli b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli index ed899f5c0f00..74dc36cf95c8 100644 --- a/src/proto_alpha/lib_protocol/per_block_vote_repr.mli +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli @@ -39,6 +39,9 @@ val all_pass : t (** Extracts a given toggle vote from a ballot. *) val get_toggle_vote : Toggle_vote_name_repr.t -> t -> Toggle_vote_repr.t +(** Update a given toggle vote from a ballot. *) +val set_toggle_vote : Toggle_vote_name_repr.t -> t -> Toggle_vote_repr.t -> t + (** Given a ballot and the old EMAs, compute the new EMAs. See [Toggle_vote_ema_repr] for the computation details. *) val update : t -> Toggle_vote_emas_repr.t -> Toggle_vote_emas_repr.t -- GitLab From 5e1f2e414dc5255524c8c8318d57777f1e5486b4 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Tue, 10 May 2022 12:21:15 +0200 Subject: [PATCH 46/48] Baker: add toggle votes options to `bake for` --- .../lib_delegate/baking_commands.ml | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_commands.ml b/src/proto_alpha/lib_delegate/baking_commands.ml index 57d845d8619f..40f804a402a3 100644 --- a/src/proto_alpha/lib_delegate/baking_commands.ml +++ b/src/proto_alpha/lib_delegate/baking_commands.ml @@ -154,7 +154,7 @@ let toggle_vote_parameter = "unexpected vote: %s, expected either \"on\", \"off\", or \"pass\"." s) -let per_block_vote_arg = +let per_block_vote_arg ?(mandatory = false) () = let open Protocol.Alpha_context in let open Toggle_vote.Name in let to_name = function Liquidity_baking -> "liquidity baking" in @@ -176,10 +176,12 @@ let per_block_vote_arg = | Some vote -> return (Per_block_vote.set_toggle_vote name ballot vote) | None -> - failwith - "Missing %s vote, please use the --%s option" - (to_name name) - (to_option_name name)) + if mandatory then + failwith + "Missing %s vote, please use the --%s option" + (to_name name) + (to_option_name name) + else return ballot) (Clic.aggregate (Clic.args2 (Clic.arg @@ -192,6 +194,14 @@ let per_block_vote_arg = in generate (Clic.constant Per_block_vote.all_pass) Toggle_vote.Name.all +let per_block_vote_file_arg = + Clic.arg + ~doc:"read per block votes as json file" + ~short:'V' + ~long:"votefile" + ~placeholder:"filename" + (Clic.parameter (fun _ s -> return s)) + let get_delegates (cctxt : Protocol_client_context.full) (pkhs : Signature.public_key_hash list) = let proj_delegate (alias, public_key_hash, public_key, secret_key_uri) = @@ -244,7 +254,7 @@ let delegate_commands () : Protocol_client_context.full Clic.command list = command ~group ~desc:"Forge and inject block using the delegates' rights." - (args8 + (args10 minimal_fees_arg minimal_nanotez_per_gas_unit_arg minimal_nanotez_per_byte_arg @@ -252,7 +262,9 @@ let delegate_commands () : Protocol_client_context.full Clic.command list = force_switch operations_arg context_path_arg - do_not_monitor_node_mempool_arg) + do_not_monitor_node_mempool_arg + (per_block_vote_arg ()) + per_block_vote_file_arg) (prefixes ["bake"; "for"] @@ sources_param) (fun ( minimal_fees, minimal_nanotez_per_gas_unit, @@ -261,7 +273,9 @@ let delegate_commands () : Protocol_client_context.full Clic.command list = force, extra_operations, context_path, - do_not_monitor_node_mempool ) + do_not_monitor_node_mempool, + per_block_vote, + per_block_vote_file ) pkhs cctxt -> get_delegates cctxt pkhs >>=? fun delegates -> @@ -273,6 +287,8 @@ let delegate_commands () : Protocol_client_context.full Clic.command list = ~minimal_fees ~force ~monitor_node_mempool:(not do_not_monitor_node_mempool) + ~per_block_vote + ?per_block_vote_file ?extra_operations ?context_path delegates); @@ -332,14 +348,6 @@ let directory_parameter = failwith "Directory doesn't exist: '%s'" p else return p) -let per_block_vote_file_arg = - Clic.arg - ~doc:"read per block votes as json file" - ~short:'V' - ~long:"votefile" - ~placeholder:"filename" - (Clic.parameter (fun _ s -> return s)) - let baker_commands () : Protocol_client_context.full Clic.command list = let open Clic in let group = @@ -358,7 +366,7 @@ let baker_commands () : Protocol_client_context.full Clic.command list = minimal_nanotez_per_gas_unit_arg minimal_nanotez_per_byte_arg keep_alive_arg - per_block_vote_arg + (per_block_vote_arg ~mandatory:true ()) per_block_vote_file_arg operations_arg) (prefixes ["run"; "with"; "local"; "node"] -- GitLab From a2609843db5cede7da98a96d24efd5bdb4c26fbc Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Thu, 12 May 2022 14:34:57 +0200 Subject: [PATCH 47/48] Proto: add a toggle vote for deactivating `Drain_delegate` --- src/proto_alpha/lib_client/mockup.ml | 25 ++++++++++----- .../lib_delegate/baking_commands.ml | 9 +++++- .../lib_delegate/per_block_vote_file.ml | 13 +++++--- .../lib_delegate/per_block_vote_file.mli | 2 +- src/proto_alpha/lib_plugin/plugin.ml | 2 ++ .../lib_protocol/alpha_context.mli | 8 +++-- src/proto_alpha/lib_protocol/apply.ml | 18 +++++++---- src/proto_alpha/lib_protocol/apply.mli | 2 ++ src/proto_alpha/lib_protocol/main.ml | 10 ++++-- .../lib_protocol/per_block_vote_repr.ml | 31 ++++++++++++------- .../lib_protocol/per_block_vote_repr.mli | 2 +- .../lib_protocol/per_block_vote_storage.ml | 6 ++-- src/proto_alpha/lib_protocol/raw_context.ml | 5 ++- .../test/integration/test_liquidity_baking.ml | 4 +-- .../lib_protocol/toggle_vote_emas_repr.ml | 31 ++++++++++++------- .../lib_protocol/toggle_vote_emas_repr.mli | 5 ++- .../lib_protocol/toggle_vote_name_repr.ml | 21 ++++++++----- .../lib_protocol/toggle_vote_name_repr.mli | 2 +- tests_python/tests_alpha/test_mockup.py | 3 +- .../tests_alpha/test_per_block_votes.py | 2 ++ tests_python/tools/constants.py | 7 ++++- .../encoding/alpha.block_header.out | 7 +++-- .../encoding/alpha.block_header.unsigned.out | 7 +++-- .../_regressions/encoding/alpha.operation.out | 8 +++-- .../encoding/alpha.operation.unsigned.out | 8 +++-- .../_regressions/rpc/alpha.client.mempool.out | 21 +++++++++++++ tezt/_regressions/rpc/alpha.client.others.out | 1 + tezt/_regressions/rpc/alpha.light.others.out | 1 + tezt/_regressions/rpc/alpha.proxy.mempool.out | 21 +++++++++++++ tezt/_regressions/rpc/alpha.proxy.others.out | 1 + .../alpha.proxy_server_data_dir.others.out | 1 + .../rpc/alpha.proxy_server_rpc.others.out | 1 + ...nt_of_rollup_node_commitment_is_stored.out | 1 + ...p_node_first_published_at_level_global.out | 8 ++--- ...nt_of_rollup_node_handles_chain_reorgs.out | 1 + ...mmitment_of_rollup_node_messages_reset.out | 1 + ...mitment_of_rollup_node_non_final_level.out | 1 + tezt/lib_tezos/baker.ml | 2 ++ .../block_header.unsigned.sample.json | 1 + .../block_header/block_header.sample.json | 1 + ...nsigned-double-baking-evidence.sample.json | 2 ++ ...eration-double-baking-evidence.sample.json | 2 ++ 42 files changed, 226 insertions(+), 79 deletions(-) diff --git a/src/proto_alpha/lib_client/mockup.ml b/src/proto_alpha/lib_client/mockup.ml index d4da7daf7395..708d9c79b4a1 100644 --- a/src/proto_alpha/lib_client/mockup.ml +++ b/src/proto_alpha/lib_client/mockup.ml @@ -32,28 +32,33 @@ open Alpha_context module Emas = struct module Opt = struct - type t = {liquidity_baking : Toggle_vote.Ema.t option} + type t = { + liquidity_baking : Toggle_vote.Ema.t option; + drain : Toggle_vote.Ema.t option; + } let threshold_encoding = let open Data_encoding in conv - (fun {liquidity_baking} -> liquidity_baking) - (fun liquidity_baking -> {liquidity_baking}) - (obj1 + (fun {liquidity_baking; drain} -> (liquidity_baking, drain)) + (fun (liquidity_baking, drain) -> {liquidity_baking; drain}) + (obj2 (opt "liquidity_baking_toggle_ema_threshold" - Toggle_vote.Ema.encoding)) + Toggle_vote.Ema.encoding) + (opt "drain_toggle_ema_threshold" Toggle_vote.Ema.encoding)) end let some (p : Toggle_vote.Emas.t) : Opt.t = - {Opt.liquidity_baking = Some p.liquidity_baking} + {Opt.liquidity_baking = Some p.liquidity_baking; drain = Some p.drain} - let none : Opt.t = {liquidity_baking = None} + let none : Opt.t = {liquidity_baking = None; drain = None} let merge (c : Toggle_vote.Emas.t) (o : Opt.t) : Toggle_vote.Emas.t = { liquidity_baking = Option.value ~default:c.liquidity_baking o.liquidity_baking; + drain = Option.value ~default:c.drain o.drain; } end @@ -742,6 +747,12 @@ module Protocol_constants_overrides = struct override_value = o.toggle_vote_ema_thresholds.liquidity_baking; pp = Toggle_vote.Ema.pp; }; + O + { + name = "drain_toggle_ema_threshold"; + override_value = o.toggle_vote_ema_thresholds.drain; + pp = Toggle_vote.Ema.pp; + }; O { name = "minimal_block_delay"; diff --git a/src/proto_alpha/lib_delegate/baking_commands.ml b/src/proto_alpha/lib_delegate/baking_commands.ml index 40f804a402a3..a1254aaa2c59 100644 --- a/src/proto_alpha/lib_delegate/baking_commands.ml +++ b/src/proto_alpha/lib_delegate/baking_commands.ml @@ -157,14 +157,21 @@ let toggle_vote_parameter = let per_block_vote_arg ?(mandatory = false) () = let open Protocol.Alpha_context in let open Toggle_vote.Name in - let to_name = function Liquidity_baking -> "liquidity baking" in + let to_name = function + | Liquidity_baking -> "liquidity baking" + | Drain -> "drain" + in let to_option_name = function | Liquidity_baking -> "liquidity-baking-toggle-vote" + | Drain -> "drain-toggle-vote" in let to_option_doc = function | Liquidity_baking -> "Vote to continue (option \"on\") or end (option \"off\") the \ liquidity baking subsidy. Or choose to pass (option \"pass\")." + | Drain -> + "Vote to continue (option \"on\") or end (option \"off\") the \ + Drain_delegate operation. Or choose to pass (option \"pass\")." in let rec generate arg = function | [] -> arg diff --git a/src/proto_alpha/lib_delegate/per_block_vote_file.ml b/src/proto_alpha/lib_delegate/per_block_vote_file.ml index 61460084b725..4c0ffbe2eff0 100644 --- a/src/proto_alpha/lib_delegate/per_block_vote_file.ml +++ b/src/proto_alpha/lib_delegate/per_block_vote_file.ml @@ -87,14 +87,16 @@ let () = (function Unexpected_content file_path -> Some file_path | _ -> None) (fun file_path -> Unexpected_content file_path) -type t = {liquidity_baking : Toggle_vote.t option} +type t = {liquidity_baking : Toggle_vote.t option; drain : Toggle_vote.t option} let encoding = let open Data_encoding in conv - (fun {liquidity_baking} -> liquidity_baking) - (fun liquidity_baking -> {liquidity_baking}) - (obj1 (opt "liquidity_baking_toggle_vote" Toggle_vote.encoding)) + (fun {liquidity_baking; drain} -> (liquidity_baking, drain)) + (fun (liquidity_baking, drain) -> {liquidity_baking; drain}) + (obj2 + (opt "liquidity_baking_toggle_vote" Toggle_vote.encoding) + (opt "drain_toggle_vote" Toggle_vote.encoding)) let check_file_exists file = if Sys.file_exists file then Result.return_unit else error (Not_found file) @@ -130,7 +132,8 @@ let merge (default : Per_block_vote.t) (vote : t) = let*! liquidity_baking = merge_vote default.liquidity_baking vote.liquidity_baking Liquidity_baking in - Lwt.return {Per_block_vote.liquidity_baking} + let*! drain = merge_vote default.drain vote.drain Drain in + Lwt.return {Per_block_vote.liquidity_baking; drain} let emit_default_vote default = List.iter_s diff --git a/src/proto_alpha/lib_delegate/per_block_vote_file.mli b/src/proto_alpha/lib_delegate/per_block_vote_file.mli index 2c381d5cac4a..7c3e139dc976 100644 --- a/src/proto_alpha/lib_delegate/per_block_vote_file.mli +++ b/src/proto_alpha/lib_delegate/per_block_vote_file.mli @@ -35,6 +35,6 @@ type error += | Malformed_json of string | Unexpected_content of string -type t = {liquidity_baking : Toggle_vote.t option} +type t = {liquidity_baking : Toggle_vote.t option; drain : Toggle_vote.t option} val read : string -> t tzresult Lwt.t diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index 8f7fda80114a..d51e8fe37f87 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -2532,9 +2532,11 @@ module RPC = struct | None -> assert false in Alpha_context.Round.get ctxt >>=? fun predecessor_round -> + Alpha_context.Per_block_vote.get_emas ctxt >>=? fun emas -> Apply.apply_contents_list ctxt chain_id + emas (Partial_construction { predecessor_level; diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index af64c23b1d5b..67256c71d908 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -703,7 +703,7 @@ end module Toggle_vote : sig module Name : sig - type t = Liquidity_baking + type t = Liquidity_baking | Drain val pp : Format.formatter -> t -> unit @@ -740,7 +740,7 @@ module Toggle_vote : sig end module Emas : sig - type t = {liquidity_baking : Ema.t} + type t = {liquidity_baking : Ema.t; drain : Ema.t} val encoding : t Data_encoding.t @@ -757,7 +757,7 @@ module Toggle_vote : sig end module Per_block_vote : sig - type t = {liquidity_baking : Toggle_vote.t} + type t = {liquidity_baking : Toggle_vote.t; drain : Toggle_vote.t} val encoding : t Data_encoding.t @@ -765,6 +765,8 @@ module Per_block_vote : sig val all_pass : t + val get_emas : context -> Toggle_vote.Emas.t tzresult Lwt.t + val get_toggle_vote : Toggle_vote.Name.t -> t -> Toggle_vote.t val set_toggle_vote : Toggle_vote.Name.t -> t -> Toggle_vote.t -> t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 2a01c4956492..c7f0b256dab9 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2657,8 +2657,12 @@ let check_manager_signature ctxt chain_id (op : _ Kind.manager contents_list) find_manager_public_key ctxt op >>=? fun public_key -> Lwt.return (Operation.check_signature public_key chain_id raw_operation) -let check_drain ctxt +type error += Drain_is_deactivated + +let check_drain ctxt emas (Single (Drain_delegate {delegate; destination; consensus_key})) = + let is_available = Per_block_vote.below_threshold ctxt emas Drain in + fail_unless is_available Drain_is_deactivated >>=? fun () -> Delegate.registered ctxt delegate >>= fun is_registered -> error_unless is_registered (Drain_delegate_on_unregistered_delegate delegate) >>?= fun () -> @@ -2680,7 +2684,8 @@ let check_drain ctxt let precheck_drain ctxt (Single (Drain_delegate {delegate; destination; _}) as op) = - check_drain ctxt op >>=? fun _active_pk -> + Per_block_vote.get_emas ctxt >>=? fun emas -> + check_drain ctxt emas op >>=? fun _active_pk -> Contract.allocated ctxt (Contract.Implicit destination) >>= fun is_destination_allocated -> (if is_destination_allocated then ok Tez.zero @@ -3259,8 +3264,8 @@ let validate_grand_parent_endorsement ctxt chain_id 0 (* dummy endorsement power: this will never be used *); }) ) -let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode - ~payload_producer (operation : kind operation) +let apply_contents_list (type kind) ctxt chain_id emas (apply_mode : apply_mode) + mode ~payload_producer (operation : kind operation) (contents_list : kind contents_list) : (context * kind contents_result_list) tzresult Lwt.t = let mempool_mode = @@ -3390,7 +3395,7 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode Amendment.record_ballot ctxt source proposal ballot >|=? fun ctxt -> (ctxt, Single_result Ballot_result) | Single (Drain_delegate {delegate; destination; consensus_key = _}) as op -> - check_drain ctxt op >>=? fun active_pk -> + check_drain ctxt emas op >>=? fun active_pk -> Operation.check_signature active_pk chain_id operation >>?= fun () -> Delegate.drain ctxt ~delegate ~destination >>=? fun ( ctxt, @@ -3441,13 +3446,14 @@ let apply_contents_list (type kind) ctxt chain_id (apply_mode : apply_mode) mode prechecked_contents_list >|= ok -let apply_operation ctxt chain_id (apply_mode : apply_mode) mode +let apply_operation ctxt chain_id emas (apply_mode : apply_mode) mode ~payload_producer hash operation = let ctxt = Origination_nonce.init ctxt hash in let ctxt = record_operation ctxt operation in apply_contents_list ctxt chain_id + emas apply_mode mode ~payload_producer diff --git a/src/proto_alpha/lib_protocol/apply.mli b/src/proto_alpha/lib_protocol/apply.mli index 2feda8443aa3..b88593e0b463 100644 --- a/src/proto_alpha/lib_protocol/apply.mli +++ b/src/proto_alpha/lib_protocol/apply.mli @@ -114,6 +114,7 @@ type apply_mode = val apply_operation : context -> Chain_id.t -> + Toggle_vote.Emas.t -> apply_mode -> Script_ir_translator.unparsing_mode -> payload_producer:Consensus_key.t -> @@ -152,6 +153,7 @@ val apply_manager_contents_list : val apply_contents_list : context -> Chain_id.t -> + Toggle_vote.Emas.t -> apply_mode -> Script_ir_translator.unparsing_mode -> payload_producer:Consensus_key.t -> diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index 35e78d70b486..4adda54cf012 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -332,13 +332,14 @@ let begin_construction ~chain_id ~predecessor_context:ctxt @ liquidity_baking_operations_results; } -let apply_operation_with_mode mode ctxt chain_id data op_count operation +let apply_operation_with_mode mode ctxt chain_id emas data op_count operation ~payload_producer = let {shell; protocol_data = Operation_data protocol_data} = operation in let operation : _ Alpha_context.operation = {shell; protocol_data} in Apply.apply_operation ctxt chain_id + emas mode Optimized ~payload_producer @@ -348,7 +349,8 @@ let apply_operation_with_mode mode ctxt chain_id data op_count operation let op_count = op_count + 1 in ({data with ctxt; op_count}, Operation_metadata result) -let apply_operation ({mode; chain_id; ctxt; op_count; _} as data) +let apply_operation + ({mode; chain_id; ctxt; toggle_vote_emas; op_count; _} as data) (operation : Alpha_context.packed_operation) = match mode with | Partial_application _ @@ -385,6 +387,7 @@ let apply_operation ({mode; chain_id; ctxt; op_count; _} as data) }) ctxt chain_id + toggle_vote_emas data op_count operation @@ -415,6 +418,7 @@ let apply_operation ({mode; chain_id; ctxt; op_count; _} as data) }) ctxt chain_id + toggle_vote_emas data op_count operation @@ -428,6 +432,7 @@ let apply_operation ({mode; chain_id; ctxt; op_count; _} as data) {predecessor_round; predecessor_level; grand_parent_round}) ctxt chain_id + toggle_vote_emas data op_count operation @@ -453,6 +458,7 @@ let apply_operation ({mode; chain_id; ctxt; op_count; _} as data) }) ctxt chain_id + toggle_vote_emas data op_count operation diff --git a/src/proto_alpha/lib_protocol/per_block_vote_repr.ml b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml index f390effb9d13..0f22a266d1f8 100644 --- a/src/proto_alpha/lib_protocol/per_block_vote_repr.ml +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.ml @@ -26,36 +26,40 @@ open Toggle_vote_name_repr open Toggle_vote_repr -type t = {liquidity_baking : Toggle_vote_repr.t} +type t = {liquidity_baking : Toggle_vote_repr.t; drain : Toggle_vote_repr.t} let encoding = (* Warning: when adding a second vote, please use compact encodings. *) let open Data_encoding in conv - (fun {liquidity_baking} -> liquidity_baking) - (fun liquidity_baking -> {liquidity_baking}) - (obj1 (req "liquidity_baking_toggle_vote" Toggle_vote_repr.encoding)) + (fun {liquidity_baking; drain} -> (liquidity_baking, drain)) + (fun (liquidity_baking, drain) -> {liquidity_baking; drain}) + (obj2 + (req "liquidity_baking_toggle_vote" Toggle_vote_repr.encoding) + (req "drain_toggle_vote" Toggle_vote_repr.encoding)) let dft_encoding = let open Data_encoding in conv - (fun {liquidity_baking} -> liquidity_baking) - (fun liquidity_baking -> {liquidity_baking}) - (obj1 + (fun {liquidity_baking; drain} -> (liquidity_baking, drain)) + (fun (liquidity_baking, drain) -> {liquidity_baking; drain}) + (obj2 (dft "liquidity_baking_toggle_vote" Toggle_vote_repr.encoding - Toggle_pass)) + Toggle_pass) + (dft "drain_toggle_vote" Toggle_vote_repr.encoding Toggle_pass)) -let all_pass = {liquidity_baking = Toggle_pass} +let all_pass = {liquidity_baking = Toggle_pass; drain = Toggle_pass} let get_toggle_vote = function | Liquidity_baking -> fun ballot -> ballot.liquidity_baking + | Drain -> fun ballot -> ballot.drain let set_toggle_vote name = match name with - | Liquidity_baking -> - fun {liquidity_baking = _} vote -> {liquidity_baking = vote} + | Liquidity_baking -> fun ballot vote -> {ballot with liquidity_baking = vote} + | Drain -> fun ballot vote -> {ballot with drain = vote} let update ballot (emas : Toggle_vote_emas_repr.t) : Toggle_vote_emas_repr.t = { @@ -64,4 +68,9 @@ let update ballot (emas : Toggle_vote_emas_repr.t) : Toggle_vote_emas_repr.t = (Toggle_vote_emas_repr.get_config Liquidity_baking) ballot.liquidity_baking emas.liquidity_baking; + drain = + Toggle_vote_ema_repr.update + (Toggle_vote_emas_repr.get_config Drain) + ballot.drain + emas.drain; } diff --git a/src/proto_alpha/lib_protocol/per_block_vote_repr.mli b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli index 74dc36cf95c8..ae1c8eebbe30 100644 --- a/src/proto_alpha/lib_protocol/per_block_vote_repr.mli +++ b/src/proto_alpha/lib_protocol/per_block_vote_repr.mli @@ -24,7 +24,7 @@ (*****************************************************************************) (** A per-block ballot. *) -type t = {liquidity_baking : Toggle_vote_repr.t} +type t = {liquidity_baking : Toggle_vote_repr.t; drain : Toggle_vote_repr.t} (** Encoding for a per-block ballot where all toggle-vote fields are required. *) val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/per_block_vote_storage.ml b/src/proto_alpha/lib_protocol/per_block_vote_storage.ml index 3a60f380e24d..17507ee748dc 100644 --- a/src/proto_alpha/lib_protocol/per_block_vote_storage.ml +++ b/src/proto_alpha/lib_protocol/per_block_vote_storage.ml @@ -36,12 +36,14 @@ let set_ema = Storage.Toggle_vote_ema.add let get_emas ctxt = let open Lwt_tzresult_syntax in let* liquidity_baking = get_ema ctxt Liquidity_baking in - return {Toggle_vote_emas_repr.liquidity_baking} + let* drain = get_ema ctxt Drain in + return {Toggle_vote_emas_repr.liquidity_baking; drain} let set_all ctxt emas = let open Lwt_result_syntax in - let {Toggle_vote_emas_repr.liquidity_baking} = emas in + let {Toggle_vote_emas_repr.liquidity_baking; drain} = emas in let*! ctxt = set_ema ctxt Liquidity_baking liquidity_baking in + let*! ctxt = set_ema ctxt Drain drain in Lwt.return ctxt let update ctxt ballots = diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index b15133c2a3fb..2fa10eff23fe 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -928,7 +928,10 @@ let prepare_first_block ~level ~timestamp ctxt = liquidity_baking_subsidy = c.liquidity_baking_subsidy; liquidity_baking_sunset_level = c.liquidity_baking_sunset_level; toggle_vote_ema_thresholds = - {liquidity_baking = c.liquidity_baking_toggle_ema_threshold}; + { + Toggle_vote_emas_repr.default_thresholds with + liquidity_baking = c.liquidity_baking_toggle_ema_threshold; + }; minimal_block_delay = c.minimal_block_delay; delay_increment_per_round = c.delay_increment_per_round; consensus_committee_size = c.consensus_committee_size; diff --git a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml index 586de3f8205a..47956ff228f4 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_liquidity_baking.ml @@ -149,9 +149,9 @@ let liquidity_baking_sunset_level n () = let lb_pass = Alpha_context.Per_block_vote.all_pass -let lb_off = {Alpha_context.Per_block_vote.liquidity_baking = Toggle_off} +let lb_off = {lb_pass with liquidity_baking = Toggle_off} -let lb_on = {Alpha_context.Per_block_vote.liquidity_baking = Toggle_on} +let lb_on = {lb_pass with liquidity_baking = Toggle_on} (* Test that subsidy shuts off at correct level alternating baking blocks with liquidity_baking_toggle_vote set to [LB_on], [LB_off], and [LB_pass] followed by [bake_after_toggle] blocks with it set to [LB_pass]. *) diff --git a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml index 5566420050f5..26c39de5c744 100644 --- a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml +++ b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.ml @@ -25,34 +25,43 @@ open Toggle_vote_name_repr -type t = {liquidity_baking : Toggle_vote_ema_repr.t} +type t = { + liquidity_baking : Toggle_vote_ema_repr.t; + drain : Toggle_vote_ema_repr.t; +} let encoding = let open Data_encoding in conv - (fun {liquidity_baking} -> liquidity_baking) - (fun liquidity_baking -> {liquidity_baking}) - (obj1 (req "liquidity_baking_toggle_ema" Toggle_vote_ema_repr.encoding)) + (fun {liquidity_baking; drain} -> (liquidity_baking, drain)) + (fun (liquidity_baking, drain) -> {liquidity_baking; drain}) + (obj2 + (req "liquidity_baking_toggle_ema" Toggle_vote_ema_repr.encoding) + (req "drain_toggle_ema" Toggle_vote_ema_repr.encoding)) let threshold_encoding = let open Data_encoding in conv - (fun {liquidity_baking} -> liquidity_baking) - (fun liquidity_baking -> {liquidity_baking}) - (obj1 + (fun {liquidity_baking; drain} -> (liquidity_baking, drain)) + (fun (liquidity_baking, drain) -> {liquidity_baking; drain}) + (obj2 (req "liquidity_baking_toggle_ema_threshold" - Toggle_vote_ema_repr.encoding)) + Toggle_vote_ema_repr.encoding) + (req "drain_toggle_ema_threshold" Toggle_vote_ema_repr.encoding)) -let get = function Liquidity_baking -> fun emas -> emas.liquidity_baking +let get = function + | Liquidity_baking -> fun emas -> emas.liquidity_baking + | Drain -> fun emas -> emas.drain let get_config = function | Liquidity_baking -> Toggle_vote_ema_repr.Config.simple_off + | Drain -> Toggle_vote_ema_repr.Config.simple_off let initial = let get name = (get_config name).initial in - {liquidity_baking = get Liquidity_baking} + {liquidity_baking = get Liquidity_baking; drain = get Drain} let default_thresholds = let get name = (get_config name).default_threshold in - {liquidity_baking = get Liquidity_baking} + {liquidity_baking = get Liquidity_baking; drain = get Drain} diff --git a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli index 2d2312160612..f41eac017c84 100644 --- a/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli +++ b/src/proto_alpha/lib_protocol/toggle_vote_emas_repr.mli @@ -24,7 +24,10 @@ (*****************************************************************************) (** The EMAs for all pending toggle votes. *) -type t = {liquidity_baking : Toggle_vote_ema_repr.t} +type t = { + liquidity_baking : Toggle_vote_ema_repr.t; + drain : Toggle_vote_ema_repr.t; +} (** Encoding for current EMAs of all pending toggle vote. *) val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml index 0a63f3a97a7c..2afc45493df5 100644 --- a/src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml +++ b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.ml @@ -23,12 +23,15 @@ (* *) (*****************************************************************************) -type t = Liquidity_baking +type t = Liquidity_baking | Drain -let to_string = function Liquidity_baking -> "liquidity_baking" +let to_string = function + | Liquidity_baking -> "liquidity_baking" + | Drain -> "drain" let of_string_opt = function | "liquidity_baking" -> Some Liquidity_baking + | "drain" -> Some Drain | _ -> None let of_string_err name = @@ -38,15 +41,12 @@ let of_string_err name = let pp ppf v = Format.pp_print_string ppf (to_string v) -let all = [Liquidity_baking] +let all = [Liquidity_baking; Drain] let encoding = let open Data_encoding in def "toggle_vote_name" - @@ conv - (fun Liquidity_baking -> ()) - (fun () -> Liquidity_baking) - (constant "liquidity_baking") + @@ string_enum (List.map (fun x -> (to_string x, x)) all) let path_length = 1 @@ -61,4 +61,9 @@ let rpc_arg = ~construct:to_string () -let compare a b = match (a, b) with Liquidity_baking, Liquidity_baking -> 0 +let compare a b = + match (a, b) with + | Liquidity_baking, Liquidity_baking -> 0 + | Liquidity_baking, _ -> -1 + | _, Liquidity_baking -> 1 + | Drain, Drain -> 0 diff --git a/src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli index ef3bad1c89f3..ef9b902b66e9 100644 --- a/src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli +++ b/src/proto_alpha/lib_protocol/toggle_vote_name_repr.mli @@ -24,7 +24,7 @@ (*****************************************************************************) (** The per-block toggle votes. *) -type t = Liquidity_baking +type t = Liquidity_baking | Drain val pp : Format.formatter -> t -> unit diff --git a/tests_python/tests_alpha/test_mockup.py b/tests_python/tests_alpha/test_mockup.py index 246b27c5fdda..f2287ce34ac4 100644 --- a/tests_python/tests_alpha/test_mockup.py +++ b/tests_python/tests_alpha/test_mockup.py @@ -642,9 +642,10 @@ def _test_create_mockup_init_show_roundtrip( "blocks_per_commitment": 5, "blocks_per_cycle": 9, "preserved_cycles": 3, - "liquidity_baking_toggle_ema_threshold": 1000000000, "liquidity_baking_subsidy": "2500000", "liquidity_baking_sunset_level": 1024, + "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "max_operations_time_to_live": 120, "frozen_deposits_percentage": 10, 'ratio_of_frozen_deposits_slashed_per_double_endorsement': { diff --git a/tests_python/tests_alpha/test_per_block_votes.py b/tests_python/tests_alpha/test_per_block_votes.py index 51a12a439ee1..55f5f14def1a 100644 --- a/tests_python/tests_alpha/test_per_block_votes.py +++ b/tests_python/tests_alpha/test_per_block_votes.py @@ -28,6 +28,8 @@ def run_vote_file(sandbox: Sandbox, filename: str, default_vote: str) -> None: filename, '--liquidity-baking-toggle-vote', default_vote, + '--drain-toggle-vote', + default_vote, ], ) if not sandbox.log_dir: diff --git a/tests_python/tools/constants.py b/tests_python/tools/constants.py index 902056a70734..d6c1657cd0e0 100644 --- a/tests_python/tools/constants.py +++ b/tests_python/tools/constants.py @@ -265,4 +265,9 @@ TENDERBAKE_NODE_LOG_LEVELS = { "validator.chain": "debug", } -TOGGLE_VOTE_BAKER_PARAMS = ['--liquidity-baking-toggle-vote', 'pass'] +TOGGLE_VOTE_BAKER_PARAMS = [ + '--liquidity-baking-toggle-vote', + 'pass', + '--drain-toggle-vote', + 'pass', +] diff --git a/tezt/_regressions/encoding/alpha.block_header.out b/tezt/_regressions/encoding/alpha.block_header.out index 509ed79748f1..8117beef05d0 100644 --- a/tezt/_regressions/encoding/alpha.block_header.out +++ b/tezt/_regressions/encoding/alpha.block_header.out @@ -15,13 +15,14 @@ encoding/alpha.block_header.out "proof_of_work_nonce": "101895ca00000000", "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0 }' -00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d5580166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d558010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c -./tezos-codec decode alpha.block_header from 00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d5580166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +./tezos-codec decode alpha.block_header from 00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d558010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c { "level": 1331, "proto": 1, "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 2, @@ -31,6 +32,6 @@ encoding/alpha.block_header.out "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", - "liquidity_baking_toggle_vote": "off", + "liquidity_baking_toggle_vote": "off", "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } diff --git a/tezt/_regressions/encoding/alpha.block_header.unsigned.out b/tezt/_regressions/encoding/alpha.block_header.unsigned.out index 0fe934a99a10..2f3e51e7411d 100644 --- a/tezt/_regressions/encoding/alpha.block_header.unsigned.out +++ b/tezt/_regressions/encoding/alpha.block_header.unsigned.out @@ -15,12 +15,13 @@ encoding/alpha.block_header.unsigned.out "proof_of_work_nonce": "101895ca00000000", "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0 }' -00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55801 +00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d5580101 -./tezos-codec decode alpha.block_header.unsigned from 00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d55801 +./tezos-codec decode alpha.block_header.unsigned from 00000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00242e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000ff043691f53c02ca1ac6f1a0c1586bf77973e04c2d9b618a8309e79651daf0d5580101 { "level": 1331, "proto": 1, "predecessor": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", "timestamp": "2020-04-20T16:20:00Z", "validation_pass": 2, @@ -30,4 +31,4 @@ encoding/alpha.block_header.unsigned.out "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", - "liquidity_baking_toggle_vote": "off" } + "liquidity_baking_toggle_vote": "off", "drain_toggle_vote": "off" } diff --git a/tezt/_regressions/encoding/alpha.operation.out b/tezt/_regressions/encoding/alpha.operation.out index 81d10cd9c175..b4da5efecdb9 100644 --- a/tezt/_regressions/encoding/alpha.operation.out +++ b/tezt/_regressions/encoding/alpha.operation.out @@ -120,6 +120,7 @@ encoding/alpha.operation.out "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0 @@ -138,6 +139,7 @@ encoding/alpha.operation.out "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0 @@ -146,9 +148,9 @@ encoding/alpha.operation.out ], "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }' -0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c -./tezos-codec decode alpha.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +./tezos-codec decode alpha.operation from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c66804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", "contents": [ { "kind": "double_baking_evidence", @@ -165,6 +167,7 @@ encoding/alpha.operation.out "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, "bh2": @@ -180,6 +183,7 @@ encoding/alpha.operation.out "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ], "signature": diff --git a/tezt/_regressions/encoding/alpha.operation.unsigned.out b/tezt/_regressions/encoding/alpha.operation.unsigned.out index 72062871fe88..dc990945c280 100644 --- a/tezt/_regressions/encoding/alpha.operation.unsigned.out +++ b/tezt/_regressions/encoding/alpha.operation.unsigned.out @@ -108,6 +108,7 @@ encoding/alpha.operation.unsigned.out "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0 @@ -126,6 +127,7 @@ encoding/alpha.operation.unsigned.out "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0 @@ -133,9 +135,9 @@ encoding/alpha.operation.unsigned.out } ] }' -0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c -./tezos-codec decode alpha.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f100000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca00000000000166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c +./tezos-codec decode alpha.operation.unsigned from 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a803000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c000000f200000533010e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8000000005e9dcbb00442e9bc4583d4f9fa6ba422733f45d3a44397141a953d2237bf8df62e5046eef700000011000000010100000008000000000000000a4c7319284b55068bb7c4e0b9f8585729db7fb27ab4ca9cff2038a1fc324f650c000000000000000000000000000000000000000000000000000000000000000000000000101895ca0000000000010166804fe735e06e97e26da8236b6341b91c625d5e82b3524ec0a88cc982365e70f8a5b9bc65df2ea6d21ee244cc3a96fb33031c394c78b1179ff1b8a44237740c { "branch": "BKpbfCvh777DQHnXjU2sqHvVUNZ7dBAdqEfKkdw8EGSkD9LSYXb", "contents": [ { "kind": "double_baking_evidence", @@ -152,6 +154,7 @@ encoding/alpha.operation.unsigned.out "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" }, "bh2": @@ -167,6 +170,7 @@ encoding/alpha.operation.unsigned.out "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round": 0, "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ" } } ] } diff --git a/tezt/_regressions/rpc/alpha.client.mempool.out b/tezt/_regressions/rpc/alpha.client.mempool.out index 95487877d313..b268e0313e03 100644 --- a/tezt/_regressions/rpc/alpha.client.mempool.out +++ b/tezt/_regressions/rpc/alpha.client.mempool.out @@ -759,12 +759,16 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "liquidity_baking_toggle_vote": { "$ref": "#/definitions/alpha.toggle_vote" }, + "drain_toggle_vote": { + "$ref": "#/definitions/alpha.toggle_vote" + }, "signature": { "$ref": "#/definitions/Signature" } }, "required": [ "signature", + "drain_toggle_vote", "liquidity_baking_toggle_vote", "proof_of_work_nonce", "payload_round", @@ -7462,6 +7466,19 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' }, "kind": "named" }, + { + "name": "drain_toggle_vote", + "layout": { + "size": "Uint8", + "reference": "alpha.toggle_vote", + "kind": "Enum" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, { "name": "signature", "layout": { @@ -11474,12 +11491,16 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "liquidity_baking_toggle_vote": { "$ref": "#/definitions/alpha.toggle_vote" }, + "drain_toggle_vote": { + "$ref": "#/definitions/alpha.toggle_vote" + }, "signature": { "$ref": "#/definitions/Signature" } }, "required": [ "signature", + "drain_toggle_vote", "liquidity_baking_toggle_vote", "proof_of_work_nonce", "payload_round", diff --git a/tezt/_regressions/rpc/alpha.client.others.out b/tezt/_regressions/rpc/alpha.client.others.out index 0e73684ce95a..2a88cfcd53d7 100644 --- a/tezt/_regressions/rpc/alpha.client.others.out +++ b/tezt/_regressions/rpc/alpha.client.others.out @@ -22,6 +22,7 @@ rpc/alpha.client.others.out "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.light.others.out b/tezt/_regressions/rpc/alpha.light.others.out index a6cf4a2bba8b..d77947f31d2f 100644 --- a/tezt/_regressions/rpc/alpha.light.others.out +++ b/tezt/_regressions/rpc/alpha.light.others.out @@ -22,6 +22,7 @@ rpc/alpha.light.others.out "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.proxy.mempool.out b/tezt/_regressions/rpc/alpha.proxy.mempool.out index ecefe615f3f1..f19522a0a127 100644 --- a/tezt/_regressions/rpc/alpha.proxy.mempool.out +++ b/tezt/_regressions/rpc/alpha.proxy.mempool.out @@ -780,12 +780,16 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "liquidity_baking_toggle_vote": { "$ref": "#/definitions/alpha.toggle_vote" }, + "drain_toggle_vote": { + "$ref": "#/definitions/alpha.toggle_vote" + }, "signature": { "$ref": "#/definitions/Signature" } }, "required": [ "signature", + "drain_toggle_vote", "liquidity_baking_toggle_vote", "proof_of_work_nonce", "payload_round", @@ -7483,6 +7487,19 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' }, "kind": "named" }, + { + "name": "drain_toggle_vote", + "layout": { + "size": "Uint8", + "reference": "alpha.toggle_vote", + "kind": "Enum" + }, + "data_kind": { + "size": 1, + "kind": "Float" + }, + "kind": "named" + }, { "name": "signature", "layout": { @@ -11495,12 +11512,16 @@ curl -s 'http://localhost:[PORT]/describe/chains/main/mempool?recurse=yes' "liquidity_baking_toggle_vote": { "$ref": "#/definitions/alpha.toggle_vote" }, + "drain_toggle_vote": { + "$ref": "#/definitions/alpha.toggle_vote" + }, "signature": { "$ref": "#/definitions/Signature" } }, "required": [ "signature", + "drain_toggle_vote", "liquidity_baking_toggle_vote", "proof_of_work_nonce", "payload_round", diff --git a/tezt/_regressions/rpc/alpha.proxy.others.out b/tezt/_regressions/rpc/alpha.proxy.others.out index 2560171bfaa3..a0df753e015a 100644 --- a/tezt/_regressions/rpc/alpha.proxy.others.out +++ b/tezt/_regressions/rpc/alpha.proxy.others.out @@ -22,6 +22,7 @@ rpc/alpha.proxy.others.out "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out index e0e18022e40c..19c35a824a22 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_data_dir.others.out @@ -22,6 +22,7 @@ rpc/alpha.proxy_server_data_dir.others.out "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out b/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out index 2f694b9a08b3..3ed3be0855a8 100644 --- a/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out +++ b/tezt/_regressions/rpc/alpha.proxy_server_rpc.others.out @@ -22,6 +22,7 @@ rpc/alpha.proxy_server_rpc.others.out "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out index 7dd882836fbd..31260ad10bee 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_commitment_is_stored.out @@ -55,6 +55,7 @@ This sequence of operations was run: "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_first_published_at_level_global.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_first_published_at_level_global.out index a2130ceeae98..7ee06162fb32 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_first_published_at_level_global.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_first_published_at_level_global.out @@ -51,11 +51,11 @@ This sequence of operations was run: "hard_storage_limit_per_operation": "60000", "quorum_min": 2000, "quorum_max": 7000, "min_proposal_quorum": 500, "liquidity_baking_subsidy": "2500000", - "liquidity_baking_sunset_level": 128, + "liquidity_baking_sunset_level": 128, "max_operations_time_to_live": 120, + "minimal_block_delay": "1", "delay_increment_per_round": "1", + "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, - "max_operations_time_to_live": 120, "minimal_block_delay": "1", - "delay_increment_per_round": "1", "consensus_committee_size": 256, - "consensus_threshold": 0, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out index fa6a8f38466f..84ceb795a23a 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_handles_chain_reorgs.out @@ -55,6 +55,7 @@ This sequence of operations was run: "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out index 61af31c70a17..69bbebb66ae7 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_messages_reset.out @@ -55,6 +55,7 @@ This sequence of operations was run: "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out index 677f63d3a276..e98ddf36dcce 100644 --- a/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out +++ b/tezt/_regressions/sc_rollup_commitment_of_rollup_node_non_final_level.out @@ -55,6 +55,7 @@ This sequence of operations was run: "minimal_block_delay": "1", "delay_increment_per_round": "1", "consensus_committee_size": 256, "consensus_threshold": 0, "liquidity_baking_toggle_ema_threshold": 1000000000, + "drain_toggle_ema_threshold": 1000000000, "minimal_participation_ratio": { "numerator": 2, "denominator": 3 }, "max_slashing_period": 2, "frozen_deposits_percentage": 5, "double_baking_punishment": "640000000", diff --git a/tezt/lib_tezos/baker.ml b/tezt/lib_tezos/baker.ml index b2d3be242be3..0d32bf933131 100644 --- a/tezt/lib_tezos/baker.ml +++ b/tezt/lib_tezos/baker.ml @@ -96,6 +96,8 @@ let run (baker : t) = ] @ (if Protocol.number baker.persistent_state.protocol < 013 then [] else ["--liquidity-baking-toggle-vote"; "pass"]) + @ (if Protocol.number baker.persistent_state.protocol < 014 then [] + else ["--drain-toggle-vote"; "pass"]) @ delegates in let on_terminate _ = diff --git a/tezt/tests/encoding_samples/alpha/block_header.unsigned/block_header.unsigned.sample.json b/tezt/tests/encoding_samples/alpha/block_header.unsigned/block_header.unsigned.sample.json index 51a6450fc42a..2ca9791bf812 100644 --- a/tezt/tests/encoding_samples/alpha/block_header.unsigned/block_header.unsigned.sample.json +++ b/tezt/tests/encoding_samples/alpha/block_header.unsigned/block_header.unsigned.sample.json @@ -13,6 +13,7 @@ "proof_of_work_nonce": "101895ca00000000", "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round":0 } diff --git a/tezt/tests/encoding_samples/alpha/block_header/block_header.sample.json b/tezt/tests/encoding_samples/alpha/block_header/block_header.sample.json index af21dd2f4598..dca1e33ce3ae 100644 --- a/tezt/tests/encoding_samples/alpha/block_header/block_header.sample.json +++ b/tezt/tests/encoding_samples/alpha/block_header/block_header.sample.json @@ -13,6 +13,7 @@ "proof_of_work_nonce": "101895ca00000000", "seed_nonce_hash": "nceUFoeQDgkJCmzdMWh19ZjBYqQD3N9fe6bXQ1ZsUKKvMn7iun5Z3", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round":0 diff --git a/tezt/tests/encoding_samples/alpha/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/alpha/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json index 8eed2982138e..e469d0880270 100644 --- a/tezt/tests/encoding_samples/alpha/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json +++ b/tezt/tests/encoding_samples/alpha/operation.unsigned/operation.unsigned-double-baking-evidence.sample.json @@ -17,6 +17,7 @@ "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round":0 @@ -35,6 +36,7 @@ "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round":0 diff --git a/tezt/tests/encoding_samples/alpha/operation/operation-double-baking-evidence.sample.json b/tezt/tests/encoding_samples/alpha/operation/operation-double-baking-evidence.sample.json index 1c8f236c2dee..24d123a719b1 100644 --- a/tezt/tests/encoding_samples/alpha/operation/operation-double-baking-evidence.sample.json +++ b/tezt/tests/encoding_samples/alpha/operation/operation-double-baking-evidence.sample.json @@ -13,6 +13,7 @@ "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round":0 @@ -28,6 +29,7 @@ "context": "CoVDyf9y9gHfAkPWofBJffo4X4bWjmehH2LeVonDcCKKzyQYwqdk", "proof_of_work_nonce": "101895ca00000000", "liquidity_baking_toggle_vote": "off", + "drain_toggle_vote": "off", "signature": "sigbQ5ZNvkjvGssJgoAnUAfY4Wvvg3QZqawBYB1j1VDBNTMBAALnCzRHWzer34bnfmzgHg3EvwdzQKdxgSghB897cono6gbQ", "payload_hash": "vh1g87ZG6scSYxKhspAUzprQVuLAyoa5qMBKcUfjgnQGnFb3dJcG", "payload_round":0 -- GitLab From 12aa0b309bd09e9d2a17fd2c94ce28927b19a7f6 Mon Sep 17 00:00:00 2001 From: "G.B. Fefe" Date: Mon, 25 Apr 2022 09:26:31 +0200 Subject: [PATCH 48/48] Proto: invoice for TZIP #??? --- src/proto_alpha/lib_protocol/init_storage.ml | 41 +++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 07df4f632a74..89e5af3220cf 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -35,22 +35,24 @@ Do not fail if something goes wrong. *) - let invoice_contract ctxt ~address ~amount_mutez = - match Tez_repr.of_mutez amount_mutez with - | None -> Lwt.return (ctxt, []) - | Some amount -> ( - ( Contract_repr.of_b58check address >>?= fun recipient -> - Token.transfer - ~origin:Protocol_migration - ctxt - `Invoice - (`Contract recipient) - amount ) - >|= function - | Ok res -> res - | Error _ -> (ctxt, [])) + *) +let invoice_contract ctxt ~address ~amount_mutez = + match Tez_repr.of_mutez amount_mutez with + | None -> Lwt.return (ctxt, []) + | Some amount -> ( + ( Contract_repr.of_b58check address >>?= fun recipient -> + Token.transfer + ~origin:Protocol_migration + ctxt + `Invoice + (`Contract recipient) + amount ) + >|= function + | Ok res -> res + | Error _ -> (ctxt, [])) + (* To patch code of legacy contracts you can add a helper function here and call it at the end of prepare_first_block. @@ -122,7 +124,16 @@ let prepare_first_block _chain_id ctxt ~typecheck ~level ~timestamp = >>=? fun ctxt -> Delegate_cycles.Migration_from_Jakarta.update ctxt >>=? fun ctxt -> Per_block_vote_storage.Migration_from_Jakarta.update ctxt >>=? fun ctxt -> - return (ctxt, [])) + invoice_contract + ctxt + ~address:"tz1X81bCXPtMiHu1d4UZF4GPhMPkvkp56ssb" + ~amount_mutez:30_000_000_000L + >>= fun (ctxt, bu1) -> + invoice_contract + ctxt + ~address:"tz3WfTf4n92oiBju27YRwsLStAFoRJzzSiw2" + ~amount_mutez:20_000_000_000L + >>= fun (ctxt, bu2) -> return (ctxt, bu1 @ bu2)) >>=? fun (ctxt, balance_updates) -> Receipt_repr.group_balance_updates balance_updates >>?= fun balance_updates -> Storage.Pending_migration.Balance_updates.add ctxt balance_updates -- GitLab