From 677869e139879485a2c99adf3811cf5325c6193b Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Wed, 2 Aug 2017 16:56:13 -0500 Subject: [PATCH] Ref #123: Implement updateauth, deleteauth Though not strictly part of issue 123, this is a necessary step in order to complete #123. Rename UpdatePermission->updateauth and DeletePermission->deleteauth, and implement them. At this point, I think #123 is fully implemented and ready for testing. --- libraries/native_contract/eos_contract.cpp | 64 ++++++++++++++++++- .../eos/native_contract/eos_contract.hpp | 2 + .../native_contract_chain_initializer.cpp | 2 + libraries/types/types.eos | 6 +- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/libraries/native_contract/eos_contract.cpp b/libraries/native_contract/eos_contract.cpp index d617174980e..c5fa51f33bc 100644 --- a/libraries/native_contract/eos_contract.cpp +++ b/libraries/native_contract/eos_contract.cpp @@ -361,9 +361,71 @@ void apply_eos_setproxy(apply_context& context) { */ } +void apply_eos_updateauth(apply_context& context) { + auto update = context.msg.as(); + EOS_ASSERT(!update.permission.empty(), message_validate_exception, "Cannot create authority with empty name"); + EOS_ASSERT(validate(update.authority), message_validate_exception, + "Invalid authority: ${auth}", ("auth", update.authority)); + if (update.permission == "active") + EOS_ASSERT(update.parent == "owner", message_validate_exception, "Cannot change active authority's parent"); + if (update.permission == "owner") + EOS_ASSERT(update.parent.empty(), message_validate_exception, "Cannot change owner authority's parent"); + + auto& db = context.mutable_db; + context.require_authorization(update.account); + + db.get(update.account); + auto& parent = db.get(boost::make_tuple(update.account, update.parent)); + for (auto accountPermission : update.authority.accounts) { + db.get(accountPermission.permission.account); + db.get(boost::make_tuple(accountPermission.permission.account, + accountPermission.permission.permission)); + } + + const auto& permission = db.find(boost::make_tuple(update.account, update.permission)); + if (permission) { + db.modify(*permission, [&update, parent = parent.id](permission_object& po) { + po.auth = update.authority; + po.parent = parent; + }); + } else { + db.create([&update, parent = parent.id](permission_object& po) { + po.name = update.permission; + po.owner = update.account; + po.auth = update.authority; + po.parent = parent; + }); + } +} + +void apply_eos_deleteauth(apply_context& context) { + auto remove = context.msg.as(); + EOS_ASSERT(remove.permission != "active", message_validate_exception, "Cannot delete active authority"); + EOS_ASSERT(remove.permission != "owner", message_validate_exception, "Cannot delete owner authority"); + + auto& db = context.mutable_db; + context.require_authorization(remove.account); + const auto& permission = db.get(boost::make_tuple(remove.account, remove.permission)); + + { // Check for children + const auto& index = db.get_index(); + auto range = index.equal_range(permission.id); + EOS_ASSERT(range.first == range.second, message_precondition_exception, + "Cannot delete an authority which has children. Delete the children first"); + } + + { // Check for links to this permission + const auto& index = db.get_index(); + auto range = index.equal_range(boost::make_tuple(remove.account, remove.permission)); + EOS_ASSERT(range.first == range.second, message_precondition_exception, + "Cannot delete a linked authority. Unlink the authority first"); + } + + db.remove(permission); +} + void apply_eos_linkauth(apply_context& context) { auto requirement = context.msg.as(); - EOS_ASSERT(!requirement.requirement.empty(), message_validate_exception, "Required permission cannot be empty"); context.require_authorization(requirement.account); diff --git a/libraries/native_contract/include/eos/native_contract/eos_contract.hpp b/libraries/native_contract/include/eos/native_contract/eos_contract.hpp index e820a6dc9b1..0471e53339e 100644 --- a/libraries/native_contract/include/eos/native_contract/eos_contract.hpp +++ b/libraries/native_contract/include/eos/native_contract/eos_contract.hpp @@ -18,6 +18,8 @@ void apply_eos_okproducer(chain::apply_context&); void apply_eos_setproducer(chain::apply_context&); void apply_eos_setproxy(chain::apply_context&); void apply_eos_setcode(chain::apply_context&); +void apply_eos_updateauth(chain::apply_context&); +void apply_eos_deleteauth(chain::apply_context&); void apply_eos_linkauth(chain::apply_context&); void apply_eos_unlinkauth(chain::apply_context&); diff --git a/libraries/native_contract/native_contract_chain_initializer.cpp b/libraries/native_contract/native_contract_chain_initializer.cpp index ba5c0bb2e09..13dffb4cc95 100644 --- a/libraries/native_contract/native_contract_chain_initializer.cpp +++ b/libraries/native_contract/native_contract_chain_initializer.cpp @@ -48,6 +48,8 @@ void native_contract_chain_initializer::register_types(chain_controller& chain, SET_APP_HANDLER( eos, eos, setproducer ); SET_APP_HANDLER( eos, eos, setproxy ); SET_APP_HANDLER( eos, eos, setcode ); + SET_APP_HANDLER( eos, eos, updateauth ); + SET_APP_HANDLER( eos, eos, deleteauth ); SET_APP_HANDLER( eos, eos, linkauth ); SET_APP_HANDLER( eos, eos, unlinkauth ); } diff --git a/libraries/types/types.eos b/libraries/types/types.eos index f2f684ee8d6..d60ff179458 100644 --- a/libraries/types/types.eos +++ b/libraries/types/types.eos @@ -116,17 +116,17 @@ struct setproxy proxy AccountName # The account to cast votes with stakeholder's stake weight -struct UpdatePermission +struct updateauth account AccountName permission PermissionName parent PermissionName authority Authority -struct DeletePermission +struct deleteauth account AccountName permission PermissionName -struct linkauth +struct linkauth # Specify a particular required permission for account to approve specified message type account AccountName # The account to require permissions for code AccountName # The contract to require permissions to invoke type FuncName