Raw File
script_interpreter.mli
(*****************************************************************************)
(*                                                                           *)
(* Open Source License                                                       *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com>     *)
(* Copyright (c) 2021 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.                                                 *)
(*                                                                           *)
(*****************************************************************************)

(** This is the Michelson interpreter.

    This module offers a way to execute either a Michelson script or a
    Michelson instruction.

    Implementation details are documented in the .ml file.

*)

open Alpha_context
open Script_typed_ir

type error += Reject of Script.location * Script.expr * execution_trace option

type error += Overflow of Script.location * execution_trace option

type error += Runtime_contract_error of Contract_hash.t

type error += Bad_contract_parameter of Contract.t (* `Permanent *)

type error += Cannot_serialize_failure

type error += Cannot_serialize_storage

type error += Michelson_too_many_recursive_calls

(** The result from script interpretation. *)
type execution_result = {
  script : Script_ir_translator.ex_script;
  code_size : int;
  storage : Script.expr;
  lazy_storage_diff : Lazy_storage.diffs option;
  operations : packed_internal_operation list;
  ticket_diffs : Z.t Ticket_token_map.t;
}

type step_constants = Script_typed_ir.step_constants = {
  source : Contract.t;
  payer : Signature.public_key_hash;
  self : Contract_hash.t;
  amount : Tez.t;
  balance : Tez.t;
  chain_id : Chain_id.t;
  now : Script_timestamp.t;
  level : Script_int.n Script_int.num;
}

(** [execute ?logger ctxt ~cached_script mode step_constant ~script
   ~entrypoint ~parameter ~internal] interprets the [script]'s
   [entrypoint] for a given [parameter].

   This will update the local storage of the contract
   [step_constants.self]. Other pieces of contextual information
   ([source], [payer], [amount], and [chaind_id]) are also passed in
   [step_constant].

   [internal] is [true] if and only if the execution happens within an
   internal operation.

   [mode] is the unparsing mode, as declared by
   {!Script_ir_translator}.

   [cached_script] is the cached elaboration of [script], that is the
   well typed abstract syntax tree produced by the type elaboration of
   [script] during a previous execution and stored in the in-memory
   cache.

*)
val execute :
  ?logger:logger ->
  Alpha_context.t ->
  cached_script:Script_ir_translator.ex_script option ->
  Script_ir_unparser.unparsing_mode ->
  step_constants ->
  script:Script.t ->
  entrypoint:Entrypoint.t ->
  parameter:Script.expr ->
  internal:bool ->
  (execution_result * context) tzresult Lwt.t

(** [execute_with_typed_parameter ?logger ctxt ~cached_script mode
   step_constant ~script ~entrypoint loc ~parameter_ty ~parameter ~internal]
   interprets the [script]'s [entrypoint] for a given (typed) [parameter].

   See {!execute} for more details about the function's arguments.
*)
val execute_with_typed_parameter :
  ?logger:logger ->
  Alpha_context.context ->
  cached_script:Script_ir_translator.ex_script option ->
  Script_ir_unparser.unparsing_mode ->
  step_constants ->
  script:Script.t ->
  entrypoint:Entrypoint.t ->
  parameter_ty:('a, _) Script_typed_ir.ty ->
  location:Script.location ->
  parameter:'a ->
  internal:bool ->
  (execution_result * context) tzresult Lwt.t

(** Internal interpretation loop
    ============================

    The following types and the following functions are exposed
    in the interface to allow the inference of a gas model in
    snoop.

    Strictly speaking, they should not be considered as part of
    the interface since they expose implementation details that
    may change in the future.

*)

module Internals : sig
  (** Internally, the interpretation loop uses a local gas counter. *)

  (** [next logger (ctxt, step_constants) local_gas_counter ks accu
      stack] is an internal function which interprets the continuation
      [ks] to execute the interpreter on the current A-stack. *)
  val next :
    logger option ->
    Local_gas_counter.outdated_context * step_constants ->
    Local_gas_counter.local_gas_counter ->
    ('a, 's) stack_ty ->
    ('a, 's, 'r, 'f) continuation ->
    'a ->
    's ->
    ('r
    * 'f
    * Local_gas_counter.outdated_context
    * Local_gas_counter.local_gas_counter)
    tzresult
    Lwt.t

  val step :
    Local_gas_counter.outdated_context * step_constants ->
    Local_gas_counter.local_gas_counter ->
    ('a, 's, 'r, 'f) Script_typed_ir.kinstr ->
    'a ->
    's ->
    ('r
    * 'f
    * Local_gas_counter.outdated_context
    * Local_gas_counter.local_gas_counter)
    tzresult
    Lwt.t

  val step_descr :
    logger option ->
    context ->
    Script_typed_ir.step_constants ->
    ('a, 's, 'r, 'f) Script_typed_ir.kdescr ->
    'a ->
    's ->
    ('r * 'f * context) tzresult Lwt.t

  (** [kstep logger ctxt step_constants kinstr accu stack] interprets the
      script represented by [kinstr] under the context [ctxt]. This will
      turn a stack whose topmost element is [accu] and remaining elements
      [stack] into a new accumulator and a new stack. This function also
      returns an updated context. If [logger] is given, [kstep] calls back
      its functions at specific points of the execution. The execution is
      parameterized by some [step_constants]. *)
  val kstep :
    logger option ->
    context ->
    step_constants ->
    ('a, 's) stack_ty ->
    ('a, 's, 'r, 'f) Script_typed_ir.kinstr ->
    'a ->
    's ->
    ('r * 'f * context) tzresult Lwt.t
end
back to top