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
|
~account
|
||||||
~destination:b3.contract
|
~destination:b3.contract
|
||||||
~amount:(tez 10L) () >>= fun result ->
|
~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. *)
|
(* Try spending an originated contract without the manager's key. *)
|
||||||
let account = { b1 with contract = spendable } in
|
let account = { b1 with contract = spendable } in
|
||||||
|
@ -14,10 +14,13 @@ type account = {
|
|||||||
|
|
||||||
let init_account ctxt account =
|
let init_account ctxt account =
|
||||||
Storage.Public_key.init ctxt account.public_key_hash account.public_key >>=? fun ctxt ->
|
Storage.Public_key.init ctxt account.public_key_hash account.public_key >>=? fun ctxt ->
|
||||||
Contract_storage.credit
|
let contract = Contract_repr.implicit_contract account.public_key_hash in
|
||||||
ctxt
|
Contract_storage.credit ctxt contract
|
||||||
(Contract_repr.implicit_contract account.public_key_hash)
|
|
||||||
Constants_repr.bootstrap_wealth >>=? fun ctxt ->
|
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
|
return ctxt
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ type error +=
|
|||||||
| Inconsistent_public_key of Ed25519.Public_key.t * Ed25519.Public_key.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 *)
|
| Missing_public_key of Ed25519.Public_key_hash.t (* `Permanent *)
|
||||||
| Failure of string (* `Permanent *)
|
| Failure of string (* `Permanent *)
|
||||||
|
| Unregistred_delegate of Ed25519.Public_key_hash.t (* `Permanent *)
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
register_error_kind
|
register_error_kind
|
||||||
@ -136,12 +137,12 @@ let () =
|
|||||||
~id:"contract.manager.missing_public_key"
|
~id:"contract.manager.missing_public_key"
|
||||||
~title:"Missing public key"
|
~title:"Missing public key"
|
||||||
~description:"The manager public key must be provided to execute the current operation"
|
~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"
|
Format.fprintf ppf "The manager public key ( with hash %a ) is missing"
|
||||||
Ed25519.Public_key_hash.pp k)
|
Ed25519.Public_key_hash.pp k)
|
||||||
Data_encoding.(obj1 (req "hash" Ed25519.Public_key_hash.encoding))
|
Data_encoding.(obj1 (req "hash" Ed25519.Public_key_hash.encoding))
|
||||||
(function Missing_public_key (k) -> Some (k) | _ -> None)
|
(function Missing_public_key k -> Some k | _ -> None)
|
||||||
(fun (k) -> Missing_public_key (k)) ;
|
(fun k -> Missing_public_key k) ;
|
||||||
register_error_kind
|
register_error_kind
|
||||||
`Permanent
|
`Permanent
|
||||||
~id:"contract.failure"
|
~id:"contract.failure"
|
||||||
@ -150,7 +151,18 @@ let () =
|
|||||||
~pp:(fun ppf s -> Format.fprintf ppf "Contract_storage.Failure %S" s)
|
~pp:(fun ppf s -> Format.fprintf ppf "Contract_storage.Failure %S" s)
|
||||||
Data_encoding.(obj1 (req "message" string))
|
Data_encoding.(obj1 (req "message" string))
|
||||||
(function Failure s -> Some s | _ -> None)
|
(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)
|
let failwith msg = fail (Failure msg)
|
||||||
|
|
||||||
@ -168,7 +180,12 @@ let create_base c contract
|
|||||||
Storage.Contract.Delegate.init c contract delegate
|
Storage.Contract.Delegate.init c contract delegate
|
||||||
end >>=? fun c ->
|
end >>=? fun c ->
|
||||||
Storage.Contract.Spendable.init c contract spendable >>=? 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 ->
|
Storage.Contract.Counter.init c contract counter >>=? fun c ->
|
||||||
(match script with
|
(match script with
|
||||||
| Some ({ Script_repr.code ; storage }, (code_fees, storage_fees)) ->
|
| 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 =
|
let create_implicit c manager ~balance =
|
||||||
create_base c (Contract_repr.implicit_contract manager)
|
create_base c (Contract_repr.implicit_contract manager)
|
||||||
~balance ~manager ~delegate:(Some manager)
|
~balance ~manager ?script:None ~delegate:None
|
||||||
?script:None
|
|
||||||
~spendable:true ~delegatable:false
|
~spendable:true ~delegatable:false
|
||||||
|
|
||||||
let delete c contract =
|
let delete c contract =
|
||||||
@ -201,7 +217,7 @@ let delete c contract =
|
|||||||
Storage.Contract.Manager.delete c contract >>=? fun c ->
|
Storage.Contract.Manager.delete c contract >>=? fun c ->
|
||||||
Storage.Contract.Delegate.remove c contract >>= fun c ->
|
Storage.Contract.Delegate.remove c contract >>= fun c ->
|
||||||
Storage.Contract.Spendable.delete 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.Counter.delete c contract >>=? fun c ->
|
||||||
Storage.Contract.Code.remove c contract >>= fun c ->
|
Storage.Contract.Code.remove c contract >>= fun c ->
|
||||||
Storage.Contract.Storage.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
|
| Some v -> return v
|
||||||
|
|
||||||
let is_delegatable c contract =
|
let is_delegatable c contract =
|
||||||
Storage.Contract.Delegatable.get_option c contract >>=? function
|
match Contract_repr.is_implicit contract with
|
||||||
| None -> begin
|
| Some _ ->
|
||||||
match Contract_repr.is_implicit contract with
|
return false
|
||||||
| Some _ -> return false
|
| None ->
|
||||||
| None -> failwith "is_delegatable"
|
Storage.Contract.Delegatable.mem c contract >>= return
|
||||||
end
|
|
||||||
| Some v -> return v
|
|
||||||
|
|
||||||
let is_spendable c contract =
|
let is_spendable c contract =
|
||||||
Storage.Contract.Spendable.get_option c contract >>=? function
|
Storage.Contract.Spendable.get_option c contract >>=? function
|
||||||
@ -320,17 +334,33 @@ let is_spendable c contract =
|
|||||||
| Some v -> return v
|
| Some v -> return v
|
||||||
|
|
||||||
let set_delegate c contract delegate =
|
let set_delegate c contract delegate =
|
||||||
(* A contract delegate can be set only if the contract is delegatable *)
|
match delegate with
|
||||||
is_delegatable c contract >>=? function
|
| None ->
|
||||||
| false -> fail (Non_delegatable_contract contract)
|
Storage.Contract.Delegate.remove c contract >>= fun c ->
|
||||||
| true ->
|
return c
|
||||||
match delegate with
|
| Some delegate ->
|
||||||
| None ->
|
begin
|
||||||
Storage.Contract.Delegate.remove c contract >>= fun c ->
|
Storage.Contract.Manager.get_option
|
||||||
return c
|
c (Contract_repr.implicit_contract delegate) >>=? function
|
||||||
| Some delegate ->
|
| None | Some (Manager_repr.Hash _) -> return false
|
||||||
Storage.Contract.Delegate.init_set c contract delegate >>= fun c ->
|
| Some (Manager_repr.Public_key _) -> return true
|
||||||
return c
|
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 =
|
let code_and_storage_fee c contract =
|
||||||
Storage.Contract.Code_fees.get_option c contract >>=? fun code_fees ->
|
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
|
Roll_storage.Contract.remove_amount c contract amount
|
||||||
else
|
else
|
||||||
match Contract_repr.is_implicit contract with
|
match Contract_repr.is_implicit contract with
|
||||||
| Some _ -> delete c contract
|
| None -> return c (* don't delete originated contract. *)
|
||||||
| None -> return c
|
| 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 =
|
let credit c contract amount =
|
||||||
Storage.Contract.Balance.get_option c contract >>=? function
|
Storage.Contract.Balance.get_option c contract >>=? function
|
||||||
|
@ -14,9 +14,7 @@ type error +=
|
|||||||
| No_roll_snapshot_for_cycle of Cycle_repr.t
|
| No_roll_snapshot_for_cycle of Cycle_repr.t
|
||||||
|
|
||||||
let get_contract_delegate c contract =
|
let get_contract_delegate c contract =
|
||||||
match Contract_repr.is_implicit contract with
|
Storage.Contract.Delegate.get_option c contract
|
||||||
| Some manager -> return (Some manager)
|
|
||||||
| None -> Storage.Contract.Delegate.get_option c contract
|
|
||||||
|
|
||||||
let get_contract_delegate_at_cycle c cycle contract =
|
let get_contract_delegate_at_cycle c cycle contract =
|
||||||
match Contract_repr.is_implicit contract with
|
match Contract_repr.is_implicit contract with
|
||||||
|
@ -65,9 +65,8 @@ module Contract = struct
|
|||||||
(Make_value(Bool))
|
(Make_value(Bool))
|
||||||
|
|
||||||
module Delegatable =
|
module Delegatable =
|
||||||
Indexed_context.Make_map
|
Indexed_context.Make_set
|
||||||
(struct let name = ["delegatable"] end)
|
(struct let name = ["delegatable"] end)
|
||||||
(Make_value(Bool))
|
|
||||||
|
|
||||||
module Delegate =
|
module Delegate =
|
||||||
Make_indexed_data_snapshotable_storage
|
Make_indexed_data_snapshotable_storage
|
||||||
|
@ -114,9 +114,8 @@ module Contract : sig
|
|||||||
and type value = bool
|
and type value = bool
|
||||||
and type t := Raw_context.t
|
and type t := Raw_context.t
|
||||||
|
|
||||||
module Delegatable : Indexed_data_storage
|
module Delegatable : Data_set_storage
|
||||||
with type key = Contract_repr.t
|
with type elt = Contract_repr.t
|
||||||
and type value = bool
|
|
||||||
and type t := Raw_context.t
|
and type t := Raw_context.t
|
||||||
|
|
||||||
module Counter : Indexed_data_storage
|
module Counter : Indexed_data_storage
|
||||||
|
Loading…
Reference in New Issue
Block a user