diff --git a/src/proto_alpha/lib_protocol/contract_repr.ml b/src/proto_alpha/lib_protocol/contract_repr.ml index e7befb910d8a6f93d0e1b2ff18aa0a0a7461f3cf..3f4dc97444d614f83c42aa62893bbea93f0bde16 100644 --- a/src/proto_alpha/lib_protocol/contract_repr.ml +++ b/src/proto_alpha/lib_protocol/contract_repr.ml @@ -59,18 +59,35 @@ let to_b58check = function | Implicit pbk -> Signature.Public_key_hash.to_b58check pbk | Originated h -> Contract_hash.to_b58check h -let of_b58check s = +let implicit_of_b58data : Base58.data -> Signature.public_key_hash option = + function + | Ed25519.Public_key_hash.Data h -> Some (Signature.Ed25519 h) + | Secp256k1.Public_key_hash.Data h -> Some (Signature.Secp256k1 h) + | P256.Public_key_hash.Data h -> Some (Signature.P256 h) + | _ -> None + +let originated_of_b58data = function + | Contract_hash.Data h -> Some h + | _ -> None + +let contract_of_b58data data = + match implicit_of_b58data data with + | Some pkh -> Some (Implicit pkh) + | None -> ( + match originated_of_b58data data with + | Some contract_hash -> Some (Originated contract_hash) + | None -> None) + +let of_b58check_gen ~of_b58data s = match Base58.decode s with | Some data -> ( - match data with - | Ed25519.Public_key_hash.Data h -> ok (Implicit (Signature.Ed25519 h)) - | Secp256k1.Public_key_hash.Data h -> - ok (Implicit (Signature.Secp256k1 h)) - | P256.Public_key_hash.Data h -> ok (Implicit (Signature.P256 h)) - | Contract_hash.Data h -> ok (Originated h) - | _ -> error (Invalid_contract_notation s)) + match of_b58data data with + | Some c -> ok c + | None -> error (Invalid_contract_notation s)) | None -> error (Invalid_contract_notation s) +let of_b58check = of_b58check_gen ~of_b58data:contract_of_b58data + let pp ppf = function | Implicit pbk -> Signature.Public_key_hash.pp ppf pbk | Originated h -> Contract_hash.pp ppf h @@ -79,44 +96,78 @@ let pp_short ppf = function | Implicit pbk -> Signature.Public_key_hash.pp_short ppf pbk | Originated h -> Contract_hash.pp_short ppf h -let cases is_contract to_contract = - Data_encoding. - [ - case - (Tag 0) - ~title:"Implicit" - Signature.Public_key_hash.encoding - (fun k -> - match is_contract k with Some (Implicit k) -> Some k | _ -> None) - (fun k -> to_contract (Implicit k)); - case - (Tag 1) - (Fixed.add_padding Contract_hash.encoding 1) - ~title:"Originated" - (fun k -> - match is_contract k with Some (Originated k) -> Some k | _ -> None) - (fun k -> to_contract (Originated k)); - ] +let implicit_case ~proj ~inj = + let open Data_encoding in + case (Tag 0) ~title:"Implicit" Signature.Public_key_hash.encoding proj inj -let encoding = +let originated_case ~proj ~inj = + let open Data_encoding in + case + (Tag 1) + (Fixed.add_padding Contract_hash.encoding 1) + ~title:"Originated" + proj + inj + +let cases is_contract to_contract = + [ + implicit_case + ~proj:(fun k -> + match is_contract k with Some (Implicit k) -> Some k | _ -> None) + ~inj:(fun k -> to_contract (Implicit k)); + originated_case + ~proj:(fun k -> + match is_contract k with Some (Originated k) -> Some k | _ -> None) + ~inj:(fun k -> to_contract (Originated k)); + ] + +let encoding_gen ~id_extra ~title_extra ~can_be ~cases ~to_b58check ~of_b58data + = let open Data_encoding in def - "contract_id" - ~title:"A contract handle" + ("contract_id" ^ id_extra) + ~title:("A contract handle" ^ title_extra) ~description: - "A contract notation as given to an RPC or inside scripts. Can be a \ - base58 implicit contract hash or a base58 originated contract hash." + ("A contract notation as given to an RPC or inside scripts. Can be a \ + base58 " ^ can_be) @@ splitted ~binary:(union ~tag_size:`Uint8 @@ cases (fun x -> Some x) (fun x -> x)) ~json: (conv to_b58check (fun s -> - match of_b58check s with + match of_b58check_gen ~of_b58data s with | Ok s -> s | Error _ -> Json.cannot_destruct "Invalid contract notation.") string) +let encoding = + encoding_gen + ~id_extra:"" + ~title_extra:"" + ~can_be:"implicit contract hash or a base58 originated contract hash." + ~cases + ~to_b58check + ~of_b58data:contract_of_b58data + +let implicit_encoding = + encoding_gen + ~id_extra:".implicit" + ~title_extra:" -- implicit account" + ~can_be:"implicit contract hash." + ~cases:(fun proj inj -> [implicit_case ~proj ~inj]) + ~to_b58check:Signature.Public_key_hash.to_b58check + ~of_b58data:implicit_of_b58data + +let originated_encoding = + encoding_gen + ~id_extra:".originated" + ~title_extra:" -- originated account" + ~can_be:"originated contract hash." + ~cases:(fun proj inj -> [originated_case ~proj ~inj]) + ~to_b58check:Contract_hash.to_b58check + ~of_b58data:originated_of_b58data + let () = let open Data_encoding in register_error_kind diff --git a/src/proto_alpha/lib_protocol/contract_repr.mli b/src/proto_alpha/lib_protocol/contract_repr.mli index a818e5654e774b2117fb33eefbb495dcb448fa0e..ac3695a6f81b37a1d16862bb9f2ceba988288a89 100644 --- a/src/proto_alpha/lib_protocol/contract_repr.mli +++ b/src/proto_alpha/lib_protocol/contract_repr.mli @@ -75,6 +75,14 @@ val pp_short : Format.formatter -> t -> unit val encoding : t Data_encoding.t +(** [implicit_encoding] is an encoding for public key hashes that is + compatible with the [encoding] of contracts for implicit accounts. *) +val implicit_encoding : Signature.Public_key_hash.t Data_encoding.t + +(** [originated_encoding] is an encoding for contract hashes that is + compatible with the [encoding] of contracts for originated accounts. *) +val originated_encoding : Contract_hash.t Data_encoding.t + (** [cases f g] exports the {!Data_encoding.cases} used to define {!encoding}. The only reason why we export that is to let {!Destination_repr.encoding}