123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365(*****************************************************************************)(* *)(* Open Source License *)(* 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. *)(* *)(*****************************************************************************)openSc_rollup_reprmodulePS=Sc_rollup_PVM_sig(*
This is the state hash of reference that both the prover of the node
and the verifier of the protocol {!Protocol_implementation} have to
agree on (if they do, it means they are using the same tree
structure).
We have to hard-code this value because the Arith PVM uses Irmin as
its Merkle proof verification backend, and the economic protocol
cannot create an empty Irmin context. Such a context is required to
create an empty tree, itself required to create the initial state of
the Arith PVM.
Utlimately, the value of this constant is decided by the prover of
reference (the only need is for it to be compatible with
{!Protocol_implementation}.)
Its value is the result of the following snippet
{|
let*! state = Prover.initial_state context in
Prover.state_hash state
|}
*)letreference_initial_state_hash=State_hash.of_b58check_exn"scs11cXwQJJ5dkpEQGq3x2MJm3cM73cbEkHJqo5eDSoRpHUPyEQLB4"typeerror+=|Arith_proof_production_failed|Arith_output_proof_production_failed|Arith_invalid_claim_about_outboxlet()=letopenData_encodinginletmsg="Invalid claim about outbox"inregister_error_kind`Permanent~id:"sc_rollup_arith_invalid_claim_about_outbox"~title:msg~pp:(funfmt()->Format.pp_print_stringfmtmsg)~description:msgunit(functionArith_invalid_claim_about_outbox->Some()|_->None)(fun()->Arith_invalid_claim_about_outbox);letmsg="Output proof production failed"inregister_error_kind`Permanent~id:"sc_rollup_arith_output_proof_production_failed"~title:msg~pp:(funfmt()->Format.fprintffmt"%s"msg)~description:msgunit(functionArith_output_proof_production_failed->Some()|_->None)(fun()->Arith_output_proof_production_failed);letmsg="Proof production failed"inregister_error_kind`Permanent~id:"sc_rollup_arith_proof_production_failed"~title:msg~pp:(funfmt()->Format.fprintffmt"%s"msg)~description:msgunit(functionArith_proof_production_failed->Some()|_->None)(fun()->Arith_proof_production_failed)moduletypeP=sigmoduleTree:Context.TREEwithtypekey=stringlistandtypevalue=bytestypetree=Tree.treevalhash_tree:tree->State_hash.ttypeproofvalproof_encoding:proofData_encoding.tvalproof_before:proof->State_hash.tvalproof_after:proof->State_hash.tvalverify_proof:proof->(tree->(tree*'a)Lwt.t)->(tree*'a)optionLwt.tvalproduce_proof:Tree.t->tree->(tree->(tree*'a)Lwt.t)->(proof*'a)optionLwt.tendmoduletypeS=sigincludePS.Svalname:stringvalparse_boot_sector:string->stringoptionvalpp_boot_sector:Format.formatter->string->unitvalpp:state->(Format.formatter->unit->unit)Lwt.tvalget_tick:state->Sc_rollup_tick_repr.tLwt.ttypestatus=|Halted|Waiting_for_input_message|Waiting_for_reveal|Parsing|Evaluatingvalget_status:state->statusLwt.tvalget_outbox:state->Sc_rollup_PVM_sig.outputlistLwt.ttypeinstruction=|IPush:int->instruction|IAdd:instruction|IStore:string->instructionvalequal_instruction:instruction->instruction->boolvalpp_instruction:Format.formatter->instruction->unitvalget_parsing_result:state->booloptionLwt.tvalget_code:state->instructionlistLwt.tvalget_stack:state->intlistLwt.tvalget_var:state->string->intoptionLwt.tvalget_evaluation_result:state->booloptionLwt.tvalget_is_stuck:state->stringoptionLwt.tendmoduleMake(Context:P):Swithtypecontext=Context.Tree.tandtypestate=Context.treeandtypeproof=Context.proof=structmoduleTree=Context.Treetypecontext=Context.Tree.ttypehash=State_hash.ttypeproof=Context.proofletproof_encoding=Context.proof_encodingletproof_start_stateproof=Context.proof_beforeproofletproof_stop_stateproof=Context.proof_afterproofletname="arith"letparse_boot_sectors=Somesletpp_boot_sectorfmts=Format.fprintffmt"%s"stypetree=Tree.treetypestatus=|Halted|Waiting_for_input_message|Waiting_for_reveal|Parsing|Evaluatingtypeinstruction=|IPush:int->instruction|IAdd:instruction|IStore:string->instructionletequal_instructioni1i2=match(i1,i2)with|IPushx,IPushy->Compare.Int.(x=y)|IAdd,IAdd->true|IStorex,IStorey->Compare.String.(x=y)|_,_->falseletpp_instructionfmt=function|IPushx->Format.fprintffmt"push(%d)"x|IAdd->Format.fprintffmt"add"|IStorex->Format.fprintffmt"store(%s)"x(*
The machine state is represented using a Merkle tree.
Here is the data model of this state represented in the tree:
- tick : Sc_rollup_tick_repr.t
The current tick counter of the machine.
- status : status
The current status of the machine.
- stack : int deque
The stack of integers.
- next_message : string option
The current input message to be processed.
- code : instruction deque
The instructions parsed from the input message.
- lexer_state : int * int
The internal state of the lexer.
- parsing_state : parsing_state
The internal state of the parser.
- parsing_result : bool option
The outcome of parsing.
- evaluation_result : bool option
The outcome of evaluation.
*)moduleState=structtypestate=treemoduleMonad:sigtype'atvalrun:'at->state->(state*'aoption)Lwt.tvalis_stuck:stringoptiontvalinternal_error:string->'atvalreturn:'a->'atmoduleSyntax:sigval(let*):'at->('a->'bt)->'btendvalremove:Tree.key->unittvalfind_value:Tree.key->'aData_encoding.t->'aoptiontvalchildren:Tree.key->'aData_encoding.t->(string*'a)listtvalget_value:default:'a->Tree.key->'aData_encoding.t->'atvalset_value:Tree.key->'aData_encoding.t->'a->unittend=structtype'at=state->(state*'aoption)Lwt.tletreturnxstate=Lwt.return(state,Somex)letbindmfstate=letopenLwt_syntaxinlet*state,res=mstateinmatchreswithNone->return(state,None)|Someres->fresstatemoduleSyntax=structlet(let*)=bindendletrunmstate=mstateletinternal_error_key=["internal_error"]letinternal_errormsgtree=letopenLwt_syntaxinlet*tree=Tree.addtreeinternal_error_key(Bytes.of_stringmsg)inreturn(tree,None)letis_stucktree=letopenLwt_syntaxinlet*v=Tree.findtreeinternal_error_keyinreturn(tree,Some(Option.mapBytes.to_stringv))letremovekeytree=letopenLwt_syntaxinlet*tree=Tree.removetreekeyinreturn(tree,Some())letdecodeencodingbytesstate=letopenLwt_syntaxinmatchData_encoding.Binary.of_bytes_optencodingbyteswith|None->internal_error"Error during decoding"state|Somev->return(state,Somev)letfind_valuekeyencodingstate=letopenLwt_syntaxinlet*obytes=Tree.findstatekeyinmatchobyteswith|None->return(state,SomeNone)|Somebytes->let*state,value=decodeencodingbytesstateinreturn(state,Somevalue)letchildrenkeyencodingstate=letopenLwt_syntaxinlet*children=Tree.liststatekeyinletrecaux=function|[]->return(state,Some[])|(key,tree)::children->(let*obytes=Tree.to_valuetreeinmatchobyteswith|None->internal_error"Invalid children"state|Somebytes->(let*state,v=decodeencodingbytesstateinmatchvwith|None->return(state,None)|Somev->(let*state,l=auxchildreninmatchlwith|None->return(state,None)|Somel->return(state,Some((key,v)::l)))))inauxchildrenletget_value~defaultkeyencoding=letopenSyntaxinlet*ov=find_valuekeyencodinginmatchovwithNone->returndefault|Somex->returnxletset_valuekeyencodingvaluetree=letopenLwt_syntaxinData_encoding.Binary.to_bytes_optencodingvalue|>function|None->internal_error"Internal_Error during encoding"tree|Somebytes->let*tree=Tree.addtreekeybytesinreturn(tree,Some())endopenMonadmoduleMake_var(P:sigtypetvalname:stringvalinitial:tvalpp:Format.formatter->t->unitvalencoding:tData_encoding.tend)=structletkey=[P.name]letcreate=set_valuekeyP.encodingP.initialletget=letopenMonad.Syntaxinlet*v=find_valuekeyP.encodinginmatchvwith|None->(* This case should not happen if [create] is properly called. *)returnP.initial|Somev->returnvletset=set_valuekeyP.encodingletpp=letopenMonad.Syntaxinlet*v=getinreturn@@funfmt()->Format.fprintffmt"@[%s : %a@]"P.nameP.ppvendmoduleMake_dict(P:sigtypetvalname:stringvalpp:Format.formatter->t->unitvalencoding:tData_encoding.tend)=structletkeyk=[P.name;k]letgetk=find_value(keyk)P.encodingletsetkv=set_value(keyk)P.encodingvletentries=children[P.name]P.encodingletmapped_tokvstate=letopenLwt_syntaxinlet*state',_=Monad.(run(setkv)state)inlet*t=Tree.find_treestate(keyk)and*t'=Tree.find_treestate'(keyk)inLwt.return(Option.equalTree.equaltt')letpp=letopenMonad.Syntaxinlet*l=entriesinletpp_elemfmt(key,value)=Format.fprintffmt"@[%s : %a@]"keyP.ppvalueinreturn@@funfmt()->Format.pp_print_listpp_elemfmtlendmoduleMake_deque(P:sigtypetvalname:stringvalencoding:tData_encoding.tend)=struct(*
A stateful deque.
[[head; end[] is the index range for the elements of the deque.
The length of the deque is therefore [end - head].
*)lethead_key=[P.name;"head"]letend_key=[P.name;"end"]letget_head=get_value~default:Z.zerohead_keyData_encoding.zletset_head=set_valuehead_keyData_encoding.zletget_end=get_value~default:(Z.of_int0)end_keyData_encoding.zletset_end=set_valueend_keyData_encoding.zletidx_keyidx=[P.name;Z.to_stringidx]lettop=letopenMonad.Syntaxinlet*head_idx=get_headinlet*end_idx=get_endinlet*v=find_value(idx_keyhead_idx)P.encodinginifZ.(leqend_idxhead_idx)thenreturnNoneelsematchvwith|None->(* By invariants of the Deque. *)assertfalse|Somex->return(Somex)letpushx=letopenMonad.Syntaxinlet*head_idx=get_headinlethead_idx'=Z.predhead_idxinlet*()=set_headhead_idx'inset_value(idx_keyhead_idx')P.encodingxletpop=letopenMonad.Syntaxinlet*head_idx=get_headinlet*end_idx=get_endinifZ.(leqend_idxhead_idx)thenreturnNoneelselet*v=find_value(idx_keyhead_idx)P.encodinginmatchvwith|None->(* By invariants of the Deque. *)assertfalse|Somex->let*()=remove(idx_keyhead_idx)inlethead_idx=Z.succhead_idxinlet*()=set_headhead_idxinreturn(Somex)letinjectx=letopenMonad.Syntaxinlet*end_idx=get_endinletend_idx'=Z.succend_idxinlet*()=set_endend_idx'inset_value(idx_keyend_idx)P.encodingxletto_list=letopenMonad.Syntaxinlet*head_idx=get_headinlet*end_idx=get_endinletrecauxlidx=ifZ.(ltidxhead_idx)thenreturnlelselet*v=find_value(idx_keyidx)P.encodinginmatchvwith|None->(* By invariants of deque *)assertfalse|Somev->aux(v::l)(Z.predidx)inaux[](Z.predend_idx)letclear=remove[P.name]endmoduleCurrent_tick=Make_var(structincludeSc_rollup_tick_reprletname="tick"end)moduleVars=Make_dict(structtypet=intletname="vars"letencoding=Data_encoding.int31letppfmtx=Format.fprintffmt"%d"xend)moduleStack=Make_deque(structtypet=intletname="stack"letencoding=Data_encoding.int31end)moduleCode=Make_deque(structtypet=instructionletname="code"letencoding=Data_encoding.(union[case~title:"push"(Tag0)Data_encoding.int31(functionIPushx->Somex|_->None)(funx->IPushx);case~title:"add"(Tag1)Data_encoding.unit(functionIAdd->Some()|_->None)(fun()->IAdd);case~title:"store"(Tag2)Data_encoding.string(functionIStorex->Somex|_->None)(funx->IStorex);])end)moduleBoot_sector=Make_var(structtypet=stringletname="boot_sector"letinitial=""letencoding=Data_encoding.stringletppfmts=Format.fprintffmt"%s"send)moduleStatus=Make_var(structtypet=statusletinitial=Haltedletencoding=Data_encoding.string_enum[("Halted",Halted);("Waiting_for_input_message",Waiting_for_input_message);("Waiting_for_reveal",Waiting_for_reveal);("Parsing",Parsing);("Evaluating",Evaluating);]letname="status"letstring_of_status=function|Halted->"Halted"|Waiting_for_input_message->"Waiting for input message"|Waiting_for_reveal->"Waiting for reveal"|Parsing->"Parsing"|Evaluating->"Evaluating"letppfmtstatus=Format.fprintffmt"%s"(string_of_statusstatus)end)moduleRequired_reveal=Make_var(structtypet=PS.Input_hash.toptionletinitial=Noneletencoding=Data_encoding.optionPS.Input_hash.encodingletname="required_pre_image_hash"letppfmtv=matchvwith|None->Format.fprintffmt"<none>"|Someh->PS.Input_hash.ppfmthend)moduleCurrent_level=Make_var(structtypet=Raw_level_repr.tletinitial=Raw_level_repr.rootletencoding=Raw_level_repr.encodingletname="current_level"letpp=Raw_level_repr.ppend)moduleMessage_counter=Make_var(structtypet=Z.toptionletinitial=Noneletencoding=Data_encoding.optionData_encoding.nletname="message_counter"letppfmt=function|None->Format.fprintffmt"None"|Somec->Format.fprintffmt"Some %a"Z.pp_printcend)moduleNext_message=Make_var(structtypet=stringoptionletinitial=Noneletencoding=Data_encoding.(optionstring)letname="next_message"letppfmt=function|None->Format.fprintffmt"None"|Somes->Format.fprintffmt"Some %s"send)typeparser_state=ParseInt|ParseVar|SkipLayoutmoduleLexer_state=Make_var(structtypet=int*intletname="lexer_buffer"letinitial=(-1,-1)letencoding=Data_encoding.(tup2int31int31)letppfmt(start,len)=Format.fprintffmt"lexer.(start = %d, len = %d)"startlenend)moduleParser_state=Make_var(structtypet=parser_stateletname="parser_state"letinitial=SkipLayoutletencoding=Data_encoding.string_enum[("ParseInt",ParseInt);("ParseVar",ParseVar);("SkipLayout",SkipLayout);]letppfmt=function|ParseInt->Format.fprintffmt"Parsing int"|ParseVar->Format.fprintffmt"Parsing var"|SkipLayout->Format.fprintffmt"Skipping layout"end)moduleParsing_result=Make_var(structtypet=booloptionletname="parsing_result"letinitial=Noneletencoding=Data_encoding.(optionbool)letppfmt=function|None->Format.fprintffmt"n/a"|Sometrue->Format.fprintffmt"parsing succeeds"|Somefalse->Format.fprintffmt"parsing fails"end)moduleEvaluation_result=Make_var(structtypet=booloptionletname="evaluation_result"letinitial=Noneletencoding=Data_encoding.(optionbool)letppfmt=function|None->Format.fprintffmt"n/a"|Sometrue->Format.fprintffmt"evaluation succeeds"|Somefalse->Format.fprintffmt"evaluation fails"end)moduleOutput_counter=Make_var(structtypet=Z.tletinitial=Z.zeroletname="output_counter"letencoding=Data_encoding.nletpp=Z.pp_printend)moduleOutput=Make_dict(structtypet=Sc_rollup_PVM_sig.outputletname="output"letencoding=Sc_rollup_PVM_sig.output_encodingletpp=Sc_rollup_PVM_sig.pp_outputend)letpp=letopenMonad.Syntaxinlet*status_pp=Status.ppinlet*message_counter_pp=Message_counter.ppinlet*next_message_pp=Next_message.ppinlet*parsing_result_pp=Parsing_result.ppinlet*parser_state_pp=Parser_state.ppinlet*lexer_state_pp=Lexer_state.ppinlet*evaluation_result_pp=Evaluation_result.ppinlet*vars_pp=Vars.ppinlet*output_pp=Output.ppinlet*stack=Stack.to_listinlet*current_tick_pp=Current_tick.ppinreturn@@funfmt()->Format.fprintffmt"@[<v 0 >@;\
%a@;\
%a@;\
%a@;\
%a@;\
%a@;\
%a@;\
%a@;\
tick : %a@;\
vars : %a@;\
output :%a@;\
stack : %a@;\
@]"status_pp()message_counter_pp()next_message_pp()parsing_result_pp()parser_state_pp()lexer_state_pp()evaluation_result_pp()current_tick_pp()vars_pp()output_pp()Format.(pp_print_listpp_print_int)stackendopenStatetypestate=State.stateopenMonadletinitial_statectxt=letstate=Tree.emptyctxtinletm=letopenMonad.Syntaxinlet*()=Status.setHaltedinreturn()inletopenLwt_syntaxinlet*state,_=runmstateinreturnstateletinstall_boot_sectorstateboot_sector=letm=letopenMonad.Syntaxinlet*()=Boot_sector.setboot_sectorinreturn()inletopenLwt_syntaxinlet*state,_=runmstateinreturnstateletstate_hashstate=letcontext_hash=Tree.hashstateinLwt.return@@State_hash.context_hash_to_state_hashcontext_hashletppstate=letopenLwt_syntaxinlet*_,pp=Monad.runppstateinmatchppwith|None->return@@funfmt_->Format.fprintffmt"<opaque>"|Somepp->let*state_hash=state_hashstateinreturn(funfmt()->Format.fprintffmt"@[%a: %a@]"State_hash.ppstate_hashpp())letboot=letopenMonad.Syntaxinlet*()=Status.createinlet*()=Next_message.createinlet*()=Status.setWaiting_for_input_messageinreturn()letresult_of~defaultmstate=letopenLwt_syntaxinlet*_,v=runmstateinmatchvwithNone->returndefault|Somev->returnvletstate_ofmstate=letopenLwt_syntaxinlet*s,_=runmstateinreturnsletget_tick=result_of~default:Sc_rollup_tick_repr.initialCurrent_tick.getletis_input_state_monadic=letopenMonad.Syntaxinlet*status=Status.getinmatchstatuswith|Waiting_for_input_message->(let*level=Current_level.getinlet*counter=Message_counter.getinmatchcounterwith|Somen->return(PS.First_after(level,n))|None->returnPS.Initial)|Waiting_for_reveal->(let*h=Required_reveal.getinmatchhwith|None->internal_error"Internal error: Reveal invariant broken"|Someh->return(PS.Needs_reveal(Reveal_raw_datah)))|_->returnPS.No_input_requiredletis_input_state=result_of~default:PS.No_input_required@@is_input_state_monadicletget_status=result_of~default:Waiting_for_input_message@@Status.getletget_outboxstate=letopenLwt_syntaxinlet+entries=result_of~default:[]Output.entriesstateinList.mapsndentriesletget_code=result_of~default:[]@@Code.to_listletget_parsing_result=result_of~default:None@@Parsing_result.getletget_stack=result_of~default:[]@@Stack.to_listletget_varstatek=(result_of~default:None@@Vars.getk)stateletget_evaluation_result=result_of~default:None@@Evaluation_result.getletget_is_stuck=result_of~default:None@@is_stuckletstart_parsing:unitt=letopenMonad.Syntaxinlet*()=Status.setParsinginlet*()=Parsing_result.setNoneinlet*()=Parser_state.setSkipLayoutinlet*()=Lexer_state.set(0,0)inlet*()=Code.clearinreturn()letset_inbox_message_monadic{PS.inbox_level;message_counter;payload}=letopenMonad.Syntaxinletpayload=matchSc_rollup_inbox_message_repr.deserializepayloadwith|Error_->None|Ok(Externalpayload)->Somepayload|Ok(Internal{payload;_})->(matchMicheline.rootpayloadwith|String(_,payload)->Somepayload|_->None)inmatchpayloadwith|Somepayload->let*boot_sector=Boot_sector.getinletmsg=boot_sector^payloadinlet*()=Current_level.setinbox_levelinlet*()=Message_counter.set(Somemessage_counter)inlet*()=Next_message.set(Somemsg)inlet*()=start_parsinginreturn()|None->let*()=Current_level.setinbox_levelinlet*()=Message_counter.set(Somemessage_counter)inlet*()=Status.setWaiting_for_input_messageinreturn()letreveal_monadic(PS.Raw_datadata)=(*
The inbox cursor is unchanged as the message comes from the
outer world.
We don't have to check that the data hash is the one we
expected as we decided to trust the initial witness.
It is the responsibility of the rollup node to check it if it
does not want to publish a wrong commitment.
Notice that a multi-page transmission is possible by embedding
a continuation encoded as an optional hash in [data].
*)letopenMonad.Syntaxinlet*()=Next_message.set(Somedata)inlet*()=start_parsinginreturn()lettickedm=letopenMonad.Syntaxinlet*tick=Current_tick.getinlet*()=Current_tick.set(Sc_rollup_tick_repr.nexttick)inmletset_input_monadicinput=matchinputwith|PS.Inbox_messagem->set_inbox_message_monadicm|PS.Reveals->reveal_monadicsletset_inputinput=set_input_monadicinput|>ticked|>state_ofletnext_char=letopenMonad.SyntaxinLexer_state.(let*start,len=getinset(start,len+1))letno_message_to_lex()=internal_error"lexer: There is no input message to lex"letcurrent_char=letopenMonad.Syntaxinlet*start,len=Lexer_state.getinlet*msg=Next_message.getinmatchmsgwith|None->no_message_to_lex()|Somes->ifCompare.Int.(start+len<String.lengths)thenreturn(Somes.[start+len])elsereturnNoneletlexeme=letopenMonad.Syntaxinlet*start,len=Lexer_state.getinlet*msg=Next_message.getinmatchmsgwith|None->no_message_to_lex()|Somes->let*()=Lexer_state.set(start+len,0)inreturn(String.subsstartlen)letpush_int_literal=letopenMonad.Syntaxinlet*s=lexemeinmatchint_of_string_optswith|Somex->Code.inject(IPushx)|None->(* By validity of int parsing. *)assertfalseletpush_var=letopenMonad.Syntaxinlet*s=lexemeinCode.inject(IStores)letstart_evaluating:unitt=letopenMonad.Syntaxinlet*()=Status.setEvaluatinginlet*()=Evaluation_result.setNoneinreturn()letstop_parsingoutcome=letopenMonad.Syntaxinlet*()=Parsing_result.set(Someoutcome)instart_evaluatingletstop_evaluatingoutcome=letopenMonad.Syntaxinlet*()=Evaluation_result.set(Someoutcome)inStatus.setWaiting_for_input_messageletparse:unitt=letopenMonad.Syntaxinletproduce_add=let*_=lexemeinlet*()=next_charinlet*()=Code.injectIAddinreturn()inletproduce_int=let*()=push_int_literalinlet*()=Parser_state.setSkipLayoutinreturn()inletproduce_var=let*()=push_varinlet*()=Parser_state.setSkipLayoutinreturn()inletis_digitd=Compare.Char.(d>='0'&&d<='9')inletis_letterd=Compare.Char.((d>='a'&&d<='z')||(d>='A'&&d<='Z'))inletis_identifier_chard=is_letterd||is_digitd||Compare.Char.(d=':')||Compare.Char.(d='%')inlet*parser_state=Parser_state.getinmatchparser_statewith|ParseInt->(let*char=current_charinmatchcharwith|Somedwhenis_digitd->next_char|Some'+'->let*()=produce_intinlet*()=produce_addinreturn()|Some(' '|'\n')->let*()=produce_intinlet*()=next_charinreturn()|None->let*()=push_int_literalinstop_parsingtrue|_->stop_parsingfalse)|ParseVar->(let*char=current_charinmatchcharwith|Somedwhenis_identifier_chard->next_char|Some'+'->let*()=produce_varinlet*()=produce_addinreturn()|Some(' '|'\n')->let*()=produce_varinlet*()=next_charinreturn()|None->let*()=push_varinstop_parsingtrue|_->stop_parsingfalse)|SkipLayout->(let*char=current_charinmatchcharwith|Some(' '|'\n')->next_char|Some'+'->produce_add|Somedwhenis_digitd->let*_=lexemeinlet*()=next_charinlet*()=Parser_state.setParseIntinreturn()|Somedwhenis_letterd->let*_=lexemeinlet*()=next_charinlet*()=Parser_state.setParseVarinreturn()|None->stop_parsingtrue|_->stop_parsingfalse)letoutput(destination,entrypoint)v=letopenMonad.SyntaxinletopenSc_rollup_outbox_message_reprinlet*counter=Output_counter.getinlet*()=Output_counter.set(Z.succcounter)inletunparsed_parameters=Micheline.(Int((),Z.of_intv)|>strip_locations)inlettransaction={unparsed_parameters;destination;entrypoint}inletmessage=Atomic_transaction_batch{transactions=[transaction]}inlet*outbox_level=Current_level.getinletoutput=Sc_rollup_PVM_sig.{outbox_level;message_index=counter;message}inOutput.set(Z.to_stringcounter)outputletidentifies_target_contractx=letopenOption_syntaxinmatchString.split_on_char'%'xwith|destination::entrypoint->(matchContract_hash.of_b58check_optdestinationwith|None->ifCompare.String.(x="out")thenreturn(Contract_hash.zero,Entrypoint_repr.default)elsefail|Somedestination->let*entrypoint=matchentrypointwith|[]->returnEntrypoint_repr.default|_->let*entrypoint=Non_empty_string.of_string(String.concat""entrypoint)inlet*entrypoint=Entrypoint_repr.of_annot_lax_optentrypointinreturnentrypointinreturn(destination,entrypoint))|[]->failletevaluate=letopenMonad.Syntaxinlet*i=Code.popinmatchiwith|None->stop_evaluatingtrue|Some(IPushx)->Stack.pushx|Some(IStorex)->(letlen=String.lengthxinifCompare.Int.(len>5)&&Compare.String.(String.subx05="hash:")thenlethash=String.subx5(len-5)inmatchPS.Input_hash.of_b58check_opthashwith|None->stop_evaluatingfalse|Somehash->let*()=Required_reveal.set(Somehash)inlet*()=Status.setWaiting_for_revealinreturn()elselet*v=Stack.topinmatchvwith|None->stop_evaluatingfalse|Somev->(matchidentifies_target_contractxwith|Somecontract_entrypoint->outputcontract_entrypointv|None->Vars.setxv))|SomeIAdd->(let*v=Stack.popinmatchvwith|None->stop_evaluatingfalse|Somex->(let*v=Stack.popinmatchvwith|None->stop_evaluatingfalse|Somey->Stack.push(x+y)))letreboot=letopenMonad.Syntaxinlet*()=Status.setWaiting_for_input_messageinlet*()=Stack.clearinlet*()=Code.clearinreturn()leteval_step=letopenMonad.Syntaxinlet*x=is_stuckinmatchxwith|Some_->reboot|None->(let*status=Status.getinmatchstatuswith|Halted->boot|Waiting_for_input_message|Waiting_for_reveal->(let*msg=Next_message.getinmatchmsgwith|None->internal_error"An input state was not provided an input."|Some_->start_parsing)|Parsing->parse|Evaluating->evaluate)letevalstate=state_of(tickedeval_step)stateletstep_transitioninput_givenstate=letopenLwt_syntaxinlet*request=is_input_statestateinlet*state=matchrequestwith|PS.No_input_required->evalstate|PS.Initial|PS.First_after_->(matchinput_givenwith|Some(PS.Inbox_message_asinput_given)->set_inputinput_givenstate|None|Some(PS.Reveal_)->state_of(internal_error"Invalid set_input: expecting inbox message, got a reveal.")state)|PS.Needs_reveal_hash->(matchinput_givenwith|Some(PS.Reveal_asinput_given)->set_inputinput_givenstate|None|Some(PS.Inbox_message_)->state_of(internal_error"Invalid set_input: expecting a reveal, got an inbox \
message.")state)inreturn(state,request)typeerror+=Arith_proof_verification_failedletverify_proofinput_givenproof=letopenLwt_tzresult_syntaxinlet*!result=Context.verify_proofproof(step_transitioninput_given)inmatchresultwith|None->failArith_proof_verification_failed|Some(_state,request)->returnrequestletproduce_proofcontextinput_givenstate=letopenLwt_tzresult_syntaxinlet*!result=Context.produce_proofcontextstate(step_transitioninput_given)inmatchresultwith|Some(tree_proof,_requested)->returntree_proof|None->failArith_proof_production_failedletverify_origination_proofproofboot_sector=letopenLwt_syntaxinletbefore=Context.proof_beforeproofinifState_hash.(before<>reference_initial_state_hash)thenreturnfalseelselet*result=Context.verify_proofproof(funstate->let*state=install_boot_sectorstateboot_sectorinreturn(state,()))inmatchresultwithNone->returnfalse|Some(_,())->returntrueletproduce_origination_proofcontextboot_sector=letopenLwt_tzresult_syntaxinlet*!state=initial_statecontextinlet*!result=Context.produce_proofcontextstate(funstate->letopenLwt_syntaxinlet*state=install_boot_sectorstateboot_sectorinreturn(state,()))inmatchresultwith|Some(proof,())->returnproof|None->failArith_proof_production_failed(* TEMPORARY: The following definitions will be extended in a future commit. *)typeoutput_proof={output_proof:Context.proof;output_proof_state:hash;output_proof_output:PS.output;}letoutput_proof_encoding=letopenData_encodinginconv(fun{output_proof;output_proof_state;output_proof_output}->(output_proof,output_proof_state,output_proof_output))(fun(output_proof,output_proof_state,output_proof_output)->{output_proof;output_proof_state;output_proof_output})(obj3(req"output_proof"Context.proof_encoding)(req"output_proof_state"State_hash.encoding)(req"output_proof_output"PS.output_encoding))letoutput_of_output_proofs=s.output_proof_outputletstate_of_output_proofs=s.output_proof_stateletoutput_key(output:PS.output)=Z.to_stringoutput.message_indexlethas_outputoutputtree=letopenLwt_syntaxinlet*equal=Output.mapped_to(output_keyoutput)outputtreeinreturn(tree,equal)letverify_output_proofp=letopenLwt_syntaxinlettransition=has_outputp.output_proof_outputinlet*result=Context.verify_proofp.output_prooftransitioninmatchresultwithNone->returnfalse|Some_->returntrueletproduce_output_proofcontextstateoutput_proof_output=letopenLwt_result_syntaxinlet*!output_proof_state=state_hashstateinlet*!result=Context.produce_proofcontextstate@@has_outputoutput_proof_outputinmatchresultwith|Some(output_proof,true)->return{output_proof;output_proof_state;output_proof_output}|Some(_,false)->failArith_invalid_claim_about_outbox|None->failArith_output_proof_production_failedmoduleInternal_for_tests=structletinsert_failurestate=letaddn=Tree.addstate["failures";string_of_intn]Bytes.emptyinletopenLwt_syntaxinlet*n=Tree.lengthstate["failures"]inaddnendendmoduleProtocol_implementation=Make(structmoduleTree=structincludeContext.Treetypetree=Context.treetypet=Context.ttypekey=stringlisttypevalue=bytesendtypetree=Context.treelethash_treet=State_hash.context_hash_to_state_hash(Tree.hasht)typeproof=Context.Proof.treeContext.Proof.tletverify_proofpf=Lwt.mapResult.to_option(Context.verify_tree_proofpf)letproduce_proof_context_state_f=(* Can't produce proof without full context*)Lwt.returnNoneletkinded_hash_to_state_hash=function|`Valuehash|`Nodehash->State_hash.context_hash_to_state_hashhashletproof_beforeproof=kinded_hash_to_state_hashproof.Context.Proof.beforeletproof_afterproof=kinded_hash_to_state_hashproof.Context.Proof.afterletproof_encoding=Context.Proof_encoding.V2.Tree32.tree_proof_encodingend)