123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2020-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. *)(* *)(*****************************************************************************)openStore_errorstypecontents={header:Block_header.t;operations:Operation.tlistlist;block_metadata_hash:Block_metadata_hash.toption;operations_metadata_hashes:Operation_metadata_hash.tlistlistoption;}typemetadata={message:stringoption;max_operations_ttl:int;last_allowed_fork_level:Int32.t;block_metadata:Bytes.t;operations_metadata:Block_validation.operation_metadatalistlist;}typelegacy_metadata={legacy_message:stringoption;legacy_max_operations_ttl:int;legacy_last_allowed_fork_level:Int32.t;legacy_block_metadata:Bytes.t;legacy_operations_metadata:Bytes.tlistlist;}typelegacy_block={legacy_hash:Block_hash.t;legacy_contents:contents;mutablelegacy_metadata:legacy_metadataoption;(* allows updating metadata field when loading cemented metadata *)}typeblock={hash:Block_hash.t;contents:contents;mutablemetadata:metadataoption;(* allows updating metadata field when loading cemented metadata *)}typet=blockletcreate_genesis_block~genesiscontext=letshell:Block_header.shell_header={level=0l;proto_level=0;predecessor=genesis.Genesis.block;(* genesis' predecessor is genesis *)timestamp=genesis.Genesis.time;fitness=[];validation_passes=0;operations_hash=Operation_list_list_hash.empty;context;}inletheader:Block_header.t={shell;protocol_data=Bytes.create0}inletcontents={header;operations=[];block_metadata_hash=None;operations_metadata_hashes=None;}inletmetadata=Some{message=Some"Genesis";max_operations_ttl=0;last_allowed_fork_level=0l;block_metadata=Bytes.create0;operations_metadata=[];}in{hash=genesis.block;contents;metadata}letcontents_encoding=letopenData_encodingindef"store.block_repr.contents"@@conv(fun{header;operations;block_metadata_hash;operations_metadata_hashes;}->(header,operations,block_metadata_hash,operations_metadata_hashes))(fun(header,operations,block_metadata_hash,operations_metadata_hashes)->{header;operations;block_metadata_hash;operations_metadata_hashes})(obj4(req"header"(dynamic_sizeBlock_header.encoding))(req"operations"(list(list(dynamic_sizeOperation.encoding))))(opt"block_metadata_hash"Block_metadata_hash.encoding)(opt"operations_metadata_hashes"(list(listOperation_metadata_hash.encoding))))letmetadata_encoding:metadataData_encoding.t=letopenData_encodingindef"store.block_repr.metadata"@@conv(fun{message;max_operations_ttl;last_allowed_fork_level;block_metadata;operations_metadata;}->(message,max_operations_ttl,last_allowed_fork_level,block_metadata,operations_metadata))(fun(message,max_operations_ttl,last_allowed_fork_level,block_metadata,operations_metadata)->{message;max_operations_ttl;last_allowed_fork_level;block_metadata;operations_metadata;})(obj5(opt"message"string)(req"max_operations_ttl"uint16)(req"last_allowed_fork_level"int32)(req"block_metadata"bytes)(req"operations_metadata"(list(listBlock_validation.operation_metadata_encoding))))letlegacy_metadata_encoding:legacy_metadataData_encoding.t=letopenData_encodingindef"store.block_repr.legacy_metadata"@@conv(fun{legacy_message;legacy_max_operations_ttl;legacy_last_allowed_fork_level;legacy_block_metadata;legacy_operations_metadata;}->(legacy_message,legacy_max_operations_ttl,legacy_last_allowed_fork_level,legacy_block_metadata,legacy_operations_metadata))(fun(legacy_message,legacy_max_operations_ttl,legacy_last_allowed_fork_level,legacy_block_metadata,legacy_operations_metadata)->{legacy_message;legacy_max_operations_ttl;legacy_last_allowed_fork_level;legacy_block_metadata;legacy_operations_metadata;})(obj5(opt"legacy_message"string)(req"legacy_max_operations_ttl"uint16)(req"legacy_last_allowed_fork_level"int32)(req"legacy_block_metadata"bytes)(req"legacy_operations_metadata"(list(listbytes))))letencoding=letopenData_encodingindef"store.block_repr"@@conv(fun{hash;contents;metadata}->(hash,contents,metadata))(fun(hash,contents,metadata)->{hash;contents;metadata})(dynamic_size~kind:`Uint30(obj3(req"hash"Block_hash.encoding)(req"contents"contents_encoding)(varopt"metadata"metadata_encoding)))letlegacy_encoding=letopenData_encodingindef"store.legacy_block_repr"@@conv(fun{legacy_hash;legacy_contents;legacy_metadata}->(legacy_hash,legacy_contents,legacy_metadata))(fun(legacy_hash,legacy_contents,legacy_metadata)->{legacy_hash;legacy_contents;legacy_metadata})(dynamic_size~kind:`Uint30(obj3(req"legacy_hash"Block_hash.encoding)(req"legacy_contents"contents_encoding)(varopt"legacy_metadata"legacy_metadata_encoding)))letwith_contents{header;operations;block_metadata_hash;operations_metadata_hashes}f=fheaderoperationsblock_metadata_hashoperations_metadata_hashes[@@ocaml.inline]letwith_metadata{message;max_operations_ttl;last_allowed_fork_level;block_metadata;operations_metadata;}f=fmessagemax_operations_ttllast_allowed_fork_levelblock_metadataoperations_metadata[@@ocaml.inline]letcontents_equalc1c2=with_contentsc1@@funh1o1b1omh1->with_contentsc2@@funh2o2b2omh2->Block_header.equalh1h2&&List.equal(List.equalOperation.equal)o1o2&&Option.equalBlock_metadata_hash.equalb1b2&&Option.equal(List.equal(List.equalOperation_metadata_hash.equal))omh1omh2letmetadata_equalm1m2=with_metadatam1@@funm1mot1lafl1bm1om1->with_metadatam2@@funm2mot2lafl2bm2om2->Option.equalString.equalm1m2&&Int.equalmot1mot2&&Int32.equallafl1lafl2&&Bytes.equalbm1bm2&&List.equal(List.equalBlock_validation.operation_metadata_equal)om1om2letequalb1b2=let{hash=h1;contents=c1;metadata=m1}=b1inlet{hash=h2;contents=c2;metadata=m2}=b2inBlock_hash.equalh1h2&&contents_equalc1c2&&Option.equalmetadata_equalm1m2letpp_jsonfmtb=letjson=Data_encoding.Json.constructencodingbinData_encoding.Json.ppfmtjson(* Contents accessors *)letdescriptorblk=(blk.hash,blk.contents.header.Block_header.shell.level)lethashblk=blk.hashletheaderblk=blk.contents.headerletoperationsblk=blk.contents.operationsletblock_metadata_hashblk=blk.contents.block_metadata_hashletoperations_metadata_hashesblk=blk.contents.operations_metadata_hashesletshell_headerblk=blk.contents.header.Block_header.shellletlevelblk=blk.contents.header.Block_header.shell.levelletproto_levelblk=blk.contents.header.Block_header.shell.proto_levelletpredecessorblk=blk.contents.header.Block_header.shell.predecessorlettimestampblk=blk.contents.header.Block_header.shell.timestampletvalidation_passesblk=blk.contents.header.Block_header.shell.validation_passesletoperations_hashblk=blk.contents.header.Block_header.shell.operations_hashletfitnessblk=blk.contents.header.Block_header.shell.fitnessletcontextblk=blk.contents.header.Block_header.shell.contextletprotocol_datablk=blk.contents.header.Block_header.protocol_data(* Metadata accessors *)letmetadatablk=blk.metadataletmessagemetadata=metadata.messageletmax_operations_ttlmetadata=metadata.max_operations_ttlletlast_allowed_fork_levelmetadata=metadata.last_allowed_fork_levelletblock_metadatametadata=metadata.block_metadataletoperations_metadatametadata=metadata.operations_metadataletcheck_block_consistency?genesis_hash?pred_blockblock=letopenLwt_result_syntaxinletblock_header=headerblockinletblock_hash=hashblockinletresult_hash=Block_header.hashblock_headerinlet*()=fail_unless(Block_hash.equalblock_hashresult_hash||matchgenesis_hashwith|Somegenesis_hash->Block_hash.equalblock_hashgenesis_hash|None->false)(Inconsistent_block_hash{level=levelblock;expected_hash=block_hash;computed_hash=result_hash;})inlet*()=matchpred_blockwith|None->return_unit|Somepred_block->fail_unless(Block_hash.equal(hashpred_block)(predecessorblock)&&Compare.Int32.(levelblock=Int32.succ(levelpred_block)))(Inconsistent_block_predecessor{block_hash;level=levelblock;expected_hash=hashpred_block;computed_hash=predecessorblock;})inletcomputed_operations_hash=Operation_list_list_hash.compute(List.mapOperation_list_hash.compute(List.map(List.mapOperation.hash)(operationsblock)))inlet*()=fail_unless(Operation_list_list_hash.equalcomputed_operations_hash(operations_hashblock))(Store_errors.Inconsistent_operations_hash{expected=operations_hashblock;got=computed_operations_hash})inreturn_unitletconvert_legacy_metadata(legacy_metadata:legacy_metadata):metadata=let{legacy_message;legacy_max_operations_ttl;legacy_last_allowed_fork_level;legacy_block_metadata;legacy_operations_metadata;}=legacy_metadatain{message=legacy_message;max_operations_ttl=legacy_max_operations_ttl;last_allowed_fork_level=legacy_last_allowed_fork_level;block_metadata=legacy_block_metadata;operations_metadata=List.map(List.map(funb->Block_validation.Metadatab))legacy_operations_metadata;}letdecode_metadatab=Data_encoding.Binary.of_string_optmetadata_encodingb|>function|Somemetadata->Somemetadata|None->Option.mapconvert_legacy_metadata(Data_encoding.Binary.of_string_optlegacy_metadata_encodingb)