Raw File
script_ir_unparser.mli
(*****************************************************************************)
(*                                                                           *)
(* Open Source License                                                       *)
(* Copyright (c) 2022 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.                                                 *)
(*                                                                           *)
(*****************************************************************************)

open Alpha_context
open Script_typed_ir

(** Flag that drives unparsing of typed values to nodes.
    - [Optimized_legacy] must be kept backward-compatible in order to compute
      valid hashes (of big map keys).
    - [Optimized] may be used as long as the result can be read by
      {!Script_ir_translator.parse_data}.
    - [Readable] produces with [string] values instead of [bytes] when feasible.
*)
type unparsing_mode = Optimized | Readable | Optimized_legacy

(** [('t, 'd) comb_witness] describes types of values belonging to a [comb]
    of type ['t] and size ['d]. *)
type ('ty, 'depth) comb_witness =
  | Comb_Pair : ('t, 'd) comb_witness -> (_ * 't, unit -> 'd) comb_witness
  | Comb_Any : (_, _) comb_witness

(** [serialize_ty_for_error ty] returns the Micheline representation of [ty]
    suitable for rendering in an error message. Does not consume gas, since
    when this function is called, the operation must have already failed. *)
val serialize_ty_for_error : ('a, 'b) ty -> Script.expr

(** [serialize_stack_for_error ctxt stack_ty] returns a Micheline representation of
    [stack_ty] as a list of Micheline expressions ONLY IF gas is unlimited
    in [ctxt]. Otherwise returns an empty list. *)
val serialize_stack_for_error : context -> ('a, 'b) stack_ty -> Script.expr list

(** [unparse_ty ~loc ctxt ty] returns the Micheline representation of a given
    type and an update context, where gas has been properly consumed. *)
val unparse_ty :
  loc:'loc ->
  context ->
  ('b, 'c) ty ->
  ('loc Script.michelson_node * context, error trace) result

(** [unparse_comparable_ty_uncarbonated ~loc ty] returns the Michelson
    representation of comparable type [ty] without consuming gas. *)
val unparse_comparable_ty_uncarbonated :
  loc:'loc -> 'a comparable_ty -> 'loc Script.michelson_node

(** [unparse_stack_uncarbonated stack_ty] returns the Micheline representation
    of [stack_ty]. Does not consume gas. *)
val unparse_stack_uncarbonated : ('a, 's) stack_ty -> Script.expr list

(** [unparse_parameter_ty ~loc ctxt ty ~entrypoints] is a specialised version of
    [unparse_ty], which also analyses [entrypoints] in order to annotate
    the returned type with adequate annotations. *)
val unparse_parameter_ty :
  loc:'loc ->
  context ->
  ('a, 'c) ty ->
  entrypoints:'a entrypoints ->
  ('loc Script.michelson_node * context, error trace) result

(** [unparse_bls12_381_g1 ~loc ctxt bls] returns the Micheline representation
    of [bls] and consumes gas from [ctxt]. *)
val unparse_bls12_381_g1 :
  loc:'loc ->
  context ->
  Script_bls.G1.t ->
  ('loc Script.michelson_node * context, error trace) result

(** [unparse_bls12_381_g1 ~loc ctxt bls] returns the Micheline representation
    of [bls] and consumes gas from [ctxt]. *)
val unparse_bls12_381_g2 :
  loc:'loc ->
  context ->
  Script_bls.G2.t ->
  ('loc Script.michelson_node * context, error trace) result

(** [unparse_bls12_381_g1 ~loc ctxt bls] returns the Micheline representation
    of [bls] and consumes gas from [ctxt]. *)
val unparse_bls12_381_fr :
  loc:'loc ->
  context ->
  Script_bls.Fr.t ->
  ('loc Script.michelson_node * context, error trace) result

(** [unparse_operation ~loc ctxt op] returns the Micheline representation of
    [op] and consumes gas from [ctxt]. Useful only for producing execution
    traces in the interpreter. *)
val unparse_operation :
  loc:'loc ->
  context ->
  Script_typed_ir.operation ->
  ('loc Script.michelson_node * context, error trace) result

(** [unparse_with_data_encoding ~loc ctxt v gas_cost enc] returns the bytes
    representation of [v] wrapped in [Micheline.Bytes], consuming [gas_cost]
    from [ctxt]. *)
val unparse_with_data_encoding :
  loc:'loc ->
  context ->
  'a ->
  Gas.cost ->
  'a Data_encoding.t ->
  ('loc Script.michelson_node * context, error trace) result Lwt.t

(** [unparse_comparable_data ctxt unparsing_mode ty v] returns the
    Micheline representation of [v] of type [ty], consuming gas from
    [ctxt]. *)
val unparse_comparable_data :
  context ->
  unparsing_mode ->
  'a comparable_ty ->
  'a ->
  (Script.expr * context) tzresult Lwt.t

(** [unparse_contract ~loc ctxt unparsin_mode contract] returns a Micheline
    representation of a given contract in a given [unparsing_mode]. Consumes
    gas [ctxt]. *)
val unparse_contract :
  loc:'loc ->
  context ->
  unparsing_mode ->
  'b typed_contract ->
  ('loc Script.michelson_node * context, error trace) result

(** Lambdas are normalized at parsing and also at unparsing. These
    normalizations require to parse and unparse data appearing inside
    PUSH and introduces a mutual dependency between this module and
    [Script_ir_translator] which is resolved as follows:
    - [Script_ir_translator.parse_data] takes the normalization function
      [unparse_code_rec] as argument,
    - the unparsing function [unparse_data_rec] and the normalization
      function [unparse_code_rec] are mutually defined in a functor
      parameterized by the missing bits from [Script_ir_translator]; see the
      module signature [MICHELSON_PARSER] below.
 *)

(** The [unparse_code_rec] function is not exported (except through
    the [Internal_for_benchmarking] module), but needs to be called by
    [parse_data] to normalize lambdas so it is passed as argument to
    the [parse_data] of the [MICHELSON_PARSER] signature below and to
    several functions of [Script_ir_translator]. To avoid repeating the
    signature of this function we define a type alias for it. *)
type unparse_code_rec =
  context ->
  stack_depth:int ->
  unparsing_mode ->
  Script.node ->
  (Script.node * context) tzresult Lwt.t

(** [MICHELSON_PARSER] signature describes a set of dependencies required to
    unparse arbitrary values in the IR. Because some of those values contain
    just a Michelson code that does not need to be parsed immediately,
    unparsing them requires extracting information from that code – that's
    why we depend on the parser here. *)

module type MICHELSON_PARSER = sig
  val opened_ticket_type :
    Script.location ->
    'a comparable_ty ->
    (address, ('a, Script_int.n Script_int.num) pair) pair comparable_ty
    tzresult

  val parse_packable_ty :
    context ->
    stack_depth:int ->
    legacy:bool ->
    Script.node ->
    (ex_ty * context) tzresult

  val parse_data :
    unparse_code_rec:unparse_code_rec ->
    elab_conf:Script_ir_translator_config.elab_config ->
    stack_depth:int ->
    context ->
    allow_forged_tickets:bool ->
    allow_forged_lazy_storage_id:bool ->
    ('a, 'ac) ty ->
    Script.node ->
    ('a * t) tzresult Lwt.t
end

module Data_unparser : functor (P : MICHELSON_PARSER) -> sig
  (** [unparse_data ctxt ~stack_depth unparsing_mode ty data] returns the
      Micheline representation of [data] of type [ty], consuming an appropriate
      amount of gas from [ctxt]. *)
  val unparse_data :
    context ->
    stack_depth:int ->
    unparsing_mode ->
    ('a, 'ac) ty ->
    'a ->
    (Script.expr * context) tzresult Lwt.t

  (** [unparse_items ctxt ~stack_depth unparsing_mode kty vty assoc] returns the
      Micheline representation of [assoc] (being an association list) with keys
      of type [kty] and values of type [vty]. Gas is being consumed from
      [ctxt]. *)
  val unparse_items :
    context ->
    stack_depth:int ->
    unparsing_mode ->
    'k comparable_ty ->
    ('v, 'vc) ty ->
    ('k * 'v) list ->
    (Script.expr list * context) tzresult Lwt.t

  (** [unparse_code ctxt ~stack_depth unparsing_mode code] returns [code]
      with [I_PUSH] instructions parsed and unparsed back to make sure that
      only forgeable values are being pushed. The gas is being consumed from
      [ctxt]. *)
  val unparse_code :
    context ->
    stack_depth:int ->
    unparsing_mode ->
    Script.node ->
    (Script.expr * context, error trace) result Lwt.t

  (** For benchmarking purpose, we also export versions of the unparsing
      functions which don't call location stripping. These functions are
      not carbonated and should not be called directly from the protocol. *)
  module Internal_for_benchmarking : sig
    val unparse_data :
      context ->
      stack_depth:int ->
      unparsing_mode ->
      ('a, 'ac) ty ->
      'a ->
      (Script.node * context) tzresult Lwt.t

    val unparse_code :
      context ->
      stack_depth:int ->
      unparsing_mode ->
      Script.node ->
      (Script.node * context) tzresult Lwt.t
  end
end
back to top