Alpha: forbid delegation to "unregistred delegate".
A "registred delegate" is a delegate that previously revealed its public key and that registred itself as delegate of its own implicit contract. An implicit contract can only be delegated to itself ; it is then considered as a "delegate contract". A delegate contract cannot be deleted.
This commit is contained in:
parent
38f46d832a
commit
92f5ad6212
@ -85,7 +85,7 @@ let run blkid ({ b1 ; b2 ; b3 ; _ } : Helpers.Account.bootstrap_accounts) =
|
||||
~account
|
||||
~destination:b3.contract
|
||||
~amount:(tez 10L) () >>= fun result ->
|
||||
Assert.inconsistent_pkh ~msg:__LOC__ result ;
|
||||
Assert.inconsistent_public_key ~msg:__LOC__ result ;
|
||||
|
||||
(* Try spending an originated contract without the manager's key. *)
|
||||
let account = { b1 with contract = spendable } in
|
||||
|
@ -14,10 +14,13 @@ type account = {
|
||||
|
||||
let init_account ctxt account =
|
||||
Storage.Public_key.init ctxt account.public_key_hash account.public_key >>=? fun ctxt ->
|
||||
Contract_storage.credit
|
||||
ctxt
|
||||
(Contract_repr.implicit_contract account.public_key_hash)
|
||||
let contract = Contract_repr.implicit_contract account.public_key_hash in
|
||||
Contract_storage.credit ctxt contract
|
||||
Constants_repr.bootstrap_wealth >>=? fun ctxt ->
|
||||
Contract_storage.update_manager_key ctxt contract
|
||||
(Some account.public_key) >>=? fun (ctxt, _) ->
|
||||
Contract_storage.set_delegate ctxt contract
|
||||
(Some account.public_key_hash) >>=? fun ctxt ->
|
||||
return ctxt
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@ type error +=
|
||||
| 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 *)
|
||||
| Unregistred_delegate of Ed25519.Public_key_hash.t (* `Permanent *)
|
||||
|
||||
let () =
|
||||
register_error_kind
|
||||
@ -136,12 +137,12 @@ let () =
|
||||
~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) ->
|
||||
~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)) ;
|
||||
(function Missing_public_key k -> Some k | _ -> None)
|
||||
(fun k -> Missing_public_key k) ;
|
||||
register_error_kind
|
||||
`Permanent
|
||||
~id:"contract.failure"
|
||||
@ -150,7 +151,18 @@ let () =
|
||||
~pp:(fun ppf s -> Format.fprintf ppf "Contract_storage.Failure %S" s)
|
||||
Data_encoding.(obj1 (req "message" string))
|
||||
(function Failure s -> Some s | _ -> None)
|
||||
(fun s -> Failure s)
|
||||
(fun s -> Failure s) ;
|
||||
register_error_kind
|
||||
`Permanent
|
||||
~id:"contract.manager.unregistred_delegate"
|
||||
~title:"Unregistred delegate"
|
||||
~description:"A contract cannot be delegated to an unregistred delegate"
|
||||
~pp:(fun ppf (k) ->
|
||||
Format.fprintf ppf "The delegate public key (with hash %a) is missing"
|
||||
Ed25519.Public_key_hash.pp k)
|
||||
Data_encoding.(obj1 (req "hash" Ed25519.Public_key_hash.encoding))
|
||||
(function Unregistred_delegate (k) -> Some (k) | _ -> None)
|
||||
(fun (k) -> Unregistred_delegate (k))
|
||||
|
||||
let failwith msg = fail (Failure msg)
|
||||
|
||||
@ -168,7 +180,12 @@ let create_base c contract
|
||||
Storage.Contract.Delegate.init c contract delegate
|
||||
end >>=? fun c ->
|
||||
Storage.Contract.Spendable.init c contract spendable >>=? fun c ->
|
||||
Storage.Contract.Delegatable.init c contract delegatable >>=? fun c ->
|
||||
begin
|
||||
if delegatable then
|
||||
Storage.Contract.Delegatable.add c contract
|
||||
else
|
||||
Lwt.return c
|
||||
end >>= fun c ->
|
||||
Storage.Contract.Counter.init c contract counter >>=? fun c ->
|
||||
(match script with
|
||||
| Some ({ Script_repr.code ; storage }, (code_fees, storage_fees)) ->
|
||||
@ -189,8 +206,7 @@ let originate c nonce ~balance ~manager ?script ~delegate ~spendable ~delegatabl
|
||||
|
||||
let create_implicit c manager ~balance =
|
||||
create_base c (Contract_repr.implicit_contract manager)
|
||||
~balance ~manager ~delegate:(Some manager)
|
||||
?script:None
|
||||
~balance ~manager ?script:None ~delegate:None
|
||||
~spendable:true ~delegatable:false
|
||||
|
||||
let delete c contract =
|
||||
@ -201,7 +217,7 @@ let delete c contract =
|
||||
Storage.Contract.Manager.delete c contract >>=? fun c ->
|
||||
Storage.Contract.Delegate.remove c contract >>= fun c ->
|
||||
Storage.Contract.Spendable.delete c contract >>=? fun c ->
|
||||
Storage.Contract.Delegatable.delete c contract >>=? fun c ->
|
||||
Storage.Contract.Delegatable.del c contract >>= fun c ->
|
||||
Storage.Contract.Counter.delete c contract >>=? fun c ->
|
||||
Storage.Contract.Code.remove c contract >>= fun c ->
|
||||
Storage.Contract.Storage.remove c contract >>= fun c ->
|
||||
@ -302,13 +318,11 @@ let get_balance c contract =
|
||||
| Some v -> return v
|
||||
|
||||
let is_delegatable c contract =
|
||||
Storage.Contract.Delegatable.get_option c contract >>=? function
|
||||
| None -> begin
|
||||
match Contract_repr.is_implicit contract with
|
||||
| Some _ -> return false
|
||||
| None -> failwith "is_delegatable"
|
||||
end
|
||||
| Some v -> return v
|
||||
match Contract_repr.is_implicit contract with
|
||||
| Some _ ->
|
||||
return false
|
||||
| None ->
|
||||
Storage.Contract.Delegatable.mem c contract >>= return
|
||||
|
||||
let is_spendable c contract =
|
||||
Storage.Contract.Spendable.get_option c contract >>=? function
|
||||
@ -320,17 +334,33 @@ let is_spendable c contract =
|
||||
| Some v -> return v
|
||||
|
||||
let set_delegate c contract delegate =
|
||||
(* A contract delegate can be set only if the contract is delegatable *)
|
||||
is_delegatable c contract >>=? function
|
||||
| false -> fail (Non_delegatable_contract contract)
|
||||
| true ->
|
||||
match delegate with
|
||||
| None ->
|
||||
Storage.Contract.Delegate.remove c contract >>= fun c ->
|
||||
return c
|
||||
| Some delegate ->
|
||||
Storage.Contract.Delegate.init_set c contract delegate >>= fun c ->
|
||||
return c
|
||||
match delegate with
|
||||
| None ->
|
||||
Storage.Contract.Delegate.remove c contract >>= fun c ->
|
||||
return c
|
||||
| Some delegate ->
|
||||
begin
|
||||
Storage.Contract.Manager.get_option
|
||||
c (Contract_repr.implicit_contract delegate) >>=? function
|
||||
| None | Some (Manager_repr.Hash _) -> return false
|
||||
| Some (Manager_repr.Public_key _) -> return true
|
||||
end >>=? fun known_delegate ->
|
||||
Storage.Contract.Delegate.mem
|
||||
c (Contract_repr.implicit_contract delegate)
|
||||
>>= fun registred_delegate ->
|
||||
is_delegatable c contract >>=? fun delegatable ->
|
||||
let self_delegation =
|
||||
match Contract_repr.is_implicit contract with
|
||||
| Some pkh -> Ed25519.Public_key_hash.equal pkh delegate
|
||||
| None -> false in
|
||||
if not known_delegate || not (registred_delegate || self_delegation) then
|
||||
fail (Unregistred_delegate delegate)
|
||||
else if not (delegatable || self_delegation) then
|
||||
fail (Non_delegatable_contract contract)
|
||||
else
|
||||
Storage.Contract.Delegate.init_set c contract delegate >>= fun c ->
|
||||
return c
|
||||
|
||||
|
||||
let code_and_storage_fee c contract =
|
||||
Storage.Contract.Code_fees.get_option c contract >>=? fun code_fees ->
|
||||
@ -375,8 +405,16 @@ let spend_from_script c contract amount =
|
||||
Roll_storage.Contract.remove_amount c contract amount
|
||||
else
|
||||
match Contract_repr.is_implicit contract with
|
||||
| Some _ -> delete c contract
|
||||
| None -> return c
|
||||
| None -> return c (* don't delete originated contract. *)
|
||||
| Some pkh ->
|
||||
Storage.Contract.Delegate.get_option c contract >>=? function
|
||||
| Some pkh' ->
|
||||
(* Don't delete "delegate" contract *)
|
||||
assert (Ed25519.Public_key_hash.equal pkh pkh') ;
|
||||
return c
|
||||
| None ->
|
||||
(* Delete empty implicit contract *)
|
||||
delete c contract
|
||||
|
||||
let credit c contract amount =
|
||||
Storage.Contract.Balance.get_option c contract >>=? function
|
||||
|
@ -14,9 +14,7 @@ type error +=
|
||||
| No_roll_snapshot_for_cycle of Cycle_repr.t
|
||||
|
||||
let get_contract_delegate c contract =
|
||||
match Contract_repr.is_implicit contract with
|
||||
| Some manager -> return (Some manager)
|
||||
| None -> Storage.Contract.Delegate.get_option c contract
|
||||
Storage.Contract.Delegate.get_option c contract
|
||||
|
||||
let get_contract_delegate_at_cycle c cycle contract =
|
||||
match Contract_repr.is_implicit contract with
|
||||
|
@ -65,9 +65,8 @@ module Contract = struct
|
||||
(Make_value(Bool))
|
||||
|
||||
module Delegatable =
|
||||
Indexed_context.Make_map
|
||||
Indexed_context.Make_set
|
||||
(struct let name = ["delegatable"] end)
|
||||
(Make_value(Bool))
|
||||
|
||||
module Delegate =
|
||||
Make_indexed_data_snapshotable_storage
|
||||
|
@ -114,9 +114,8 @@ module Contract : sig
|
||||
and type value = bool
|
||||
and type t := Raw_context.t
|
||||
|
||||
module Delegatable : Indexed_data_storage
|
||||
with type key = Contract_repr.t
|
||||
and type value = bool
|
||||
module Delegatable : Data_set_storage
|
||||
with type elt = Contract_repr.t
|
||||
and type t := Raw_context.t
|
||||
|
||||
module Counter : Indexed_data_storage
|
||||
|
Loading…
Reference in New Issue
Block a user