123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2022 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. *)(* *)(*****************************************************************************)(* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3103
This may be a bit heavy in practice. We could also assume that in
practice, many bits in this bitfield will be set to one. Hence, we
could consider a better encoding which is smaller in the optimistic
case. For example:
1. When all the slots are attested, the encoding can be represented
in one bit.
2. Otherwise, we can pack slots by [8]. Have a header of [slots/8]
which is [1] if all the slots in this set are [1], [0]
otherwise. For all pack with a bit set to [0], we give the explicit
representation. Hence, if there are [256] slots, and [2] are not
attested, this representation will be of size [32] bits + [16] bits
= [48] bits which is better than [256] bits. *)(* A set of (attested) slot indexes. *)typet=Bitset.tletencoding=Bitset.encodingletempty=Bitset.emptyletis_attestedtindex=letopenDal_slot_index_reprinmatchBitset.memt(to_intindex)with|Okb->b|Error_->(* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3104
Should we do something here? *)falseletcommittindex=letopenDal_slot_index_reprinmatchBitset.addt(to_intindex)with|Okt->t|Error_->(* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3104
Should we do something here? *)tletoccupied_size_in_bits=Bitset.occupied_size_in_bitsletexpected_size_in_bits~max_index=(* We compute an encoding of the data-availability attestations
which is a (tight) upper bound of what we expect. *)letopenBitsetinletopenDal_slot_index_reprinmatchaddempty@@to_intmax_indexwith|Error_->(* Happens if max_index < 1 *)0|Okt->occupied_size_in_bitstletnumber_of_attested_slots=Bitset.hamming_weighttypeshard_index=intmoduleShard_map=Map.Make(structtypet=shard_indexletcompare=Compare.Int.compareend)moduleAccountability=structtypeattested_slots=tmoduleSlotMap=Map.Make(Compare.Int)typet={number_of_attested_shards:intSlotMap.t;number_of_slots:int}letinit~number_of_slots={number_of_attested_shards=SlotMap.empty;number_of_slots}(* This function must be called at most once for a given attester; otherwise
the count will be flawed. *)letrecord_number_of_attested_shardstbaker_attested_slotsnumber_of_baker_shards=letreciterslot_indexmap=ifCompare.Int.(slot_index>=t.number_of_slots)thenmapelseletmap=matchBitset.membaker_attested_slotsslot_indexwith|Error_->(* impossible, as [slot_index] is non-negative *)map|Oktrue->(* slot is attested by baker *)SlotMap.updateslot_index(function|None->Somenumber_of_baker_shards|Someold_number_of_attested_shards->Some(old_number_of_attested_shards+number_of_baker_shards))map|Okfalse->(* slot is not attested by baker, nothing to update *)mapiniter(slot_index+1)mapinletnumber_of_attested_shards=iter0t.number_of_attested_shardsin{twithnumber_of_attested_shards}letis_slot_attestedt~threshold~number_of_shardsslot_index=letindex=Dal_slot_index_repr.to_intslot_indexinletnumber_of_attested_shards=matchSlotMap.findindext.number_of_attested_shardswith|None->0|Somev->vinCompare.Int.(number_of_attested_shards>=threshold*number_of_shards/100)end