Proto: store the public key of the manager in the contract
This commit is contained in:
parent
3d19e3bd59
commit
de8967540f
@ -23,6 +23,7 @@
|
||||
"Roll_repr",
|
||||
"Vote_repr",
|
||||
"Operation_repr",
|
||||
"Manager_repr",
|
||||
"Block_header_repr",
|
||||
|
||||
"Storage_sigs",
|
||||
|
@ -149,28 +149,15 @@ let apply_manager_operation_content
|
||||
Contract.set_delegate ctxt source delegate >>=? fun ctxt ->
|
||||
return (ctxt, origination_nonce, None)
|
||||
|
||||
let check_signature_and_update_public_key ctxt id public_key op =
|
||||
begin
|
||||
match public_key with
|
||||
| None -> return ctxt
|
||||
| Some public_key ->
|
||||
Public_key.reveal ctxt id public_key
|
||||
end >>=? fun ctxt ->
|
||||
Public_key.get ctxt id >>=? fun public_key ->
|
||||
Operation.check_signature public_key op >>=? fun () ->
|
||||
return ctxt
|
||||
|
||||
let apply_sourced_operation
|
||||
ctxt baker_contract pred_block block_prio
|
||||
operation origination_nonce ops =
|
||||
match ops with
|
||||
| Manager_operations { source ; public_key ; fee ; counter ; operations = contents } ->
|
||||
Contract.must_exist ctxt source >>=? fun () ->
|
||||
Contract.get_manager ctxt source >>=? fun manager ->
|
||||
check_signature_and_update_public_key
|
||||
ctxt manager public_key operation >>=? fun ctxt ->
|
||||
Contract.check_counter_increment
|
||||
ctxt source counter >>=? fun () ->
|
||||
Contract.update_manager_key ctxt source public_key >>=? fun (ctxt,public_key) ->
|
||||
Operation.check_signature public_key operation >>=? fun () ->
|
||||
Contract.check_counter_increment ctxt source counter >>=? fun () ->
|
||||
Contract.increment_counter ctxt source >>=? fun ctxt ->
|
||||
Contract.spend ctxt source fee >>=? fun ctxt ->
|
||||
(match baker_contract with
|
||||
@ -187,10 +174,10 @@ let apply_sourced_operation
|
||||
(ctxt, origination_nonce, None) contents
|
||||
| Delegate_operations { source ; operations = contents } ->
|
||||
let delegate = Ed25519.Public_key.hash source in
|
||||
check_signature_and_update_public_key
|
||||
ctxt delegate (Some source) operation >>=? fun ctxt ->
|
||||
Public_key.reveal ctxt delegate source >>=? fun ctxt ->
|
||||
Operation.check_signature source operation >>=? fun () ->
|
||||
(* TODO, see how to extract the public key hash after this operation to
|
||||
pass it to apply_delegate_operation_content *)
|
||||
pass it to apply_delegate_operation_content *)
|
||||
fold_left_s (fun ctxt content ->
|
||||
apply_delegate_operation_content
|
||||
ctxt delegate pred_block block_prio content)
|
||||
|
@ -16,6 +16,9 @@ type error +=
|
||||
| Unspendable_contract of Contract_repr.contract (* `Permanent *)
|
||||
| Non_existing_contract of Contract_repr.contract (* `Temporary *)
|
||||
| Non_delegatable_contract of Contract_repr.contract (* `Permanent *)
|
||||
| Inconsistent_hash of Ed25519.Public_key.t * Ed25519.Public_key_hash.t * Ed25519.Public_key_hash.t (* `Permanent *)
|
||||
| Inconsistent_public_key of Ed25519.Public_key.t * Ed25519.Public_key.t (* `Permanent *)
|
||||
| Missing_public_key of Ed25519.Public_key_hash.t (* `Permanent *)
|
||||
| Failure of string (* `Permanent *)
|
||||
|
||||
let () =
|
||||
@ -129,6 +132,47 @@ let () =
|
||||
Data_encoding.(obj1 (req "contract" Contract_repr.encoding))
|
||||
(function Non_delegatable_contract c -> Some c | _ -> None)
|
||||
(fun c -> Non_delegatable_contract c) ;
|
||||
register_error_kind
|
||||
`Permanent
|
||||
~id:"contract.manager.inconsistent_hash"
|
||||
~title:"Inconsistent public key hash"
|
||||
~description:"A revealed manager public key is inconsistent with the announced hash"
|
||||
~pp:(fun ppf (k, eh, ph) ->
|
||||
Format.fprintf ppf "The hash of the manager public key %s is not %a as announced but %a"
|
||||
(Ed25519.Public_key.to_b58check k)
|
||||
Ed25519.Public_key_hash.pp ph
|
||||
Ed25519.Public_key_hash.pp eh)
|
||||
Data_encoding.(obj3
|
||||
(req "public_key" Ed25519.Public_key.encoding)
|
||||
(req "expected_hash" Ed25519.Public_key_hash.encoding)
|
||||
(req "provided_hash" Ed25519.Public_key_hash.encoding))
|
||||
(function Inconsistent_hash (k, eh, ph) -> Some (k, eh, ph) | _ -> None)
|
||||
(fun (k, eh, ph) -> Inconsistent_hash (k, eh, ph)) ;
|
||||
register_error_kind
|
||||
`Permanent
|
||||
~id:"contract.manager.inconsistent_public_key"
|
||||
~title:"Inconsistent public key"
|
||||
~description:"A provided manager public key is different with the public key stored in the contract"
|
||||
~pp:(fun ppf (eh, ph) ->
|
||||
Format.fprintf ppf "Expected manager public key %s but %s was provided"
|
||||
(Ed25519.Public_key.to_b58check ph)
|
||||
(Ed25519.Public_key.to_b58check eh))
|
||||
Data_encoding.(obj2
|
||||
(req "public_key" Ed25519.Public_key.encoding)
|
||||
(req "expected_public_key" Ed25519.Public_key.encoding))
|
||||
(function Inconsistent_public_key (eh, ph) -> Some (eh, ph) | _ -> None)
|
||||
(fun (eh, ph) -> Inconsistent_public_key (eh, ph)) ;
|
||||
register_error_kind
|
||||
`Permanent
|
||||
~id:"contract.manager.missing_public_key"
|
||||
~title:"Missing public key"
|
||||
~description:"The manager public key must be provided to execute the current operation"
|
||||
~pp:(fun ppf (k) ->
|
||||
Format.fprintf ppf "The manager public key ( with hash %a ) is missing"
|
||||
Ed25519.Public_key_hash.pp k)
|
||||
Data_encoding.(obj1 (req "hash" Ed25519.Public_key_hash.encoding))
|
||||
(function Missing_public_key (k) -> Some (k) | _ -> None)
|
||||
(fun (k) -> Missing_public_key (k)) ;
|
||||
register_error_kind
|
||||
`Permanent
|
||||
~id:"contract.failure"
|
||||
@ -138,7 +182,7 @@ let () =
|
||||
Data_encoding.(obj1 (req "message" string))
|
||||
(function Failure s -> Some s | _ -> None)
|
||||
(fun s -> Failure s)
|
||||
|
||||
|
||||
let failwith msg = fail (Failure msg)
|
||||
|
||||
let create_base c contract ~balance ~manager ~delegate ?script ~spendable ~delegatable =
|
||||
@ -146,7 +190,7 @@ let create_base c contract ~balance ~manager ~delegate ?script ~spendable ~deleg
|
||||
| None -> return 0l
|
||||
| Some _ -> Storage.Contract.Global_counter.get c) >>=? fun counter ->
|
||||
Storage.Contract.Balance.init c contract balance >>=? fun c ->
|
||||
Storage.Contract.Manager.init c contract manager >>=? fun c ->
|
||||
Storage.Contract.Manager.init c contract (Manager_repr.hash manager) >>=? fun c ->
|
||||
begin
|
||||
match delegate with
|
||||
| None -> return c
|
||||
@ -254,7 +298,28 @@ let get_manager c contract =
|
||||
| Some manager -> return manager
|
||||
| None -> failwith "get_manager"
|
||||
end
|
||||
| Some v -> return v
|
||||
| Some (Manager_repr.Hash v) -> return v
|
||||
| Some (Manager_repr.Public_key v) -> return (Ed25519.Public_key.hash v)
|
||||
|
||||
let update_manager_key c contract = function
|
||||
| Some public_key ->
|
||||
begin Storage.Contract.Manager.get c contract >>=? function
|
||||
| (Manager_repr.Public_key v) -> (* key revealed for the second time *)
|
||||
if Ed25519.Public_key.(v = public_key) then return (c,v)
|
||||
else fail (Inconsistent_public_key (v,public_key))
|
||||
| (Manager_repr.Hash v) ->
|
||||
let actual_hash = Ed25519.Public_key.hash public_key in
|
||||
if (Ed25519.Public_key_hash.equal actual_hash v) then
|
||||
let v = (Manager_repr.public_key public_key) in
|
||||
Storage.Contract.Manager.set c contract v >>=? fun c ->
|
||||
return (c,public_key) (* reveal and update key *)
|
||||
else fail (Inconsistent_hash (public_key,v,actual_hash))
|
||||
end
|
||||
| None ->
|
||||
begin Storage.Contract.Manager.get c contract >>=? function
|
||||
| (Manager_repr.Public_key v) -> return (c,v) (* already revealed *)
|
||||
| (Manager_repr.Hash v) -> fail (Missing_public_key (v))
|
||||
end
|
||||
|
||||
let get_delegate_opt = Roll_storage.get_contract_delegate
|
||||
|
||||
|
@ -16,6 +16,9 @@ type error +=
|
||||
| Unspendable_contract of Contract_repr.contract (* `Permanent *)
|
||||
| Non_existing_contract of Contract_repr.contract (* `Temporary *)
|
||||
| Non_delegatable_contract of Contract_repr.contract (* `Permanent *)
|
||||
| Inconsistent_hash of Ed25519.Public_key.t * Ed25519.Public_key_hash.t * Ed25519.Public_key_hash.t (* `Permanent *)
|
||||
| Inconsistent_public_key of Ed25519.Public_key.t * Ed25519.Public_key.t (* `Permanent *)
|
||||
| Missing_public_key of Ed25519.Public_key_hash.t (* `Permanent *)
|
||||
| Failure of string (* `Permanent *)
|
||||
|
||||
val delete : Storage.t -> Contract_repr.t -> Storage.t tzresult Lwt.t
|
||||
@ -32,6 +35,10 @@ val is_delegatable : Storage.t -> Contract_repr.t -> bool tzresult Lwt.t
|
||||
val is_spendable : Storage.t -> Contract_repr.t -> bool tzresult Lwt.t
|
||||
|
||||
val get_manager: Storage.t -> Contract_repr.t -> Ed25519.Public_key_hash.t tzresult Lwt.t
|
||||
val update_manager_key:
|
||||
Storage.t -> Contract_repr.t -> Ed25519.Public_key.t option ->
|
||||
(Storage.t * Ed25519.Public_key.t) tzresult Lwt.t
|
||||
|
||||
val get_delegate_opt: Storage.t -> Contract_repr.t -> Ed25519.Public_key_hash.t option tzresult Lwt.t
|
||||
val get_balance: Storage.t -> Contract_repr.t -> Tez_repr.t tzresult Lwt.t
|
||||
val get_counter: Storage.t -> Contract_repr.t -> int32 tzresult Lwt.t
|
||||
|
53
src/proto/alpha/manager_repr.ml
Normal file
53
src/proto/alpha/manager_repr.ml
Normal file
@ -0,0 +1,53 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2016. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* Tezos Protocol Implementation - Low level Repr. of Managers' keys *)
|
||||
|
||||
type manager_key =
|
||||
| Hash of Ed25519.Public_key_hash.t
|
||||
| Public_key of Ed25519.Public_key.t
|
||||
|
||||
type t = manager_key
|
||||
|
||||
let hash hash = Hash hash
|
||||
let public_key hash = Public_key hash
|
||||
|
||||
open Data_encoding
|
||||
|
||||
let hash_encoding =
|
||||
(obj1
|
||||
(req "hash" Ed25519.Public_key_hash.encoding)
|
||||
)
|
||||
|
||||
let pubkey_encoding =
|
||||
(obj1
|
||||
(req "public_key" Ed25519.Public_key.encoding)
|
||||
)
|
||||
|
||||
let hash_case tag =
|
||||
case ~tag hash_encoding
|
||||
(function
|
||||
| Hash hash -> Some hash
|
||||
| _ -> None)
|
||||
(fun hash -> Hash hash)
|
||||
|
||||
let pubkey_case tag =
|
||||
case ~tag pubkey_encoding
|
||||
(function
|
||||
| Public_key hash -> Some hash
|
||||
| _ -> None)
|
||||
(fun hash -> Public_key hash)
|
||||
|
||||
|
||||
let encoding =
|
||||
union [
|
||||
hash_case 0 ;
|
||||
pubkey_case 1 ;
|
||||
]
|
||||
|
22
src/proto/alpha/manager_repr.mli
Normal file
22
src/proto/alpha/manager_repr.mli
Normal file
@ -0,0 +1,22 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2016. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* Tezos Protocol Implementation - Low level Repr. of Managers' keys *)
|
||||
|
||||
(** The public key of the manager of a contract is reveled only after the
|
||||
first operation. At Origination time, the manager provides only the hash
|
||||
of its public key that is stored in the contract. When the public key
|
||||
is actually reveeld, the public key instead of the hash of the key *)
|
||||
type manager_key =
|
||||
| Hash of Ed25519.Public_key_hash.t
|
||||
| Public_key of Ed25519.Public_key.t
|
||||
|
||||
type t = manager_key
|
||||
|
||||
val encoding : t Data_encoding.encoding
|
@ -295,10 +295,10 @@ module Contract = struct
|
||||
module Manager =
|
||||
Make_indexed_data_storage(struct
|
||||
type key = Contract_repr.t
|
||||
type value = Ed25519.Public_key_hash.t
|
||||
type value = Manager_repr.t
|
||||
let name = "contract manager"
|
||||
let key = Key.Contract.manager
|
||||
let encoding = Ed25519.Public_key_hash.encoding
|
||||
let encoding = Manager_repr.encoding
|
||||
end)
|
||||
|
||||
module Spendable =
|
||||
|
@ -136,7 +136,7 @@ module Contract : sig
|
||||
(** The manager of a contract *)
|
||||
module Manager : Indexed_data_storage
|
||||
with type key = Contract_repr.t
|
||||
and type value = Ed25519.Public_key_hash.t
|
||||
and type value = Manager_repr.t
|
||||
and type context := t
|
||||
|
||||
(** The delegate of a contract, if any. *)
|
||||
|
@ -424,6 +424,9 @@ module Contract : sig
|
||||
|
||||
val get_manager:
|
||||
context -> contract -> public_key_hash tzresult Lwt.t
|
||||
val update_manager_key:
|
||||
context -> contract -> public_key option -> (context * public_key) tzresult Lwt.t
|
||||
|
||||
val get_delegate_opt:
|
||||
context -> contract -> public_key_hash option tzresult Lwt.t
|
||||
val is_delegatable:
|
||||
|
@ -224,6 +224,7 @@ module Account = struct
|
||||
let set_delegate
|
||||
?(block = `Prevalidation)
|
||||
?(fee = 5L)
|
||||
?src_pk
|
||||
~contract
|
||||
~manager_sk
|
||||
delegate_opt =
|
||||
@ -234,6 +235,7 @@ module Account = struct
|
||||
~source:contract
|
||||
~manager_sk
|
||||
~fee
|
||||
?src_pk
|
||||
delegate_opt
|
||||
|
||||
let balance ?(block = `Prevalidation) (account : t) =
|
||||
@ -370,7 +372,19 @@ module Assert = struct
|
||||
|
||||
let inconsistent_pkh ~msg =
|
||||
Assert.contain_error ~msg ~f:begin ecoproto_error (function
|
||||
| Public_key_storage.Inconsistent_hash _ -> true
|
||||
| Contract_storage.Inconsistent_hash _ -> true
|
||||
| _ -> false)
|
||||
end
|
||||
|
||||
let inconsistent_public_key ~msg =
|
||||
Assert.contain_error ~msg ~f:begin ecoproto_error (function
|
||||
| Contract_storage.Inconsistent_public_key _ -> true
|
||||
| _ -> false)
|
||||
end
|
||||
|
||||
let missing_public_key ~msg =
|
||||
Assert.contain_error ~msg ~f:begin ecoproto_error (function
|
||||
| Contract_storage.Missing_public_key _ -> true
|
||||
| _ -> false)
|
||||
end
|
||||
|
||||
|
@ -78,6 +78,7 @@ module Account : sig
|
||||
val set_delegate :
|
||||
?block:Client_proto_rpcs.block ->
|
||||
?fee:int64 ->
|
||||
?src_pk:public_key ->
|
||||
contract:Contract.t ->
|
||||
manager_sk:secret_key ->
|
||||
public_key_hash option ->
|
||||
@ -176,6 +177,8 @@ module Assert : sig
|
||||
val balance_too_low : msg:string -> 'a tzresult -> unit
|
||||
val non_spendable : msg:string -> 'a tzresult -> unit
|
||||
val inconsistent_pkh : msg:string -> 'a tzresult -> unit
|
||||
val inconsistent_public_key : msg:string -> 'a tzresult -> unit
|
||||
val missing_public_key : msg:string -> 'a tzresult -> unit
|
||||
|
||||
(** Origination assertions *)
|
||||
|
||||
|
@ -64,6 +64,7 @@ let run blkid ({ b1 ; b2 ; _ } : Helpers.Account.bootstrap_accounts) =
|
||||
|
||||
(* Change delegate of a non-delegatable contract *)
|
||||
Helpers.Account.set_delegate
|
||||
~src_pk:b1.pk
|
||||
~contract:nd_contract
|
||||
~manager_sk:b1.sk
|
||||
(Some b2.pkh) >>= fun result ->
|
||||
@ -71,6 +72,7 @@ let run blkid ({ b1 ; b2 ; _ } : Helpers.Account.bootstrap_accounts) =
|
||||
|
||||
(* Change delegate of a delegatable contract *)
|
||||
Helpers.Account.set_delegate
|
||||
~src_pk:b1.pk
|
||||
~contract:d_contract
|
||||
~manager_sk:b1.sk
|
||||
(Some b2.pkh) >>= fun _result ->
|
||||
|
@ -100,7 +100,7 @@ let run blkid ({ b1 ; b2 ; b3 ; _ } : Helpers.Account.bootstrap_accounts) =
|
||||
~account
|
||||
~destination:b2.contract
|
||||
~amount:10_00L () >>= fun result ->
|
||||
Assert.inconsistent_pkh ~msg:__LOC__ result ;
|
||||
Assert.inconsistent_public_key ~msg:__LOC__ result ;
|
||||
|
||||
return blkh
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user