From dcf27f48d999a1d7e1aada98ee6ae2e854bd87b9 Mon Sep 17 00:00:00 2001 From: Benjamin Canou Date: Mon, 21 May 2018 21:23:48 +0200 Subject: [PATCH] Alpha: do not produce multiple revelations --- .../lib_protocol/src/alpha_context.mli | 2 ++ .../lib_protocol/src/contract_services.ml | 21 ++++++++++++++++ .../lib_protocol/src/contract_services.mli | 3 +++ .../lib_protocol/src/contract_storage.ml | 6 +++++ .../lib_protocol/src/contract_storage.mli | 2 ++ .../lib_protocol/src/helpers_services.ml | 24 ++++++++++++------- .../test/helpers/helpers_assert.ml | 1 + .../test/helpers/helpers_operation.ml | 3 ++- 8 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/proto_alpha/lib_protocol/src/alpha_context.mli b/src/proto_alpha/lib_protocol/src/alpha_context.mli index b68a3d064..0da9010bb 100644 --- a/src/proto_alpha/lib_protocol/src/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/src/alpha_context.mli @@ -456,6 +456,8 @@ module Contract : sig val get_manager_key: context -> contract -> public_key tzresult Lwt.t + val is_manager_key_revealed: + context -> contract -> bool tzresult Lwt.t val reveal_manager_key: context -> contract -> public_key -> context tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/src/contract_services.ml b/src/proto_alpha/lib_protocol/src/contract_services.ml index 53c5d0fc0..13014ef95 100644 --- a/src/proto_alpha/lib_protocol/src/contract_services.ml +++ b/src/proto_alpha/lib_protocol/src/contract_services.ml @@ -60,6 +60,16 @@ module S = struct ~output: (obj1 (req "manager" Signature.Public_key_hash.encoding)) RPC_path.(custom_root /: Contract.arg / "manager") + let manager_key = + RPC_service.post_service + ~description: "Access the manager of a contract." + ~query: RPC_query.empty + ~input: empty + ~output: (obj2 + (req "manager" Signature.Public_key_hash.encoding) + (opt "key" Signature.Public_key.encoding)) + RPC_path.(custom_root /: Contract.arg / "manager_key") + let delegate = RPC_service.post_service ~description: "Access the delegate of a contract, if any." @@ -148,6 +158,14 @@ let () = | Some v -> return v) in register_field S.balance Contract.get_balance ; register_field S.manager Contract.get_manager ; + register_field S.manager_key + (fun ctxt c -> + Contract.get_manager ctxt c >>=? fun mgr -> + Contract.is_manager_key_revealed ctxt c >>=? fun revealed -> + if revealed then + Contract.get_manager_key ctxt c >>=? fun key -> + return (mgr, Some key) + else return (mgr, None)) ; register_opt_field S.delegate Delegate.get ; register_field S.counter Contract.get_counter ; register_field S.spendable Contract.is_spendable ; @@ -179,6 +197,9 @@ let balance ctxt block contract = let manager ctxt block contract = RPC_context.make_call1 S.manager ctxt block contract () () +let manager_key ctxt block contract = + RPC_context.make_call1 S.manager_key ctxt block contract () () + let delegate ctxt block contract = RPC_context.make_call1 S.delegate ctxt block contract () () diff --git a/src/proto_alpha/lib_protocol/src/contract_services.mli b/src/proto_alpha/lib_protocol/src/contract_services.mli index a5c2f8174..955381124 100644 --- a/src/proto_alpha/lib_protocol/src/contract_services.mli +++ b/src/proto_alpha/lib_protocol/src/contract_services.mli @@ -33,6 +33,9 @@ val balance: val manager: 'a #RPC_context.simple -> 'a -> Contract.t -> public_key_hash shell_tzresult Lwt.t +val manager_key: + 'a #RPC_context.simple -> 'a -> Contract.t -> (public_key_hash * public_key option) shell_tzresult Lwt.t + val delegate: 'a #RPC_context.simple -> 'a -> Contract.t -> public_key_hash shell_tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/src/contract_storage.ml b/src/proto_alpha/lib_protocol/src/contract_storage.ml index f6d8aaec6..03868bfae 100644 --- a/src/proto_alpha/lib_protocol/src/contract_storage.ml +++ b/src/proto_alpha/lib_protocol/src/contract_storage.ml @@ -295,6 +295,12 @@ let get_manager_key c contract = | Some (Manager_repr.Hash _) -> fail (Unrevealed_manager_key contract) | Some (Manager_repr.Public_key v) -> return v +let is_manager_key_revealed c contract = + Storage.Contract.Manager.get_option c contract >>=? function + | None -> return false + | Some (Manager_repr.Hash _) -> return false + | Some (Manager_repr.Public_key _) -> return true + let reveal_manager_key c contract public_key = Storage.Contract.Manager.get c contract >>=? function | Public_key _ -> fail (Previously_revealed_key contract) diff --git a/src/proto_alpha/lib_protocol/src/contract_storage.mli b/src/proto_alpha/lib_protocol/src/contract_storage.mli index 34d40fbc4..932d8cadc 100644 --- a/src/proto_alpha/lib_protocol/src/contract_storage.mli +++ b/src/proto_alpha/lib_protocol/src/contract_storage.mli @@ -45,6 +45,8 @@ val get_manager: val get_manager_key: Raw_context.t -> Contract_repr.t -> Signature.Public_key.t tzresult Lwt.t +val is_manager_key_revealed: + Raw_context.t -> Contract_repr.t -> bool tzresult Lwt.t val reveal_manager_key: Raw_context.t -> Contract_repr.t -> Signature.Public_key.t -> diff --git a/src/proto_alpha/lib_protocol/src/helpers_services.ml b/src/proto_alpha/lib_protocol/src/helpers_services.ml index 84476c389..2ff60c63c 100644 --- a/src/proto_alpha/lib_protocol/src/helpers_services.ml +++ b/src/proto_alpha/lib_protocol/src/helpers_services.ml @@ -298,15 +298,21 @@ module Forge = struct let operations ctxt block ~branch ~source ?sourcePubKey ~counter ~fee operations = - let operations = - match sourcePubKey with - | None -> operations - | Some pk -> Reveal pk :: operations in - let ops = - Manager_operations { source ; - counter ; operations ; fee } in - (RPC_context.make_call0 S.operations ctxt block - () ({ branch }, Sourced_operations ops)) + Contract_services.manager_key ctxt block source >>= function + | Error _ as e -> Lwt.return e + | Ok (_, revealed) -> + let operations = + match revealed with + | Some _ -> operations + | None -> + match sourcePubKey with + | None -> operations + | Some pk -> Reveal pk :: operations in + let ops = + Manager_operations { source ; + counter ; operations ; fee } in + (RPC_context.make_call0 S.operations ctxt block + () ({ branch }, Sourced_operations ops)) let reveal ctxt block ~branch ~source ~sourcePubKey ~counter ~fee ()= diff --git a/src/proto_alpha/lib_protocol/test/helpers/helpers_assert.ml b/src/proto_alpha/lib_protocol/test/helpers/helpers_assert.ml index 889bd2780..521fa45a0 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/helpers_assert.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/helpers_assert.ml @@ -181,6 +181,7 @@ let contain_error_alpha ?msg ~f = function let unknown_contract ~msg = let f = function | Proto_alpha.Raw_context.Storage_error _ -> true + | Proto_alpha.Contract_storage.Empty_implicit_contract _ -> true | _ -> false in contain_error_alpha ~msg ~f diff --git a/src/proto_alpha/lib_protocol/test/helpers/helpers_operation.ml b/src/proto_alpha/lib_protocol/test/helpers/helpers_operation.ml index 3fa6aed99..6f5d5aa27 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/helpers_operation.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/helpers_operation.ml @@ -17,13 +17,14 @@ let manager (src : Helpers_account.t) ?(fee = Tez.zero) operations context = Alpha_context.prepare ~level:0l ~timestamp:(Time.now ()) ~fitness:[] context >>=? fun context -> Contract.get_counter context src.contract >>=? fun counter -> + Contract.is_manager_key_revealed context src.contract >>=? fun revealed -> let counter = Int32.succ counter in return @@ Manager_operations { source = src.contract ; fee ; counter ; - operations = Reveal src.pub :: operations ; + operations = (if revealed then operations else Reveal src.pub :: operations) ; }