123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2023 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. *)(* *)(*****************************************************************************)openTezos_michelineopenProtocolopenAlpha_contexttypelocalized_node={parser_loc:Micheline_parser.locationoption;canonical_loc:Micheline.canonical_location;node:stringMicheline.canonical;}letprint_localized_node_locationfmtlocalized_node=matchlocalized_node.parser_locwith|Someparser_loc->Format.fprintffmt"%s"(Format.kasprintfString.capitalize_ascii"%a"Micheline_parser.print_locationparser_loc)|None->Format.fprintffmt"At position %d"localized_node.canonical_locletprint_localized_nodefmtlocalized_node=Micheline_printer.print_expr_unwrappedfmt(Micheline_printer.printableFun.idlocalized_node.node)letlocalize_node~(parsed:stringMichelson_v1_parser.parser_result)(n:(Micheline.canonical_location,string)Micheline.node):localized_node=letcanonical_loc=Micheline.locationninletparser_loc=letopenOption_syntaxinlet*oloc=List.assoc~equal:Int.equalcanonical_locparsed.unexpansion_tableinlet+ploc,_=List.assoc~equal:Int.equalolocparsed.expansion_tableinplocin{parser_loc;canonical_loc;node=Micheline.strip_locationsn}letlocalized_node_encoding:localized_nodeData_encoding.t=Data_encoding.(conv(fun{parser_loc;canonical_loc;node}->(parser_loc,canonical_loc,node))(fun(parser_loc,canonical_loc,node)->{parser_loc;canonical_loc;node})(obj3(req"parser_location"(optionMicheline_parser.location_encoding))(req"canonical_location"Micheline_encoding.canonical_location_encoding)(req"node"(Micheline_encoding.canonical_encoding~variant:"alpha_client"Data_encoding.string))))typeerror+=|Wrong_stack_itemoflocalized_node|Wrong_stackoflocalized_node|Wrong_other_contracts_itemoflocalized_node|Wrong_other_contractsoflocalized_node|Wrong_extra_big_maps_itemoflocalized_node|Wrong_extra_big_mapsoflocalized_node|Invalid_address_for_smart_contractofstring|Duplicated_tzt_top_primofstring*localized_node|Wrong_tzt_top_prim_arityofstring*localized_node*int|Unknown_tzt_top_primofstring*localized_node|Missing_mandatory_tzt_top_primofstring|Invalid_format_for_tzt_top_primofstring*localized_node|Invalid_tzt_topleveloflocalized_nodelet()=Protocol_client_context.register_error_kind`Permanent~id:"michelson.stack.wrong_stack_item"~title:"Wrong stack item"~description:"Failed to parse an item in a typed stack."~pp:(funppfnode->Format.fprintfppf"%a,@ Unexpected format for an item in a typed stack. Expected: \
Stack_elt <ty> <value>; got %a."print_localized_node_locationnodeprint_localized_nodenode)localized_node_encoding(functionWrong_stack_itemnode->Somenode|_->None)(funnode->Wrong_stack_itemnode);Protocol_client_context.register_error_kind`Permanent~id:"michelson.stack.wrong_stack"~title:"Wrong stack"~description:"Failed to parse a typed stack."~pp:(funppfnode->Format.fprintfppf"%a,@ Unexpected format for a typed stack. Expected a sequence of \
Stack_elt <ty> <value>; got %a."print_localized_node_locationnodeprint_localized_nodenode)localized_node_encoding(functionWrong_stacknode->Somenode|_->None)(funnode->Wrong_stacknode);Protocol_client_context.register_error_kind`Permanent~id:"michelson.wrong_other_contracts_item"~title:"Wrong description of an other contract"~description:"Failed to parse an item in a description of other contracts."~pp:(funppfnode->Format.fprintfppf"%a,@ Unexpected format for an item in a description of other \
contracts. Expected: Contract <address> <ty>; got %a."print_localized_node_locationnodeprint_localized_nodenode)localized_node_encoding(functionWrong_other_contracts_itemnode->Somenode|_->None)(funnode->Wrong_other_contracts_itemnode);Protocol_client_context.register_error_kind`Permanent~id:"michelson.wrong_other_contracts"~title:"Wrong description of a list of other contracts"~description:"Failed to parse a description of other contracts."~pp:(funppfnode->Format.fprintfppf"%a,@ Unexpected format for a description of other contracts. Expected \
a sequence of Contract <address> <ty>; got %a."print_localized_node_locationnodeprint_localized_nodenode)localized_node_encoding(functionWrong_other_contractsnode->Somenode|_->None)(funnode->Wrong_other_contractsnode);Protocol_client_context.register_error_kind`Permanent~id:"michelson.wrong_extra_big_maps_item"~title:"Wrong description of an extra big map"~description:"Failed to parse an item in a description of extra big maps."~pp:(funppfnode->Format.fprintfppf"%a,@ Unexpected format for an item in a description of extra big \
maps. Expected: Big_map <index> <key_type> <value_type> <content>; \
got %a."print_localized_node_locationnodeprint_localized_nodenode)localized_node_encoding(functionWrong_extra_big_maps_itemnode->Somenode|_->None)(funnode->Wrong_extra_big_maps_itemnode);Protocol_client_context.register_error_kind`Permanent~id:"michelson.wrong_extra_big_maps"~title:"Wrong description of a list of extra big maps"~description:"Failed to parse a description of extra big maps."~pp:(funppfnode->Format.fprintfppf"%a,@ Unexpected format for a description of extra big maps. Expected \
a sequence of Big_map <index> <key_type> <value_type> <content>; got \
%a."print_localized_node_locationnodeprint_localized_nodenode)localized_node_encoding(functionWrong_extra_big_mapsnode->Somenode|_->None)(funnode->Wrong_extra_big_mapsnode);Protocol_client_context.register_error_kind`Permanent~id:"InvalidAddressForSmartContract"~title:"Invalid address for smart contract"~description:"Invalid input, expected a smart contract address in base58 check \
notation (KT1...)"Data_encoding.(obj1(req"invalid_address"string))~pp:(funppfliteral->Format.fprintfppf"Bad argument value for a smart contract address. Expected an address \
in base58 checked notation starting with 'KT1', but given '%s'"literal)(functionInvalid_address_for_smart_contractstr->Somestr|_->None)(funstr->Invalid_address_for_smart_contractstr);Protocol_client_context.register_error_kind`Permanent~id:"tzt.wrong_toplevel_arity"~title:"Wrong arity for a TZT toplevel primitive"~description:"A known toplevel TZT primitive was used with a bad arity."~pp:(funppf(prim,node,arity)->Format.fprintfppf"%a,@ Wrong arity for TZT toplevel primitive %s, expected %d \
arguments, got %a"print_localized_node_locationnodeprimarityprint_localized_nodenode)Data_encoding.(obj3(req"prim"string)(req"node"localized_node_encoding)(req"arity"int16))(function|Wrong_tzt_top_prim_arity(prim,node,arity)->Some(prim,node,arity)|_->None)(fun(prim,node,arity)->Wrong_tzt_top_prim_arity(prim,node,arity));Protocol_client_context.register_error_kind`Permanent~id:"tzt.duplicated_toplevel"~title:"Duplicated TZT toplevel primitive"~description:"A toplevel TZT primitive was used several times."~pp:(funppf(prim,node)->Format.fprintfppf"%a,@ The TZT toplevel primitive %s, cannot be used because it has \
already been used. A TZT toplevel primitive can only be used once per \
unit test."print_localized_node_locationnodeprim)Data_encoding.(obj2(req"prim"string)(req"node"localized_node_encoding))(function|Duplicated_tzt_top_prim(prim,node)->Some(prim,node)|_->None)(fun(prim,node)->Duplicated_tzt_top_prim(prim,node));Protocol_client_context.register_error_kind`Permanent~id:"tzt.unknown_toplevel"~title:"Unknown TZT toplevel primitive"~description:"A toplevel TZT primitive was unknown."~pp:(funppf(prim,node)->Format.fprintfppf"%a,@ The TZT toplevel primitive %s is unknown."print_localized_node_locationnodeprim)Data_encoding.(obj2(req"prim"string)(req"node"localized_node_encoding))(function|Unknown_tzt_top_prim(prim,node)->Some(prim,node)|_->None)(fun(prim,node)->Unknown_tzt_top_prim(prim,node));Protocol_client_context.register_error_kind`Permanent~id:"tzt.missing_mandatory"~title:"Missing TZT mandatory toplevel primitive"~description:"A mandatory toplevel TZT primitive was missing."~pp:(funppfprim->Format.fprintfppf"The mandatory TZT toplevel primitive %s is missing."prim)Data_encoding.(obj1(req"prim"string))(functionMissing_mandatory_tzt_top_primprim->Someprim|_->None)(funprim->Missing_mandatory_tzt_top_primprim);Protocol_client_context.register_error_kind`Permanent~id:"tzt.invalid_format"~title:"Invalid format for a TZT toplevel primitive"~description:"Invalid format for a TZT toplevel primitive"~pp:(funppf(prim,node)->Format.fprintfppf"%a,@ Invalid format for TZT toplevel primitive %s."print_localized_node_locationnodeprim)Data_encoding.(obj2(req"prim"string)(req"node"localized_node_encoding))(function|Invalid_format_for_tzt_top_prim(prim,node)->Some(prim,node)|_->None)(fun(prim,node)->Invalid_format_for_tzt_top_prim(prim,node));Protocol_client_context.register_error_kind`Permanent~id:"tzt.invalid_toplevel"~title:"Invalid format for TZT toplevel entry"~description:"Invalid format for a TZT toplevel entry"~pp:(funppfnode->Format.fprintfppf"%a,@ Invalid format for TZT toplevel entry, expected a sequence of \
primitive applications, got %a."print_localized_node_locationnodeprint_localized_nodenode)localized_node_encoding(functionInvalid_tzt_toplevelnode->Somenode|_->None)(funnode->Invalid_tzt_toplevelnode)letparse_expression(node:(_,string)Micheline.node)=Environment.wrap_tzresult@@Michelson_v1_primitives.prims_of_strings(Micheline.strip_locationsnode)letparse_stack_item~parsed=letopenResult_syntaxinfunction|Micheline.Prim(_loc,"Stack_elt",[ty;v],_annot)->let*ty=parse_expressiontyinlet*v=parse_expressionvinreturn(ty,v)|e->tzfail(Wrong_stack_item(localize_node~parsede))letparse_other_contract_item~parsed=letopenResult_syntaxinfunction|Micheline.Prim(_loc,"Contract",[address;ty],_annot)ase->let*address=parse_expressionaddressinlet*address=matchMicheline.rootaddresswith|Micheline.String(_loc,s)->(matchEnvironment.Base58.decodeswith|Some(Contract_hash.Datah)->returnh|Some_|None->tzfail(Invalid_address_for_smart_contracts))|_->tzfail(Wrong_other_contracts_item(localize_node~parsede))inlet*ty=parse_expressiontyinreturnRPC.Scripts.S.{address;ty}|e->tzfail(Wrong_other_contracts_item(localize_node~parsede))letparse_extra_big_map_item~parsed=letopenResult_syntaxinfunction|Micheline.Prim(_loc,"Big_map",[id;kty;vty;items],_annot)ase->let*id=parse_expressionidinlet*id=matchMicheline.rootidwith|Micheline.Int(_loc,id)->return(Big_map.Id.parse_zid)|_->tzfail(Wrong_other_contracts_item(localize_node~parsede))inlet*kty=parse_expressionktyinlet*vty=parse_expressionvtyinlet*items=parse_expressionitemsinreturnRPC.Scripts.S.{id;kty;vty;items}|e->tzfail(Wrong_extra_big_maps_item(localize_node~parsede))letparse_sequence?node~(parsed:stringMichelson_v1_parser.parser_result)~errorparse_item=letnode=Option.value~default:(Micheline.rootparsed.expanded)nodeinleterror()=error(localize_node~parsednode)inmatchnodewith|Micheline.Seq(_loc,l)->record_trace_evalerror@@List.map_e(parse_item~parsed)l|_->Result_syntax.tzfail(error())letparse_stack?nodeparsed=parse_sequence?node~parsed~error:(funnode->Wrong_stacknode)parse_stack_itemletparse_other_contracts?nodeparsed=parse_sequence?node~parsed~error:(funnode->Wrong_other_contractsnode)parse_other_contract_itemletparse_extra_big_maps?nodeparsed=parse_sequence?node~parsed~error:(funnode->Wrong_extra_big_mapsnode)parse_extra_big_map_itemtypeunit_test_optional={now:Script_timestamp.toption;level:Script_int.nScript_int.numoption;sender:Contract.toption;source:Signature.public_key_hashoption;chain_id:Chain_id.toption;self:Contract_hash.toption;parameter:Script.exproption;amount:Tez.toption;balance:Tez.toption;other_contracts:RPC.Scripts.S.other_contract_descriptionlistoption;extra_big_maps:RPC.Scripts.S.extra_big_map_descriptionlistoption;}typeunit_test={input:(Script.expr*Script.expr)list;code:Script.expr;output:(Micheline.canonical_location,string)Micheline.node;optional:unit_test_optional;}(* Same as unit_test but all fields are optional. Used only during
parsing. *)typetemp_unit_test={temp_input:(Script.expr*Script.expr)listoption;temp_code:Script.exproption;temp_output:(Micheline.canonical_location,string)Micheline.nodeoption;temp_optional:unit_test_optional;}(* Same as Option.value_fe but takes an error instead of a trace. *)letvalue_fe_erropt~error=Option.value_feopt~error:(fun()->TzTrace.make(error()))(* TODO: #6678
Reuse protocol elaboration functions from the
Script_ir_translator module instead of duplicating them here. *)letparse_muteznode~error=letmutez_opt=matchnodewith|Micheline.Int(_loc,z)->Tez.of_mutez(Z.to_int64z)|_->Noneinvalue_fe_errmutez_opt~errorletparse_chain_idnode~error=matchnodewith|Micheline.String(_loc,s)->record_trace_evalerror@@Chain_id.of_b58checks|Bytes(_loc,b)->value_fe_err~error@@Data_encoding.Binary.of_bytes_optChain_id.encodingb|_->Result_syntax.tzfail@@error()letparse_timestampnode~error=value_fe_err~error@@matchnodewith|Micheline.String(_loc,s)->Script_timestamp.of_strings|Int(_loc,z)->Some(Script_timestamp.of_zintz)|_->Noneletparse_natnode~error=value_fe_err~error@@matchnodewith|Micheline.Int(_loc,z)->Script_int.(is_nat(of_zintz))|_->Noneletparse_key_hashnode~error=matchnodewith|Micheline.String(_loc,s)->record_trace_evalerror@@Signature.Public_key_hash.of_b58checks|Bytes(_loc,b)->value_fe_err~error@@Data_encoding.Binary.of_bytes_optSignature.Public_key_hash.encodingb|_->Result_syntax.tzfail@@error()letparse_addressnode~error=matchnodewith|Micheline.String(_loc,s)->record_trace_evalerror@@Environment.wrap_tzresult@@Contract.of_b58checks|Bytes(_loc,b)->value_fe_err~error@@Data_encoding.Binary.of_bytes_optContract.encodingb|_->Result_syntax.tzfail@@error()letparse_contract_hashnode~error=value_fe_err~error@@matchnodewith|Micheline.String(_loc,s)->Contract_hash.of_b58check_opts|Bytes(_loc,b)->Data_encoding.Binary.of_bytes_optContract_hash.encodingb|_->Noneletparse_unit_test(parsed:stringMichelson_v1_parser.parser_result)=letopenResult_syntaxinletopenMichelineinletrecparseut=function|[]->returnut|(Prim(_loc,prim,[arg],_annots)ase)::l->(letcheck_duplicated=function|None->return_unit|Some_->tzfail(Duplicated_tzt_top_prim(prim,localize_node~parsede))inletinvalid_format()=Invalid_format_for_tzt_top_prim(prim,localize_node~parsede)inlettrace_invalid_formatres=record_trace_evalinvalid_formatresinmatchprimwith|"input"->let*()=check_duplicatedut.temp_inputinlet*items=trace_invalid_format@@parse_stack~node:argparsedinparse{utwithtemp_input=Someitems}l|"output"->let*()=check_duplicatedut.temp_outputinparse{utwithtemp_output=Somearg}l|"code"->let*()=check_duplicatedut.temp_codeinlet*c=trace_invalid_format@@parse_expressionarginparse{utwithtemp_code=Somec}l|"amount"->let*()=check_duplicatedut.temp_optional.amountinlet*t=parse_mutezarg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithamount=Somet}}l|"balance"->let*()=check_duplicatedut.temp_optional.balanceinlet*t=parse_mutezarg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithbalance=Somet}}l|"chain_id"->let*()=check_duplicatedut.temp_optional.chain_idinlet*chain_id=parse_chain_idarg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithchain_id=Somechain_id};}l|"now"->let*()=check_duplicatedut.temp_optional.nowinlet*time=parse_timestamparg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithnow=Sometime}}l|"level"->let*()=check_duplicatedut.temp_optional.levelinlet*level=parse_natarg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithlevel=Somelevel};}l|"sender"->let*()=check_duplicatedut.temp_optional.senderinlet*addr=parse_addressarg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithsender=Someaddr};}l|"source"->let*()=check_duplicatedut.temp_optional.sourceinlet*addr=parse_key_hasharg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithsource=Someaddr};}l|"self"->let*()=check_duplicatedut.temp_optional.selfinlet*addr=parse_contract_hasharg~error:invalid_formatinparse{utwithtemp_optional={ut.temp_optionalwithself=Someaddr}}l|"parameter"->let*()=check_duplicatedut.temp_optional.parameterinlet*ty=parse_expressionarginparse{utwithtemp_optional={ut.temp_optionalwithparameter=Somety};}l|"other_contracts"->let*()=check_duplicatedut.temp_optional.other_contractsinlet*items=parse_other_contracts~node:argparsedinparse{utwithtemp_optional={ut.temp_optionalwithother_contracts=Someitems};}l|"big_maps"->let*()=check_duplicatedut.temp_optional.extra_big_mapsinlet*items=parse_extra_big_maps~node:argparsedinparse{utwithtemp_optional={ut.temp_optionalwithextra_big_maps=Someitems};}l|_->tzfail@@Unknown_tzt_top_prim(prim,localize_node~parsede))|(Prim(_loc,prim,([]|_::_::_),_annots)ase)::_->tzfail@@Wrong_tzt_top_prim_arity(prim,localize_node~parsede,1)|((Seq_|Int_|String_|Bytes_)ase)::_->tzfail@@Invalid_tzt_toplevel(localize_node~parsede)inletnodes=matchMicheline.rootparsed.expandedwith|Seq(_,nodes)->nodes|node->[node]inlet*ut=parse{temp_input=None;temp_code=None;temp_output=None;temp_optional={now=None;level=None;sender=None;source=None;chain_id=None;self=None;parameter=None;amount=None;balance=None;other_contracts=None;extra_big_maps=None;};}nodesinletcheck_mandatoryoptprim=Option.value_eopt~error:(TzTrace.make@@Missing_mandatory_tzt_top_primprim)inlet*input=check_mandatoryut.temp_input"input"inlet*code=check_mandatoryut.temp_code"code"inlet*output=check_mandatoryut.temp_output"output"inreturn{input;code;output;optional=ut.temp_optional}