123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)(* *)(*****************************************************************************)openProtocol_client_contextopenProtocol.Alpha_contexttypehighwatermark={round:Round.t;level:int32}lethighwatermark_encoding:highwatermarkData_encoding.t=letopenData_encodinginconv(fun{round;level}->(round,level))(fun(round,level)->{round;level})(obj2(req"round"Protocol.Alpha_context.Round.encoding)(req"level"int32))letpp_highwatermarkfmt{round;level}=Format.fprintffmt"level: %ld, round: %a"levelRound.pproundtypeerror+=Block_previously_bakedofhighwatermarktypeerror+=Block_previously_preattestedofhighwatermarktypeerror+=Block_previously_attestedofhighwatermarklet()=register_error_kind`Permanent~id:"highwatermarks.block_previously_baked"~title:"Block previously baked"~description:"Trying to bake a block at a level previously baked"~pp:(funppfhighwatermark->Format.fprintfppf"A block with a higher watermark than the current one (%a) was \
previously baked."pp_highwatermarkhighwatermark)highwatermark_encoding(function|Block_previously_bakedhighwatermark->Somehighwatermark|_->None)(funhighwatermark->Block_previously_bakedhighwatermark);register_error_kind`Permanent~id:"highwatermarks.block_previously_preattested"~title:"Block previously preattested"~description:"Trying to preattest a block at a level previously preattested"~pp:(funppfhighwatermark->Format.fprintfppf"A preattestaion with a higher watermark than the current one (%a) was \
already produced."pp_highwatermarkhighwatermark)highwatermark_encoding(function|Block_previously_preattestedhighwatermark->Somehighwatermark|_->None)(funhighwatermark->Block_previously_preattestedhighwatermark);register_error_kind`Permanent~id:"highwatermarks.block_previously_attested"~title:"Block previously attested"~description:"Trying to attest a block at a level previously attested"~pp:(funppfhighwatermark->Format.fprintfppf"An attestation with a higher watermark than the current one (%a) was \
already produced."pp_highwatermarkhighwatermark)highwatermark_encoding(function|Block_previously_attestedhighwatermark->Somehighwatermark|_->None)(funhighwatermark->Block_previously_attestedhighwatermark)moduleDelegateMap=Map.Make(structtypet=Signature.Public_key_hash.tletcompare=Signature.Public_key_hash.compareend)lethighwatermark_delegate_map_encoding=letopenData_encodinginconvDelegateMap.bindingsDelegateMap.(funl->List.fold_left(funmap(k,v)->addkvmap)emptyl)(list(obj2(req"delegate"Signature.Public_key_hash.encoding)(req"highwatermark"highwatermark_encoding)))typehighwatermarks={blocks:highwatermarkDelegateMap.t;preattestations:highwatermarkDelegateMap.t;attestations:highwatermarkDelegateMap.t;}typet=highwatermarksletencoding~use_legacy_attestation_name=letopenData_encodinginconv(fun{blocks;preattestations;attestations}->(blocks,preattestations,attestations))(fun(blocks,preattestations,attestations)->{blocks;preattestations;attestations})(obj3(req"blocks"highwatermark_delegate_map_encoding)(req(ifuse_legacy_attestation_namethen"preendorsements"else"preattestations")highwatermark_delegate_map_encoding)(req(ifuse_legacy_attestation_namethen"endorsements"else"attestations")highwatermark_delegate_map_encoding))letload_encoding=letopenData_encodinginunion[case~title:"new"(Tag0)(encoding~use_legacy_attestation_name:false)Option.someFun.id;case~title:"old"(Tag1)(encoding~use_legacy_attestation_name:true)Option.someFun.id;]letempty={blocks=DelegateMap.empty;preattestations=DelegateMap.empty;attestations=DelegateMap.empty;}(* We do not lock these functions. The caller will be already locked. *)letload(cctxt:#Protocol_client_context.full)location:ttzresultLwt.t=protect(fun()->cctxt#load(Baking_files.filenamelocation)load_encoding~default:empty)letsave_highwatermarks(cctxt:#Protocol_client_context.full)filenamehighwatermarks:unittzresultLwt.t=protect(fun()->(* TODO: improve the backend so we don't write partial informations *)cctxt#writefilenamehighwatermarks(encoding~use_legacy_attestation_name:false))letmay_signhighwatermarks~delegate~level~round=matchDelegateMap.finddelegatehighwatermarkswith|None->true|Somehighwatermark->ifCompare.Int32.(highwatermark.level<level)thentrueelseifCompare.Int32.(highwatermark.level=level)thenRound.(highwatermark.round<round)elsefalseletmay_sign_blockcctxt(location:[`Highwatermarks]Baking_files.location)~delegate~level~round=letopenLwt_result_syntaxinlet*all_highwatermarks=loadcctxtlocationinreturn@@may_signall_highwatermarks.blocks~delegate~level~roundletmay_sign_preattestationcctxtlocation~delegate~level~round=letopenLwt_result_syntaxinlet*all_highwatermarks=loadcctxtlocationinreturn@@may_signall_highwatermarks.preattestations~delegate~level~roundletmay_sign_attestationcctxtlocation~delegate~level~round=letopenLwt_result_syntaxinlet*all_highwatermarks=loadcctxtlocationinreturn@@may_signall_highwatermarks.attestations~delegate~level~roundletrecordmap~delegate~new_level~new_round=DelegateMap.updatedelegate(function|None->Some{level=new_level;round=new_round}|Some({level;round}asprev)->ifCompare.Int32.(new_level>level)thenSome{level=new_level;round=new_round}elseifCompare.Int32.(new_level=level)thenifRound.(new_round>round)thenSome{level=new_level;round=new_round}elseSomeprevelseSomeprev)mapletrecord_block(cctxt:#Protocol_client_context.full)location~delegate~level~round=letopenLwt_result_syntaxinletfilename=Baking_files.filenamelocationinlet*highwatermarks=loadcctxtlocationinletnew_blocks=recordhighwatermarks.blocks~delegate~new_level:level~new_round:roundinsave_highwatermarkscctxtfilename{highwatermarkswithblocks=new_blocks}letrecord_preattestation(cctxt:#Protocol_client_context.full)location~delegate~level~round=letopenLwt_result_syntaxinletfilename=Baking_files.filenamelocationinlet*highwatermarks=loadcctxtlocationinletnew_preattestations=recordhighwatermarks.preattestations~delegate~new_level:level~new_round:roundinsave_highwatermarkscctxtfilename{highwatermarkswithpreattestations=new_preattestations}letrecord_attestation(cctxt:#Protocol_client_context.full)location~delegate~level~round=letopenLwt_result_syntaxinletfilename=Baking_files.filenamelocationinlet*highwatermarks=loadcctxtlocationinletnew_attestations=recordhighwatermarks.attestations~delegate~new_level:level~new_round:roundinsave_highwatermarkscctxtfilename{highwatermarkswithattestations=new_attestations}