From 8425270150e0026279532cf1d6eed0768f959739 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Tue, 15 Aug 2017 12:13:36 -0500 Subject: [PATCH] Fix tracking of used_authorizations across notified accounts Previously, only the used_authorizations from the original message were being tracked, even though the original message might notify other accounts which in turn might require more authorizations. This is now fixed so that all required auths from all handlers called in the processing of a message and its notifications are tracked. This fixes "irrelevant authority" errors which were being thrown incorrectly. --- libraries/chain/chain_controller.cpp | 43 +++++++------------ .../include/eos/chain/chain_controller.hpp | 3 +- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/libraries/chain/chain_controller.cpp b/libraries/chain/chain_controller.cpp index 25b0d6daa..c183be567 100644 --- a/libraries/chain/chain_controller.cpp +++ b/libraries/chain/chain_controller.cpp @@ -607,43 +607,18 @@ void chain_controller::validate_expiration(const SignedTransaction& trx) const } FC_CAPTURE_AND_RETHROW((trx)) } -/** - * When processing a message it needs to run: - * - * code::precondition( message.code, message.apply ) - * code::apply( message.code, message.apply ) - * - * Then for each recipient it needs to run - * - * ```` - * recipient::precondition( message.code, message.apply ) - * recipient::apply( message.code, message.apply ) - * ``` - * - * The data that can be read is anything declared in trx.scope - * The data that can be written is anything stored in * / [code | recipient] / * - * - * The order of execution of precondition and apply can impact the validity of the - * entire message. - */ void chain_controller::process_message(const ProcessedTransaction& trx, AccountName code, - const Message& message, MessageOutput& output) { + const Message& message, MessageOutput& output, apply_context* parent_context) { apply_context apply_ctx(*this, _db, trx, message, code); apply_message(apply_ctx); - // process_message recurses for each notified account, but we only want to run this check at the top level - if (code == message.code && (_skip_flags & skip_authority_check) == false) - EOS_ASSERT(apply_ctx.all_authorizations_used(), tx_irrelevant_auth, - "Message declared authorities it did not need: ${unused}", - ("unused", apply_ctx.unused_authorizations())("message", message)); - output.notify.reserve( apply_ctx.notified.size() ); for( uint32_t i = 0; i < apply_ctx.notified.size(); ++i ) { try { auto notify_code = apply_ctx.notified[i]; output.notify.push_back( {notify_code} ); - process_message( trx, notify_code, message, output.notify.back().output ); + process_message(trx, notify_code, message, output.notify.back().output, &apply_ctx); } FC_CAPTURE_AND_RETHROW((apply_ctx.notified[i])) } @@ -654,8 +629,20 @@ void chain_controller::process_message(const ProcessedTransaction& trx, AccountN } for( auto& asynctrx : apply_ctx.async_transactions ) { - output.async_transactions.emplace_back( std::move( asynctrx ) ); + output.async_transactions.emplace_back( std::move( asynctrx ) ); } + + // propagate used_authorizations up the context chain + if (parent_context != nullptr) + for (int i = 0; i < apply_ctx.used_authorizations.size(); ++i) + if (apply_ctx.used_authorizations[i]) + parent_context->used_authorizations[i] = true; + + // process_message recurses for each notified account, but we only want to run this check at the top level + if (parent_context == nullptr && (_skip_flags & skip_authority_check) == false) + EOS_ASSERT(apply_ctx.all_authorizations_used(), tx_irrelevant_auth, + "Message declared authorities it did not need: ${unused}", + ("unused", apply_ctx.unused_authorizations())("message", message)); } void chain_controller::apply_message(apply_context& context) diff --git a/libraries/chain/include/eos/chain/chain_controller.hpp b/libraries/chain/include/eos/chain/chain_controller.hpp index d56df89ba..202cee399 100644 --- a/libraries/chain/include/eos/chain/chain_controller.hpp +++ b/libraries/chain/include/eos/chain/chain_controller.hpp @@ -302,7 +302,8 @@ namespace eos { namespace chain { types::AccountName code_account, types::FuncName type) const; - void process_message(const ProcessedTransaction& trx, AccountName code, const Message& message, MessageOutput& output); + void process_message(const ProcessedTransaction& trx, AccountName code, const Message& message, + MessageOutput& output, apply_context* parent_context = nullptr); void apply_message(apply_context& c); bool should_check_for_duplicate_transactions()const { return !(_skip_flags&skip_transaction_dupe_check); } -- GitLab