1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Nomadic Development. <contact@tezcore.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. *)(* *)(*****************************************************************************)openProtocolopenAlpha_context(** The assumed number of blocks between operation-creation time and
the actual time when the operation is included in a block. *)letdefault_operation_inclusion_latency=3typeEnvironment.Error_monad.error+=Cannot_parse_operation(* `Branch *)typeEnvironment.Error_monad.error+=Cannot_serialize_loglet()=Environment.Error_monad.register_error_kind`Branch~id:"operation.cannot_parse"~title:"Cannot parse operation"~description:"The operation is ill-formed or for another protocol version"~pp:(funppf()->Format.fprintfppf"The operation cannot be parsed")Data_encoding.unit(functionCannot_parse_operation->Some()|_->None)(fun()->Cannot_parse_operation);(* Cannot serialize log *)Environment.Error_monad.register_error_kind`Temporary~id:"michelson_v1.cannot_serialize_log"~title:"Not enough gas to serialize execution trace"~description:"Execution trace with stacks was to big to be serialized with the \
provided gas"Data_encoding.empty(functionCannot_serialize_log->Some()|_->None)(fun()->Cannot_serialize_log)moduleView_helpers=structopenTezos_michelinetypeEnvironment.Error_monad.error+=Viewed_contract_has_no_scripttypeEnvironment.Error_monad.error+=View_callback_origination_failedtypeEnvironment.Error_monad.error+=|Illformed_view_typeofstring*Script.exprtypeEnvironment.Error_monad.error+=|View_never_returnsofstring*Contract.ttypeEnvironment.Error_monad.error+=|View_unexpected_returnofstring*Contract.tlet()=Environment.Error_monad.register_error_kind`Permanent~id:"viewedContractHasNoScript"~title:"Viewed contract has no script"~description:"A view was called on a contract with no script."~pp:(funppf()->Format.fprintfppf"A view was called on a contract with no script.")Data_encoding.(unit)(functionViewed_contract_has_no_script->Some()|_->None)(fun()->Viewed_contract_has_no_script);Environment.Error_monad.register_error_kind`Permanent~id:"viewCallbackOriginationFailed"~title:"View callback origination failed"~description:"View callback origination failed"~pp:(funppf()->Format.fprintfppf"Error during origination of view callback contract.")Data_encoding.(unit)(functionView_callback_origination_failed->Some()|_->None)(fun()->View_callback_origination_failed);Environment.Error_monad.register_error_kind`Permanent~id:"illformedViewType"~title:"An entrypoint type is incompatible with TZIP-4 view type."~description:"An entrypoint type is incompatible with TZIP-4 view type."~pp:(funppf(entrypoint,typ)->Format.fprintfppf"The view %s has type %a, it is not compatible with a TZIP-4 view \
type."entrypointMicheline_printer.print_expr(Micheline_printer.printable(funx->x)(Michelson_v1_primitives.strings_of_primstyp)))Data_encoding.(obj2(req"entrypoint"string)(req"type"Script.expr_encoding))(functionIllformed_view_type(etp,exp)->Some(etp,exp)|_->None)(fun(etp,exp)->Illformed_view_type(etp,exp));Environment.Error_monad.register_error_kind`Permanent~id:"viewNeverReturns"~title:"A view never returned a transaction to the given callback contract"~description:"A view never initiated a transaction to the given callback contract."~pp:(funppf(entrypoint,callback)->Format.fprintfppf"The view %s never initiated a transaction to the given callback \
contract %a."entrypointContract.ppcallback)Data_encoding.(obj2(req"entrypoint"string)(req"callback"Contract.encoding))(functionView_never_returns(e,c)->Some(e,c)|_->None)(fun(e,c)->View_never_returns(e,c));Environment.Error_monad.register_error_kind`Permanent~id:"viewUnexpectedReturn"~title:"A view returned an unexpected list of operations"~description:"A view initiated a list of operations while the TZIP-4 standard \
expects only a transaction to the given callback contract."~pp:(funppf(entrypoint,callback)->Format.fprintfppf"The view %s initiated a list of operations while the TZIP-4 \
standard expects only a transaction to the given callback contract \
%a."entrypointContract.ppcallback)Data_encoding.(obj2(req"entrypoint"string)(req"callback"Contract.encoding))(functionView_never_returns(e,c)->Some(e,c)|_->None)(fun(e,c)->View_never_returns(e,c))(* This script is actually never run, its usage is to ensure a
contract that has the type `contract <ty>` is originated, which
will be required as callback of the view. *)letmake_viewer_scriptty:Script.t=letloc=0inletty=Micheline.roottyinletcode=Micheline.strip_locations@@Micheline.Seq(loc,[Micheline.Prim(loc,Script.K_parameter,[ty],[]);Micheline.Prim(loc,Script.K_storage,[Micheline.Prim(loc,Script.T_unit,[],[])],[]);Micheline.Prim(loc,Script.K_code,[Micheline.Prim(loc,Script.I_FAILWITH,[],[])],[]);])inletstorage=Micheline.strip_locations(Micheline.Prim(loc,Script.D_Unit,[],[]))in{code=Script.lazy_exprcode;storage=Script.lazy_exprstorage}letmake_view_parameterinputcallback=letloc=0inMicheline.strip_locations(Micheline.Prim(loc,Script.D_Pair,[input;Micheline.Bytes(loc,Data_encoding.Binary.to_bytes_exnContract.encodingcallback);],[]))letextract_view_output_typeentrypointty=matchMicheline.roottywith|Micheline.Prim(_,Script.T_pair,[_;Micheline.Prim(_,Script.T_contract,[ty],_)],_)->ok(Micheline.strip_locationsty)|_->Environment.Error_monad.error(Illformed_view_type(entrypoint,ty))(* 'view' entrypoints returns their value by calling a callback contract, thus
the expected result is a unique internal transaction to this callback. *)letextract_parameter_from_operationsentrypointoperationscallback=letunexpected_return=Environment.Error_monad.error@@View_unexpected_return(entrypoint,callback)inmatchoperationswith|[Internal_operation{operation=Transaction{destination;parameters;_};_};]whenContract.equaldestinationcallback->okparameters|[]->Environment.Error_monad.error(View_never_returns(entrypoint,callback))|_->unexpected_returnendmoduleRPC=structopenEnvironmentopenAlpha_contextopenEnvironment.Error_monadletparse_operation(op:Operation.raw)=matchData_encoding.Binary.of_bytes_optOperation.protocol_data_encodingop.protowith|Someprotocol_data->ok{shell=op.shell;protocol_data}|None->errorCannot_parse_operationletpath=RPC_path.(open_root/"helpers")moduleRegistration=structletpatched_services=ref(RPC_directory.empty:Updater.rpc_contextRPC_directory.t)letregister0_fullctxt~chunkedsf=patched_services:=RPC_directory.register~chunked!patched_servicess(functxtqi->Services_registration.rpc_initctxt>>=?functxt->fctxtqi)letregister0~chunkedsf=register0_fullctxt~chunkeds(fun{context;_}->fcontext)letregister0_noctxt~chunkedsf=patched_services:=RPC_directory.register~chunked!patched_servicess(fun_qi->fqi)letopt_register0_fullctxt~chunkedsf=patched_services:=RPC_directory.opt_register~chunked!patched_servicess(functxtqi->Services_registration.rpc_initctxt>>=?functxt->fctxtqi)letopt_register0~chunkedsf=opt_register0_fullctxt~chunkeds(fun{context;_}->fcontext)letregister1_fullctxt~chunkedsf=patched_services:=RPC_directory.register~chunked!patched_servicess(fun(ctxt,arg)qi->Services_registration.rpc_initctxt>>=?functxt->fctxtargqi)letregister1~chunkedsf=register1_fullctxt~chunkeds(fun{context;_}x->fcontextx)letregister2_fullctxt~chunkedsf=patched_services:=RPC_directory.register~chunked!patched_servicess(fun((ctxt,arg1),arg2)qi->Services_registration.rpc_initctxt>>=?functxt->fctxtarg1arg2qi)letregister2~chunkedsf=register2_fullctxt~chunkeds(fun{context;_}a1a2qi->fcontexta1a2qi)endletunparsing_mode_encoding=letopenScript_ir_translatorinletopenData_encodinginunion~tag_size:`Uint8[case(Tag0)~title:"Readable"(constant"Readable")(function|Readable->Some()|Optimized|Optimized_legacy->None)(fun()->Readable);case(Tag1)~title:"Optimized"(constant"Optimized")(function|Optimized->Some()|Readable|Optimized_legacy->None)(fun()->Optimized);case(Tag2)~title:"Optimized_legacy"(constant"Optimized_legacy")(function|Optimized_legacy->Some()|Readable|Optimized->None)(fun()->Optimized_legacy);]moduleScripts=structmoduleS=structopenData_encodingletpath=RPC_path.(path/"scripts")letrun_code_input_encoding=merge_objs(obj10(req"script"Script.expr_encoding)(req"storage"Script.expr_encoding)(req"input"Script.expr_encoding)(req"amount"Tez.encoding)(req"balance"Tez.encoding)(req"chain_id"Chain_id.encoding)(opt"source"Contract.encoding)(opt"payer"Contract.encoding)(opt"gas"Gas.Arith.z_integral_encoding)(dft"entrypoint"string"default"))(obj1(opt"unparsing_mode"unparsing_mode_encoding))letrun_code_output_encoding=conv(fun(storage,operations,lazy_storage_diff)->(storage,operations,lazy_storage_diff,lazy_storage_diff))(fun(storage,operations,legacy_lazy_storage_diff,lazy_storage_diff)->letlazy_storage_diff=Option.eitherlazy_storage_difflegacy_lazy_storage_diffin(storage,operations,lazy_storage_diff))(obj4(req"storage"Script.expr_encoding)(req"operations"(listOperation.internal_operation_encoding))(opt"big_map_diff"Lazy_storage.legacy_big_map_diff_encoding)(opt"lazy_storage_diff"Lazy_storage.encoding))lettrace_code_input_encoding=run_code_input_encodinglettrace_encoding=def"scripted.trace"@@list@@obj3(req"location"Script.location_encoding)(req"gas"Gas.encoding)(req"stack"(list(obj2(req"item"Script.expr_encoding)(opt"annot"string))))lettrace_code_output_encoding=conv(fun(storage,operations,trace,lazy_storage_diff)->(storage,operations,trace,lazy_storage_diff,lazy_storage_diff))(fun(storage,operations,trace,legacy_lazy_storage_diff,lazy_storage_diff)->letlazy_storage_diff=Option.eitherlazy_storage_difflegacy_lazy_storage_diffin(storage,operations,trace,lazy_storage_diff))(obj5(req"storage"Script.expr_encoding)(req"operations"(listOperation.internal_operation_encoding))(req"trace"trace_encoding)(opt"big_map_diff"Lazy_storage.legacy_big_map_diff_encoding)(opt"lazy_storage_diff"Lazy_storage.encoding))letrun_view_encoding=letopenData_encodinginobj8(req"contract"Contract.encoding)(req"entrypoint"string)(req"input"Script.expr_encoding)(req"chain_id"Chain_id.encoding)(opt"source"Contract.encoding)(opt"payer"Contract.encoding)(opt"gas"Gas.Arith.z_integral_encoding)(req"unparsing_mode"unparsing_mode_encoding)letrun_code=RPC_service.post_service~description:"Run a piece of code in the current context"~query:RPC_query.empty~input:run_code_input_encoding~output:run_code_output_encodingRPC_path.(path/"run_code")lettrace_code=RPC_service.post_service~description:"Run a piece of code in the current context, keeping a trace"~query:RPC_query.empty~input:trace_code_input_encoding~output:trace_code_output_encodingRPC_path.(path/"trace_code")letrun_view=RPC_service.post_service~description:"Simulate a call to a view following the TZIP-4 standard. See \
https://gitlab.com/tzip/tzip/-/blob/master/proposals/tzip-4/tzip-4.md#view-entrypoints."~input:run_view_encoding~output:(obj1(req"data"Script.expr_encoding))~query:RPC_query.emptyRPC_path.(path/"run_view")lettypecheck_code=RPC_service.post_service~description:"Typecheck a piece of code in the current context"~query:RPC_query.empty~input:(obj3(req"program"Script.expr_encoding)(opt"gas"Gas.Arith.z_integral_encoding)(opt"legacy"bool))~output:(obj2(req"type_map"Script_tc_errors_registration.type_map_enc)(req"gas"Gas.encoding))RPC_path.(path/"typecheck_code")letscript_size=RPC_service.post_service~description:"Compute the size of a script in the current context"~query:RPC_query.empty~input:(obj4(req"program"Script.expr_encoding)(req"storage"Script.expr_encoding)(opt"gas"Gas.Arith.z_integral_encoding)(opt"legacy"bool))~output:(obj1(req"script_size"int31))RPC_path.(path/"script_size")lettypecheck_data=RPC_service.post_service~description:"Check that some data expression is well formed and of a given \
type in the current context"~query:RPC_query.empty~input:(obj4(req"data"Script.expr_encoding)(req"type"Script.expr_encoding)(opt"gas"Gas.Arith.z_integral_encoding)(opt"legacy"bool))~output:(obj1(req"gas"Gas.encoding))RPC_path.(path/"typecheck_data")letpack_data=RPC_service.post_service~description:"Computes the serialized version of some data expression using the \
same algorithm as script instruction PACK"~input:(obj3(req"data"Script.expr_encoding)(req"type"Script.expr_encoding)(opt"gas"Gas.Arith.z_integral_encoding))~output:(obj2(req"packed"bytes)(req"gas"Gas.encoding))~query:RPC_query.emptyRPC_path.(path/"pack_data")letnormalize_data=RPC_service.post_service~description:"Normalizes some data expression using the requested unparsing mode"~input:(obj4(req"data"Script.expr_encoding)(req"type"Script.expr_encoding)(req"unparsing_mode"unparsing_mode_encoding)(opt"legacy"bool))~output:(obj1(req"normalized"Script.expr_encoding))~query:RPC_query.emptyRPC_path.(path/"normalize_data")letnormalize_script=RPC_service.post_service~description:"Normalizes a Michelson script using the requested unparsing mode"~input:(obj2(req"script"Script.expr_encoding)(req"unparsing_mode"unparsing_mode_encoding))~output:(obj1(req"normalized"Script.expr_encoding))~query:RPC_query.emptyRPC_path.(path/"normalize_script")letnormalize_type=RPC_service.post_service~description:"Normalizes some Michelson type by expanding `pair a b c` as `pair \
a (pair b c)"~input:(obj1(req"type"Script.expr_encoding))~output:(obj1(req"normalized"Script.expr_encoding))~query:RPC_query.emptyRPC_path.(path/"normalize_type")letrun_operation=RPC_service.post_service~description:"Run an operation without signature checks"~query:RPC_query.empty~input:(obj2(req"operation"Operation.encoding)(req"chain_id"Chain_id.encoding))~output:Apply_results.operation_data_and_metadata_encodingRPC_path.(path/"run_operation")letsimulate_operation=RPC_service.post_service~description:"Simulate an operation"~query:RPC_query.empty~input:(obj3(req"operation"Operation.encoding)(req"chain_id"Chain_id.encoding)(dft"latency"int16default_operation_inclusion_latency))~output:Apply_results.operation_data_and_metadata_encodingRPC_path.(path/"simulate_operation")letentrypoint_type=RPC_service.post_service~description:"Return the type of the given entrypoint"~query:RPC_query.empty~input:(obj2(req"script"Script.expr_encoding)(dft"entrypoint"string"default"))~output:(obj1(req"entrypoint_type"Script.expr_encoding))RPC_path.(path/"entrypoint")letlist_entrypoints=RPC_service.post_service~description:"Return the list of entrypoints of the given script"~query:RPC_query.empty~input:(obj1(req"script"Script.expr_encoding))~output:(obj2(dft"unreachable"(Data_encoding.list(obj1(req"path"(Data_encoding.listMichelson_v1_primitives.prim_encoding))))[])(req"entrypoints"(assocScript.expr_encoding)))RPC_path.(path/"entrypoints")endmoduletypeUNPARSING_MODE=sigvalunparsing_mode:Script_ir_translator.unparsing_modeendmoduleTraced_interpreter(Unparsing_mode:UNPARSING_MODE)=structtypelog_element=|Log:context*Script.location*('a*'s)*('a,'s)Script_typed_ir.stack_ty->log_elementletunparse_stackctxt(stack,stack_ty)=(* We drop the gas limit as this function is only used for debugging/errors. *)letctxt=Gas.set_unlimitedctxtinletrecunparse_stack:typeas.(a,s)Script_typed_ir.stack_ty*(a*s)->(Script.expr*stringoption)listtzresultLwt.t=function|Bot_t,(EmptyCell,EmptyCell)->return_nil|Item_t(ty,rest_ty,annot),(v,rest)->Script_ir_translator.unparse_datactxtUnparsing_mode.unparsing_modetyv>>=?fun(data,_ctxt)->unparse_stack(rest_ty,rest)>|=?funrest->letannot=matchScript_ir_annot.unparse_var_annotannotwith|[]->None|[a]->Somea|_->assertfalseinletdata=Micheline.strip_locationsdatain(data,annot)::restinunparse_stack(stack_ty,stack)lettrace_logger():Script_typed_ir.logger=letlog:log_elementlistref=ref[]inletlog_interp_ctxtlocstystack=log:=Log(ctxt,loc,stack,sty)::!loginletlog_entry__ctxt_loc_sty_stack=()inletlog_exit_ctxtlocstystack=log:=Log(ctxt,loc,stack,sty)::!loginletlog_control_=()inletget_log()=List.map_es(fun(Log(ctxt,loc,stack,stack_ty))->traceCannot_serialize_log(unparse_stackctxt(stack,stack_ty))>>=?funstack->return(loc,Gas.levelctxt,stack))!log>>=?funres->return(Some(List.revres))in{log_exit;log_entry;log_interp;get_log;log_control}letexecutectxtstep_constants~script~entrypoint~parameter=letopenScript_interpreterinletlogger=trace_logger()inexecute~logger~cached_script:NonectxtUnparsing_mode.unparsing_modestep_constants~script~entrypoint~parameter~internal:true>>=?fun({ctxt;storage;lazy_storage_diff;operations},_)->logger.get_log()>|=?funtrace->lettrace=Option.value~default:[]tracein({ctxt;storage;lazy_storage_diff;operations},trace)endlettypecheck_data:legacy:bool->context->Script.expr*Script.expr->contexttzresultLwt.t=fun~legacyctxt(data,exp_ty)->record_trace(Script_tc_errors.Ill_formed_type(None,exp_ty,0))(Script_ir_translator.parse_parameter_tyctxt~legacy(Micheline.rootexp_ty))>>?=fun(Ex_tyexp_ty,ctxt)->trace_eval(fun()->Lwt.return(Script_ir_translator.serialize_ty_for_errorctxtexp_ty>|?fun(exp_ty,_ctxt)->Script_tc_errors.Ill_typed_data(None,data,exp_ty)))(letallow_forged=true(* Safe since we ignore the value afterwards. *)inScript_ir_translator.parse_datactxt~legacy~allow_forgedexp_ty(Micheline.rootdata))>|=?fun(_,ctxt)->ctxtmoduleUnparse_types=struct(* Same as the unparsing functions for types in Script_ir_translator but
does not consume gas and never folds (pair a (pair b c)) *)openScript_ir_translatoropenMichelineopenMichelson_v1_primitivesopenScript_ir_annotopenScript_typed_irletrecunparse_comparable_ty:typea.acomparable_ty->Script.node=function|Unit_keymeta->Prim(-1,T_unit,[],unparse_type_annotmeta.annot)|Never_keymeta->Prim(-1,T_never,[],unparse_type_annotmeta.annot)|Int_keymeta->Prim(-1,T_int,[],unparse_type_annotmeta.annot)|Nat_keymeta->Prim(-1,T_nat,[],unparse_type_annotmeta.annot)|Signature_keymeta->Prim(-1,T_signature,[],unparse_type_annotmeta.annot)|String_keymeta->Prim(-1,T_string,[],unparse_type_annotmeta.annot)|Bytes_keymeta->Prim(-1,T_bytes,[],unparse_type_annotmeta.annot)|Mutez_keymeta->Prim(-1,T_mutez,[],unparse_type_annotmeta.annot)|Bool_keymeta->Prim(-1,T_bool,[],unparse_type_annotmeta.annot)|Key_hash_keymeta->Prim(-1,T_key_hash,[],unparse_type_annotmeta.annot)|Key_keymeta->Prim(-1,T_key,[],unparse_type_annotmeta.annot)|Timestamp_keymeta->Prim(-1,T_timestamp,[],unparse_type_annotmeta.annot)|Address_keymeta->Prim(-1,T_address,[],unparse_type_annotmeta.annot)|Chain_id_keymeta->Prim(-1,T_chain_id,[],unparse_type_annotmeta.annot)|Pair_key((l,al),(r,ar),meta)->lettl=add_field_annotalNone(unparse_comparable_tyl)inlettr=add_field_annotarNone(unparse_comparable_tyr)inPrim(-1,T_pair,[tl;tr],unparse_type_annotmeta.annot)|Union_key((l,al),(r,ar),meta)->lettl=add_field_annotalNone(unparse_comparable_tyl)inlettr=add_field_annotarNone(unparse_comparable_tyr)inPrim(-1,T_or,[tl;tr],unparse_type_annotmeta.annot)|Option_key(t,meta)->Prim(-1,T_option,[unparse_comparable_tyt],unparse_type_annotmeta.annot)letunparse_memo_sizememo_size=letz=Alpha_context.Sapling.Memo_size.unparse_to_zmemo_sizeinInt(-1,z)letrecunparse_ty:typea.aty->Script.node=funty->letreturn(name,args,annot)=Prim(-1,name,args,annot)inmatchtywith|Unit_tmeta->return(T_unit,[],unparse_type_annotmeta.annot)|Int_tmeta->return(T_int,[],unparse_type_annotmeta.annot)|Nat_tmeta->return(T_nat,[],unparse_type_annotmeta.annot)|Signature_tmeta->return(T_signature,[],unparse_type_annotmeta.annot)|String_tmeta->return(T_string,[],unparse_type_annotmeta.annot)|Bytes_tmeta->return(T_bytes,[],unparse_type_annotmeta.annot)|Mutez_tmeta->return(T_mutez,[],unparse_type_annotmeta.annot)|Bool_tmeta->return(T_bool,[],unparse_type_annotmeta.annot)|Key_hash_tmeta->return(T_key_hash,[],unparse_type_annotmeta.annot)|Key_tmeta->return(T_key,[],unparse_type_annotmeta.annot)|Timestamp_tmeta->return(T_timestamp,[],unparse_type_annotmeta.annot)|Address_tmeta->return(T_address,[],unparse_type_annotmeta.annot)|Operation_tmeta->return(T_operation,[],unparse_type_annotmeta.annot)|Chain_id_tmeta->return(T_chain_id,[],unparse_type_annotmeta.annot)|Never_tmeta->return(T_never,[],unparse_type_annotmeta.annot)|Bls12_381_g1_tmeta->return(T_bls12_381_g1,[],unparse_type_annotmeta.annot)|Bls12_381_g2_tmeta->return(T_bls12_381_g2,[],unparse_type_annotmeta.annot)|Bls12_381_fr_tmeta->return(T_bls12_381_fr,[],unparse_type_annotmeta.annot)|Contract_t(ut,meta)->lett=unparse_tyutinreturn(T_contract,[t],unparse_type_annotmeta.annot)|Pair_t((utl,l_field,l_var),(utr,r_field,r_var),meta)->letannot=unparse_type_annotmeta.annotinletutl=unparse_tyutlinlettl=add_field_annotl_fieldl_varutlinletutr=unparse_tyutrinlettr=add_field_annotr_fieldr_varutrinreturn(T_pair,[tl;tr],annot)|Union_t((utl,l_field),(utr,r_field),meta)->letannot=unparse_type_annotmeta.annotinletutl=unparse_tyutlinlettl=add_field_annotl_fieldNoneutlinletutr=unparse_tyutrinlettr=add_field_annotr_fieldNoneutrinreturn(T_or,[tl;tr],annot)|Lambda_t(uta,utr,meta)->letta=unparse_tyutainlettr=unparse_tyutrinreturn(T_lambda,[ta;tr],unparse_type_annotmeta.annot)|Option_t(ut,meta)->letannot=unparse_type_annotmeta.annotinletut=unparse_tyutinreturn(T_option,[ut],annot)|List_t(ut,meta)->lett=unparse_tyutinreturn(T_list,[t],unparse_type_annotmeta.annot)|Ticket_t(ut,meta)->lett=unparse_comparable_tyutinreturn(T_ticket,[t],unparse_type_annotmeta.annot)|Set_t(ut,meta)->lett=unparse_comparable_tyutinreturn(T_set,[t],unparse_type_annotmeta.annot)|Map_t(uta,utr,meta)->letta=unparse_comparable_tyutainlettr=unparse_tyutrinreturn(T_map,[ta;tr],unparse_type_annotmeta.annot)|Big_map_t(uta,utr,meta)->letta=unparse_comparable_tyutainlettr=unparse_tyutrinreturn(T_big_map,[ta;tr],unparse_type_annotmeta.annot)|Sapling_transaction_t(memo_size,meta)->return(T_sapling_transaction,[unparse_memo_sizememo_size],unparse_type_annotmeta.annot)|Sapling_state_t(memo_size,meta)->return(T_sapling_state,[unparse_memo_sizememo_size],unparse_type_annotmeta.annot)|Chest_tmeta->return(T_chest,[],unparse_type_annotmeta.annot)|Chest_key_tmeta->return(T_chest_key,[],unparse_type_annotmeta.annot)endletrun_operation_servicectxt()({shell;protocol_data=Operation_dataprotocol_data},chain_id)=(* this code is a duplicate of Apply without signature check *)letpartial_precheck_manager_contents(typekind)ctxt(op:kindKind.managercontents):contexttzresultLwt.t=let(Manager_operation{source;fee;counter;operation;gas_limit;storage_limit})=opinGas.consume_limit_in_blockctxtgas_limit>>?=functxt->letctxt=Gas.set_limitctxtgas_limitinFees.check_storage_limitctxt~storage_limit>>?=fun()->Contract.must_be_allocatedctxt(Contract.implicit_contractsource)>>=?fun()->Contract.check_counter_incrementctxtsourcecounter>>=?fun()->(matchoperationwith|Revealpk->Contract.reveal_manager_keyctxtsourcepk|Transaction{parameters;_}->(* Here the data comes already deserialized, so we need to fake the deserialization to mimic apply *)letarg_bytes=Data_encoding.Binary.to_bytes_exnScript.lazy_expr_encodingparametersinletarg=matchData_encoding.Binary.of_bytes_optScript.lazy_expr_encodingarg_byteswith|Somearg->arg|None->assertfalseinLwt.return@@record_traceApply.Gas_quota_exceeded_init_deserialize@@(* Fail if not enough gas for complete deserialization cost *)(Script.force_decode_in_contextctxtarg>|?fun(_arg,ctxt)->ctxt)|Origination{script;_}->(* Here the data comes already deserialized, so we need to fake the deserialization to mimic apply *)letscript_bytes=Data_encoding.Binary.to_bytes_exnScript.encodingscriptinletscript=matchData_encoding.Binary.of_bytes_optScript.encodingscript_byteswith|Somescript->script|None->assertfalseinLwt.return@@record_traceApply.Gas_quota_exceeded_init_deserialize@@(* Fail if not enough gas for complete deserialization cost *)(Script.force_decode_in_contextctxtscript.code>>?fun(_code,ctxt)->Script.force_decode_in_contextctxtscript.storage>|?fun(_storage,ctxt)->ctxt)|_->returnctxt)>>=?functxt->Contract.get_manager_keyctxtsource>>=?fun_public_key->(* signature check unplugged from here *)Contract.increment_counterctxtsource>>=?functxt->Contract.spendctxt(Contract.implicit_contractsource)feeinletrecpartial_precheck_manager_contents_list:typekind.Alpha_context.t->kindKind.managercontents_list->contexttzresultLwt.t=functxtcontents_list->matchcontents_listwith|Single(Manager_operation_asop)->partial_precheck_manager_contentsctxtop|Cons((Manager_operation_asop),rest)->partial_precheck_manager_contentsctxtop>>=?functxt->partial_precheck_manager_contents_listctxtrestinletretcontents=(Operation_dataprotocol_data,Apply_results.Operation_metadata{contents})inletoperation:_operation={shell;protocol_data}inlethash=Operation.hash{shell;protocol_data}inletctxt=Contract.init_origination_noncectxthashinletbaker=Tezos_crypto.Signature.V0.Public_key_hash.zeroinmatchprotocol_data.contentswith|Single(Manager_operation_)asop->partial_precheck_manager_contents_listctxtop>>=?functxt->Apply.apply_manager_contents_listctxtOptimizedbakerchain_idop>|=fun(_ctxt,result)->ok@@retresult|Cons(Manager_operation_,_)asop->partial_precheck_manager_contents_listctxtop>>=?functxt->Apply.apply_manager_contents_listctxtOptimizedbakerchain_idop>|=fun(_ctxt,result)->ok@@retresult|_->Apply.apply_contents_listctxtchain_idOptimizedshell.branchbakeroperationoperation.protocol_data.contents>|=?fun(_ctxt,result)->retresult(*
The execution of an operation depends on the state of the
cache. In particular, gas consumption is usually impacted by
cache hits and misses.
Unfortunately, the state of the cache is different between the
context at operation-creation time and the context when is
included in a block.
Therefore, the simulation tries to predict the state of the
cache in a [time_in_blocks] assumed to be close to the inclusion
time of the operation.
*)letsimulate_operation_servicectxt()(op,chain_id,time_in_blocks)=letctxt=Cache.Admin.future_cache_expectationctxt~time_in_blocksinrun_operation_servicectxt()(op,chain_id)letregister()=letoriginate_dummy_contractctxtscriptbalance=letctxt=Contract.init_origination_noncectxtOperation_hash.zeroinLwt.return(Contract.fresh_contract_from_current_noncectxt)>>=?fun(ctxt,dummy_contract)->Contract.originatectxtdummy_contract~balance~delegate:None~script:(script,None)>>=?functxt->return(ctxt,dummy_contract)inletscript_entrypoint_typectxtexprentrypoint=letctxt=Gas.set_unlimitedctxtinletlegacy=falseinletopenScript_ir_translatorinparse_toplevelctxt~legacyexpr>>=?fun({arg_type;root_name;_},ctxt)->Lwt.return((parse_parameter_tyctxt~legacyarg_type>>?fun(Ex_tyarg_type,_)->Script_ir_translator.find_entrypoint~root_namearg_typeentrypoint)>>?fun(_f,Ex_tyty)->unparse_tyctxtty>|?fun(ty_node,_)->Micheline.strip_locationsty_node)inRegistration.register0~chunked:trueS.run_code(functxt()((code,storage,parameter,amount,balance,chain_id,source,payer,gas,entrypoint),unparsing_mode)->letunparsing_mode=Option.value~default:Readableunparsing_modeinletstorage=Script.lazy_exprstorageinletcode=Script.lazy_exprcodeinoriginate_dummy_contractctxt{storage;code}balance>>=?fun(ctxt,dummy_contract)->letsource,payer=match(source,payer)with|Somesource,Somepayer->(source,payer)|Somesource,None->(source,source)|None,Somepayer->(payer,payer)|None,None->(dummy_contract,dummy_contract)inletgas=matchgaswith|Somegas->gas|None->Constants.hard_gas_limit_per_operationctxtinletctxt=Gas.set_limitctxtgasinletstep_constants=letopenScript_interpreterin{source;payer;self=dummy_contract;amount;chain_id}inScript_interpreter.executectxtunparsing_modestep_constants~cached_script:None~script:{storage;code}~entrypoint~parameter~internal:true>|=?fun({Script_interpreter.storage;operations;lazy_storage_diff;_;},_)->(storage,operations,lazy_storage_diff));Registration.register0~chunked:trueS.trace_code(functxt()((code,storage,parameter,amount,balance,chain_id,source,payer,gas,entrypoint),unparsing_mode)->letunparsing_mode=Option.value~default:Readableunparsing_modeinletstorage=Script.lazy_exprstorageinletcode=Script.lazy_exprcodeinoriginate_dummy_contractctxt{storage;code}balance>>=?fun(ctxt,dummy_contract)->letsource,payer=match(source,payer)with|Somesource,Somepayer->(source,payer)|Somesource,None->(source,source)|None,Somepayer->(payer,payer)|None,None->(dummy_contract,dummy_contract)inletgas=matchgaswith|Somegas->gas|None->Constants.hard_gas_limit_per_operationctxtinletctxt=Gas.set_limitctxtgasinletstep_constants=letopenScript_interpreterin{source;payer;self=dummy_contract;amount;chain_id}inletmoduleUnparsing_mode=structletunparsing_mode=unparsing_modeendinletmoduleInterp=Traced_interpreter(Unparsing_mode)inInterp.executectxtstep_constants~script:{storage;code}~entrypoint~parameter>|=?fun({Script_interpreter.storage;operations;lazy_storage_diff;_;},trace)->(storage,operations,trace,lazy_storage_diff));Registration.register0~chunked:trueS.run_view(functxt()(contract,entrypoint,input,chain_id,source,payer,gas,unparsing_mode)->Contract.get_scriptctxtcontract>>=?fun(ctxt,script_opt)->Option.fold~some:ok~none:(Error_monad.errorView_helpers.Viewed_contract_has_no_script)script_opt>>?=funscript->Script_repr.(force_decodescript.code)>>?=fundecoded_script->script_entrypoint_typectxtdecoded_scriptentrypoint>>=?funview_ty->View_helpers.extract_view_output_typeentrypointview_ty>>?=funty->Error_monad.traceView_helpers.View_callback_origination_failed@@originate_dummy_contractctxt(View_helpers.make_viewer_scriptty)Tez.zero>>=?fun(ctxt,viewer_contract)->letsource,payer=match(source,payer)with|Somesource,Somepayer->(source,payer)|Somesource,None->(source,source)|None,Somepayer->(payer,payer)|None,None->(contract,contract)inletgas=Option.value~default:(Constants.hard_gas_limit_per_operationctxt)gasinletctxt=Gas.set_limitctxtgasinletstep_constants=letopenScript_interpreterin{source;payer;self=contract;amount=Tez.zero;chain_id}inletparameter=View_helpers.make_view_parameter(Micheline.rootinput)viewer_contractinScript_interpreter.executectxtunparsing_modestep_constants~script~cached_script:None~entrypoint~parameter~internal:true>>=?fun({Script_interpreter.operations;_},(_,_))->View_helpers.extract_parameter_from_operationsentrypointoperationsviewer_contract>>?=funparameter->Lwt.return(Script_repr.force_decodeparameter));Registration.register0~chunked:falseS.typecheck_code(functxt()(expr,maybe_gas,legacy)->letlegacy=Option.value~default:falselegacyinletctxt=matchmaybe_gaswith|None->Gas.set_unlimitedctxt|Somegas->Gas.set_limitctxtgasinScript_ir_translator.typecheck_code~legacyctxtexpr>|=?fun(res,ctxt)->(res,Gas.levelctxt));Registration.register0~chunked:falseS.script_size(functxt()(expr,storage,maybe_gas,legacy)->letlegacy=Option.value~default:falselegacyinletctxt=matchmaybe_gaswith|None->Gas.set_unlimitedctxt|Somegas->Gas.set_limitctxtgasinletcode=Script.lazy_exprexprinScript_ir_translator.parse_code~legacyctxt~code>>=?fun(Ex_code{code;arg_type;storage_type;views;root_name;code_size;},ctxt)->Script_ir_translator.parse_data~legacy~allow_forged:truectxtstorage_type(Micheline.rootstorage)>>=?fun(storage,_)->letscript=Script_ir_translator.Ex_script{code;arg_type;storage_type;views;root_name;code_size;storage;}inletsize,cost=Script_ir_translator.script_sizescriptinGas.consumectxtcost>>?=fun_ctxt->return@@size);Registration.register0~chunked:falseS.typecheck_data(functxt()(data,ty,maybe_gas,legacy)->letlegacy=Option.value~default:falselegacyinletctxt=matchmaybe_gaswith|None->Gas.set_unlimitedctxt|Somegas->Gas.set_limitctxtgasintypecheck_data~legacyctxt(data,ty)>|=?functxt->Gas.levelctxt);Registration.register0~chunked:trueS.pack_data(functxt()(expr,typ,maybe_gas)->letopenScript_ir_translatorinletctxt=matchmaybe_gaswith|None->Gas.set_unlimitedctxt|Somegas->Gas.set_limitctxtgasinparse_packable_tyctxt~legacy:true(Micheline.roottyp)>>?=fun(Ex_tytyp,ctxt)->parse_datactxt~legacy:true~allow_forged:truetyp(Micheline.rootexpr)>>=?fun(data,ctxt)->Script_ir_translator.pack_datactxttypdata>|=?fun(bytes,ctxt)->(bytes,Gas.levelctxt));Registration.register0~chunked:trueS.normalize_data(functxt()(expr,typ,unparsing_mode,legacy)->letopenScript_ir_translatorinletlegacy=Option.value~default:falselegacyinletctxt=Gas.set_unlimitedctxtinScript_ir_translator.parse_any_tyctxt~legacy(Micheline.roottyp)>>?=fun(Ex_tytyp,ctxt)->parse_datactxt~legacy~allow_forged:truetyp(Micheline.rootexpr)>>=?fun(data,ctxt)->Script_ir_translator.unparse_datactxtunparsing_modetypdata>|=?fun(normalized,_ctxt)->Micheline.strip_locationsnormalized);Registration.register0~chunked:trueS.normalize_script(functxt()(script,unparsing_mode)->letctxt=Gas.set_unlimitedctxtinScript_ir_translator.unparse_codectxtunparsing_mode(Micheline.rootscript)>|=?fun(normalized,_ctxt)->Micheline.strip_locationsnormalized);Registration.register0~chunked:trueS.normalize_type(functxt()typ->letopenScript_ir_translatorinletctxt=Gas.set_unlimitedctxtin(* Unfortunately, Script_ir_translator.parse_any_ty is not exported *)Script_ir_translator.parse_tyctxt~legacy:true~allow_lazy_storage:true~allow_operation:true~allow_contract:true~allow_ticket:true(Micheline.roottyp)>>?=fun(Ex_tytyp,_ctxt)->letnormalized=Unparse_types.unparse_tytypinreturn@@Micheline.strip_locationsnormalized);Registration.register0~chunked:trueS.run_operationrun_operation_service;Registration.register0~chunked:trueS.simulate_operationsimulate_operation_service;Registration.register0~chunked:trueS.entrypoint_type(functxt()(expr,entrypoint)->script_entrypoint_typectxtexprentrypoint);Registration.register0~chunked:trueS.list_entrypoints(functxt()expr->letctxt=Gas.set_unlimitedctxtinletlegacy=falseinletopenScript_ir_translatorinparse_toplevel~legacyctxtexpr>>=?fun({arg_type;root_name;_},ctxt)->Lwt.return(parse_parameter_tyctxt~legacyarg_type>>?fun(Ex_tyarg_type,_)->Script_ir_translator.list_entrypoints~root_namearg_typectxt>|?fun(unreachable_entrypoint,map)->(unreachable_entrypoint,Entrypoints_map.fold(funentry(_,ty)acc->(entry,Micheline.strip_locationsty)::acc)map[])))letrun_code?unparsing_mode?gas?(entrypoint="default")~script~storage~input~amount~balance~chain_id~source~payerctxtblock=RPC_context.make_call0S.run_codectxtblock()((script,storage,input,amount,balance,chain_id,source,payer,gas,entrypoint),unparsing_mode)lettrace_code?unparsing_mode?gas?(entrypoint="default")~script~storage~input~amount~balance~chain_id~source~payerctxtblock=RPC_context.make_call0S.trace_codectxtblock()((script,storage,input,amount,balance,chain_id,source,payer,gas,entrypoint),unparsing_mode)letrun_view?gas~contract~entrypoint~input~chain_id?source?payer~unparsing_modectxtblock=RPC_context.make_call0S.run_viewctxtblock()(contract,entrypoint,input,chain_id,source,payer,gas,unparsing_mode)lettypecheck_code?gas?legacy~scriptctxtblock=RPC_context.make_call0S.typecheck_codectxtblock()(script,gas,legacy)letscript_size?gas?legacy~script~storagectxtblock=RPC_context.make_call0S.script_sizectxtblock()(script,storage,gas,legacy)lettypecheck_data?gas?legacy~data~tyctxtblock=RPC_context.make_call0S.typecheck_datactxtblock()(data,ty,gas,legacy)letpack_data?gas~data~tyctxtblock=RPC_context.make_call0S.pack_datactxtblock()(data,ty,gas)letnormalize_data?legacy~data~ty~unparsing_modectxtblock=RPC_context.make_call0S.normalize_datactxtblock()(data,ty,unparsing_mode,legacy)letnormalize_script~script~unparsing_modectxtblock=RPC_context.make_call0S.normalize_scriptctxtblock()(script,unparsing_mode)letnormalize_type~tyctxtblock=RPC_context.make_call0S.normalize_typectxtblock()tyletrun_operation~op~chain_idctxtblock=RPC_context.make_call0S.run_operationctxtblock()(op,chain_id)letsimulate_operation~op~chain_id~latencyctxtblock=RPC_context.make_call0S.simulate_operationctxtblock()(op,chain_id,latency)letentrypoint_type~script~entrypointctxtblock=RPC_context.make_call0S.entrypoint_typectxtblock()(script,entrypoint)letlist_entrypointsctxtblock~script=RPC_context.make_call0S.list_entrypointsctxtblock()scriptendmoduleContract=structmoduleS=structletpath=(RPC_path.(open_root/"context"/"contracts"):RPC_context.tRPC_path.context)letget_storage_normalized=letopenData_encodinginRPC_service.post_service~description:"Access the data of the contract and normalize it using the \
requested unparsing mode."~input:(obj1(req"unparsing_mode"unparsing_mode_encoding))~query:RPC_query.empty~output:(optionScript.expr_encoding)RPC_path.(path/:Contract.rpc_arg/"storage"/"normalized")letget_script_normalized=letopenData_encodinginRPC_service.post_service~description:"Access the script of the contract and normalize it using the \
requested unparsing mode."~input:(obj1(req"unparsing_mode"unparsing_mode_encoding))~query:RPC_query.empty~output:(optionScript.encoding)RPC_path.(path/:Contract.rpc_arg/"script"/"normalized")endletregister()=(* Patched RPC: get_storage *)Registration.register1~chunked:trueS.get_storage_normalized(functxtcontract()unparsing_mode->Contract.get_scriptctxtcontract>>=?fun(ctxt,script)->matchscriptwith|None->return_none|Somescript->letctxt=Gas.set_unlimitedctxtinletopenScript_ir_translatorinparse_scriptctxt~legacy:true~allow_forged_in_storage:truescript>>=?fun(Ex_scriptscript,ctxt)->unparse_scriptctxtunparsing_modescript>>=?fun(script,ctxt)->Script.force_decode_in_contextctxtscript.storage>>?=fun(storage,_ctxt)->return_somestorage);(* Patched RPC: get_script *)Registration.register1~chunked:trueS.get_script_normalized(functxtcontract()unparsing_mode->Contract.get_scriptctxtcontract>>=?fun(ctxt,script)->matchscriptwith|None->return_none|Somescript->letctxt=Gas.set_unlimitedctxtinletopenScript_ir_translatorinparse_scriptctxt~legacy:true~allow_forged_in_storage:truescript>>=?fun(Ex_scriptscript,ctxt)->unparse_scriptctxtunparsing_modescript>>=?fun(script,_ctxt)->return_somescript)letget_storage_normalizedctxtblock~contract~unparsing_mode=RPC_context.make_call1S.get_storage_normalizedctxtblockcontract()unparsing_modeletget_script_normalizedctxtblock~contract~unparsing_mode=RPC_context.make_call1S.get_script_normalizedctxtblockcontract()unparsing_modeendmoduleBig_map=structmoduleS=structletpath=(RPC_path.(open_root/"context"/"big_maps"):RPC_context.tRPC_path.context)letbig_map_get_normalized=letopenData_encodinginRPC_service.post_service~description:"Access the value associated with a key in a big map, normalize \
the output using the requested unparsing mode."~query:RPC_query.empty~input:(obj1(req"unparsing_mode"unparsing_mode_encoding))~output:Script.expr_encodingRPC_path.(path/:Big_map.Id.rpc_arg/:Script_expr_hash.rpc_arg/"normalized")endletregister()=Registration.register2~chunked:trueS.big_map_get_normalized(functxtidkey()unparsing_mode->letopenScript_ir_translatorinletctxt=Gas.set_unlimitedctxtinBig_map.existsctxtid>>=?fun(ctxt,types)->matchtypeswith|None->raiseNot_found|Some(_,value_type)->(parse_big_map_value_tyctxt~legacy:true(Micheline.rootvalue_type)>>?=fun(Ex_tyvalue_type,ctxt)->Big_map.get_optctxtidkey>>=?fun(_ctxt,value)->matchvaluewith|None->raiseNot_found|Somevalue->parse_datactxt~legacy:true~allow_forged:truevalue_type(Micheline.rootvalue)>>=?fun(value,ctxt)->unparse_datactxtunparsing_modevalue_typevalue>|=?fun(value,_ctxt)->Micheline.strip_locationsvalue))letbig_map_get_normalizedctxtblockidkey~unparsing_mode=RPC_context.make_call2S.big_map_get_normalizedctxtblockidkey()unparsing_modeendmoduleForge=structmoduleS=structopenData_encodingletpath=RPC_path.(path/"forge")letoperations=RPC_service.post_service~description:"Forge an operation"~query:RPC_query.empty~input:Operation.unsigned_encoding~output:bytesRPC_path.(path/"operations")letempty_proof_of_work_nonce=Bytes.makeConstants_repr.proof_of_work_nonce_size'\000'letprotocol_data=RPC_service.post_service~description:"Forge the protocol-specific part of a block header"~query:RPC_query.empty~input:(obj4(req"priority"uint16)(opt"nonce_hash"Nonce_hash.encoding)(dft"proof_of_work_nonce"(Fixed.bytesAlpha_context.Constants.proof_of_work_nonce_size)empty_proof_of_work_nonce)(dft"liquidity_baking_escape_vote"boolfalse))~output:(obj1(req"protocol_data"bytes))RPC_path.(path/"protocol_data")endletregister()=Registration.register0_noctxt~chunked:trueS.operations(fun()(shell,proto)->return(Data_encoding.Binary.to_bytes_exnOperation.unsigned_encoding(shell,proto)));Registration.register0_noctxt~chunked:trueS.protocol_data(fun()(priority,seed_nonce_hash,proof_of_work_nonce,liquidity_baking_escape_vote)->return(Data_encoding.Binary.to_bytes_exnBlock_header.contents_encoding{priority;seed_nonce_hash;proof_of_work_nonce;liquidity_baking_escape_vote;}))moduleManager=structletoperationsctxtblock~branch~source?sourcePubKey~counter~fee~gas_limit~storage_limitoperations=Contract_services.manager_keyctxtblocksource>>=function|Error_ase->Lwt.returne|Okrevealed->letops=List.map(fun(Manageroperation)->Contents(Manager_operation{source;counter;operation;fee;gas_limit;storage_limit;}))operationsinletops=match(sourcePubKey,revealed)with|None,_|_,Some_->ops|Somepk,None->letoperation=RevealpkinContents(Manager_operation{source;counter;operation;fee;gas_limit;storage_limit;})::opsinEnvironment.wrap_tzresult@@Operation.of_listops>>?=funops->RPC_context.make_call0S.operationsctxtblock()({branch},ops)letrevealctxtblock~branch~source~sourcePubKey~counter~fee()=operationsctxtblock~branch~source~sourcePubKey~counter~fee~gas_limit:Gas.Arith.zero~storage_limit:Z.zero[]lettransactionctxtblock~branch~source?sourcePubKey~counter~amount~destination?(entrypoint="default")?parameters~gas_limit~storage_limit~fee()=letparameters=Option.fold~some:Script.lazy_expr~none:Script.unit_parameterparametersinoperationsctxtblock~branch~source?sourcePubKey~counter~fee~gas_limit~storage_limit[Manager(Transaction{amount;parameters;destination;entrypoint})]letoriginationctxtblock~branch~source?sourcePubKey~counter~balance?delegatePubKey~script~gas_limit~storage_limit~fee()=operationsctxtblock~branch~source?sourcePubKey~counter~fee~gas_limit~storage_limit[Manager(Origination{delegate=delegatePubKey;script;credit=balance;preorigination=None;});]letdelegationctxtblock~branch~source?sourcePubKey~counter~feedelegate=operationsctxtblock~branch~source?sourcePubKey~counter~fee~gas_limit:Gas.Arith.zero~storage_limit:Z.zero[Manager(Delegationdelegate)]endletoperationctxtblock~branchoperation=RPC_context.make_call0S.operationsctxtblock()({branch},Contents_list(Singleoperation))letendorsementctxtb~branch~level()=operationctxtb~branch(Endorsement{level})letproposalsctxtb~branch~source~period~proposals()=operationctxtb~branch(Proposals{source;period;proposals})letballotctxtb~branch~source~period~proposal~ballot()=operationctxtb~branch(Ballot{source;period;proposal;ballot})letfailing_noopctxtb~branch~message()=operationctxtb~branch(Failing_noopmessage)letseed_nonce_revelationctxtblock~branch~level~nonce()=operationctxtblock~branch(Seed_nonce_revelation{level;nonce})letdouble_baking_evidencectxtblock~branch~bh1~bh2()=operationctxtblock~branch(Double_baking_evidence{bh1;bh2})letdouble_endorsement_evidencectxtblock~branch~op1~op2~slot()=operationctxtblock~branch(Double_endorsement_evidence{op1;op2;slot})letempty_proof_of_work_nonce=Bytes.makeConstants_repr.proof_of_work_nonce_size'\000'letprotocol_datactxtblock~priority?seed_nonce_hash?(proof_of_work_nonce=empty_proof_of_work_nonce)~liquidity_baking_escape_vote()=RPC_context.make_call0S.protocol_datactxtblock()(priority,seed_nonce_hash,proof_of_work_nonce,liquidity_baking_escape_vote)endmoduleParse=structmoduleS=structopenData_encodingletpath=RPC_path.(path/"parse")letoperations=RPC_service.post_service~description:"Parse operations"~query:RPC_query.empty~input:(obj2(req"operations"(list(dynamic_sizeOperation.raw_encoding)))(opt"check_signature"bool))~output:(list(dynamic_sizeOperation.encoding))RPC_path.(path/"operations")letblock=RPC_service.post_service~description:"Parse a block"~query:RPC_query.empty~input:Block_header.raw_encoding~output:Block_header.protocol_data_encodingRPC_path.(path/"block")endletparse_protocol_dataprotocol_data=matchData_encoding.Binary.of_bytes_optBlock_header.protocol_data_encodingprotocol_datawith|None->Stdlib.failwith"Cant_parse_protocol_data"|Someprotocol_data->protocol_dataletregister()=Registration.register0~chunked:trueS.operations(fun_ctxt()(operations,check)->List.map_es(funraw->parse_operationraw>>?=funop->(matchcheckwith|Sometrue->return_unit(* FIXME *)(* I.check_signature ctxt *)(* op.protocol_data.signature op.shell op.protocol_data.contents *)|Somefalse|None->return_unit)>|=?fun()->op)operations);Registration.register0_noctxt~chunked:falseS.block(fun()raw_block->return@@parse_protocol_dataraw_block.protocol_data)letoperationsctxtblock?checkoperations=RPC_context.make_call0S.operationsctxtblock()(operations,check)letblockctxtblockshellprotocol_data=RPC_context.make_call0S.blockctxtblock()({shell;protocol_data}:Block_header.raw)endletrequested_levels~defaultctxtcycleslevels=match(levels,cycles)with|[],[]->ok[default]|levels,cycles->(* explicitly fail when requested levels or cycle are in the past...
or too far in the future... *)letlevels=List.sort_uniqLevel.compare(List.rev_append(List.rev_map(Level.from_rawctxt)levels)(Stdlib.List.concat_map(Level.levels_in_cyclectxt)cycles))inList.map_e(funlevel->letcurrent_level=Level.currentctxtinifLevel.(level<=current_level)thenok(level,None)elseBaking.earlier_predecessor_timestampctxtlevel>|?funtimestamp->(level,Sometimestamp))levelsmoduleBaking_rights=structtypet={level:Raw_level.t;delegate:Tezos_crypto.Signature.V0.Public_key_hash.t;priority:int;timestamp:Timestamp.toption;}letencoding=letopenData_encodinginconv(fun{level;delegate;priority;timestamp}->(level,delegate,priority,timestamp))(fun(level,delegate,priority,timestamp)->{level;delegate;priority;timestamp})(obj4(req"level"Raw_level.encoding)(req"delegate"Tezos_crypto.Signature.V0.Public_key_hash.encoding)(req"priority"uint16)(opt"estimated_time"Timestamp.encoding))moduleS=structopenData_encodingletcustom_root=RPC_path.(open_root/"helpers"/"baking_rights")typebaking_rights_query={levels:Raw_level.tlist;cycles:Cycle.tlist;delegates:Tezos_crypto.Signature.V0.Public_key_hash.tlist;max_priority:intoption;all:bool;}letbaking_rights_query=letopenRPC_queryinquery(funlevelscyclesdelegatesmax_priorityall->{levels;cycles;delegates;max_priority;all})|+multi_field"level"Raw_level.rpc_arg(funt->t.levels)|+multi_field"cycle"Cycle.rpc_arg(funt->t.cycles)|+multi_field"delegate"Signature.Public_key_hash.rpc_arg(funt->t.delegates)|+opt_field"max_priority"RPC_arg.int(funt->t.max_priority)|+flag"all"(funt->t.all)|>sealletbaking_rights=RPC_service.get_service~description:"Retrieves the list of delegates allowed to bake a block.\n\
By default, it gives the best baking priorities for bakers that \
have at least one opportunity below the 64th priority for the \
next block.\n\
Parameters `level` and `cycle` can be used to specify the (valid) \
level(s) in the past or future at which the baking rights have to \
be returned. When asked for (a) whole cycle(s), baking \
opportunities are given by default up to the priority 8.\n\
Parameter `delegate` can be used to restrict the results to the \
given delegates. If parameter `all` is set, all the baking \
opportunities for each baker at each level are returned, instead \
of just the first one.\n\
Returns the list of baking slots. Also returns the minimal \
timestamps that correspond to these slots. The timestamps are \
omitted for levels in the past, and are only estimates for levels \
later that the next block, based on the hypothesis that all \
predecessor blocks were baked at the first priority."~query:baking_rights_query~output:(listencoding)custom_rootendletbaking_prioritiesctxtmax_prio(level,pred_timestamp)=Baking.baking_prioritiesctxtlevel>>=?funcontract_list->letreclooplaccpriority=ifCompare.Int.(priority>max_prio)thenreturn(List.revacc)elselet(Misc.LCons(pk,next))=linletdelegate=Tezos_crypto.Signature.V0.Public_key.hashpkin(matchpred_timestampwith|None->ok_none|Somepred_timestamp->Baking.minimal_time(Constants.parametricctxt)~prioritypred_timestamp>|?funt->Somet)>>?=funtimestamp->letacc={level=level.level;delegate;priority;timestamp}::accinnext()>>=?funl->looplacc(priority+1)inloopcontract_list[]0letbaking_priorities_of_delegatesctxt~all~max_priodelegates(level,pred_timestamp)=Baking.baking_prioritiesctxtlevel>>=?funcontract_list->letreclooplaccprioritydelegates=matchdelegateswith|[]->return(List.revacc)|_::_->(ifCompare.Int.(priority>max_prio)thenreturn(List.revacc)elselet(Misc.LCons(pk,next))=linnext()>>=?funl->matchList.partition(fun(pk',_)->Tezos_crypto.Signature.V0.Public_key.equalpkpk')delegateswith|[],_->looplacc(priority+1)delegates|(_,delegate)::_,delegates'->(matchpred_timestampwith|None->ok_none|Somepred_timestamp->Baking.minimal_time(Constants.parametricctxt)~prioritypred_timestamp>|?funt->Somet)>>?=funtimestamp->letacc={level=level.level;delegate;priority;timestamp}::accinletdelegates''=ifallthendelegateselsedelegates'inlooplacc(priority+1)delegates'')inloopcontract_list[]0delegatesletremove_duplicated_delegatesrights=List.rev@@fst@@List.fold_left(fun(acc,previous)r->ifTezos_crypto.Signature.V0.Public_key_hash.Set.memr.delegatepreviousthen(acc,previous)else(r::acc,Tezos_crypto.Signature.V0.Public_key_hash.Set.addr.delegateprevious))([],Tezos_crypto.Signature.V0.Public_key_hash.Set.empty)rightsletregister()=Registration.register0~chunked:trueS.baking_rights(functxtq()->requested_levels~default:(Level.succctxt(Level.currentctxt),Some(Timestamp.currentctxt))ctxtq.cyclesq.levels>>?=funlevels->letmax_priority=matchq.max_prioritywith|Somemax->max|None->(matchq.cycleswith[]->64|_::_->8)inmatchq.delegateswith|[]->List.map_es(baking_prioritiesctxtmax_priority)levels>|=?funrights->ifq.allthenList.concatrightselseStdlib.List.concat_mapremove_duplicated_delegatesrights|_::_asdelegates->List.filter_map_s(fundelegate->Alpha_context.Contract.get_manager_keyctxtdelegate>>=function|Okpk->Lwt.return(Some(pk,delegate))|Error_->Lwt.return_none)delegates>>=fundelegates->List.map_es(funlevel->baking_priorities_of_delegatesctxt~all:q.all~max_prio:max_prioritydelegateslevel)levels>|=?List.concat)letgetctxt?(levels=[])?(cycles=[])?(delegates=[])?(all=false)?max_priorityblock=RPC_context.make_call0S.baking_rightsctxtblock{levels;cycles;delegates;max_priority;all}()endmoduleEndorsing_rights=structtypet={level:Raw_level.t;delegate:Tezos_crypto.Signature.V0.Public_key_hash.t;slots:intlist;estimated_time:Time.toption;}letencoding=letopenData_encodinginconv(fun{level;delegate;slots;estimated_time}->(level,delegate,slots,estimated_time))(fun(level,delegate,slots,estimated_time)->{level;delegate;slots;estimated_time})(obj4(req"level"Raw_level.encoding)(req"delegate"Tezos_crypto.Signature.V0.Public_key_hash.encoding)(req"slots"(listuint16))(opt"estimated_time"Timestamp.encoding))moduleS=structopenData_encodingletcustom_root=RPC_path.(open_root/"helpers"/"endorsing_rights")typeendorsing_rights_query={levels:Raw_level.tlist;cycles:Cycle.tlist;delegates:Tezos_crypto.Signature.V0.Public_key_hash.tlist;}letendorsing_rights_query=letopenRPC_queryinquery(funlevelscyclesdelegates->{levels;cycles;delegates})|+multi_field"level"Raw_level.rpc_arg(funt->t.levels)|+multi_field"cycle"Cycle.rpc_arg(funt->t.cycles)|+multi_field"delegate"Signature.Public_key_hash.rpc_arg(funt->t.delegates)|>sealletendorsing_rights=RPC_service.get_service~description:"Retrieves the delegates allowed to endorse a block.\n\
By default, it gives the endorsement slots for delegates that \
have at least one in the next block.\n\
Parameters `level` and `cycle` can be used to specify the (valid) \
level(s) in the past or future at which the endorsement rights \
have to be returned. Parameter `delegate` can be used to restrict \
the results to the given delegates.\n\
Returns the list of endorsement slots. Also returns the minimal \
timestamps that correspond to these slots. The timestamps are \
omitted for levels in the past, and are only estimates for levels \
later that the next block, based on the hypothesis that all \
predecessor blocks were baked at the first priority."~query:endorsing_rights_query~output:(listencoding)custom_rootendletendorsement_slotsctxt(level,estimated_time)=Baking.endorsement_rightsctxtlevel>|=?funrights->Signature.Public_key_hash.Map.fold(fundelegate(_,slots,_)acc->{level=level.level;delegate;slots;estimated_time}::acc)rights[]letregister()=Registration.register0~chunked:trueS.endorsing_rights(functxtq()->requested_levels~default:(Level.currentctxt,Some(Timestamp.currentctxt))ctxtq.cyclesq.levels>>?=funlevels->List.map_es(endorsement_slotsctxt)levels>|=?funrights->letrights=List.concatrightsinmatchq.delegateswith|[]->rights|_::_asdelegates->letis_requestedp=List.exists(Tezos_crypto.Signature.V0.Public_key_hash.equalp.delegate)delegatesinList.filteris_requestedrights)letgetctxt?(levels=[])?(cycles=[])?(delegates=[])block=RPC_context.make_call0S.endorsing_rightsctxtblock{levels;cycles;delegates}()endmoduleS=structopenData_encodingtypelevel_query={offset:int32}letlevel_query:level_queryRPC_query.t=letopenRPC_queryinquery(funoffset->{offset})|+field"offset"RPC_arg.int320l(funt->t.offset)|>sealletcurrent_level=RPC_service.get_service~description:"Returns the level of the interrogated block, or the one of a block \
located `offset` blocks after in the chain (or before when \
negative). For instance, the next block if `offset` is 1."~query:level_query~output:Level.encodingRPC_path.(path/"current_level")letlevels_in_current_cycle=RPC_service.get_service~description:"Levels of a cycle"~query:level_query~output:(obj2(req"first"Raw_level.encoding)(req"last"Raw_level.encoding))RPC_path.(path/"levels_in_current_cycle")endletregister()=Scripts.register();Forge.register();Parse.register();Contract.register();Big_map.register();Baking_rights.register();Endorsing_rights.register();Registration.register0~chunked:falseS.current_level(functxtq()->Lwt.return(Level.from_raw_with_offsetctxt~offset:q.offset(Level.currentctxt).level));Registration.opt_register0~chunked:trueS.levels_in_current_cycle(functxtq()->letrev_levels=Level.levels_in_current_cyclectxt~offset:q.offset()inmatchrev_levelswith|[]->return_none|[level]->return(Some(level.level,level.level))|last::default_first::rest->(* The [rev_levels] list is reversed, the last level is the head *)letfirst=List.lastdefault_firstrestinreturn(Some(first.level,last.level)))letcurrent_levelctxt?(offset=0l)block=RPC_context.make_call0S.current_levelctxtblock{offset}()letlevels_in_current_cyclectxt?(offset=0l)block=RPC_context.make_call0S.levels_in_current_cyclectxtblock{offset}()letrpc_services=register();RPC_directory.mergerpc_services!Registration.patched_servicesend