diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index 1074703f8c6defaca79cad2a2502b472f722b1da..d026951e852d8af38182bc3bf8d81ac35a525732 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -67,6 +67,10 @@ Minor Changes - Arithmetic errors on Michelson ``mutez`` type have been exported so they can now be caught outside of the protocol. (MR :gl:`!9934`) +- Michelson error traces for elaboration of invalid data was made more + consistent by adding errors in some cases (BLS12-381 values, Sapling + transactions, and timelocks). (MR :gl:`!10227`) + Internal -------- @@ -74,4 +78,4 @@ Internal previously not registered, making the error message a bit obscure. (MR :gl:`!9603`) - Move some Michelson elaboration and erasure functions to the gas - monad. (MR :gl:`!10071`) + monad. (MR :gl:`!10071`, :gl:`!10211`) diff --git a/src/proto_alpha/lib_protocol/script_ir_translator.ml b/src/proto_alpha/lib_protocol/script_ir_translator.ml index 05e977e164f8b4213deb4011c81341a6bc3f6515..2fcb84fe85c07821d954e6b168777df154cef830 100644 --- a/src/proto_alpha/lib_protocol/script_ir_translator.ml +++ b/src/proto_alpha/lib_protocol/script_ir_translator.ml @@ -1435,105 +1435,109 @@ let opened_ticket_type loc ty = comparable_pair_3_t loc address_t ty nat_t (* -- parse data of primitive types -- *) -let parse_unit ctxt ~legacy = - let open Result_syntax in +let parse_unit ~legacy = + let open Gas_monad.Syntax in function | Prim (loc, D_Unit, [], annot) -> - let* () = - if legacy (* Legacy check introduced before Ithaca. *) then return_unit + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result.return_unit else error_unexpected_annot loc annot in - let+ ctxt = Gas.consume ctxt Typecheck_costs.unit in - ((), ctxt) + let+$ () = Typecheck_costs.unit in + () | Prim (loc, D_Unit, l, _) -> tzfail @@ Invalid_arity (loc, D_Unit, 0, List.length l) | expr -> tzfail @@ unexpected expr [] Constant_namespace [D_Unit] -let parse_bool ctxt ~legacy = - let open Result_syntax in +let parse_bool ~legacy = + let open Gas_monad.Syntax in function | Prim (loc, D_True, [], annot) -> - let* () = - if legacy (* Legacy check introduced before Ithaca. *) then return_unit + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result.return_unit else error_unexpected_annot loc annot in - let+ ctxt = Gas.consume ctxt Typecheck_costs.bool in - (true, ctxt) + let+$ () = Typecheck_costs.bool in + true | Prim (loc, D_False, [], annot) -> - let* () = - if legacy (* Legacy check introduced before Ithaca. *) then return_unit + let*? () = + if legacy (* Legacy check introduced before Ithaca. *) then + Result.return_unit else error_unexpected_annot loc annot in - let+ ctxt = Gas.consume ctxt Typecheck_costs.bool in - (false, ctxt) + let+$ () = Typecheck_costs.bool in + false | Prim (loc, ((D_True | D_False) as c), l, _) -> tzfail @@ Invalid_arity (loc, c, 0, List.length l) | expr -> tzfail @@ unexpected expr [] Constant_namespace [D_True; D_False] -let parse_string ctxt : Script.node -> (Script_string.t * context) tzresult = - let open Result_syntax in +let parse_string : Script.node -> (Script_string.t, error trace) Gas_monad.t = + let open Gas_monad.Syntax in function | String (loc, v) as expr -> - let* ctxt = Gas.consume ctxt (Typecheck_costs.check_printable v) in - record_trace - (Invalid_syntactic_constant - (loc, strip_locations expr, "a printable ascii string")) - (let+ s = Script_string.of_string v in - (s, ctxt)) + let*$ () = Typecheck_costs.check_printable v in + Gas_monad.record_trace_eval + ~error_details:(Informative ()) + (fun () -> + Invalid_syntactic_constant + (loc, strip_locations expr, "a printable ascii string")) + (Gas_monad.of_result @@ Script_string.of_string v) | expr -> tzfail @@ Invalid_kind (location expr, [String_kind], kind expr) -let parse_bytes ctxt = - let open Result_syntax in +let parse_bytes = + let open Gas_monad.Syntax in function - | Bytes (_, v) -> return (v, ctxt) + | Bytes (_, v) -> return v | expr -> tzfail @@ Invalid_kind (location expr, [Bytes_kind], kind expr) -let parse_int ctxt = - let open Result_syntax in +let parse_int = + let open Gas_monad.Syntax in function - | Int (_, v) -> return (Script_int.of_zint v, ctxt) + | Int (_, v) -> return (Script_int.of_zint v) | expr -> tzfail @@ Invalid_kind (location expr, [Int_kind], kind expr) -let parse_nat ctxt : - Script.node -> (Script_int.n Script_int.num * context) tzresult = - let open Result_syntax in +let parse_nat : + Script.node -> (Script_int.n Script_int.num, error trace) Gas_monad.t = + let open Gas_monad.Syntax in function | Int (loc, v) as expr -> ( let v = Script_int.of_zint v in match Script_int.is_nat v with - | Some nat -> return (nat, ctxt) + | Some nat -> return nat | None -> tzfail @@ Invalid_syntactic_constant (loc, strip_locations expr, "a non-negative integer")) | expr -> tzfail @@ Invalid_kind (location expr, [Int_kind], kind expr) -let parse_mutez ctxt : Script.node -> (Tez.t * context) tzresult = - let open Result_syntax in +let parse_mutez : Script.node -> (Tez.t, error trace) Gas_monad.t = + let open Gas_monad.Syntax in function | Int (loc, v) as expr -> ( match let open Option in bind (catch (fun () -> Z.to_int64 v)) Tez.of_mutez with - | Some tez -> Ok (tez, ctxt) + | Some tez -> return tez | None -> tzfail @@ Invalid_syntactic_constant (loc, strip_locations expr, "a valid mutez amount")) | expr -> tzfail @@ Invalid_kind (location expr, [Int_kind], kind expr) -let parse_timestamp ctxt : - Script.node -> (Script_timestamp.t * context) tzresult = - let open Result_syntax in +let parse_timestamp : + Script.node -> (Script_timestamp.t, error trace) Gas_monad.t = + let open Gas_monad.Syntax in function | Int (_, v) (* As unparsed with [Optimized] or out of bounds [Readable]. *) -> - return (Script_timestamp.of_zint v, ctxt) + return (Script_timestamp.of_zint v) | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( - let* ctxt = Gas.consume ctxt (Typecheck_costs.timestamp_readable s) in + let*$ () = Typecheck_costs.timestamp_readable s in match Script_timestamp.of_string s with - | Some v -> return (v, ctxt) + | Some v -> return v | None -> tzfail @@ Invalid_syntactic_constant @@ -1541,25 +1545,25 @@ let parse_timestamp ctxt : | expr -> tzfail @@ Invalid_kind (location expr, [String_kind; Int_kind], kind expr) -let parse_key ctxt : Script.node -> (public_key * context) tzresult = - let open Result_syntax in +let parse_key : Script.node -> (public_key, error trace) Gas_monad.t = + let open Gas_monad.Syntax in function | Bytes (loc, bytes) as expr -> ( (* As unparsed with [Optimized]. *) - let* ctxt = Gas.consume ctxt Typecheck_costs.public_key_optimized in + let*$ () = Typecheck_costs.public_key_optimized in match Data_encoding.Binary.of_bytes_opt Signature.Public_key.encoding bytes with - | Some k -> return (k, ctxt) + | Some k -> return k | None -> tzfail @@ Invalid_syntactic_constant (loc, strip_locations expr, "a valid public key")) | String (loc, s) as expr -> ( (* As unparsed with [Readable]. *) - let* ctxt = Gas.consume ctxt Typecheck_costs.public_key_readable in + let*$ () = Typecheck_costs.public_key_readable in match Signature.Public_key.of_b58check_opt s with - | Some k -> return (k, ctxt) + | Some k -> return k | None -> tzfail @@ Invalid_syntactic_constant @@ -1568,26 +1572,26 @@ let parse_key ctxt : Script.node -> (public_key * context) tzresult = tzfail @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) -let parse_key_hash ctxt : Script.node -> (public_key_hash * context) tzresult = - let open Result_syntax in +let parse_key_hash : Script.node -> (public_key_hash, error trace) Gas_monad.t = + let open Gas_monad.Syntax in function | Bytes (loc, bytes) as expr -> ( (* As unparsed with [Optimized]. *) - let* ctxt = Gas.consume ctxt Typecheck_costs.key_hash_optimized in + let*$ () = Typecheck_costs.key_hash_optimized in match Data_encoding.Binary.of_bytes_opt Signature.Public_key_hash.encoding bytes with - | Some k -> return (k, ctxt) + | Some k -> return k | None -> tzfail @@ Invalid_syntactic_constant (loc, strip_locations expr, "a valid key hash")) | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( - let* ctxt = Gas.consume ctxt Typecheck_costs.key_hash_readable in + let*$ () = Typecheck_costs.key_hash_readable in match Signature.Public_key_hash.of_b58check_opt s with - | Some k -> return (k, ctxt) + | Some k -> return k | None -> tzfail @@ Invalid_syntactic_constant @@ -1596,23 +1600,23 @@ let parse_key_hash ctxt : Script.node -> (public_key_hash * context) tzresult = tzfail @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) -let parse_signature ctxt : Script.node -> (signature * context) tzresult = - let open Result_syntax in +let parse_signature : Script.node -> (signature, error trace) Gas_monad.t = + let open Gas_monad.Syntax in function | Bytes (loc, bytes) as expr (* As unparsed with [Optimized]. *) -> ( - let* ctxt = Gas.consume ctxt Typecheck_costs.signature_optimized in + let*$ () = Typecheck_costs.signature_optimized in match Data_encoding.Binary.of_bytes_opt Script_signature.encoding bytes with - | Some k -> return (k, ctxt) + | Some k -> return k | None -> tzfail @@ Invalid_syntactic_constant (loc, strip_locations expr, "a valid signature")) | String (loc, s) as expr (* As unparsed with [Readable]. *) -> ( - let* ctxt = Gas.consume ctxt Typecheck_costs.signature_readable in + let*$ () = Typecheck_costs.signature_readable in match Script_signature.of_b58check_opt s with - | Some s -> return (s, ctxt) + | Some s -> return s | None -> tzfail @@ Invalid_syntactic_constant @@ -1621,24 +1625,24 @@ let parse_signature ctxt : Script.node -> (signature * context) tzresult = tzfail @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) -let parse_chain_id ctxt : Script.node -> (Script_chain_id.t * context) tzresult +let parse_chain_id : Script.node -> (Script_chain_id.t, error trace) Gas_monad.t = - let open Result_syntax in + let open Gas_monad.Syntax in function | Bytes (loc, bytes) as expr -> ( - let* ctxt = Gas.consume ctxt Typecheck_costs.chain_id_optimized in + let*$ () = Typecheck_costs.chain_id_optimized in match Data_encoding.Binary.of_bytes_opt Script_chain_id.encoding bytes with - | Some k -> return (k, ctxt) + | Some k -> return k | None -> tzfail @@ Invalid_syntactic_constant (loc, strip_locations expr, "a valid chain id")) | String (loc, s) as expr -> ( - let* ctxt = Gas.consume ctxt Typecheck_costs.chain_id_readable in + let*$ () = Typecheck_costs.chain_id_readable in match Script_chain_id.of_b58check_opt s with - | Some s -> return (s, ctxt) + | Some s -> return s | None -> tzfail @@ Invalid_syntactic_constant @@ -1647,49 +1651,183 @@ let parse_chain_id ctxt : Script.node -> (Script_chain_id.t * context) tzresult tzfail @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) -let parse_address ctxt : Script.node -> (address * context) tzresult = - let open Result_syntax in - let destination_allowed loc {destination; entrypoint} ctxt = +let parse_address ~sc_rollup_enable ~zk_rollup_enable : + Script.node -> (address, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + let destination_allowed loc {destination; entrypoint} = match destination with - | Destination.Sc_rollup _ when not (Constants.sc_rollup_enable ctxt) -> + | Destination.Sc_rollup _ when not sc_rollup_enable -> tzfail @@ Sc_rollup_disabled loc - | Destination.Zk_rollup _ when not (Constants.zk_rollup_enable ctxt) -> + | Destination.Zk_rollup _ when not zk_rollup_enable -> tzfail @@ Zk_rollup_disabled loc - | _ -> Ok ({destination; entrypoint}, ctxt) + | _ -> return {destination; entrypoint} in function | Bytes (loc, bytes) as expr (* As unparsed with [Optimized]. *) -> ( - let* ctxt = Gas.consume ctxt Typecheck_costs.contract_optimized in + let*$ () = Typecheck_costs.contract_optimized in match Data_encoding.Binary.of_bytes_opt Data_encoding.(tup2 Destination.encoding Entrypoint.value_encoding) bytes with | Some (destination, entrypoint) -> - destination_allowed loc {destination; entrypoint} ctxt + destination_allowed loc {destination; entrypoint} | None -> tzfail @@ Invalid_syntactic_constant (loc, strip_locations expr, "a valid address")) | String (loc, s) (* As unparsed with [Readable]. *) -> - let* ctxt = Gas.consume ctxt Typecheck_costs.contract_readable in + let*$ () = Typecheck_costs.contract_readable in let* addr, entrypoint = match String.index_opt s '%' with | None -> return (s, Entrypoint.default) | Some pos -> let len = String.length s - pos - 1 in let name = String.sub s (pos + 1) len in - let+ entrypoint = Entrypoint.of_string_strict ~loc name in + let+? entrypoint = Entrypoint.of_string_strict ~loc name in (String.sub s 0 pos, entrypoint) in - let* destination = Destination.of_b58check addr in - destination_allowed loc {destination; entrypoint} ctxt + let*? destination = Destination.of_b58check addr in + destination_allowed loc {destination; entrypoint} | expr -> tzfail @@ Invalid_kind (location expr, [String_kind; Bytes_kind], kind expr) -let parse_never expr : (never * context) tzresult = - Result_syntax.tzfail @@ Invalid_never_expr (location expr) +let parse_never expr : (never, error trace) Gas_monad.t = + Gas_monad.Syntax.tzfail @@ Invalid_never_expr (location expr) + +let parse_bls12_381_g1 : + Script.node -> (Script_bls.G1.t, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + function + | Bytes (loc, bs) as expr -> ( + let*$ () = Typecheck_costs.bls12_381_g1 in + match Script_bls.G1.of_bytes_opt bs with + | Some pt -> return pt + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid BLS12-381 G1 element"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_bls12_381_g2 : + Script.node -> (Script_bls.G2.t, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + function + | Bytes (loc, bs) as expr -> ( + let*$ () = Typecheck_costs.bls12_381_g2 in + match Script_bls.G2.of_bytes_opt bs with + | Some pt -> return pt + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid BLS12-381 G2 element"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_bls12_381_fr : + Script.node -> (Script_bls.Fr.t, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + function + | Bytes (loc, bs) as expr -> ( + let*$ () = Typecheck_costs.bls12_381_fr in + match Script_bls.Fr.of_bytes_opt bs with + | Some pt -> return pt + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid BLS12-381 field element"))) + | Int (_, v) -> + let*$ () = Typecheck_costs.bls12_381_fr in + return (Script_bls.Fr.of_z v) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_sapling_transaction ~memo_size : + Script.node -> (Sapling.transaction, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + function + | Bytes (loc, bytes) as expr -> ( + match + Data_encoding.Binary.of_bytes_opt Sapling.transaction_encoding bytes + with + | Some transaction -> ( + match Sapling.transaction_get_memo_size transaction with + | None -> return transaction + | Some transac_memo_size -> + let*? () = + memo_size_eq + ~error_details:(Informative ()) + memo_size + transac_memo_size + in + return transaction) + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid Sapling transaction"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_sapling_transaction_deprecated ~memo_size : + Script.node -> (Sapling.Legacy.transaction, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + function + | Bytes (loc, bytes) as expr -> ( + match + Data_encoding.Binary.of_bytes_opt + Sapling.Legacy.transaction_encoding + bytes + with + | Some transaction -> ( + match Sapling.Legacy.transaction_get_memo_size transaction with + | None -> return transaction + | Some transac_memo_size -> + let*? () = + memo_size_eq + ~error_details:(Informative ()) + memo_size + transac_memo_size + in + return transaction) + | None -> + tzfail + (Invalid_syntactic_constant + ( loc, + strip_locations expr, + "a valid Sapling transaction (deprecated format)" ))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_chest_key : + Script.node -> (Script_timelock.chest_key, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + function + | Bytes (loc, bytes) as expr -> ( + let*$ () = Typecheck_costs.chest_key in + match + Data_encoding.Binary.of_bytes_opt + Script_timelock.chest_key_encoding + bytes + with + | Some chest_key -> return chest_key + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid time-lock chest key"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + +let parse_chest : + Script.node -> (Script_timelock.chest, error trace) Gas_monad.t = + let open Gas_monad.Syntax in + function + | Bytes (loc, bytes) as expr -> ( + let*$ () = Typecheck_costs.chest ~bytes:(Bytes.length bytes) in + match + Data_encoding.Binary.of_bytes_opt Script_timelock.chest_encoding bytes + with + | Some chest -> return chest + | None -> + tzfail + (Invalid_syntactic_constant + (loc, strip_locations expr, "a valid time-lock chest"))) + | expr -> tzfail (Invalid_kind (location expr, [Bytes_kind], kind expr)) (* -- parse data of complex types -- *) @@ -1946,6 +2084,14 @@ let rec parse_data : let fail_parse_data () = tzfail (parse_data_error ()) in let traced_no_lwt body = record_trace_eval parse_data_error body in let traced body = trace_eval parse_data_error body in + let traced_from_gas_monad ctxt body = + Lwt.return @@ traced_no_lwt + @@ + let open Result_syntax in + let* res, ctxt = Gas_monad.run ctxt body in + let+ res in + (res, ctxt) + in let traced_fail err = Lwt.return @@ traced_no_lwt (Result_syntax.tzfail err) in @@ -2071,29 +2217,39 @@ let rec parse_data : let legacy = elab_conf.legacy in match (ty, script_data) with | Unit_t, expr -> - Lwt.return @@ traced_no_lwt - @@ (parse_unit ctxt ~legacy expr : (a * context) tzresult) - | Bool_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_bool ctxt ~legacy expr - | String_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_string ctxt expr - | Bytes_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_bytes ctxt expr - | Int_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_int ctxt expr - | Nat_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_nat ctxt expr - | Mutez_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_mutez ctxt expr - | Timestamp_t, expr -> - Lwt.return @@ traced_no_lwt @@ parse_timestamp ctxt expr - | Key_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_key ctxt expr - | Key_hash_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_key_hash ctxt expr - | Signature_t, expr -> - Lwt.return @@ traced_no_lwt @@ parse_signature ctxt expr + traced_from_gas_monad ctxt + @@ (parse_unit ~legacy expr : (a, error trace) Gas_monad.t) + | Bool_t, expr -> traced_from_gas_monad ctxt @@ parse_bool ~legacy expr + | String_t, expr -> traced_from_gas_monad ctxt @@ parse_string expr + | Bytes_t, expr -> traced_from_gas_monad ctxt @@ parse_bytes expr + | Int_t, expr -> traced_from_gas_monad ctxt @@ parse_int expr + | Nat_t, expr -> traced_from_gas_monad ctxt @@ parse_nat expr + | Mutez_t, expr -> traced_from_gas_monad ctxt @@ parse_mutez expr + | Timestamp_t, expr -> traced_from_gas_monad ctxt @@ parse_timestamp expr + | Key_t, expr -> traced_from_gas_monad ctxt @@ parse_key expr + | Key_hash_t, expr -> traced_from_gas_monad ctxt @@ parse_key_hash expr + | Signature_t, expr -> traced_from_gas_monad ctxt @@ parse_signature expr | Operation_t, _ -> (* operations cannot appear in parameters or storage, the protocol should never parse the bytes of an operation *) assert false - | Chain_id_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_chain_id ctxt expr - | Address_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_address ctxt expr + | Chain_id_t, expr -> traced_from_gas_monad ctxt @@ parse_chain_id expr + | Address_t, expr -> + traced_from_gas_monad ctxt + @@ parse_address + ~sc_rollup_enable:(Constants.sc_rollup_enable ctxt) + ~zk_rollup_enable:(Constants.zk_rollup_enable ctxt) + expr | Contract_t (arg_ty, _), expr -> traced - (let*? address, ctxt = parse_address ctxt expr in + (let*? address, ctxt = + Gas_monad.run ctxt + @@ parse_address + ~sc_rollup_enable:(Constants.sc_rollup_enable ctxt) + ~zk_rollup_enable:(Constants.zk_rollup_enable ctxt) + expr + in + let*? address in let loc = location expr in let+ ctxt, typed_contract = parse_contract_data @@ -2294,75 +2450,24 @@ let rec parse_data : else traced_fail (Unexpected_forged_value loc) in (Big_map {id; diff; key_type = tk; value_type = tv}, ctxt) - | Never_t, expr -> Lwt.return @@ traced_no_lwt @@ parse_never expr + | Never_t, expr -> traced_from_gas_monad ctxt @@ parse_never expr (* Bls12_381 types *) - | Bls12_381_g1_t, Bytes (_, bs) -> ( - let*? ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_g1 in - match Script_bls.G1.of_bytes_opt bs with - | Some pt -> return (pt, ctxt) - | None -> fail_parse_data ()) | Bls12_381_g1_t, expr -> - traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) - | Bls12_381_g2_t, Bytes (_, bs) -> ( - let*? ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_g2 in - match Script_bls.G2.of_bytes_opt bs with - | Some pt -> return (pt, ctxt) - | None -> fail_parse_data ()) + traced_from_gas_monad ctxt @@ parse_bls12_381_g1 expr | Bls12_381_g2_t, expr -> - traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) - | Bls12_381_fr_t, Bytes (_, bs) -> ( - let*? ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_fr in - match Script_bls.Fr.of_bytes_opt bs with - | Some pt -> return (pt, ctxt) - | None -> fail_parse_data ()) - | Bls12_381_fr_t, Int (_, v) -> - let*? ctxt = Gas.consume ctxt Typecheck_costs.bls12_381_fr in - return (Script_bls.Fr.of_z v, ctxt) + traced_from_gas_monad ctxt @@ parse_bls12_381_g2 expr | Bls12_381_fr_t, expr -> - traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + traced_from_gas_monad ctxt @@ parse_bls12_381_fr expr (* /!\ When adding new lazy storage kinds, you may want to guard the parsing of identifiers with [allow_forged]. *) (* Sapling *) - | Sapling_transaction_t memo_size, Bytes (_, bytes) -> ( - match - Data_encoding.Binary.of_bytes_opt Sapling.transaction_encoding bytes - with - | Some transaction -> ( - match Sapling.transaction_get_memo_size transaction with - | None -> return (transaction, ctxt) - | Some transac_memo_size -> - let*? () = - memo_size_eq - ~error_details:(Informative ()) - memo_size - transac_memo_size - in - return (transaction, ctxt)) - | None -> fail_parse_data ()) - | Sapling_transaction_t _, expr -> - traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) - | Sapling_transaction_deprecated_t memo_size, Bytes (_, bytes) -> ( - match - Data_encoding.Binary.of_bytes_opt - Sapling.Legacy.transaction_encoding - bytes - with - | Some transaction -> ( - match Sapling.Legacy.transaction_get_memo_size transaction with - | None -> return (transaction, ctxt) - | Some transac_memo_size -> - let*? () = - memo_size_eq - ~error_details:(Informative ()) - memo_size - transac_memo_size - in - return (transaction, ctxt)) - | None -> fail_parse_data ()) - | Sapling_transaction_deprecated_t _, expr -> - traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + | Sapling_transaction_t memo_size, expr -> + traced_from_gas_monad ctxt @@ parse_sapling_transaction ~memo_size expr + | Sapling_transaction_deprecated_t memo_size, expr -> + traced_from_gas_monad ctxt + @@ parse_sapling_transaction_deprecated ~memo_size expr | Sapling_state_t memo_size, Int (loc, id) -> if allow_forged then let id = Sapling.Id.parse_z id in @@ -2384,28 +2489,8 @@ let rec parse_data : traced_fail (Invalid_kind (location expr, [Int_kind; Seq_kind], kind expr)) (* Time lock*) - | Chest_key_t, Bytes (_, bytes) -> ( - let*? ctxt = Gas.consume ctxt Typecheck_costs.chest_key in - match - Data_encoding.Binary.of_bytes_opt - Script_timelock.chest_key_encoding - bytes - with - | Some chest_key -> return (chest_key, ctxt) - | None -> fail_parse_data ()) - | Chest_key_t, expr -> - traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) - | Chest_t, Bytes (_, bytes) -> ( - let*? ctxt = - Gas.consume ctxt (Typecheck_costs.chest ~bytes:(Bytes.length bytes)) - in - match - Data_encoding.Binary.of_bytes_opt Script_timelock.chest_encoding bytes - with - | Some chest -> return (chest, ctxt) - | None -> fail_parse_data ()) - | Chest_t, expr -> - traced_fail (Invalid_kind (location expr, [Bytes_kind], kind expr)) + | Chest_key_t, expr -> traced_from_gas_monad ctxt @@ parse_chest_key expr + | Chest_t, expr -> traced_from_gas_monad ctxt @@ parse_chest expr and parse_view : type storage storagec.