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 6b38c0f94a26653f9156d4b4ce30402e7a0cb960..6b01041224a57492813956dcfc8e12b78a48a86e 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 @@ -1622,7 +1622,11 @@ let commands_rw () = in match r with | Ok _ -> return_unit - | Error [Environment.Ecoproto_error Delegate_storage.Active_delegate] -> + | Error + [ + Environment.Ecoproto_error + Delegate_storage.Contract.Active_delegate; + ] -> let*! () = cctxt#message "Delegate already activated." in return_unit | Error el -> Lwt.return_error el); diff --git a/src/proto_alpha/lib_protocol/alpha_context.ml b/src/proto_alpha/lib_protocol/alpha_context.ml index 0d730ba4372a6bd28cc61772258090c027aa20f3..63ee7e4e2037ac316679932e66d21bd9900fbdd2 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.ml +++ b/src/proto_alpha/lib_protocol/alpha_context.ml @@ -306,6 +306,12 @@ module Contract = struct let get_manager_key = Contract_manager_storage.get_manager_key + module Delegate = struct + let find = Contract_delegate_storage.find + + include Delegate_storage.Contract + end + module Internal_for_tests = struct include Contract_repr include Contract_storage @@ -480,11 +486,9 @@ 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 + + let deactivated = Delegate_activation_storage.is_inactive 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 c430caa37d61aa669002a98a54b8272ebbac8019..fd1de02d68aa4a8dbb3405ece18d93cfcb64b228 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -1350,9 +1350,6 @@ module Seed : sig val compute_randao : context -> context tzresult Lwt.t - val cycle_end : - context -> Cycle.t -> (context * Nonce.unrevealed list) tzresult Lwt.t - (* RPC *) type seed_computation_status = | Nonce_revelation_stage @@ -1670,15 +1667,13 @@ end (** This module re-exports definitions from {!Contract_repr} and {!Contract_storage}. *) module Contract : sig - type t = - | Implicit of Signature.Public_key_hash.t - | Originated of Contract_hash.t + type t = Implicit of public_key_hash | Originated of Contract_hash.t type error += Non_existing_contract of t include BASIC_DATA with type t := t - val implicit_encoding : Signature.public_key_hash Data_encoding.t + val implicit_encoding : public_key_hash Data_encoding.t val originated_encoding : Contract_hash.t Data_encoding.t @@ -1804,6 +1799,18 @@ 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 + (** See {!Contract_delegate_storage.find}. *) + val find : context -> t -> public_key_hash option tzresult Lwt.t + + (** See {!Delegate_storage.Contract.init}. *) + val init : context -> t -> public_key_hash -> context tzresult Lwt.t + + (** See {!Delegate_storage.Contract.set}. *) + val set : context -> t -> public_key_hash option -> context tzresult Lwt.t + end + (** This module discloses definitions that are only useful for tests and must not be used otherwise. *) module Internal_for_tests : sig @@ -1871,7 +1878,7 @@ end (** This module re-exports definitions from {!Tx_rollup_withdraw_repr}. *) 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; } @@ -2005,7 +2012,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 @@ -2160,7 +2167,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; } @@ -2191,10 +2198,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 -> @@ -2230,16 +2236,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 -> @@ -2254,16 +2254,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 -> @@ -2311,8 +2305,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 @@ -2481,7 +2475,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 @@ -2518,23 +2512,11 @@ end {!Delegate_missed_endorsements_storage}, {!Delegate_slashed_deposits_storage}, {!Delegate_cycles}. *) module Delegate : sig - val init : - context -> - Contract.t -> - Signature.Public_key_hash.t -> - context tzresult Lwt.t - - (** See {!Contract_delegate_storage.find}. *) - 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 + 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 -> @@ -2560,10 +2542,7 @@ 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 + (context * Receipt.balance_updates * public_key_hash list) tzresult Lwt.t val already_slashed_for_double_endorsing : context -> public_key_hash -> Level.t -> bool tzresult Lwt.t @@ -2589,15 +2568,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 @@ -2606,25 +2585,20 @@ 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 (** See {!Contract_delegate_storage.delegated_contracts}. *) - 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 - (** See {!Contract_delegate_storage.registered}. *) - val registered : context -> Signature.Public_key_hash.t -> bool tzresult 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 (** See {!Delegate_activation_storage.last_cycle_before_deactivation}. *) 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 @@ -2705,8 +2679,7 @@ module Vote : sig val clear_proposals : context -> context 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 @@ -2732,13 +2705,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 @@ -2827,7 +2799,7 @@ module Dal : sig val expected_size_in_bits : max_index:Slot_index.t -> int - val shards : context -> endorser:Signature.Public_key_hash.t -> int list + val shards : context -> endorser:public_key_hash -> int list val record_available_shards : context -> t -> int list -> context end @@ -2914,8 +2886,7 @@ module Sc_rollup : sig val in_memory_size : t -> Cache_memory_helpers.sint - 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 : sig include S.HASH @@ -2937,7 +2908,7 @@ module Sc_rollup : sig type internal_inbox_message = { payload : Script.expr; sender : Contract_hash.t; - source : Signature.public_key_hash; + source : public_key_hash; } type t = Internal of internal_inbox_message | External of string @@ -3111,7 +3082,7 @@ module Sc_rollup : sig rollup -> payload:Script.expr -> sender:Contract_hash.t -> - source:Signature.public_key_hash -> + source:public_key_hash -> (t * Z.t * context) tzresult Lwt.t val inbox : context -> rollup -> (t * context) tzresult Lwt.t @@ -3656,8 +3627,8 @@ module Sc_rollup : sig val start_game : context -> t -> - player:Signature.public_key_hash -> - opponent:Signature.public_key_hash -> + player:public_key_hash -> + opponent:public_key_hash -> context tzresult Lwt.t val game_move : @@ -3752,7 +3723,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} @@ -3809,8 +3780,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 -> @@ -3819,7 +3789,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 -> @@ -4006,7 +3976,7 @@ type 'kind operation = { and 'kind protocol_data = { contents : 'kind contents_list; - signature : Signature.t option; + signature : signature option; } and _ contents_list = @@ -4019,7 +3989,7 @@ and _ contents = | Preendorsement : consensus_content -> Kind.preendorsement contents | Endorsement : consensus_content -> Kind.endorsement contents | Dal_slot_availability : - Signature.Public_key_hash.t * Dal.Endorsement.t + public_key_hash * Dal.Endorsement.t -> Kind.dal_slot_availability contents | Seed_nonce_revelation : { level : Raw_level.t; @@ -4051,13 +4021,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; @@ -4065,7 +4035,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; @@ -4075,7 +4045,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; @@ -4084,14 +4054,12 @@ and _ manager_operation = } -> Kind.transaction manager_operation | Origination : { - delegate : Signature.Public_key_hash.t option; + delegate : public_key_hash option; script : Script.t; credit : Tez.tez; } -> 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; } @@ -4704,8 +4672,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 ] @@ -4727,7 +4695,7 @@ module Token : sig type sink = [ `Storage_fees | `Double_signing_punishments - | `Lost_endorsing_rewards of Signature.Public_key_hash.t * bool * bool + | `Lost_endorsing_rewards of public_key_hash * bool * bool | `Burned | `Tx_rollup_rejection_punishments | `Sc_rollup_refutation_punishments diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index f82c5a2095f8d5552c686c8566990da7cdda68c2..43cbd7fea9c25744aec038862b42b08d35c61918 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -273,7 +273,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 'loc execution_arg = @@ -522,7 +522,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) -> @@ -1011,7 +1011,7 @@ let apply_manager_operation : 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) @@ -2175,8 +2175,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/bootstrap_storage.ml b/src/proto_alpha/lib_protocol/bootstrap_storage.ml index b9abaec549892bbc65886880f281d64cd5368800..592bdebbec46a3168cd6f2d1e6bf2f66c0ca07e7 100644 --- a/src/proto_alpha/lib_protocol/bootstrap_storage.ml +++ b/src/proto_alpha/lib_protocol/bootstrap_storage.ml @@ -59,7 +59,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)) @@ -84,7 +84,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.ml b/src/proto_alpha/lib_protocol/contract_delegate_storage.ml index 8dbb1063250d137bb618ecbbea219224ce703804..75efd48243daa84662d3c0079af54998d5758763 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 ac62d6ecd423259ca153c08f7596a7c9f697c14f..189a03df8fdf1ea3d5f861ba8b749297952dac6e 100644 --- a/src/proto_alpha/lib_protocol/contract_delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/contract_delegate_storage.mli @@ -34,15 +34,9 @@ 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] - has already a delegate. *) + This function assumes that [contract] does not have a delegate already. *) val init : Raw_context.t -> Contract_repr.t -> @@ -54,20 +48,19 @@ val init : This function does not affect the value of the expression [find ctxt contract]. - This function is undefined if [contract] is not allocated. *) + This function assumes that [contract] is allocated. *) val unlink : Raw_context.t -> Contract_repr.t -> Raw_context.t tzresult Lwt.t (** [delete ctxt contract] behaves as [unlink ctxt contract], but in addition removes the association of the [contract] to its current delegate, leaving the former without delegate. - This function is undefined if [contract] is not allocated. *) + This function assumes that [contract] is 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. *) + This function assumes that [contract] is allocated and has a delegate. *) val set : Raw_context.t -> Contract_repr.t -> diff --git a/src/proto_alpha/lib_protocol/contract_services.ml b/src/proto_alpha/lib_protocol/contract_services.ml index 89ea4ce0f4fe1ab65cb8ecbead5ca83a95ce3028..e7f7bd5766f0cf4184100b19038bb0320ad11e93 100644 --- a/src/proto_alpha/lib_protocol/contract_services.ml +++ b/src/proto_alpha/lib_protocol/contract_services.ml @@ -401,7 +401,7 @@ let 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 @@ -555,7 +555,7 @@ let 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/contract_storage.mli b/src/proto_alpha/lib_protocol/contract_storage.mli index 8b6890c863c6cadc5467ca72fb148f4531b4a5b9..c08e7b45fb5797bfdf19c545da4008764bdec865 100644 --- a/src/proto_alpha/lib_protocol/contract_storage.mli +++ b/src/proto_alpha/lib_protocol/contract_storage.mli @@ -46,7 +46,7 @@ type error += Signature.Public_key_hash.t (** [allocated ctxt contract] returns [true] if and only if the - contract is stored in [Storage.Contract.Balance]. *) + contract is stored in {!Storage.Contract.Spendable_balance}. *) val allocated : Raw_context.t -> Contract_repr.t -> bool Lwt.t (** [exists ctxt contract] returns [true] if and only if either the diff --git a/src/proto_alpha/lib_protocol/delegate_activation_storage.mli b/src/proto_alpha/lib_protocol/delegate_activation_storage.mli index 911bf6c30b08035023d5ee78d24d7de876b0939d..390d37cbef2f0ca55d48ca6f063f1fe5ea3e5c7a 100644 --- a/src/proto_alpha/lib_protocol/delegate_activation_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_activation_storage.mli @@ -40,7 +40,7 @@ val last_cycle_before_deactivation : Raw_context.t -> Signature.Public_key_hash.t -> Cycle_repr.t tzresult Lwt.t (** [set_inactive context delegate] adds [delegate] to the set of inactive - * contracts. *) + contracts. *) val set_inactive : Raw_context.t -> Signature.Public_key_hash.t -> Raw_context.t Lwt.t diff --git a/src/proto_alpha/lib_protocol/delegate_cycles.ml b/src/proto_alpha/lib_protocol/delegate_cycles.ml index 0a2dac5e6c7823e0cda08a4dac964bd385fcd2f0..27c1fa572ed7d4b6b5d99576309a64ad5eaf47e0 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.ml +++ b/src/proto_alpha/lib_protocol/delegate_cycles.ml @@ -41,8 +41,8 @@ let update_activity ctxt last_cycle = delegate >>=? fun cycle -> if Cycle_repr.(cycle <= last_cycle) then - Delegate_storage.set_inactive ctxt delegate >|=? fun ctxt -> - (ctxt, delegate :: deactivated) + Stake_storage.set_inactive ctxt delegate >>= fun ctxt -> + return (ctxt, delegate :: deactivated) else return (ctxt, deactivated)) >|=? fun (ctxt, deactivated) -> (ctxt, deactivated) @@ -247,7 +247,8 @@ let distribute_endorsing_rewards ctxt last_cycle unrevealed_nonces = (ctxt, []) delegates -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 7fb56220567c59efae60e2592c7368f4687808d5..1b7f8a87bad6cc85ca7982ef207c33d5e6fb0ae0 100644 --- a/src/proto_alpha/lib_protocol/delegate_cycles.mli +++ b/src/proto_alpha/lib_protocol/delegate_cycles.mli @@ -34,7 +34,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) 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 2d1ef3030d6bb43880a7a7a89ad25644ac687bcd..48d3be9240d52a292ec1990e807bd0d9a2a1928f 100644 --- a/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_missed_endorsements_storage.ml @@ -50,7 +50,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_services.ml b/src/proto_alpha/lib_protocol/delegate_services.ml index e8426d3dd35b8cab5563732f32e2b693ed5934d8..5efd3ecbe425df52ee6d5afeabc2a87dbe0aa507 100644 --- a/src/proto_alpha/lib_protocol/delegate_services.ml +++ b/src/proto_alpha/lib_protocol/delegate_services.ml @@ -356,7 +356,7 @@ module S = struct end let check_delegate_registered ctxt pkh = - Delegate.registered ctxt pkh >>=? function + Delegate.registered ctxt pkh >>= function | true -> return_unit | false -> fail (Not_registered pkh) diff --git a/src/proto_alpha/lib_protocol/delegate_storage.ml b/src/proto_alpha/lib_protocol/delegate_storage.ml index 3399246a130c97d92ee1f087b9469cd42d3fb269..28e96c3f2ff1a888a84eb251005c4f946425c4fa 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.ml +++ b/src/proto_alpha/lib_protocol/delegate_storage.ml @@ -26,64 +26,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 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 @@ -101,96 +46,166 @@ let () = (function Unregistered_delegate k -> Some k | _ -> None) (fun k -> Unregistered_delegate k) -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 deactivated = Delegate_activation_storage.is_inactive - -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 -> - 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 -> - Contract_delegate_storage.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 -> - Contract_delegate_storage.registered c delegate - >>=? fun registered_delegate -> - let self_delegation = - match contract with - | Implicit pkh -> Signature.Public_key_hash.equal pkh delegate - | Originated _ -> false +let registered = Storage.Delegates.mem + +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 + + 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 + if is_registered then + let* () = + let* is_inactive = Delegate_activation_storage.is_inactive c delegate in + fail_unless is_inactive Active_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 - | Contract_repr.Implicit pkh -> - Contract_delegate_storage.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 () -> + 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 - >>=? fun balance_and_frozen_bonds -> + in + let* c = 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 -> set_active c delegate - else return c + 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 + + 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* () = + 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 -> + let* c = Contract_delegate_storage.delete c contract in + return c + | Some delegate -> + let* () = + let*! is_delegate_registered = registered c delegate in + fail_when + (not is_delegate_registered) + (Unregistered_delegate delegate) + in + 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 let fold = Storage.Delegates.fold @@ -215,7 +230,7 @@ let spendable_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 diff --git a/src/proto_alpha/lib_protocol/delegate_storage.mli b/src/proto_alpha/lib_protocol/delegate_storage.mli index 78eadc0204a93579e178d132c306a57b86c65c64..784d7732f492b8c411fe88145fcf5c2f5a3836cf 100644 --- a/src/proto_alpha/lib_protocol/delegate_storage.mli +++ b/src/proto_alpha/lib_protocol/delegate_storage.mli @@ -26,6 +26,7 @@ (*****************************************************************************) (** This module groups everything related to delegate registration. + For the invariants maintained, see the submodule {!Contract}. It also groups "trivial" getters/setters related to delegates. @@ -35,34 +36,59 @@ *) 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 -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 - -val deactivated : - Raw_context.t -> Signature.Public_key_hash.t -> bool 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 +(** This module ensures the following invariants: + - registered delegates (i.e. those that appear in {!Storage.Delegates}) are + self-delegated, that is a delegate's implicit account delegates to itself + (i.e. {!Contract_delegate_storage.find} [delegate] returns [delegate]), + - registered delegates have their public keys revealed, + - registered delegates cannot change their delegation, + - stake is properly moved when changing delegation. +*) +module Contract : sig + type error += + | (* `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. + + This functions assumes that [contract] is allocated. + + This function returns the {!Unregistered_delegate} 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 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 the {!Unregistered_delegate} error when self-delegating and when the public key is not yet revealed. + It returns the {!Empty_delegate_account} error when self-delegating and the implicit account is not {{!Contract_storage.allocated}allocated}. + It returns the {!Active_delegate} error when self-delegating and the delegate is already active. + It returns the {!Unregistered_delegate} error when trying to set the delegate to an unregistered delegate. + It returns the {!Current_delegate} error when contract is already delegated to the same delegate. + It returns the {!No_deletion} error when trying to unset or change the delegate of a registered delegate. *) + val set : + Raw_context.t -> + Contract_repr.t -> + Signature.Public_key_hash.t option -> + Raw_context.t tzresult Lwt.t +end + +(** Has a delegate been registered in the delegate table? *) +val registered : Raw_context.t -> Signature.Public_key_hash.t -> bool Lwt.t (** Iterate on all registered delegates. *) val fold : diff --git a/src/proto_alpha/lib_protocol/stake_storage.ml b/src/proto_alpha/lib_protocol/stake_storage.ml index 76e3f1bf6ec8ba567143e2290f19bc750e368fa1..08549fa26a2c5bc84bd10820600bcbbe8fc2b714 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 = would also have it 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_delegates_with_minimal_stake.remove ctxt delegate -let activate_only_call_from_delegate_storage ctxt delegate = - get_initialized_stake ctxt delegate >>=? fun (staking_balance, ctxt) -> - let minimal_stake = Constants_storage.minimal_stake ctxt in - if Tez_repr.(staking_balance >= minimal_stake) then - Storage.Stake.Active_delegates_with_minimal_stake.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 minimal_stake = Constants_storage.minimal_stake ctxt in + if Tez_repr.(staking_balance >= minimal_stake) then + Storage.Stake.Active_delegates_with_minimal_stake.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 84e7e67ab64ae08bb6f74dc06e66a0d3ff73d02b..515d001f2f2fe9823f00beb0acf33116923afea2 100644 --- a/src/proto_alpha/lib_protocol/stake_storage.mli +++ b/src/proto_alpha/lib_protocol/stake_storage.mli @@ -46,10 +46,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 : 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 880961fcc6cdfc4ec1a5ab890de1895a855c8428..101f50fb89c2713ceb1f8e25c640c9aa53a52c4e 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." @@ -221,7 +221,8 @@ let bootstrap_manager_already_registered_delegate ~fee () = else Incremental.add_operation ~expect_apply_failure:(function - | Environment.Ecoproto_error Delegate_storage.Active_delegate :: _ -> + | Environment.Ecoproto_error Delegate_storage.Contract.Active_delegate + :: _ -> return_unit | _ -> failwith "Delegate is already active and operation should fail.") i diff --git a/src/proto_alpha/lib_protocol/test/integration/operations/test_voting.ml b/src/proto_alpha/lib_protocol/test/integration/operations/test_voting.ml index 772137cfa47585f4fd9422a4426eb404059a4ff1..1ca7ec09ae115c80a9fc2aecd9c01ec1e1695c90 100644 --- a/src/proto_alpha/lib_protocol/test/integration/operations/test_voting.ml +++ b/src/proto_alpha/lib_protocol/test/integration/operations/test_voting.ml @@ -335,6 +335,16 @@ let wrong_voting_period_kind loc = function | [Environment.Ecoproto_error (Wrong_voting_period_kind _)] -> return_unit | err -> wrong_error "Wrong_voting_period_kind" err loc +let proposals_from_unregistered_delegate loc = function + | [Environment.Ecoproto_error (Proposals_from_unregistered_delegate _)] -> + return_unit + | err -> wrong_error "Proposals_from_unregistered_delegate" err loc + +let ballot_from_unregistered_delegate loc = function + | [Environment.Ecoproto_error (Ballot_from_unregistered_delegate _)] -> + return_unit + | err -> wrong_error "Ballot_from_unregistered_delegate" err loc + let source_not_in_vote_listings loc = function | [Environment.Ecoproto_error Source_not_in_vote_listings] -> return_unit | err -> wrong_error "Source_not_in_vote_listings" err loc @@ -1330,6 +1340,13 @@ let test_proposals_source_not_in_vote_listings () = let* block, funder = context_init1 ~blocks_per_cycle:10l () in let fresh_account = Account.new_account () in let proposer = Contract.Implicit fresh_account.pkh in + let assert_fails_with_unregistered_delegate block = + assert_validate_proposals_fails + ~expected_error:proposals_from_unregistered_delegate + ~proposer + ~proposals:[Protocol_hash.zero] + block + in let assert_fails_with_source_not_in_vote_listings block = assert_validate_proposals_fails ~expected_error:source_not_in_vote_listings @@ -1338,15 +1355,15 @@ let test_proposals_source_not_in_vote_listings () = block in (* Fail when the source has no contract in the storage. *) - let* () = assert_fails_with_source_not_in_vote_listings block __LOC__ in + let* () = assert_fails_with_unregistered_delegate block __LOC__ in let* operation = Op.transaction (B block) funder proposer Tez.one in let* block = Block.bake block ~operation in (* Fail when the contract's public key is unreavealed. *) - let* () = assert_fails_with_source_not_in_vote_listings block __LOC__ in + let* () = assert_fails_with_unregistered_delegate block __LOC__ in let* operation = Op.revelation (B block) fresh_account.pk in let* block = Block.bake block ~operation in (* Fail when the source is not a delegate. *) - let* () = assert_fails_with_source_not_in_vote_listings block __LOC__ in + let* () = assert_fails_with_unregistered_delegate block __LOC__ in let* operation = Op.delegation (B block) proposer (Some fresh_account.pkh) in let* block = Block.bake block ~operation in (* Fail when the source is a delegate, but not yet in the vote listings. *) @@ -1790,16 +1807,24 @@ let test_ballot_source_not_in_vote_listings () = ~ballot:Vote.Yay block in + let assert_fails_with_unregistered_delegate block = + assert_validate_ballot_fails + ~expected_error:ballot_from_unregistered_delegate + ~voter + ~proposal + ~ballot:Vote.Yay + block + in (* Fail when the source has no contract in the storage. *) - let* () = assert_fails_with_source_not_in_vote_listings block __LOC__ in + let* () = assert_fails_with_unregistered_delegate block __LOC__ in let* operation = Op.transaction (B block) funder voter Tez.one in let* block = Block.bake block ~operation in (* Fail when the contract's public key is unreavealed. *) - let* () = assert_fails_with_source_not_in_vote_listings block __LOC__ in + let* () = assert_fails_with_unregistered_delegate block __LOC__ in let* operation = Op.revelation (B block) fresh_account.pk in let* block = Block.bake block ~operation in (* Fail when the source is not a delegate. *) - let* () = assert_fails_with_source_not_in_vote_listings block __LOC__ in + let* () = assert_fails_with_unregistered_delegate block __LOC__ in let* operation = Op.delegation (B block) voter (Some fresh_account.pkh) in let* block = Block.bake block ~operation in (* Fail when the source is a delegate, but not yet in the vote listings. *) 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 3717b5e8317a35d12345e255f27a2ce4e003b520..3704c98b187e5275181a71d62be0eb2f89fb3b03 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. *) @@ -341,7 +341,7 @@ let test_delegated_balance () = (* Check that the delegated balance of [delegate] is null. *) check_delegated_balance_is ctxt ~loc:__LOC__ delegate Tez.zero >>=? fun () -> (* 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. *) @@ -365,7 +365,7 @@ let test_delegated_balance () = check_delegated_balance_is ctxt ~loc:__LOC__ delegate user_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. *) @@ -407,7 +407,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 @@ -422,7 +423,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 @@ -496,7 +497,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 4a05fb1a885e7d9e132c526f87c3b45bc7ec7193..1d3edd5f6c2f7db8e5f0bdc89c0ed23e73c6913a 100644 --- a/src/proto_alpha/lib_protocol/test/integration/test_token.ml +++ b/src/proto_alpha/lib_protocol/test/integration/test_token.ml @@ -516,13 +516,13 @@ let build_test_cases () = (* Configure baker1, and baker2 as delegates by self-delegation, for which revealing their manager key is a prerequisite. *) wrap (Contract.reveal_manager_key ctxt baker1 baker1_pk) >>=? fun ctxt -> - wrap (Delegate.set ctxt (Contract.Implicit baker1) (Some baker1)) + wrap (Contract.Delegate.set ctxt (Contract.Implicit baker1) (Some baker1)) >>=? fun ctxt -> wrap (Contract.reveal_manager_key ctxt baker2 baker2_pk) >>=? fun ctxt -> - wrap (Delegate.set ctxt (Contract.Implicit baker2) (Some baker2)) + wrap (Contract.Delegate.set ctxt (Contract.Implicit baker2) (Some baker2)) (* Let user1 delegate to baker2. *) >>=? fun ctxt -> - wrap (Delegate.set ctxt (Contract.Implicit user1) (Some baker2)) + wrap (Contract.Delegate.set ctxt (Contract.Implicit user1) (Some baker2)) >>=? fun ctxt -> let tx_rollup1 = mk_rollup () in let bond_id1 = Bond_id.Tx_rollup_bond_id tx_rollup1 in diff --git a/src/proto_alpha/lib_protocol/validate_errors.ml b/src/proto_alpha/lib_protocol/validate_errors.ml index 00f517d5a3c5ae9abc07c39d52105ec3d1d2107e..eb7e00753be8eb4f407a8b23eed5b55dea0e4293 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.ml +++ b/src/proto_alpha/lib_protocol/validate_errors.ml @@ -411,6 +411,7 @@ module Voting = struct | Conflicting_dictator_proposals of Operation_hash.t | Testnet_dictator_multiple_proposals | Testnet_dictator_conflicting_operation + | Proposals_from_unregistered_delegate of Signature.Public_key_hash.t | (* Ballot errors *) Ballot_for_wrong_proposal of { current : Protocol_hash.t; @@ -418,6 +419,7 @@ module Voting = struct } | Already_submitted_a_ballot | Conflicting_ballot of {conflicting_operation : Operation_hash.t} + | Ballot_from_unregistered_delegate of Signature.Public_key_hash.t let () = (* Shared voting errors *) @@ -666,6 +668,21 @@ module Voting = struct Data_encoding.empty (function Testnet_dictator_conflicting_operation -> Some () | _ -> None) (fun () -> Testnet_dictator_conflicting_operation) ; + register_error_kind + `Permanent + ~id:"operation.proposals_from_unregistered_delegate" + ~title:"Proposals from an unregistered delegate" + ~description:"Cannot submit proposals with an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot submit proposals with public key hash %a (unregistered \ + delegate)." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Proposals_from_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Proposals_from_unregistered_delegate c) ; (* Ballot errors *) register_error_kind @@ -723,7 +740,21 @@ module Voting = struct | Conflicting_ballot {conflicting_operation} -> Some conflicting_operation | _ -> None) - (fun conflicting_operation -> Conflicting_ballot {conflicting_operation}) + (fun conflicting_operation -> Conflicting_ballot {conflicting_operation}) ; + register_error_kind + `Permanent + ~id:"operation.ballot_from_unregistered_delegate" + ~title:"Ballot from an unregistered delegate" + ~description:"Cannot cast a ballot for an unregistered delegate." + ~pp:(fun ppf c -> + Format.fprintf + ppf + "Cannot cast a ballot for public key hash %a (unregistered delegate)." + Signature.Public_key_hash.pp + c) + Data_encoding.(obj1 (req "delegate" Signature.Public_key_hash.encoding)) + (function Ballot_from_unregistered_delegate c -> Some c | _ -> None) + (fun c -> Ballot_from_unregistered_delegate c) end module Anonymous = struct diff --git a/src/proto_alpha/lib_protocol/validate_errors.mli b/src/proto_alpha/lib_protocol/validate_errors.mli index 2d52451bdf471e8844f07edc872df98bd4da9f4a..d83d9fdb111f44937cb792019a30d590cea58ed7 100644 --- a/src/proto_alpha/lib_protocol/validate_errors.mli +++ b/src/proto_alpha/lib_protocol/validate_errors.mli @@ -113,6 +113,7 @@ module Voting : sig | Conflicting_dictator_proposals of Operation_hash.t | Testnet_dictator_multiple_proposals | Testnet_dictator_conflicting_operation + | Proposals_from_unregistered_delegate of Signature.Public_key_hash.t | (* Ballot errors *) Ballot_for_wrong_proposal of { current : Protocol_hash.t; @@ -120,6 +121,7 @@ module Voting : sig } | Already_submitted_a_ballot | Conflicting_ballot of {conflicting_operation : Operation_hash.t} + | Ballot_from_unregistered_delegate of Signature.Public_key_hash.t end (** Errors that may arise while validating an anonymous operation. *) diff --git a/src/proto_alpha/lib_protocol/validate_operation.ml b/src/proto_alpha/lib_protocol/validate_operation.ml index 94d3b45d03da8a23e19250be0aed1d6a6b7a30a6..6c9a67ade92a297528a7f97e548a0046fd08d6f6 100644 --- a/src/proto_alpha/lib_protocol/validate_operation.ml +++ b/src/proto_alpha/lib_protocol/validate_operation.ml @@ -964,6 +964,11 @@ module Voting = struct Compare.Int32.(expected = period_index) (Wrong_voting_period_index {expected; provided = period_index}) + let check_proposals_source_is_registered ctxt source = + let open Lwt_tzresult_syntax in + let*! is_registered = Delegate.registered ctxt source in + fail_unless is_registered (Proposals_from_unregistered_delegate source) + (** Check that the list of proposals is not empty and does not contain duplicates. *) let check_proposal_list_sanity proposals = @@ -1034,12 +1039,20 @@ module Voting = struct let*! has_ballot = Vote.has_recorded_ballot ctxt source in fail_when has_ballot Already_submitted_a_ballot + let check_ballot_source_is_registered ctxt source = + let open Lwt_tzresult_syntax in + let*! is_registered = Delegate.registered ctxt source in + fail_unless is_registered (Ballot_from_unregistered_delegate source) + (** Check that a Proposals operation can be safely applied. @return [Error Wrong_voting_period_index] if the operation's period and the [context]'s current period do not have the same index. + @return [Error Proposals_from_unregistered_delegate] if the + source is not a registered delegate. + @return [Error Empty_proposals] if the list of proposals is empty. @return [Error Proposals_contain_duplicate] if the list of @@ -1099,6 +1112,7 @@ module Voting = struct vs.voting_state oph) else + let* () = check_proposals_source_is_registered vi.ctxt source in let*? () = check_proposal_list_sanity proposals in let*? () = check_period_kind_for_proposals current_period in let* () = check_in_listings vi.ctxt source in @@ -1131,6 +1145,9 @@ module Voting = struct (** Check that a Ballot operation can be safely applied. + @return [Error Ballot_from_unregistered_delegate] if the + source is not a registered delegate. + @return [Error Conflicting_ballot] if the source has already submitted a ballot in the current block/mempool. @@ -1163,6 +1180,7 @@ module Voting = struct let (Single (Ballot {source; period; proposal; ballot = _})) = operation.protocol_data.contents in + let* () = check_ballot_source_is_registered vi.ctxt source in let*? () = check_ballot_conflicts vs.voting_state source in let* current_period = Voting_period.get_current vi.ctxt in let*? () = check_period_index ~expected:current_period.index period in