123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2021 Nomadic Labs, <contact@nomadic-labs.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)typeerror+=|(* `Branch *)Unrevealed_manager_keyofContract_repr.t|(* `Permanent *)Inconsistent_hashof{public_key:Signature.Public_key.t;expected_hash:Signature.Public_key_hash.t;provided_hash:Signature.Public_key_hash.t;}|(* `Branch *)Previously_revealed_keyofContract_repr.t|(* `Branch *)Missing_manager_contractofContract_repr.tlet()=register_error_kind`Branch~id:"contract.unrevealed_key"~title:"Manager operation precedes key revelation"~description:"One tried to apply a manager operation without revealing the manager \
public key"~pp:(funppfs->Format.fprintfppf"Unrevealed manager key for contract %a."Contract_repr.pps)Data_encoding.(obj1(req"contract"Contract_repr.encoding))(functionUnrevealed_manager_keys->Somes|_->None)(funs->Unrevealed_manager_keys);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:(funppf(k,eh,ph)->Format.fprintfppf"The hash of the manager public key %s is not %a as announced but %a"(Signature.Public_key.to_b58checkk)Signature.Public_key_hash.ppphSignature.Public_key_hash.ppeh)Data_encoding.(obj3(req"public_key"Signature.Public_key.encoding)(req"expected_hash"Signature.Public_key_hash.encoding)(req"provided_hash"Signature.Public_key_hash.encoding))(function|Inconsistent_hash{public_key;expected_hash;provided_hash}->Some(public_key,expected_hash,provided_hash)|_->None)(fun(public_key,expected_hash,provided_hash)->Inconsistent_hash{public_key;expected_hash;provided_hash});register_error_kind`Branch~id:"contract.previously_revealed_key"~title:"Manager operation already revealed"~description:"One tried to reveal twice a manager public key"~pp:(funppfs->Format.fprintfppf"Previously revealed manager key for contract %a."Contract_repr.pps)Data_encoding.(obj1(req"contract"Contract_repr.encoding))(functionPreviously_revealed_keys->Somes|_->None)(funs->Previously_revealed_keys);register_error_kind`Branch~id:"contract.missing_manager_contract"~title:"Missing manager contract"~description:"The manager contract is missing from the storage"~pp:(funppfs->Format.fprintfppf"The contract %a is missing from the storage."Contract_repr.pps)Data_encoding.(obj1(req"contract"Contract_repr.encoding))(functionMissing_manager_contracts->Somes|_->None)(funs->Missing_manager_contracts)letinit=Storage.Contract.Manager.initletis_manager_key_revealedcmanager=letopenLwt_result_syntaxinletcontract=Contract_repr.Implicitmanagerinlet*key_opt=Storage.Contract.Manager.findccontractinmatchkey_optwith|None->return_false|Some(Manager_repr.Hash_)->return_false|Some(Manager_repr.Public_key_)->return_trueletcheck_public_keypublic_keyexpected_hash=letprovided_hash=Signature.Public_key.hashpublic_keyinerror_unless(Signature.Public_key_hash.equalprovided_hashexpected_hash)(Inconsistent_hash{public_key;expected_hash;provided_hash})letreveal_manager_key?(check_consistency=true)cmanagerpublic_key=letopenLwt_result_syntaxinletcontract=Contract_repr.Implicitmanagerinlet*key_opt=Storage.Contract.Manager.getccontractinmatchkey_optwith|Public_key_->tzfail(Previously_revealed_keycontract)|Hashexpected_hash->(* Ensure that the manager is equal to the retrieved hash. *)let*?()=error_unless(Signature.Public_key_hash.equalmanagerexpected_hash)(Inconsistent_hash{public_key;expected_hash;provided_hash=manager})in(* TODO tezos/tezos#3078
We keep the consistency check and the optional argument to
preserve the semantics of reveal_manager_key prior to
tezos/tezos!5182, when called outside the scope of
[apply_operation].
Inside appply.ml, it is used with
?check_consistency=false. Ultimately this parameter should go
away, and the split check_publick_key / reveal_manager_key
pattern has to be exported to usage outside apply.ml *)let*()=when_check_consistency(fun()->Lwt.return@@check_public_keypublic_keyexpected_hash)inletpk=Manager_repr.Public_keypublic_keyinStorage.Contract.Manager.updateccontractpkletget_manager_key?errorctxtpkh=letopenLwt_result_syntaxinletcontract=Contract_repr.Implicitpkhinlet*key_opt=Storage.Contract.Manager.findctxtcontractinmatchkey_optwith|None->(matcherrorwith|None->tzfail(Missing_manager_contractcontract)|Someerror->tzfailerror)|Some(Manager_repr.Hash_)->(matcherrorwith|None->tzfail(Unrevealed_manager_keycontract)|Someerror->tzfailerror)|Some(Manager_repr.Public_keypk)->returnpkletremove_existing=Storage.Contract.Manager.remove_existing