Alpha, Gas: gas accounting for serialization of data and types

Also gas accounting in errors, failures and trace
This commit is contained in:
Alain Mebsout 2018-06-27 12:39:28 +02:00 committed by Benjamin Canou
parent fa4a3a9fe4
commit a69333d21f
10 changed files with 598 additions and 447 deletions

View File

@ -10,39 +10,32 @@
open Proto_alpha open Proto_alpha
open Alpha_context open Alpha_context
open Tezos_micheline open Tezos_micheline
open Script_typed_ir
open Script_tc_errors open Script_tc_errors
open Script_ir_annot
open Script_ir_translator
open Script_interpreter open Script_interpreter
open Michelson_v1_printer open Michelson_v1_printer
let print_ty (type t) ppf (ty : t ty) = let print_ty ppf ty =
unparse_ty ty Michelson_v1_printer.print_expr_unwrapped ppf ty
|> Micheline.strip_locations
|> Michelson_v1_printer.print_expr_unwrapped ppf
let print_var_annot ppf annot = let print_var_annot ppf annot =
List.iter (Format.fprintf ppf "@ %s") (unparse_var_annot annot) List.iter (Format.fprintf ppf "@ %s") annot
let print_stack_ty (type t) ?(depth = max_int) ppf (s : t stack_ty) = let print_stack_ty ?(depth = max_int) ppf s =
let rec loop let rec loop depth ppf = function
: type t. int -> Format.formatter -> t stack_ty -> unit | [] -> ()
= fun depth ppf -> function
| Empty_t -> ()
| _ when depth <= 0 -> | _ when depth <= 0 ->
Format.fprintf ppf "..." Format.fprintf ppf "..."
| Item_t (last, Empty_t, annot) -> | [last, annot] ->
Format.fprintf ppf "%a%a" Format.fprintf ppf "%a%a"
print_ty last print_ty last
print_var_annot annot print_var_annot annot
| Item_t (last, rest, annot) -> | (last, annot) :: rest ->
Format.fprintf ppf "%a%a@ :@ %a" Format.fprintf ppf "%a%a@ :@ %a"
print_ty last print_ty last
print_var_annot annot print_var_annot annot
(loop (depth - 1)) rest in (loop (depth - 1)) rest in
match s with match s with
| Empty_t -> | [] ->
Format.fprintf ppf "[]" Format.fprintf ppf "[]"
| sty -> | sty ->
Format.fprintf ppf "@[<hov 2>[ %a ]@]" (loop depth) sty Format.fprintf ppf "@[<hov 2>[ %a ]@]" (loop depth) sty
@ -338,7 +331,7 @@ let report_errors ~details ~show_source ?parsed ppf errs =
- @[<v 0>expected return stack type:@ %a,@]@,\ - @[<v 0>expected return stack type:@ %a,@]@,\
- @[<v 0>actual stack type:@ %a.@]@]" - @[<v 0>actual stack type:@ %a.@]@]"
print_loc loc print_loc loc
(fun ppf -> print_stack_ty ppf) (Item_t (exp, Empty_t, None)) (fun ppf -> print_stack_ty ppf) [exp, []]
(fun ppf -> print_stack_ty ppf) got (fun ppf -> print_stack_ty ppf) got
| Bad_stack (loc, name, depth, sty) -> | Bad_stack (loc, name, depth, sty) ->
Format.fprintf ppf Format.fprintf ppf

View File

@ -200,7 +200,7 @@ module Scripts = struct
let ctxt = match maybe_gas with let ctxt = match maybe_gas with
| None -> Gas.set_unlimited ctxt | None -> Gas.set_unlimited ctxt
| Some gas -> Gas.set_limit ctxt gas in | Some gas -> Gas.set_limit ctxt gas in
Lwt.return (parse_ty ~allow_big_map:false ~allow_operation:false (Micheline.root typ)) >>=? fun (Ex_ty typ) -> Lwt.return (parse_ty ctxt ~allow_big_map:false ~allow_operation:false (Micheline.root typ)) >>=? fun (Ex_ty typ) ->
parse_data ctxt typ (Micheline.root expr) >>=? fun (data, ctxt) -> parse_data ctxt typ (Micheline.root expr) >>=? fun (data, ctxt) ->
Script_ir_translator.pack_data ctxt typ data >>=? fun (bytes, ctxt) -> Script_ir_translator.pack_data ctxt typ data >>=? fun (bytes, ctxt) ->
return (bytes, Gas.level ctxt) return (bytes, Gas.level ctxt)

View File

@ -236,21 +236,27 @@ module Cost_of = struct
end end
module Unparse = struct module Unparse = struct
let prim_cost = alloc_cost 4 (* location, primitive name, list, annotation *) let prim_cost nb_args =
alloc_cost 4 (* location, primitive name, list, annotation *) +@
(nb_args *@ alloc_cost 2)
let seq_cost nb_args =
alloc_cost 2 (* location, list *) +@
(nb_args *@ alloc_cost 2)
let string_cost length = let string_cost length =
alloc_cost 3 +@ alloc_bytes_cost length alloc_cost 3 +@ alloc_bytes_cost length
let cycle = step_cost 1 let cycle = step_cost 1
let bool = prim_cost let bool = prim_cost 0
let unit = prim_cost let unit = prim_cost 0
(* FIXME: not sure we should count the length of strings and bytes (* FIXME: not sure we should count the length of strings and bytes
as they are shared *) as they are shared *)
let string s = string_cost (String.length s) let string s = string_cost (String.length s)
let bytes s = alloc_bytes_cost (MBytes.length s) let bytes s = alloc_bytes_cost (MBytes.length s)
(* Approximates log10(x) *) (* Approximates log10(x) *)
let int i = let z i =
let decimal_digits = (Z.numbits (Z.abs (Script_int.to_zint i))) / 4 in let decimal_digits = (Z.numbits (Z.abs i)) / 4 in
prim_cost +@ (alloc_bytes_cost decimal_digits) prim_cost 0 +@ (alloc_bytes_cost decimal_digits)
let int i = z (Script_int.to_zint i)
let tez = string_cost 19 (* max length of 64 bit int *) let tez = string_cost 19 (* max length of 64 bit int *)
let timestamp x = Script_timestamp.to_zint x |> Script_int.of_zint |> int let timestamp x = Script_timestamp.to_zint x |> Script_int.of_zint |> int
let operation bytes = string_cost (MBytes.length bytes * 2) let operation bytes = string_cost (MBytes.length bytes * 2)
@ -258,17 +264,15 @@ module Cost_of = struct
let key_hash = string_cost 36 let key_hash = string_cost 36
let signature = string_cost 128 let signature = string_cost 128
let contract = string_cost 36 let contract = string_cost 36
let pair = prim_cost +@ alloc_cost 4 let pair = prim_cost 2
let union = prim_cost +@ alloc_cost 2 let union = prim_cost 1
let lambda = prim_cost +@ alloc_cost 3 let some = prim_cost 1
let some = prim_cost +@ alloc_cost 2 let none = prim_cost 0
let none = prim_cost let list_element = prim_cost 1
let list_element = prim_cost +@ alloc_cost 2
let set_element = alloc_cost 2 let set_element = alloc_cost 2
let map_element = alloc_cost 2 let map_element = alloc_cost 2
let primitive_type = prim_cost let one_arg_type = prim_cost 1
let one_arg_type = prim_cost +@ alloc_cost 2 let two_arg_type = prim_cost 2
let two_arg_type = prim_cost +@ alloc_cost 4
let set_to_list = set_to_list let set_to_list = set_to_list
let map_to_list = map_to_list let map_to_list = map_to_list

View File

@ -135,9 +135,12 @@ module Cost_of : sig
end end
module Unparse : sig module Unparse : sig
val prim_cost : int -> Gas.cost
val seq_cost : int -> Gas.cost
val cycle : Gas.cost val cycle : Gas.cost
val unit : Gas.cost val unit : Gas.cost
val bool : Gas.cost val bool : Gas.cost
val z : Z.t -> Gas.cost
val int : 'a Script_int.num -> Gas.cost val int : 'a Script_int.num -> Gas.cost
val tez : Gas.cost val tez : Gas.cost
val string : string -> Gas.cost val string : string -> Gas.cost
@ -155,8 +158,6 @@ module Cost_of : sig
val union : Gas.cost val union : Gas.cost
val lambda : Gas.cost
val some : Gas.cost val some : Gas.cost
val none : Gas.cost val none : Gas.cost
@ -164,7 +165,6 @@ module Cost_of : sig
val set_element : Gas.cost val set_element : Gas.cost
val map_element : Gas.cost val map_element : Gas.cost
val primitive_type : Gas.cost
val one_arg_type : Gas.cost val one_arg_type : Gas.cost
val two_arg_type : Gas.cost val two_arg_type : Gas.cost
val set_to_list : 'a Script_typed_ir.set -> Gas.cost val set_to_list : 'a Script_typed_ir.set -> Gas.cost

View File

@ -21,6 +21,9 @@ type error += Reject of Script.location * Script.expr * execution_trace option
type error += Overflow of Script.location * execution_trace option type error += Overflow of Script.location * execution_trace option
type error += Runtime_contract_error : Contract.t * Script.expr -> error type error += Runtime_contract_error : Contract.t * Script.expr -> error
type error += Bad_contract_parameter of Contract.t (* `Permanent *) type error += Bad_contract_parameter of Contract.t (* `Permanent *)
type error += Cannot_serialize_log
type error += Cannot_serialize_failure
type error += Cannot_serialize_storage
let () = let () =
let open Data_encoding in let open Data_encoding in
@ -82,7 +85,37 @@ let () =
the wrong type" the wrong type"
Data_encoding.(obj1 (req "contract" Contract.encoding)) Data_encoding.(obj1 (req "contract" Contract.encoding))
(function Bad_contract_parameter c -> Some c | _ -> None) (function Bad_contract_parameter c -> Some c | _ -> None)
(fun c -> Bad_contract_parameter c) (fun c -> Bad_contract_parameter c) ;
(* Cannot serialize log *)
register_error_kind
`Temporary
~id:"cannotSerializeLog"
~title:"Not enough gas to serialize execution trace"
~description:"Execution trace with stacks was to big to be serialized with \
the provided gas"
Data_encoding.empty
(function Cannot_serialize_log -> Some () | _ -> None)
(fun () -> Cannot_serialize_log) ;
(* Cannot serialize failure *)
register_error_kind
`Temporary
~id:"cannotSerializeFailure"
~title:"Not enough gas to serialize argument of FAILWITH"
~description:"Argument of FAILWITH was too big to be serialized with \
the provided gas"
Data_encoding.empty
(function Cannot_serialize_failure -> Some () | _ -> None)
(fun () -> Cannot_serialize_failure) ;
(* Cannot serialize storage *)
register_error_kind
`Temporary
~id:"cannotSerializeStorage"
~title:"Not enough gas to serialize execution storage"
~description:"The returned storage was too big to be serialized with \
the provided gas"
Data_encoding.empty
(function Cannot_serialize_storage -> Some () | _ -> None)
(fun () -> Cannot_serialize_storage)
(* ---- interpreter ---------------------------------------------------------*) (* ---- interpreter ---------------------------------------------------------*)
@ -132,7 +165,9 @@ let rec interp
match log with match log with
| None -> return (ret, ctxt) | None -> return (ret, ctxt)
| Some log -> | Some log ->
unparse_stack ctxt (ret, descr.aft) >>=? fun stack -> trace
Cannot_serialize_log
(unparse_stack ctxt (ret, descr.aft)) >>=? fun stack ->
log := (descr.loc, Gas.level ctxt, stack) :: !log ; log := (descr.loc, Gas.level ctxt, stack) :: !log ;
return (ret, ctxt) in return (ret, ctxt) in
let get_log (log : execution_trace ref option) = let get_log (log : execution_trace ref option) =
@ -544,7 +579,8 @@ let rec interp
Lwt.return (Gas.consume ctxt Interp_costs.push) >>=? fun ctxt -> Lwt.return (Gas.consume ctxt Interp_costs.push) >>=? fun ctxt ->
logged_return (Item (lam, rest), ctxt) logged_return (Item (lam, rest), ctxt)
| Failwith tv, Item (v, _) -> | Failwith tv, Item (v, _) ->
unparse_data ctxt Optimized tv v >>=? fun (v, _ctxt) -> trace Cannot_serialize_failure
(unparse_data ctxt Optimized tv v) >>=? fun (v, _ctxt) ->
let v = Micheline.strip_locations v in let v = Micheline.strip_locations v in
fail (Reject (loc, v, get_log log)) fail (Reject (loc, v, get_log log))
| Nop, stack -> | Nop, stack ->
@ -658,10 +694,12 @@ let rec interp
(credit, Item (credit, Item
(init, rest)))))) -> (init, rest)))))) ->
Lwt.return (Gas.consume ctxt Interp_costs.create_contract) >>=? fun ctxt -> Lwt.return (Gas.consume ctxt Interp_costs.create_contract) >>=? fun ctxt ->
unparse_ty ctxt param_type >>=? fun (u_param_type, ctxt) ->
unparse_ty ctxt storage_type >>=? fun (u_storage_type, ctxt) ->
let code = let code =
Micheline.strip_locations Micheline.strip_locations
(Seq (0, [ Prim (0, K_parameter, [ unparse_ty param_type ], []) ; (Seq (0, [ Prim (0, K_parameter, [ u_param_type ], []) ;
Prim (0, K_storage, [ unparse_ty storage_type ], []) ; Prim (0, K_storage, [ u_storage_type ], []) ;
Prim (0, K_code, [ Micheline.root code ], []) ])) in Prim (0, K_code, [ Micheline.root code ], []) ])) in
unparse_data ctxt Optimized storage_type init >>=? fun (storage, ctxt) -> unparse_data ctxt Optimized storage_type init >>=? fun (storage, ctxt) ->
let storage = Micheline.strip_locations storage in let storage = Micheline.strip_locations storage in
@ -732,7 +770,8 @@ let rec interp
begin match log with begin match log with
| None -> return_unit | None -> return_unit
| Some log -> | Some log ->
unparse_stack ctxt (stack, code.bef) >>=? fun stack -> trace Cannot_serialize_log
(unparse_stack ctxt (stack, code.bef)) >>=? fun stack ->
log := (code.loc, Gas.level ctxt, stack) :: !log ; log := (code.loc, Gas.level ctxt, stack) :: !log ;
return_unit return_unit
end >>=? fun () -> end >>=? fun () ->
@ -755,7 +794,8 @@ and execute ?log ctxt mode ~source ~payer ~self script amount arg :
(Runtime_contract_error (self, script_code)) (Runtime_contract_error (self, script_code))
(interp ?log ctxt ~source ~payer ~self amount code (arg, storage)) (interp ?log ctxt ~source ~payer ~self amount code (arg, storage))
>>=? fun ((ops, sto), ctxt) -> >>=? fun ((ops, sto), ctxt) ->
unparse_data ctxt mode storage_type sto >>=? fun (storage, ctxt) -> trace Cannot_serialize_storage
(unparse_data ctxt mode storage_type sto) >>=? fun (storage, ctxt) ->
return (Micheline.strip_locations storage, ops, ctxt, return (Micheline.strip_locations storage, ops, ctxt,
Script_ir_translator.extract_big_map storage_type sto) Script_ir_translator.extract_big_map storage_type sto)

View File

@ -16,6 +16,9 @@ type error += Reject of Script.location * Script.expr * execution_trace option
type error += Overflow of Script.location * execution_trace option type error += Overflow of Script.location * execution_trace option
type error += Runtime_contract_error : Contract.t * Script.expr -> error type error += Runtime_contract_error : Contract.t * Script.expr -> error
type error += Bad_contract_parameter of Contract.t (* `Permanent *) type error += Bad_contract_parameter of Contract.t (* `Permanent *)
type error += Cannot_serialize_log
type error += Cannot_serialize_failure
type error += Cannot_serialize_storage
type execution_result = type execution_result =
{ ctxt : context ; { ctxt : context ;

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,7 @@ val big_map_update :
('key, 'value) Script_typed_ir.big_map ('key, 'value) Script_typed_ir.big_map
val ty_eq : val ty_eq :
context ->
'ta Script_typed_ir.ty -> 'tb Script_typed_ir.ty -> 'ta Script_typed_ir.ty -> 'tb Script_typed_ir.ty ->
('ta Script_typed_ir.ty, 'tb Script_typed_ir.ty) eq tzresult ('ta Script_typed_ir.ty, 'tb Script_typed_ir.ty) eq tzresult
@ -69,13 +70,16 @@ val unparse_data :
(Script.node * context) tzresult Lwt.t (Script.node * context) tzresult Lwt.t
val parse_ty : val parse_ty :
context ->
allow_big_map: bool -> allow_big_map: bool ->
allow_operation: bool -> allow_operation: bool ->
Script.node -> ex_ty tzresult Script.node -> ex_ty tzresult
val unparse_ty : 'a Script_typed_ir.ty -> Script.node
val parse_toplevel val unparse_ty :
: Script.expr -> (Script.node * Script.node * Script.node) tzresult context -> 'a Script_typed_ir.ty -> (Script.node * context) tzresult Lwt.t
val parse_toplevel :
Script.expr -> (Script.node * Script.node * Script.node) tzresult
val typecheck_code : val typecheck_code :
context -> Script.expr -> (type_map * context) tzresult Lwt.t context -> Script.expr -> (type_map * context) tzresult Lwt.t

View File

@ -9,7 +9,6 @@
open Alpha_context open Alpha_context
open Script open Script
open Script_typed_ir
(* ---- Error definitions ---------------------------------------------------*) (* ---- Error definitions ---------------------------------------------------*)
@ -17,7 +16,8 @@ open Script_typed_ir
(* Auxiliary types for error documentation *) (* Auxiliary types for error documentation *)
type namespace = Type_namespace | Constant_namespace | Instr_namespace | Keyword_namespace type namespace = Type_namespace | Constant_namespace | Instr_namespace | Keyword_namespace
type kind = Int_kind | String_kind | Bytes_kind | Prim_kind | Seq_kind type kind = Int_kind | String_kind | Bytes_kind | Prim_kind | Seq_kind
type type_map = (int * ((Script.expr * Script.annot) list * (Script.expr * Script.annot) list)) list type unparsed_stack_ty = (Script.expr * Script.annot) list
type type_map = (int * (unparsed_stack_ty * unparsed_stack_ty)) list
(* Structure errors *) (* Structure errors *)
type error += Invalid_arity of Script.location * prim * int * int type error += Invalid_arity of Script.location * prim * int * int
@ -31,35 +31,38 @@ type error += Unexpected_operation of Script.location
(* Instruction typing errors *) (* Instruction typing errors *)
type error += Fail_not_in_tail_position of Script.location type error += Fail_not_in_tail_position of Script.location
type error += Undefined_binop : Script.location * prim * _ ty * _ ty -> error type error += Undefined_binop : Script.location * prim * Script.expr * Script.expr -> error
type error += Undefined_unop : Script.location * prim * _ ty -> error type error += Undefined_unop : Script.location * prim * Script.expr -> error
type error += Bad_return : Script.location * _ stack_ty * _ ty -> error type error += Bad_return : Script.location * unparsed_stack_ty * Script.expr -> error
type error += Bad_stack : Script.location * prim * int * _ stack_ty -> error type error += Bad_stack : Script.location * prim * int * unparsed_stack_ty -> error
type error += Unmatched_branches : Script.location * _ stack_ty * _ stack_ty -> error type error += Unmatched_branches : Script.location * unparsed_stack_ty * unparsed_stack_ty -> error
type error += Self_in_lambda of Script.location type error += Self_in_lambda of Script.location
type error += Bad_stack_length type error += Bad_stack_length
type error += Bad_stack_item of int type error += Bad_stack_item of int
type error += Inconsistent_annotations of string * string type error += Inconsistent_annotations of string * string
type error += Inconsistent_type_annotations : Script.location * _ ty * _ ty -> error type error += Inconsistent_type_annotations : Script.location * Script.expr * Script.expr -> error
type error += Inconsistent_field_annotations of string * string type error += Inconsistent_field_annotations of string * string
type error += Unexpected_annotation of Script.location type error += Unexpected_annotation of Script.location
type error += Ungrouped_annotations of Script.location type error += Ungrouped_annotations of Script.location
type error += Invalid_map_body : Script.location * _ stack_ty -> error type error += Invalid_map_body : Script.location * unparsed_stack_ty -> error
type error += Invalid_map_block_fail of Script.location type error += Invalid_map_block_fail of Script.location
type error += Invalid_iter_body : Script.location * _ stack_ty * _ stack_ty -> error type error += Invalid_iter_body : Script.location * unparsed_stack_ty * unparsed_stack_ty -> error
type error += Type_too_large : Script.location * int * int -> error type error += Type_too_large : Script.location * int * int -> error
(* Value typing errors *) (* Value typing errors *)
type error += Invalid_constant : Script.location * Script.expr * _ ty -> error type error += Invalid_constant : Script.location * Script.expr * Script.expr -> error
type error += Invalid_contract of Script.location * Contract.t type error += Invalid_contract of Script.location * Contract.t
type error += Comparable_type_expected : Script.location * _ ty -> error type error += Comparable_type_expected : Script.location * Script.expr -> error
type error += Inconsistent_types : _ ty * _ ty -> error type error += Inconsistent_types : Script.expr * Script.expr -> error
type error += Unordered_map_keys of Script.location * Script.expr type error += Unordered_map_keys of Script.location * Script.expr
type error += Unordered_set_values of Script.location * Script.expr type error += Unordered_set_values of Script.location * Script.expr
type error += Duplicate_map_keys of Script.location * Script.expr type error += Duplicate_map_keys of Script.location * Script.expr
type error += Duplicate_set_values of Script.location * Script.expr type error += Duplicate_set_values of Script.location * Script.expr
(* Toplevel errors *) (* Toplevel errors *)
type error += Ill_typed_data : string option * Script.expr * _ ty -> error type error += Ill_typed_data : string option * Script.expr * Script.expr -> error
type error += Ill_formed_type of string option * Script.expr * Script.location type error += Ill_formed_type of string option * Script.expr * Script.location
type error += Ill_typed_contract : Script.expr * type_map -> error type error += Ill_typed_contract : Script.expr * type_map -> error
(* Gas related errors *)
type error += Cannot_serialize_error

View File

@ -8,11 +8,8 @@
(**************************************************************************) (**************************************************************************)
open Alpha_context open Alpha_context
open Micheline
open Script open Script
open Script_typed_ir
open Script_tc_errors open Script_tc_errors
open Script_ir_translator
(* Helpers for encoding *) (* Helpers for encoding *)
let type_map_enc = let type_map_enc =
@ -27,49 +24,12 @@ let type_map_enc =
(req "stackBefore" stack_enc) (req "stackBefore" stack_enc)
(req "stackAfter" stack_enc))) (req "stackAfter" stack_enc)))
let rec strip_var_annots = function let stack_ty_enc =
| Int _ | String _ | Bytes _ as atom -> atom
| Seq (loc, args) -> Seq (loc, List.map strip_var_annots args)
| Prim (loc, name, args, annots) ->
let not_var_annot s = Compare.Char.(String.get s 0 <> '@') in
let annots = List.filter not_var_annot annots in
Prim (loc, name, List.map strip_var_annots args, annots)
let ex_ty_enc =
Data_encoding.conv
(fun (Ex_ty ty) ->
strip_locations (strip_var_annots (unparse_ty ty)))
(fun expr ->
match parse_ty ~allow_big_map:true ~allow_operation:true (root expr) with
| Ok ty -> ty
| _ -> assert false)
Script.expr_encoding
let var_annot_enc =
let open Data_encoding in let open Data_encoding in
conv
(function `Var_annot x -> "@" ^ x)
(function x ->
assert (Compare.Int.(String.length x > 0) && Compare.Char.(String.get x 0 = '@')) ;
`Var_annot (String.sub x 1 (String.length x - 1)))
string
let ex_stack_ty_enc =
let open Data_encoding in
let rec unfold = function
| Ex_stack_ty (Item_t (ty, rest, annot)) ->
(Ex_ty ty, annot) :: unfold (Ex_stack_ty rest)
| Ex_stack_ty Empty_t -> [] in
let rec fold = function
| (Ex_ty ty, annot) :: rest ->
let Ex_stack_ty rest = fold rest in
Ex_stack_ty (Item_t (ty, rest, annot))
| [] -> Ex_stack_ty Empty_t in
conv unfold fold
(list (list
(obj2 (obj2
(req "type" ex_ty_enc) (req "type" Script.expr_encoding)
(opt "annot" var_annot_enc))) (dft "annots" (list string) [])))
(* main registration *) (* main registration *)
let () = let () =
@ -290,13 +250,13 @@ let () =
over which it is not defined." over which it is not defined."
(located (obj3 (located (obj3
(req "operatorName" prim_encoding) (req "operatorName" prim_encoding)
(req "wrongLeftOperandType" ex_ty_enc) (req "wrongLeftOperandType" Script.expr_encoding)
(req "wrongRightOperandType" ex_ty_enc))) (req "wrongRightOperandType" Script.expr_encoding)))
(function (function
| Undefined_binop (loc, n, tyl, tyr) -> | Undefined_binop (loc, n, tyl, tyr) ->
Some (loc, (n, Ex_ty tyl, Ex_ty tyr)) Some (loc, (n, tyl, tyr))
| _ -> None) | _ -> None)
(fun (loc, (n, Ex_ty tyl, Ex_ty tyr)) -> (fun (loc, (n, tyl, tyr)) ->
Undefined_binop (loc, n, tyl, tyr)) ; Undefined_binop (loc, n, tyl, tyr)) ;
(* Undefined unary operation *) (* Undefined unary operation *)
register_error_kind register_error_kind
@ -308,12 +268,12 @@ let () =
over which it is not defined." over which it is not defined."
(located (obj2 (located (obj2
(req "operatorName" prim_encoding) (req "operatorName" prim_encoding)
(req "wrongOperandType" ex_ty_enc))) (req "wrongOperandType" Script.expr_encoding)))
(function (function
| Undefined_unop (loc, n, ty) -> | Undefined_unop (loc, n, ty) ->
Some (loc, (n, Ex_ty ty)) Some (loc, (n, ty))
| _ -> None) | _ -> None)
(fun (loc, (n, Ex_ty ty)) -> (fun (loc, (n, ty)) ->
Undefined_unop (loc, n, ty)) ; Undefined_unop (loc, n, ty)) ;
(* Bad return *) (* Bad return *)
register_error_kind register_error_kind
@ -323,12 +283,12 @@ let () =
~description: ~description:
"Unexpected stack at the end of a lambda or script." "Unexpected stack at the end of a lambda or script."
(located (obj2 (located (obj2
(req "expectedReturnType" ex_ty_enc) (req "expectedReturnType" Script.expr_encoding)
(req "wrongStackType" ex_stack_ty_enc))) (req "wrongStackType" stack_ty_enc)))
(function (function
| Bad_return (loc, sty, ty) -> Some (loc, (Ex_ty ty, Ex_stack_ty sty)) | Bad_return (loc, sty, ty) -> Some (loc, (ty, sty))
| _ -> None) | _ -> None)
(fun (loc, (Ex_ty ty, Ex_stack_ty sty)) -> (fun (loc, (ty, sty)) ->
Bad_return (loc, sty, ty)) ; Bad_return (loc, sty, ty)) ;
(* Bad stack *) (* Bad stack *)
register_error_kind register_error_kind
@ -340,11 +300,11 @@ let () =
(located (obj3 (located (obj3
(req "primitiveName" prim_encoding) (req "primitiveName" prim_encoding)
(req "relevantStackPortion" int16) (req "relevantStackPortion" int16)
(req "wrongStackType" ex_stack_ty_enc))) (req "wrongStackType" stack_ty_enc)))
(function (function
| Bad_stack (loc, name, s, sty) -> Some (loc, (name, s, Ex_stack_ty sty)) | Bad_stack (loc, name, s, sty) -> Some (loc, (name, s, sty))
| _ -> None) | _ -> None)
(fun (loc, (name, s, Ex_stack_ty sty)) -> (fun (loc, (name, s, sty)) ->
Bad_stack (loc, name, s, sty)) ; Bad_stack (loc, name, s, sty)) ;
(* Inconsistent annotations *) (* Inconsistent annotations *)
register_error_kind register_error_kind
@ -377,12 +337,12 @@ let () =
~title:"Types contain inconsistent annotations" ~title:"Types contain inconsistent annotations"
~description:"The two types contain annotations that do not match" ~description:"The two types contain annotations that do not match"
(located (obj2 (located (obj2
(req "type1" ex_ty_enc) (req "type1" Script.expr_encoding)
(req "type2" ex_ty_enc))) (req "type2" Script.expr_encoding)))
(function (function
| Inconsistent_type_annotations (loc, ty1, ty2) -> Some (loc, (Ex_ty ty1, Ex_ty ty2)) | Inconsistent_type_annotations (loc, ty1, ty2) -> Some (loc, (ty1, ty2))
| _ -> None) | _ -> None)
(fun (loc, (Ex_ty ty1, Ex_ty ty2)) -> Inconsistent_type_annotations (loc, ty1, ty2)) ; (fun (loc, (ty1, ty2)) -> Inconsistent_type_annotations (loc, ty1, ty2)) ;
(* Unexpected annotation *) (* Unexpected annotation *)
register_error_kind register_error_kind
`Permanent `Permanent
@ -412,13 +372,13 @@ let () =
"At the join point at the end of two code branches \ "At the join point at the end of two code branches \
the stacks have inconsistent lengths or contents." the stacks have inconsistent lengths or contents."
(located (obj2 (located (obj2
(req "firstStackType" ex_stack_ty_enc) (req "firstStackType" stack_ty_enc)
(req "otherStackType" ex_stack_ty_enc))) (req "otherStackType" stack_ty_enc)))
(function (function
| Unmatched_branches (loc, stya, styb) -> | Unmatched_branches (loc, stya, styb) ->
Some (loc, (Ex_stack_ty stya, Ex_stack_ty styb)) Some (loc, (stya, styb))
| _ -> None) | _ -> None)
(fun (loc, (Ex_stack_ty stya, Ex_stack_ty styb)) -> (fun (loc, (stya, styb)) ->
Unmatched_branches (loc, stya, styb)) ; Unmatched_branches (loc, stya, styb)) ;
(* Bad stack item *) (* Bad stack item *)
register_error_kind register_error_kind
@ -470,13 +430,13 @@ let () =
~description: ~description:
"A data expression was invalid for its expected type." "A data expression was invalid for its expected type."
(located (obj2 (located (obj2
(req "expectedType" ex_ty_enc) (req "expectedType" Script.expr_encoding)
(req "wrongExpression" Script.expr_encoding))) (req "wrongExpression" Script.expr_encoding)))
(function (function
| Invalid_constant (loc, expr, ty) -> | Invalid_constant (loc, expr, ty) ->
Some (loc, (Ex_ty ty, expr)) Some (loc, (ty, expr))
| _ -> None) | _ -> None)
(fun (loc, (Ex_ty ty, expr)) -> (fun (loc, (ty, expr)) ->
Invalid_constant (loc, expr, ty)) ; Invalid_constant (loc, expr, ty)) ;
(* Invalid contract *) (* Invalid contract *)
register_error_kind register_error_kind
@ -501,11 +461,11 @@ let () =
~description: ~description:
"A non comparable type was used in a place where \ "A non comparable type was used in a place where \
only comparable types are accepted." only comparable types are accepted."
(located (obj1 (req "wrongType" ex_ty_enc))) (located (obj1 (req "wrongType" Script.expr_encoding)))
(function (function
| Comparable_type_expected (loc, ty) -> Some (loc, Ex_ty ty) | Comparable_type_expected (loc, ty) -> Some (loc, ty)
| _ -> None) | _ -> None)
(fun (loc, Ex_ty ty) -> (fun (loc, ty) ->
Comparable_type_expected (loc, ty)) ; Comparable_type_expected (loc, ty)) ;
(* Inconsistent types *) (* Inconsistent types *)
register_error_kind register_error_kind
@ -518,14 +478,12 @@ let () =
two types have to be proven, it is always accompanied \ two types have to be proven, it is always accompanied \
with another error that provides more context." with another error that provides more context."
(obj2 (obj2
(req "firstType" ex_ty_enc) (req "firstType" Script.expr_encoding)
(req "otherType" ex_ty_enc)) (req "otherType" Script.expr_encoding))
(function (function
| Inconsistent_types (tya, tyb) -> | Inconsistent_types (tya, tyb) -> Some (tya, tyb)
Some (Ex_ty tya, Ex_ty tyb)
| _ -> None) | _ -> None)
(fun (Ex_ty tya, Ex_ty tyb) -> (fun (tya, tyb) -> Inconsistent_types (tya, tyb)) ;
Inconsistent_types (tya, tyb)) ;
(* -- Instruction typing errors ------------------- *) (* -- Instruction typing errors ------------------- *)
(* Invalid map body *) (* Invalid map body *)
register_error_kind register_error_kind
@ -536,13 +494,11 @@ let () =
"The body of a map block did not match the expected type" "The body of a map block did not match the expected type"
(obj2 (obj2
(req "loc" Script.location_encoding) (req "loc" Script.location_encoding)
(req "bodyType" ex_stack_ty_enc)) (req "bodyType" stack_ty_enc))
(function (function
| Invalid_map_body (loc, stack) -> | Invalid_map_body (loc, stack) -> Some (loc, stack)
Some (loc, Ex_stack_ty stack)
| _ -> None) | _ -> None)
(fun (loc, Ex_stack_ty stack) -> (fun (loc, stack) -> Invalid_map_body (loc, stack)) ;
Invalid_map_body (loc, stack)) ;
(* Invalid map block FAIL *) (* Invalid map block FAIL *)
register_error_kind register_error_kind
`Permanent `Permanent
@ -565,12 +521,12 @@ let () =
the ITER." the ITER."
(obj3 (obj3
(req "loc" Script.location_encoding) (req "loc" Script.location_encoding)
(req "befStack" ex_stack_ty_enc) (req "befStack" stack_ty_enc)
(req "aftStack" ex_stack_ty_enc)) (req "aftStack" stack_ty_enc))
(function (function
| Invalid_iter_body (loc, bef, aft) -> Some (loc, Ex_stack_ty bef, Ex_stack_ty aft) | Invalid_iter_body (loc, bef, aft) -> Some (loc, bef, aft)
| _ -> None) | _ -> None)
(fun (loc, Ex_stack_ty bef, Ex_stack_ty aft) -> Invalid_iter_body (loc, bef, aft)) ; (fun (loc, bef, aft) -> Invalid_iter_body (loc, bef, aft)) ;
(* Type too large *) (* Type too large *)
register_error_kind register_error_kind
`Permanent `Permanent
@ -597,13 +553,12 @@ let () =
(always followed by more precise errors)." (always followed by more precise errors)."
(obj3 (obj3
(opt "identifier" string) (opt "identifier" string)
(req "expectedType" ex_ty_enc) (req "expectedType" Script.expr_encoding)
(req "illTypedExpression" Script.expr_encoding)) (req "illTypedExpression" Script.expr_encoding))
(function (function
| Ill_typed_data (name, expr, ty) -> Some (name, Ex_ty ty, expr) | Ill_typed_data (name, expr, ty) -> Some (name, ty, expr)
| _ -> None) | _ -> None)
(fun (name, Ex_ty ty, expr) -> (fun (name, ty, expr) -> Ill_typed_data (name, expr, ty)) ;
Ill_typed_data (name, expr, ty)) ;
(* Ill formed type *) (* Ill formed type *)
register_error_kind register_error_kind
`Permanent `Permanent
@ -638,4 +593,14 @@ let () =
Some (expr, type_map) Some (expr, type_map)
| _ -> None) | _ -> None)
(fun (expr, type_map) -> (fun (expr, type_map) ->
Ill_typed_contract (expr, type_map)) Ill_typed_contract (expr, type_map)) ;
(* Cannot serialize error *)
register_error_kind
`Temporary
~id:"cannotSerializeError"
~title:"Not enough gas to serialize error"
~description:"The error was too big to be serialized with \
the provided gas"
Data_encoding.empty
(function Cannot_serialize_error -> Some () | _ -> None)
(fun () -> Cannot_serialize_error)