package octez-protocol-alpha-libs

  1. Overview
  2. Docs
Octez protocol alpha libraries

Install

Dune Dependency

Authors

Maintainers

Sources

tezos-octez-v20.1.tag.bz2
sha256=ddfb5076eeb0b32ac21c1eed44e8fc86a6743ef18ab23fff02d36e365bb73d61
sha512=d22a827df5146e0aa274df48bc2150b098177ff7e5eab52c6109e867eb0a1f0ec63e6bfbb0e3645a6c2112de3877c91a17df32ccbff301891ce4ba630c997a65

doc/src/octez-protocol-alpha-libs.client/client_proto_tzt.ml.html

Source file client_proto_tzt.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
(*****************************************************************************)
(*                                                                           *)
(* SPDX-License-Identifier: MIT                                              *)
(* Copyright (c) 2023 Nomadic Labs <contact@nomadic-labs.com>                *)
(*                                                                           *)
(*****************************************************************************)

open Protocol
open Alpha_context
open Tezos_micheline

type unit_test_with_source = {
  source : string;
  parsed : string Michelson_v1_parser.parser_result;
}

let convert_error trace =
  let open Result_syntax in
  let open Micheline in
  function
  | Script_interpreter.Reject (_loc, value, _trace) ->
      let value = Michelson_v1_primitives.strings_of_prims value in
      return (Prim (0, "Failed", [root value], []))
  | Tez_repr.Addition_overflow _ | Tez_repr.Multiplication_overflow _
  | Script_interpreter.Overflow _ ->
      return (Prim (0, "Overflow", [], []))
  | Tez_repr.Subtraction_underflow (a, b) ->
      return
        (Prim
           ( 0,
             "MutezUnderflow",
             [
               Int (0, Z.of_int64 @@ Tez_repr.to_mutez a);
               Int (0, Z.of_int64 @@ Tez_repr.to_mutez b);
             ],
             [] ))
  | Tez_repr.Negative_multiplicator _ -> return (Prim (0, "NegMul", [], []))
  | Tez_repr.Invalid_divisor _ -> return (Prim (0, "InvalidDivisor", [], []))
  | Raw_context.Operation_quota_exceeded | Raw_context.Block_quota_exceeded ->
      return (Prim (0, "Gas_exhaustion", [], []))
  | _ ->
      return
        (Prim
           ( 0,
             "StaticError",
             [String (0, Format.asprintf "%a" Error_monad.pp_print_trace trace)],
             [] ))

let convert_trace = function
  | Environment.Ecoproto_error err :: _ as trace -> convert_error trace err
  | _ -> assert false

let match_output ~got ~expected =
  let open Result_syntax in
  let open Micheline in
  let rec match_pattern pattern expression =
    match (pattern, expression) with
    (* Wildcard *)
    | Prim (_, "_", [], []), _ -> true
    (* Int *)
    | Int (_p_loc, p), Int (_e_loc, e) -> Z.equal p e
    | Int _, _ | _, Int _ -> false
    (* String *)
    | String (_p_loc, p), String (_e_loc, e) -> Compare.String.(p = e)
    | String _, _ | _, String _ -> false
    (* Bytes *)
    | Bytes (_p_loc, p), Bytes (_e_loc, e) -> Compare.Bytes.(p = e)
    | Bytes _, _ | _, Bytes _ -> false
    (* Seq *)
    | Seq (_p_loc, p), Seq (_e_loc, e) -> (
        match List.for_all2 ~when_different_lengths:() match_pattern p e with
        | Ok b -> b
        | Error () -> false)
    | Seq _, _ | _, Seq _ -> false
    (* Prim *)
    | ( Prim (_p_loc, p_prim, p_args, p_annots),
        Prim (_e_loc, e_prim, e_args, e_annots) ) -> (
        Compare.String.(p_prim = "_" || p_prim = e_prim)
        && (match
              List.for_all2
                ~when_different_lengths:()
                match_pattern
                p_args
                e_args
            with
           | Ok b -> b
           | Error () -> false)
        &&
        match
          List.for_all2
            ~when_different_lengths:()
            Compare.String.( = )
            p_annots
            e_annots
        with
        | Ok b -> b
        | Error () -> false)
  in
  if match_pattern expected got then return_unit
  else
    let pp fmt e =
      Micheline_printer.print_expr_unwrapped
        fmt
        (Micheline_printer.printable Fun.id (Micheline.strip_locations e))
    in
    (* TODO: proper error instead of failwith *)
    error_with "Got output: %a@.Expected: %a@." pp got pp expected

let run_unit_test (cctxt : #Protocol_client_context.rpc_context)
    ~(chain : Chain_services.chain) ~block ~(test : unit_test_with_source) () =
  let open Lwt_result_syntax in
  let*? ut = Michelson_v1_stack.parse_unit_test test.parsed in
  let all_contracts =
    let other_contracts =
      Option.value ~default:[] ut.optional.other_contracts
    in
    match (ut.optional.self, ut.optional.parameter) with
    | Some self, Some param ->
        RPC.Scripts.S.{address = self; ty = param} :: other_contracts
    | None, _ | Some _, None -> other_contracts
  in
  let* chain_id =
    match ut.optional.chain_id with
    | Some chain_id -> return chain_id
    | None -> Chain_services.chain_id cctxt ~chain ()
  in
  let amount = Option.value ~default:Tez.zero ut.optional.amount in
  let*! res =
    match ut.output with
    | Micheline.Seq _ as stack ->
        let*? stack = Michelson_v1_stack.parse_stack ~node:stack test.parsed in
        let* stack =
          Plugin.RPC.Scripts.normalize_stack
            cctxt
            (chain, block)
            ~stack
            ~unparsing_mode:Readable
            ~legacy:true
            ~other_contracts:(Some all_contracts)
            ~extra_big_maps:ut.optional.extra_big_maps
        in
        return (Michelson_v1_printer.unparse_stack 0 stack)
    | expected_output -> return expected_output
  in
  (* Wildcard patterns in output stack is incompatible with output stack normalization.
     When the output stack contains a wildcard pattern, the normalization is expected
     to fail. To support wildcard patterns, we silently skip output stack normalization
     when it fails. *)
  let expected_output = match res with Ok x -> x | Error _ -> ut.output in
  let*! res =
    Plugin.RPC.Scripts.run_instr
      ~legacy:true
      ~gas:None
      ~input:ut.input
      ~code:ut.code
      ~now:ut.optional.now
      ~level:ut.optional.level
      ~sender:ut.optional.sender
      ~source:ut.optional.source
      ~chain_id
      ~self:ut.optional.self
      ~parameter:ut.optional.parameter
      ~amount
      ~balance:ut.optional.balance
      ~other_contracts:(Some all_contracts)
      ~extra_big_maps:ut.optional.extra_big_maps
      ~unparsing_mode:None
      cctxt
      (chain, block)
  in
  let*? output =
    match res with
    | Ok (output, _gas) ->
        Result_syntax.return (Michelson_v1_printer.unparse_stack 0 output)
    | Error err -> convert_trace err
  in
  let*? () = match_output ~expected:expected_output ~got:output in
  return_unit
OCaml

Innovation. Community. Security.