123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* Copyright (c) 2021 Nomadic Labs <contact@nomadic-labs.com> *)(* *)(* 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. *)(* *)(*****************************************************************************)openAlpha_contexttypeerror+=|(* `Permanent *)Insufficient_endorsing_powerof{endorsing_power:int;consensus_threshold:int;}let()=register_error_kind`Permanent~id:"baking.insufficient_endorsing_power"~title:"Insufficient endorsing power"~description:"The endorsing power is insufficient to satisfy the consensus threshold."~pp:(funppf(endorsing_power,consensus_threshold)->Format.fprintfppf"The endorsing power (%d) is insufficient to satisfy the consensus \
threshold (%d)."endorsing_powerconsensus_threshold)Data_encoding.(obj2(req"endorsing_power"int31)(req"consensus_threshold"int31))(function|Insufficient_endorsing_power{endorsing_power;consensus_threshold}->Some(endorsing_power,consensus_threshold)|_->None)(fun(endorsing_power,consensus_threshold)->Insufficient_endorsing_power{endorsing_power;consensus_threshold})letbonus_baking_rewardctxt~endorsing_power=letconsensus_threshold=Constants.consensus_thresholdctxtinletbaking_reward_bonus_per_slot=Constants.baking_reward_bonus_per_slotctxtinletextra_endorsing_power=endorsing_power-consensus_thresholdinerror_whenCompare.Int.(extra_endorsing_power<0)(Insufficient_endorsing_power{endorsing_power;consensus_threshold})>>?fun()->Tez.(baking_reward_bonus_per_slot*?Int64.of_intextra_endorsing_power)typeordered_slots={delegate:Signature.public_key_hash;consensus_key:Signature.public_key_hash;slots:Slot.tlist;}(* Slots returned by this function are assumed by consumers to be in increasing
order, hence the use of [Slot.Range.rev_fold_es]. *)letendorsing_rights(ctxt:t)level=letconsensus_committee_size=Constants.consensus_committee_sizectxtinSlot.Range.create~min:0~count:consensus_committee_size>>?=funslots->Slot.Range.rev_fold_es(fun(ctxt,map)slot->Stake_distribution.slot_ownerctxtlevelslot>>=?fun(ctxt,consensus_pk)->letmap=Signature.Public_key_hash.Map.updateconsensus_pk.delegate(function|None->Some{delegate=consensus_pk.delegate;consensus_key=consensus_pk.consensus_pkh;slots=[slot];}|Someslots->Some{slotswithslots=slot::slots.slots})mapinreturn(ctxt,map))(ctxt,Signature.Public_key_hash.Map.empty)slotsletendorsing_rights_by_first_slotctxtlevel=Slot.Range.create~min:0~count:(Constants.consensus_committee_sizectxt)>>?=funslots->Slot.Range.fold_es(fun(ctxt,(delegates_map,slots_map))slot->Stake_distribution.slot_ownerctxtlevelslot>|=?fun(ctxt,consensus_pk)->letinitial_slot,delegates_map=matchSignature.Public_key_hash.Map.findconsensus_pk.delegatedelegates_mapwith|None->(slot,Signature.Public_key_hash.Map.addconsensus_pk.delegateslotdelegates_map)|Someinitial_slot->(initial_slot,delegates_map)in(* [slots_map]'keys are the minimal slots of delegates because
we fold on slots in increasing order *)letslots_map=Slot.Map.updateinitial_slot(function|None->Some(consensus_pk,1)|Some(consensus_pk,count)->Some(consensus_pk,count+1))slots_mapin(ctxt,(delegates_map,slots_map)))(ctxt,(Signature.Public_key_hash.Map.empty,Slot.Map.empty))slots>>=?fun(ctxt,(_,slots_map))->return(ctxt,slots_map)