123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Nomadic Development. <contact@tezcore.com> *)(* Copyright (c) 2021-2022 Nomadic Labs, <contact@nomadic-labs.com> *)(* Copyright (c) 2022 TriliTech <contact@trili.tech> *)(* *)(* 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_contextopenTezos_michelinetypeEnvironment.Error_monad.error+=Viewed_contract_has_no_scripttypeEnvironment.Error_monad.error+=View_callback_origination_failedtypeEnvironment.Error_monad.error+=|Illformed_view_typeofEntrypoint.t*Script.exprtypeEnvironment.Error_monad.error+=|View_never_returnsofEntrypoint.t*Contract_hash.ttypeEnvironment.Error_monad.error+=|View_unexpected_returnofEntrypoint.t*Contract_hash.ttypeEnvironment.Error_monad.error+=View_not_foundofContract_hash.t*stringtypeEnvironment.Error_monad.error+=Viewer_unexpected_storagelet()=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 %a has type %a, it is not compatible with a TZIP-4 view type."Entrypoint.ppentrypointMicheline_printer.print_expr(Micheline_printer.printable(funx->x)(Michelson_v1_primitives.strings_of_primstyp)))Data_encoding.(obj2(req"entrypoint"Entrypoint.simple_encoding)(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 %a never initiated a transaction to the given callback \
contract %a."Entrypoint.ppentrypointContract_hash.ppcallback)Data_encoding.(obj2(req"entrypoint"Entrypoint.simple_encoding)(req"callback"Contract.originated_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 %a initiated a list of operations while the TZIP-4 standard \
expects only a transaction to the given callback contract %a."Entrypoint.ppentrypointContract_hash.ppcallback)Data_encoding.(obj2(req"entrypoint"Entrypoint.simple_encoding)(req"callback"Contract.originated_encoding))(functionView_unexpected_return(e,c)->Some(e,c)|_->None)(fun(e,c)->View_unexpected_return(e,c));Environment.Error_monad.register_error_kind`Permanent~id:"viewNotFound"~title:"A view could not be found"~description:"The contract does not have a view of the given name."~pp:(funppf(contract,name)->Format.fprintfppf"The contract %a does not have a view named `%s`."Contract_hash.ppcontractname)Data_encoding.(obj2(req"contract"Contract.originated_encoding)(req"view"string))(functionView_not_found(k,n)->Some(k,n)|_->None)(fun(k,n)->View_not_found(k,n));Environment.Error_monad.register_error_kind`Permanent~id:"viewerUnexpectedStorage"~title:"A VIEW instruction returned an unexpected value"~description:"A VIEW instruction returned an unexpected value."~pp:(funppf()->Format.fprintfppf"The simulated view returned an unexpected value.")Data_encoding.unit(functionViewer_unexpected_storage->Some()|_->None)(fun()->Viewer_unexpected_storage)(* 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_tzip4_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|[Script_typed_ir.Internal_operation{operation=Transaction_to_smart_contract{destination;unparsed_parameters;entrypoint=_;amount=_;parameters=_;parameters_ty=_;location=_;};sender=_;nonce=_;};]whenContract_hash.equaldestinationcallback->Okunparsed_parameters|[]->Environment.Error_monad.error(View_never_returns(entrypoint,callback))|_->unexpected_return(* [make_michelson_viewer_script contract view input input_ty output_ty]
generates a script that calls a view from a given contract, and stores the
result in its storage. *)letmake_michelson_viewer_scriptaddressviewinputinput_tyoutput_ty:Script.t=letloc=0inletaddress=Micheline.String(loc,Contract.to_b58checkaddress)inletpushtyvalue=Micheline.Prim(loc,Script.I_PUSH,[ty;value],[])inletstorage_decl=Micheline.Prim(loc,Script.T_option,[output_ty],[])inletbody=Micheline.Seq(loc,[Micheline.Prim(loc,Script.I_DROP,[],[]);push(Micheline.Prim(loc,Script.T_address,[],[]))address;pushinput_ty(Micheline.rootinput);Micheline.Prim(loc,Script.I_VIEW,[Micheline.String(loc,view);output_ty],[]);Micheline.Prim(loc,Script.I_NIL,[Micheline.Prim(loc,Script.T_operation,[],[])],[]);Micheline.Prim(loc,Script.I_PAIR,[],[]);])inletcode=Micheline.strip_locations@@Micheline.Seq(loc,[Micheline.Prim(loc,Script.K_parameter,[Micheline.Prim(loc,Script.T_unit,[],[])],[]);Micheline.Prim(loc,Script.K_storage,[storage_decl],[]);Micheline.Prim(loc,Script.K_code,[body],[]);])inletstorage=Micheline.strip_locations(Micheline.Prim(loc,Script.D_None,[],[]))in{code=Script.lazy_exprcode;storage=Script.lazy_exprstorage}(* Extracts the value from the mock script generated by
[make_michelson_viewer_script]. *)letextract_value_from_storage(storage:Script.expr)=matchMicheline.rootstoragewith|Micheline.Prim(_,Script.D_Some,[value],[])->Okvalue|_->Environment.Error_monad.error@@Viewer_unexpected_storage