1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150(*****************************************************************************)(* *)(* 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_semmoduletypeP=sigmoduleTree:Context.TREEwithtypekey=stringlistandtypevalue=bytestypetree=Tree.treetypeproofvalproof_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|WaitingForInputMessage|Parsing|Evaluatingvalget_status:state->statusLwt.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.tree=structmoduleTree=Context.Treetypecontext=Context.Tree.ttypehash=State_hash.ttypeproof={tree_proof:Context.proof;given:PS.inputoption;requested:PS.input_request;}letproof_encoding=letopenData_encodinginconv(fun{tree_proof;given;requested}->(tree_proof,given,requested))(fun(tree_proof,given,requested)->{tree_proof;given;requested})(obj3(req"tree_proof"Context.proof_encoding)(req"given"(optionPS.input_encoding))(req"requested"PS.input_request_encoding))letproof_start_statep=Context.proof_beforep.tree_proofletproof_stop_statep=match(p.given,p.requested)with|None,PS.No_input_required->Some(Context.proof_afterp.tree_proof)|None,_->None|_->Some(Context.proof_afterp.tree_proof)letproof_input_givenp=p.givenletproof_input_requestedp=p.requestedletname="arith"letparse_boot_sectors=Somesletpp_boot_sectorfmts=Format.fprintffmt"%s"stypetree=Tree.treetypestatus=Halted|WaitingForInputMessage|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())endopenMonadmoduleMakeVar(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.ppvendmoduleMakeDict(P:sigtypetvalname:stringvalpp:Format.formatter->t->unitvalencoding:tData_encoding.tend)=structletkeyk=[P.name;k]letgetk=find_value(keyk)P.encodingletsetkv=set_value(keyk)P.encodingvletmapped_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=children[P.name]P.encodinginletpp_elemfmt(key,value)=Format.fprintffmt"@[%s : %a@]"keyP.ppvalueinreturn@@funfmt()->Format.pp_print_listpp_elemfmtlendmoduleMakeDeque(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]endmoduleCurrentTick=MakeVar(structincludeSc_rollup_tick_reprletname="tick"end)moduleVars=MakeDict(structtypet=intletname="vars"letencoding=Data_encoding.int31letppfmtx=Format.fprintffmt"%d"xend)moduleStack=MakeDeque(structtypet=intletname="stack"letencoding=Data_encoding.int31end)moduleCode=MakeDeque(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=MakeVar(structtypet=stringletname="boot_sector"letinitial=""letencoding=Data_encoding.stringletppfmts=Format.fprintffmt"%s"send)moduleStatus=MakeVar(structtypet=statusletinitial=Haltedletencoding=Data_encoding.string_enum[("Halted",Halted);("WaitingForInput",WaitingForInputMessage);("Parsing",Parsing);("Evaluating",Evaluating);]letname="status"letstring_of_status=function|Halted->"Halted"|WaitingForInputMessage->"WaitingForInputMessage"|Parsing->"Parsing"|Evaluating->"Evaluating"letppfmtstatus=Format.fprintffmt"%s"(string_of_statusstatus)end)moduleCurrentLevel=MakeVar(structtypet=Raw_level_repr.tletinitial=Raw_level_repr.rootletencoding=Raw_level_repr.encodingletname="current_level"letpp=Raw_level_repr.ppend)moduleMessageCounter=MakeVar(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)moduleNextMessage=MakeVar(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|SkipLayoutmoduleLexerState=MakeVar(structtypet=int*intletname="lexer_buffer"letinitial=(-1,-1)letencoding=Data_encoding.(tup2int31int31)letppfmt(start,len)=Format.fprintffmt"lexer.(start = %d, len = %d)"startlenend)moduleParserState=MakeVar(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)moduleParsingResult=MakeVar(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)moduleEvaluationResult=MakeVar(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)moduleOutputCounter=MakeVar(structtypet=Z.tletinitial=Z.zeroletname="output_counter"letencoding=Data_encoding.zletpp=Z.pp_printend)moduleOutput=MakeDict(structtypet=Sc_rollup_PVM_sem.outputletname="output"letencoding=Sc_rollup_PVM_sem.output_encodingletpp=Sc_rollup_PVM_sem.pp_outputend)letpp=letopenMonad.Syntaxinlet*status_pp=Status.ppinlet*message_counter_pp=MessageCounter.ppinlet*next_message_pp=NextMessage.ppinlet*parsing_result_pp=ParsingResult.ppinlet*parser_state_pp=ParserState.ppinlet*lexer_state_pp=LexerState.ppinlet*evaluation_result_pp=EvaluationResult.ppinlet*vars_pp=Vars.ppinlet*output_pp=Output.ppinlet*stack=Stack.to_listinreturn@@funfmt()->Format.fprintffmt"@[<v 0 >@;\
%a@;\
%a@;\
%a@;\
%a@;\
%a@;\
%a@;\
%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()vars_pp()output_pp()Format.(pp_print_listpp_print_int)stackendopenStatetypestate=State.stateletppstate=letopenLwt_syntaxinlet*_,pp=Monad.runppstateinmatchppwith|None->return@@funfmt_->Format.fprintffmt"<opaque>"|Somepp->returnppopenMonadletinitial_statectxtboot_sector=letstate=Tree.emptyctxtinletm=letopenMonad.Syntaxinlet*()=Boot_sector.setboot_sectorinlet*()=Status.setHaltedinreturn()inletopenLwt_syntaxinlet*state,_=runmstateinreturnstateletstate_hashstate=letm=letopenMonad.Syntaxinlet*status=Status.getinmatchstatuswith|Halted->returnState_hash.zero|_->Context_hash.to_bytes@@Tree.hashstate|>funh->return@@State_hash.hash_bytes[h]inletopenLwt_syntaxinlet*state=Monad.runmstateinmatchstatewith|_,Somehash->returnhash|_->(* Hash computation always succeeds. *)assertfalseletboot=letopenMonad.Syntaxinlet*()=Status.createinlet*()=NextMessage.createinlet*()=Status.setWaitingForInputMessageinreturn()letresult_of~defaultmstate=letopenLwt_syntaxinlet*_,v=runmstateinmatchvwithNone->returndefault|Somev->returnvletstate_ofmstate=letopenLwt_syntaxinlet*s,_=runmstateinreturnsletget_tick=result_of~default:Sc_rollup_tick_repr.initialCurrentTick.getletis_input_state_monadic=letopenMonad.Syntaxinlet*status=Status.getinmatchstatuswith|WaitingForInputMessage->(let*level=CurrentLevel.getinlet*counter=MessageCounter.getinmatchcounterwith|Somen->return(PS.First_after(level,n))|None->returnPS.Initial)|_->returnPS.No_input_requiredletis_input_state=result_of~default:PS.No_input_required@@is_input_state_monadicletget_status=result_of~default:WaitingForInputMessage@@Status.getletget_code=result_of~default:[]@@Code.to_listletget_parsing_result=result_of~default:None@@ParsingResult.getletget_stack=result_of~default:[]@@Stack.to_listletget_varstatek=(result_of~default:None@@Vars.getk)stateletget_evaluation_result=result_of~default:None@@EvaluationResult.getletget_is_stuck=result_of~default:None@@is_stuckletset_input_monadicinput=letopenPSinlet{inbox_level;message_counter;payload}=inputinletopenMonad.Syntaxinlet*boot_sector=Boot_sector.getinletmsg=boot_sector^payloadinlet*()=CurrentLevel.setinbox_levelinlet*()=MessageCounter.set(Somemessage_counter)inlet*()=NextMessage.set(Somemsg)inreturn()letset_inputinput=state_of@@set_input_monadicinputletnext_char=letopenMonad.SyntaxinLexerState.(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=LexerState.getinlet*msg=NextMessage.getinmatchmsgwith|None->no_message_to_lex()|Somes->ifCompare.Int.(start+len<String.lengths)thenreturn(Somes.[start+len])elsereturnNoneletlexeme=letopenMonad.Syntaxinlet*start,len=LexerState.getinlet*msg=NextMessage.getinmatchmsgwith|None->no_message_to_lex()|Somes->let*()=LexerState.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_parsing:unitt=letopenMonad.Syntaxinlet*()=Status.setParsinginlet*()=ParsingResult.setNoneinlet*()=ParserState.setSkipLayoutinlet*()=LexerState.set(0,0)inlet*()=Status.setParsinginlet*()=Code.clearinreturn()letstart_evaluating:unitt=letopenMonad.Syntaxinlet*()=EvaluationResult.setNoneinlet*()=Stack.clearinlet*()=Status.setEvaluatinginreturn()letstop_parsingoutcome=letopenMonad.Syntaxinlet*()=ParsingResult.set(Someoutcome)instart_evaluatingletstop_evaluatingoutcome=letopenMonad.Syntaxinlet*()=EvaluationResult.set(Someoutcome)inStatus.setWaitingForInputMessageletparse:unitt=letopenMonad.Syntaxinletproduce_add=let*_=lexemeinlet*()=next_charinlet*()=Code.injectIAddinreturn()inletproduce_int=let*()=push_int_literalinlet*()=ParserState.setSkipLayoutinreturn()inletproduce_var=let*()=push_varinlet*()=ParserState.setSkipLayoutinreturn()inletis_digitd=Compare.Char.(d>='0'&&d<='9')inletis_letterd=Compare.Char.(d>='a'&&d<='z')inlet*parser_state=ParserState.getinmatchparser_statewith|ParseInt->(let*char=current_charinmatchcharwith|Somedwhenis_digitd->next_char|Some'+'->let*()=produce_intinlet*()=produce_addinreturn()|Some' '->let*()=produce_intinlet*()=next_charinreturn()|None->let*()=push_int_literalinstop_parsingtrue|_->stop_parsingfalse)|ParseVar->(let*char=current_charinmatchcharwith|Somedwhenis_letterd->next_char|Some'+'->let*()=produce_varinlet*()=produce_addinreturn()|Some' '->let*()=produce_varinlet*()=next_charinreturn()|None->let*()=push_varinstop_parsingtrue|_->stop_parsingfalse)|SkipLayout->(let*char=current_charinmatchcharwith|Some' '->next_char|Some'+'->produce_add|Somedwhenis_digitd->let*_=lexemeinlet*()=next_charinlet*()=ParserState.setParseIntinreturn()|Somedwhenis_letterd->let*_=lexemeinlet*()=next_charinlet*()=ParserState.setParseVarinreturn()|None->stop_parsingtrue|_->stop_parsingfalse)letoutputv=letopenMonad.SyntaxinletopenSc_rollup_outbox_message_reprinlet*counter=OutputCounter.getinlet*()=OutputCounter.set(Z.succcounter)inletunparsed_parameters=Micheline.(Int((),Z.of_intv)|>strip_locations)inletdestination=Contract_hash.zeroinletentrypoint=Entrypoint_repr.defaultinlettransaction={unparsed_parameters;destination;entrypoint}inletmessage=Atomic_transaction_batch{transactions=[transaction]}inlet*outbox_level=CurrentLevel.getinletoutput=Sc_rollup_PVM_sem.{outbox_level;message_index=counter;message}inOutput.set(Z.to_stringcounter)outputletevaluate=letopenMonad.Syntaxinlet*i=Code.popinmatchiwith|None->stop_evaluatingtrue|Some(IPushx)->Stack.pushx|Some(IStorex)->(let*v=Stack.topinmatchvwith|None->stop_evaluatingfalse|Somev->ifCompare.String.(x="out")thenoutputvelseVars.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.setWaitingForInputMessageinlet*()=Stack.clearinlet*()=Code.clearinreturn()leteval_step=letopenMonad.Syntaxinlet*x=is_stuckinmatchxwith|Some_->reboot|None->(let*status=Status.getinmatchstatuswith|Halted->boot|WaitingForInputMessage->(let*msg=NextMessage.getinmatchmsgwith|None->internal_error"An input state was not provided an input message."|Some_->start_parsing)|Parsing->parse|Evaluating->evaluate)lettickedm=letopenMonad.Syntaxinlet*tick=CurrentTick.getinlet*()=CurrentTick.set(Sc_rollup_tick_repr.nexttick)inmletevalstate=state_of(tickedeval_step)stateletstep_transitioninput_givenstate=letopenLwt_syntaxinlet*request=is_input_statestateinlet*state=matchrequestwith|PS.No_input_required->evalstate|_->(matchinput_givenwith|Someinput->set_inputinputstate|None->returnstate)inreturn(state,request)letverify_proofproof=letopenLwt_syntaxinlet*result=Context.verify_proofproof.tree_proof(step_transitionproof.given)inmatchresultwith|None->returnfalse|Some(_,request)->return(PS.input_request_equalrequestproof.requested)typeerror+=Arith_proof_production_failedletproduce_proofcontextinput_givenstate=letopenLwt_result_syntaxinlet*!result=Context.produce_proofcontextstate(step_transitioninput_given)inmatchresultwith|Some(tree_proof,requested)->return{tree_proof;given=input_given;requested}|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_->returntruetypeerror+=Arith_output_proof_production_failedtypeerror+=Arith_invalid_claim_about_outboxletproduce_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_failedendmoduleProtocolImplementation=Make(structmoduleTree=structincludeContext.Treetypetree=Context.treetypet=Context.ttypekey=stringlisttypevalue=bytesendtypetree=Context.treetypeproof=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.hash_bytes[Context_hash.to_byteshash]letproof_beforeproof=kinded_hash_to_state_hashproof.Context.Proof.beforeletproof_afterproof=kinded_hash_to_state_hashproof.Context.Proof.afterletproof_encoding=Context.Proof_encoding.V1.Tree32.tree_proof_encodingend)