123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790(*****************************************************************************)(* *)(* 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. *)(* *)(*****************************************************************************)includeEnvironment_context_intfopenError_monadleterr_implementation_mismatch~expected~got=Format.kasprintfinvalid_arg"Context implementation mismatch: expecting %s, got %s"expectedgotmoduleEquality_witness:sigtype(_,_)eq=Refl:('a,'a)eqtype'atvalmake:unit->'atvaleq:'at->'bt->('a,'b)eqoptionvalhash:'at->intend=structtype(_,_)eq=Refl:('a,'a)eqtype_equality=..moduletypeInst=sigtypettype_equality+=Eq:tequalityendtype'at=(moduleInstwithtypet='a)letmake:typea.unit->at=fun()->letmoduleInst=structtypet=atype_equality+=Eq:tequalityendin(moduleInst)leteq:typeab.at->bt->(a,b)eqoption=fun(moduleA)(moduleB)->matchA.EqwithB.Eq->SomeRefl|_->Nonelethash:typea.at->int=fun(moduleA)->Hashtbl.hashA.EqendmoduleContext=structtypekey=stringlisttypevalue=Bytes.ttype('ctxt,'tree)ops=(moduleSwithtypet='ctxtandtypetree='tree)type_kind=..type('a,'b)equality_witness='aEquality_witness.t*'bEquality_witness.tletequality_witness()=(Equality_witness.make(),Equality_witness.make())letequiv(a,b)(c,d)=(Equality_witness.eqac,Equality_witness.eqbd)typecache_value=..typedelayed_value=unit->cache_valueLwt.tletdelaye()=Lwt.returnetypecache=delayed_valueEnvironment_cache.ttypet=|Context:{kind:'akind;impl_name:string;ctxt:'a;ops:('a,'b)ops;equality_witness:('a,'b)equality_witness;cache:cache;}->tletmake~kind~impl_name~ctxt~ops~equality_witness=Context{kind;impl_name;ctxt;ops;equality_witness;cache=Environment_cache.uninitialised;}letmem(Context{ops=(moduleOps);ctxt;_})key=Ops.memctxtkeyletadd(Context({ops=(moduleOps);ctxt;_}asc))keyvalue=letopenLwt_syntaxinlet+ctxt=Ops.addctxtkeyvalueinContext{cwithctxt}letfind(Context{ops=(moduleOps);ctxt;_})key=Ops.findctxtkeyletremove(Context({ops=(moduleOps);ctxt;_}asc))key=letopenLwt_syntaxinlet+ctxt=Ops.removectxtkeyinContext{cwithctxt}(* trees *)typetree=|Tree:{ops:('a,'b)ops;impl_name:string;tree:'b;equality_witness:('a,'b)equality_witness;}->treeletmem_tree(Context{ops=(moduleOps);ctxt;_})key=Ops.mem_treectxtkeyletadd_tree(Context({ops=(moduleOps);ctxt;_}asc))key(Treet)=letopenLwt_syntaxinmatchequivc.equality_witnesst.equality_witnesswith|SomeRefl,SomeRefl->let+ctxt=Ops.add_treectxtkeyt.treeinContext{cwithctxt}|_->err_implementation_mismatch~expected:c.impl_name~got:t.impl_nameletfind_tree(Context{ops=(moduleOps)asops;ctxt;equality_witness;impl_name;_})key=letopenLwt_syntaxinlet+t=Ops.find_treectxtkeyinOption.map(funtree->Tree{ops;tree;equality_witness;impl_name})tletlist(Context{ops=(moduleOps)asops;ctxt;equality_witness;impl_name;_})?offset?lengthkey=letopenLwt_syntaxinlet+ls=Ops.listctxt?offset?lengthkeyinList.fold_left(funacc(k,tree)->letv=Tree{ops;tree;equality_witness;impl_name}in(k,v)::acc)[](List.revls)letlength(Context{ops=(moduleOps);ctxt;_})key=Ops.lengthctxtkeyletfold?depth(Context{ops=(moduleOps)asops;ctxt;equality_witness;impl_name;_})key~order~init~f=Ops.fold?depthctxtkey~order~init~f:(funkvacc->letv=Tree{ops;tree=v;equality_witness;impl_name}infkvacc)(* Tree *)moduleTree=structletppppf(Tree{ops=(moduleOps);tree;_})=Ops.Tree.ppppftreelethash(Tree{ops=(moduleOps);tree;_})=Ops.Tree.hashtreeletkind(Tree{ops=(moduleOps);tree;_})=Ops.Tree.kindtreeletto_value(Tree{ops=(moduleOps);tree;_})=Ops.Tree.to_valuetreeletof_value(Context{ops=(moduleOps)asops;ctxt;equality_witness;impl_name;_})v=letopenLwt_syntaxinlet+tree=Ops.Tree.of_valuectxtvinTree{ops;tree;equality_witness;impl_name}letequal(Tree{ops=(moduleOps);tree;equality_witness;_})(Treet)=matchequivequality_witnesst.equality_witnesswith|SomeRefl,SomeRefl->Ops.Tree.equaltreet.tree|_->falseletempty(Context{ops=(moduleOps)asops;equality_witness;ctxt;impl_name;_})=letempty=Ops.Tree.emptyctxtinTree{ops;equality_witness;tree=empty;impl_name}letis_empty(Tree{ops=(moduleOps);tree;_})=Ops.Tree.is_emptytreeletmem(Tree{ops=(moduleOps);tree;_})key=Ops.Tree.memtreekeyletadd(Tree({ops=(moduleOps);tree;_}asc))keyvalue=letopenLwt_syntaxinlet+tree=Ops.Tree.addtreekeyvalueinTree{cwithtree}letfind(Tree{ops=(moduleOps);tree;_})key=Ops.Tree.findtreekeyletmem_tree(Tree{ops=(moduleOps);tree;_})key=Ops.Tree.mem_treetreekeyletadd_tree(Tree({ops=(moduleOps);_}asc))key(Treet)=letopenLwt_syntaxinmatchequivc.equality_witnesst.equality_witnesswith|SomeRefl,SomeRefl->let+tree=Ops.Tree.add_treec.treekeyt.treeinTree{cwithtree}|_->err_implementation_mismatch~expected:c.impl_name~got:t.impl_nameletfind_tree(Tree({ops=(moduleOps);tree;_}asc))key=letopenLwt_syntaxinlet+t=Ops.Tree.find_treetreekeyinOption.map(funtree->Tree{cwithtree})tletremove(Tree({ops=(moduleOps);tree;_}asc))key=letopenLwt_syntaxinlet+tree=Ops.Tree.removetreekeyinTree{cwithtree}letlist(Tree{ops=(moduleOps)asops;tree;equality_witness;impl_name})?offset?lengthkey=letopenLwt_syntaxinlet+ls=Ops.Tree.listtree?offset?lengthkeyinList.fold_left(funacc(k,tree)->letv=Tree{ops;tree;equality_witness;impl_name}in(k,v)::acc)[](List.revls)letlength(Tree{ops=(moduleOps);tree;_})key=Ops.Tree.lengthtreekeyletfold?depth(Tree{ops=(moduleOps)asops;tree=t;equality_witness;impl_name})key~order~init~f=Ops.Tree.fold?depthtkey~order~init~f:(funkvacc->letv=Tree{ops;tree=v;equality_witness;impl_name}infkvacc)letclear?depth(Tree{ops=(moduleOps);tree;_})=Ops.Tree.clear?depthtreeletconfig(Tree{ops=(moduleOps);tree;_})=Ops.Tree.configtreeendletconfig(Context{ops=(moduleOps);ctxt;_})=Ops.configctxt(* Proof *)moduleProof=Tezos_context_sigs.Context.Proof_types(* In-memory context for proof *)moduleProof_context=structmoduleM=structincludeTezos_context_memory.Contextletset_protocol=add_protocolletfork_test_chainc~protocol:_~expiration:_=Lwt.returncendletequality_witness:(M.t,M.tree)equality_witness=equality_witness()letops=(moduleM:Swithtypet='ctxtandtypetree='tree)letimpl_name="proof"letinject:M.tree->tree=funtree->Tree{ops;tree;equality_witness;impl_name}letproject:tree->M.tree=fun(Treet)->matchequivt.equality_witnessequality_witnesswith|SomeRefl,SomeRefl->t.tree|_->err_implementation_mismatch~expected:impl_name~got:t.impl_nameend(* In-memory context for proof, using [Context_binary] which produces more
compact Merkle proofs. *)moduleProof_context_binary=structmoduleM=structincludeTezos_context_memory.Context_binaryletset_protocol=add_protocolletfork_test_chainc~protocol:_~expiration:_=Lwt.returncendletequality_witness:(M.t,M.tree)equality_witness=equality_witness()letops=(moduleM:Swithtypet='ctxtandtypetree='tree)letimpl_name="proof_binary"letinject:M.tree->tree=funtree->Tree{ops;tree;equality_witness;impl_name}letproject:tree->M.tree=fun(Treet)->matchequivt.equality_witnessequality_witnesswith|SomeRefl,SomeRefl->t.tree|_->err_implementation_mismatch~expected:impl_name~got:t.impl_nameendmoduletypeProof_context=sigmoduleM:Svalinject:M.tree->treevalproject:tree->M.treeendtypeproof_version_expanded=Tezos_context_helpers.Context.proof_version_expandedletdecode_proof_version=Tezos_context_helpers.Context.decode_proof_versionletproof_context_of_proof_version_expanded:proof_version_expanded->(moduleProof_context)=function|{is_binary=true;_}->(moduleProof_context_binary)|{is_binary=false;_}->(moduleProof_context)letproof_context~kindproof=matchdecode_proof_versionproof.Proof.versionwith|Error`Invalid_proof_version->Lwt.fail_with"Environment_context.verify_tree_proof: Invalid version"|Okv->ifkind=`Tree&&v.is_streamthenLwt.fail_with"Environment_context.verify_tree_proof: Received stream proof"elseifkind=`Stream&¬v.is_streamthenLwt.fail_with"Environment_context.verify_stream_proof: Received tree proof"elseLwt.return_ok(proof_context_of_proof_version_expandedv)letverify_tree_proofproof(f:tree->(tree*'a)Lwt.t)=letopenLwt_result_syntaxinlet*(moduleProof_context)=proof_context~kind:`Treeproofinlet*tree,r=Proof_context.M.verify_tree_proofproof(funtree->lettree=Proof_context.injecttreeinlet*!tree,r=ftreeinLwt.return(Proof_context.projecttree,r))inreturn(Proof_context.injecttree,r)letverify_stream_proofproof(f:tree->(tree*'a)Lwt.t)=letopenLwt_result_syntaxinlet*(moduleProof_context)=proof_context~kind:`Streamproofinlet*tree,r=Proof_context.M.verify_stream_proofproof(funtree->lettree=Proof_context.injecttreeinlet*!tree,r=ftreeinLwt.return(Proof_context.projecttree,r))inreturn(Proof_context.injecttree,r)letequal_config=Tezos_context_sigs.Config.equaltypecache_key=Environment_cache.keytypeblock_cache={context_hash:Tezos_crypto.Hashed.Context_hash.t;cache:cache;}typesource_of_cache=[`Force_load|`Load|`Lazy|`Inheritedofblock_cache*Tezos_crypto.Hashed.Context_hash.t]typebuilder=Environment_cache.key->cache_valuetzresultLwt.tmoduleCache=structtypekey=Environment_cache.keytypevalue=cache_value=..typeidentifier=Environment_cache.identifiertypesize=Environment_cache.sizetypeindex=Environment_cache.indexmoduleEvents=structopenInternal_event.Simpleletsection=["protocol_cache"]letstart_loading_cache=declare_0~section~level:Info~name:"start_loading_cache"~msg:"start loading cache now"()letstop_loading_cache=declare_0~section~level:Info~name:"stop_loading_cache"~msg:"stop loading cache now"()letstart_loading_cache_lazily=declare_0~section~level:Debug~name:"start_loading_cache_lazily"~msg:"start loading cache lazily"()letstop_loading_cache_lazily=declare_0~section~level:Debug~name:"stop_loading_cache_lazily"~msg:"stop loading cache lazily"()letemit=Internal_event.Simple.emitletobservestart_eventstop_eventf=letopenLwt_result_syntaxinlet*!()=emitstart_event()inlet*ret=f()inlet*!()=emitstop_event()inreturnretendletkey_of_identifier=Environment_cache.key_of_identifierletidentifier_of_key=Environment_cache.identifier_of_keyletppfmt(Context{cache;_})=Environment_cache.ppfmtcacheletcache_number_path=["number_of_caches"]letcache_pathcache_index=["cache";string_of_intcache_index]letcache_limit_pathcache=cache_pathcache@["limit"]letget_cache_numberctxt=letopenLwt_syntaxinlet+cn=findctxtcache_number_pathinmatchcnwith|None->0|Somev->Data_encoding.(Binary.of_bytes_exnint31v)letset_cache_numberctxtcache_number=ifcache_number=0thenLwt.returnctxtelseletbytes=Data_encoding.(Binary.to_bytes_exnint31)cache_numberinaddctxtcache_number_pathbytesletget_cache_limitctxtcache_handle=letopenLwt_syntaxinlet+c=findctxt(cache_limit_pathcache_handle)inOption.mapData_encoding.(Binary.of_bytes_exnint31)cletset_cache_limitctxtcache_handlelimit=letpath=cache_limit_pathcache_handleinletbytes=Data_encoding.(Binary.to_bytes_exnint31)limitinaddctxtpathbytesletset_cache_layout(Contextctxt)layout=letopenLwt_syntaxinletcache=Environment_cache.from_layoutlayoutinletctxt=Context{ctxtwithcache}inletcache_number=List.lengthlayoutinlet*ctxt=set_cache_numberctxtcache_numberinList.fold_left_i_s(funictxtlimit->set_cache_limitctxtilimit)ctxtlayoutletget_cache_layoutctxt=letopenLwt_syntaxinlet*n=get_cache_numberctxtinList.map_s(funindex->let*o=get_cache_limitctxtindexinmatchowith|None->(*
[set_cache_layout] must be called at the beginning of
each protocol activation so that the storage contains
a consistent description of the layout. If this
invariant holds, then there always is a limit in the
context.
*)assertfalse|Somelimit->Lwt.returnlimit)(0--(n-1))letupdate(Contextctxt)keyvalue=letdelayed_value=Option.map(fun(value,index)->(delayvalue,index))valueinletcache=Environment_cache.updatectxt.cachekeydelayed_valueinContext{ctxtwithcache}letcache_domain_path=["domain"]letsync(Contextctxt)~cache_nonce=letopenEnvironment_cacheinletopenData_encodinginletcache,domain=syncctxt.cache~cache_nonceinletbytes=Binary.to_bytes_exndomain_encodingdomaininletctxt=Context{ctxtwithcache}inaddctxtcache_domain_pathbytesletclear(Contextctxt)=Context{ctxtwithcache=Environment_cache.clearctxt.cache}letlist_keys(Context{cache;_})=Environment_cache.list_keyscacheletfuture_cache_expectation(Contextctxt)~time_in_blocks=letopenEnvironment_cacheinletcache=future_cache_expectationctxt.cache~time_in_blocksinContext{ctxtwithcache}letfind_domainctxt=letopenLwt_syntaxinlet+v=findctxtcache_domain_pathinOption.map(Data_encoding.Binary.of_bytes_exnEnvironment_cache.domain_encoding)vletfind(Context{cache;_})key=Option.map_s(funvalue->value())(Environment_cache.findcachekey)letloadctxtinherited~value_of_key=letopenLwt_syntaxinletopenEnvironment_cacheinlet*o=find_domainctxtinmatchowith|None->(*
This case can happen if a reorganization occurs on the
very first block of the protocol that introduces the
cache.
Indeed, in the first block, the predecessor block had no
cache so no domain can be found in the storage. However,
a cache can be inherited from a block in a canceled
chain.
*)return_ok@@clearinherited|Somedomain->from_cacheinheriteddomain~value_of_keyletload_nowctxtcachebuilder=letopenLwt_result_syntaxinloadctxtcache~value_of_key:(funkey->let*value=builderkeyinreturn(delayvalue))letload_on_demandctxtcachebuilder=letopenLwt_syntaxinletbuilderkey=let*r=builderkeyinmatchrwith|Error_->(*
This error is critical as it means that there have been a
cached [value] for [key] in the past but that [builder] is
unable to build it again. We stop everything at this point
because a node cannot run if it does not have the same
cache as other nodes in the chain.
*)Lwt.fail_with"Environment_context.load_on_demand: Unable to load value"|Okvalue->Lwt.returnvalueinloadctxtcache~value_of_key:(funkey->letlazy_value=letcache=refNoneinfun()->match!cachewith|Somevalue->returnvalue|None->let+r=builderkeyincache:=Somer;rinreturn_oklazy_value)letload_cachectxtcachemodebuilder=Events.(matchmodewith|`Load->observestart_loading_cachestop_loading_cache@@fun()->load_nowctxtcachebuilder|`Lazy->observestart_loading_cache_lazilystop_loading_cache_lazily@@fun()->load_on_demandctxtcachebuilder)letensure_valid_recycling(Contextctxt)cache=letopenLwt_syntaxinlet*layout=get_cache_layout(Contextctxt)inifEnvironment_cache.compatible_layoutcachelayoutthenLwt.returncacheelseLwt.return(Environment_cache.from_layoutlayout)letkey_rank(Contextctxt)key=Environment_cache.key_rankctxt.cachekeyletcache_size(Contextctxt)~cache_index=Environment_cache.cache_sizectxt.cache~cache_indexletcache_size_limit(Contextctxt)~cache_index=Environment_cache.cache_size_limitctxt.cache~cache_indexmoduleInternal_for_tests=structletsame_cache_domainsctxtctxt'=letopenLwt_syntaxinlet*domain=find_domainctxtinlet*domain'=find_domainctxt'inreturn_ok@@Option.equalEnvironment_cache.Internal_for_tests.equal_domaindomaindomain'endendletload_cache(Contextctxt)modebuilder=letopenLwt_syntaxinmatchmodewith|`Inherited({context_hash;cache},predecessor_context_hash)->ifTezos_crypto.Hashed.Context_hash.equalcontext_hashpredecessor_context_hashthen(*
We can safely reuse the cache of the predecessor block.
*)return_okcacheelse(*
The client of [load_cache] has provided a cache that is not
the cache of the predecessor but the predecessor and the
block have a common ancestor. Therefore, the inherited
cache is supposed to contain many entries that can be
recycled to build the new cache.
*)let*cache=Cache.ensure_valid_recycling(Contextctxt)cacheinCache.load_cache(Contextctxt)cache`Loadbuilder|(`Load|`Lazy)asmode->let*layout=Cache.get_cache_layout(Contextctxt)inletcache=Environment_cache.from_layoutlayoutinCache.load_cache(Contextctxt)cachemodebuilder(**
The following cache is for the cache to avoid reloading the cache from the
context when it has been used in the last cache-related operations.
The cache is indexed by the block hash that has produced it.
Notice that there is no guarantee that, after a call to [load_cache b], the
[cache_cache] holds the cache of the block [b]. Indeed, a subsequent call
to [load_cache bb] will take precedence. This is true even if the promise
for [b] has not resolved yet. Either way, whatever the pattern of
concurrent calls, the cache is safe in that:
- The cache that is returned by [load_cache b] is always the cache for the
block [b].
- If an error occurs during the loading of a cache, then the cache-cache
simply becomes empty.
*)moduleCache_cache=Aches_lwt.Lache.Make_result(Aches.Rache.SingletonTransferMap(Block_hash))letcache_cache:(cache,errortrace)Cache_cache.t=(* The cache is a singleton cache, this is set during the instantiation of
the module in the functor application above. This is why [-1] is an
acceptable value for the size limit: it is ignored and the functor's
value is used instead. *)Cache_cache.create(-1)letload_cacheblock_hash(Contextctxt)modebuilder=letopenLwt_result_syntaxinlet*cache=matchmodewith|`Force_load->letp=load_cache(Contextctxt)`LoadbuilderinCache_cache.putcache_cacheblock_hashp;p|(`Load|`Lazy|`Inherited_)asmode->Cache_cache.bind_or_putcache_cacheblock_hash(fun_block_hash->load_cache(Contextctxt)modebuilder)(funp->Lwt.returnp)inreturn(Context{ctxtwithcache})(* misc *)letset_protocol(Context({ops=(moduleOps);ctxt;_}asc))protocol_hash=letopenLwt_syntaxinlet+ctxt=Ops.set_protocolctxtprotocol_hashinContext{cwithctxt}letget_protocol(Context{ops=(moduleOps);ctxt;_})=Ops.get_protocolctxtletfork_test_chain(Context({ops=(moduleOps);ctxt;_}asc))~protocol~expiration=letopenLwt_syntaxinlet+ctxt=Ops.fork_test_chainctxt~protocol~expirationinContext{cwithctxt}letget_hash_version(Context{ops=(moduleOps);ctxt;_})=Ops.get_hash_versionctxtletset_hash_version(Context({ops=(moduleOps);ctxt;_}asc))v=letopenLwt_result_syntaxinlet+ctxt=Ops.set_hash_versionctxtvinContext{cwithctxt}endmoduleRegister(C:S)=structtype_Context.kind+=Context:C.tContext.kindletequality_witness:(C.t,C.tree)Context.equality_witness=Context.equality_witness()letops=(moduleC:Swithtypet='ctxtandtypetree='tree)endtypevalidation_result={context:Context.t;fitness:Fitness.t;message:stringoption;max_operations_ttl:int;last_allowed_fork_level:Int32.t;}typequota={max_size:int;max_op:intoption}typerpc_context={block_hash:Tezos_crypto.Hashed.Block_hash.t;block_header:Block_header.shell_header;context:Context.t;}typeheader_context_hash_semantics=|Resulting_context|Predecessor_resulting_context