Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file script_repr.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.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. *)(* *)(*****************************************************************************)typelocation=Micheline.canonical_locationletlocation_encoding=Micheline.canonical_location_encodingtypeannot=Micheline.annottypeexpr=Michelson_v1_primitives.primMicheline.canonicaltypelazy_expr=exprData_encoding.lazy_ttypenode=(location,Michelson_v1_primitives.prim)Micheline.nodeletexpr_encoding=Micheline.canonical_encoding_v1~variant:"michelson_v1"Michelson_v1_primitives.prim_encodingtypeerror+=Lazy_script_decode(* `Permanent *)let()=register_error_kind`Permanent~id:"invalid_binary_format"~title:"Invalid binary format"~description:"Could not deserialize some piece of data from its binary representation"Data_encoding.empty(functionLazy_script_decode->Some()|_->None)(fun()->Lazy_script_decode)letlazy_expr_encoding=Data_encoding.lazy_encodingexpr_encodingletlazy_exprexpr=Data_encoding.make_lazyexpr_encodingexprtypet={code:lazy_expr;storage:lazy_expr}letencoding=letopenData_encodingindef"scripted.contracts"@@conv(fun{code;storage}->(code,storage))(fun(code,storage)->{code;storage})(obj2(req"code"lazy_expr_encoding)(req"storage"lazy_expr_encoding))moduleS=Saturation_reprmoduleMicheline_size=structtypet={nodes:S.may_saturateS.t;string_bytes:S.may_saturateS.t;z_bytes:S.may_saturateS.t;}letmake~nodes~string_bytes~z_bytes={nodes;string_bytes;z_bytes}letzero={nodes=S.zero;string_bytes=S.zero;z_bytes=S.zero}letadd_intaccn=letnumbits=Z.numbitsninletz_bytes=S.safe_int((numbits+7)/8)(* Compute the number of bytes in a Z.t *)in{nodes=S.succacc.nodes;string_bytes=acc.string_bytes;z_bytes=S.addacc.z_bytesz_bytes;}letadd_stringaccn=letstring_bytes=S.safe_int(String.lengthn)in{nodes=S.succacc.nodes;string_bytes=S.addacc.string_bytesstring_bytes;z_bytes=acc.z_bytes;}letadd_bytesaccn=letstring_bytes=S.safe_int(Bytes.lengthn)in{nodes=S.succacc.nodes;string_bytes=S.addacc.string_bytesstring_bytes;z_bytes=acc.z_bytes;}letadd_nodes={swithnodes=S.succs.nodes}(* We model annotations as Seqs of Strings *)letof_annotsaccannots=List.fold_left(funaccs->add_stringaccs)accannotsletrecof_nodesaccnodesmore_nodes=letopenMichelineinmatchnodeswith|[]->(matchmore_nodeswith|[]->acc|nodes::more_nodes->(of_nodes[@ocaml.tailcall])accnodesmore_nodes)|Int(_,n)::nodes->letacc=add_intaccnin(of_nodes[@ocaml.tailcall])accnodesmore_nodes|String(_,s)::nodes->letacc=add_stringaccsin(of_nodes[@ocaml.tailcall])accnodesmore_nodes|Bytes(_,s)::nodes->letacc=add_bytesaccsin(of_nodes[@ocaml.tailcall])accnodesmore_nodes|Prim(_,_,args,annots)::nodes->letacc=add_nodeaccinletacc=of_annotsaccannotsin(of_nodes[@ocaml.tailcall])accargs(nodes::more_nodes)|Seq(_,args)::nodes->letacc=add_nodeaccin(of_nodes[@ocaml.tailcall])accargs(nodes::more_nodes)letof_nodenode=of_nodeszero[node][]letdot_products1s2=S.add(S.muls1.nodess2.nodes)(S.add(S.muls1.string_bytess2.string_bytes)(S.muls1.z_bytess2.z_bytes))end(* Costs pertaining to deserialization of Micheline values (bytes to Micheline).
The costs are given in atomic steps (see [Gas_limit_repr]). *)moduleMicheline_decoding=struct(* Cost vector allowing to compute decoding costs as a function of the
size of the Micheline term *)letmicheline_size_dependent_cost=lettraversal_cost=S.safe_int60inletstring__per_byte_cost=S.safe_int10inletz__per_byte_cost=S.safe_int10inMicheline_size.make~nodes:traversal_cost~string_bytes:string__per_byte_cost~z_bytes:z__per_byte_costletbytes_dependent_cost=S.safe_int20end(* Costs pertaining to serialization of Micheline values (Micheline to bytes)
The costs are given in atomic steps (see [Gas_limit_repr]). *)moduleMicheline_encoding=struct(* Cost vector allowing to compute encoding cost as a function of the
size of the Micheline term *)letmicheline_size_dependent_cost=lettraversal_cost=S.safe_int100inletstring__per_byte_cost=S.safe_int10inletz__per_byte_cost=S.safe_int25inMicheline_size.make~nodes:traversal_cost~string_bytes:string__per_byte_cost~z_bytes:z__per_byte_costletbytes_dependent_cost=S.safe_int33endletexpr_sizeexpr=Micheline_size.of_node(Micheline.rootexpr)(* Compute the cost of serializing a term of given [size]. *)letserialization_costsize=Gas_limit_repr.atomic_step_cost@@Micheline_size.dot_productsizeMicheline_encoding.micheline_size_dependent_cost(* Compute the cost of deserializing a term of given [size]. *)letdeserialization_costsize=Gas_limit_repr.atomic_step_cost@@Micheline_size.dot_productsizeMicheline_decoding.micheline_size_dependent_cost(* Estimate the cost of deserializing a term encoded in [bytes_len] bytes. *)letdeserialization_cost_estimated_from_bytesbytes_len=Gas_limit_repr.atomic_step_cost@@S.mulMicheline_decoding.bytes_dependent_cost(S.safe_intbytes_len)(* Estimate the cost of serializing a term from its encoded form,
having [bytes_len] bytes. *)letserialization_cost_estimated_from_bytesbytes_len=Gas_limit_repr.atomic_step_cost@@S.mulMicheline_encoding.bytes_dependent_cost(S.safe_intbytes_len)(* Cost of running [strip_locations] on a term with [size] nodes.
Note that [strip_locations] will reallocate a fresh Micheline tree.
This only depends on the total number of nodes (not the size of
the leaves). *)letcost_micheline_strip_locationssize=Gas_limit_repr.atomic_step_cost@@S.mul(S.safe_intsize)(S.safe_int51)(* This is currently used to estimate the cost of serializing an operation. *)letbytes_node_costs=serialization_cost_estimated_from_bytes(Bytes.lengths)letdeserialized_costexpr=Gas_limit_repr.atomic_step_cost@@deserialization_cost(expr_sizeexpr)letserialized_costbytes=Gas_limit_repr.atomic_step_cost@@serialization_cost_estimated_from_bytes(Bytes.lengthbytes)letforce_decode_costlexpr=Data_encoding.apply_lazy~fun_value:(fun_->Gas_limit_repr.free)~fun_bytes:(funb->deserialization_cost_estimated_from_bytes(Bytes.lengthb))~fun_combine:(fun__->Gas_limit_repr.free)lexprletforce_decodelexpr=matchData_encoding.force_decodelexprwith|Somev->okv|None->errorLazy_script_decodeletforce_bytes_costexpr=(* Estimating the cost directly from the bytes would be cheaper, but
using [serialized_cost] is more accurate. *)Data_encoding.apply_lazy~fun_value:(funv->serialization_cost(expr_sizev))~fun_bytes:(fun_->Gas_limit_repr.free)~fun_combine:(fun__->Gas_limit_repr.free)exprletforce_bytesexpr=matchData_encoding.force_bytesexprwith|bytes->okbytes|exception_->errorLazy_script_decodeletunit=Micheline.strip_locations(Prim(0,Michelson_v1_primitives.D_Unit,[],[]))letunit_parameter=lazy_exprunitletis_unit_parameter=letunit_bytes=Data_encoding.force_bytesunit_parameterinData_encoding.apply_lazy~fun_value:(funv->matchMicheline.rootvwith|Prim(_,Michelson_v1_primitives.D_Unit,[],[])->true|_->false)~fun_bytes:(funb->Compare.Bytes.equalbunit_bytes)~fun_combine:(funres_->res)letrecstrip_annotationsnode=letopenMichelineinmatchnodewith|(Int(_,_)|String(_,_)|Bytes(_,_))asleaf->leaf|Prim(loc,name,args,_)->Prim(loc,name,List.mapstrip_annotationsargs,[])|Seq(loc,args)->Seq(loc,List.mapstrip_annotationsargs)letrecmicheline_nodesnodeacck=matchnodewith|Micheline.Int(_,_)->k(acc+1)|Micheline.String(_,_)->k(acc+1)|Micheline.Bytes(_,_)->k(acc+1)|Micheline.Prim(_,_,subterms,_)->micheline_nodes_listsubterms(acc+1)k|Micheline.Seq(_,subterms)->micheline_nodes_listsubterms(acc+1)kandmicheline_nodes_listsubtermsacck=matchsubtermswith|[]->kacc|n::nodes->micheline_nodes_listnodesacc(funacc->micheline_nodesnacck)letmicheline_nodesnode=micheline_nodesnode0(funx->x)letstrip_locations_costnode=letnodes=micheline_nodesnodeincost_micheline_strip_locationsnodes