Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #210: Check required_auths on custom_operation #1629

Merged
merged 7 commits into from
Aug 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 48 additions & 42 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2270,34 +2270,36 @@ set<address> database_api::get_potential_address_signatures( const signed_transa

set<public_key_type> database_api_impl::get_potential_signatures( const signed_transaction& trx )const
{
bool allow_non_immediate_owner = ( _db.head_block_time() >= HARDFORK_CORE_584_TIME );
auto chain_time = _db.head_block_time();
bool allow_non_immediate_owner = ( chain_time >= HARDFORK_CORE_584_TIME );
bool ignore_custom_op_reqd_auths = MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( chain_time );

set<public_key_type> result;
trx.get_required_signatures(
_db.get_chain_id(),
flat_set<public_key_type>(),
[&]( account_id_type id )
{
const auto& auth = id(_db).active;
for( const auto& k : auth.get_keys() )
result.insert(k);
return &auth;
},
[&]( account_id_type id )
{
const auto& auth = id(_db).owner;
for( const auto& k : auth.get_keys() )
result.insert(k);
return &auth;
},
allow_non_immediate_owner,
_db.get_global_properties().parameters.max_authority_depth
);
auto get_active = [this, &result]( account_id_type id ){
const auto& auth = id( _db ).active;
for( const auto& k : auth.get_keys() )
result.insert( k );
return &auth;
};
auto get_owner = [this, &result]( account_id_type id ){
const auto& auth = id( _db ).owner;
for( const auto& k : auth.get_keys() )
result.insert( k );
return &auth;
};

trx.get_required_signatures( _db.get_chain_id(),
flat_set<public_key_type>(),
get_active, get_owner,
allow_non_immediate_owner,
ignore_custom_op_reqd_auths,
_db.get_global_properties().parameters.max_authority_depth );

// Insert keys in required "other" authories
flat_set<account_id_type> required_active;
flat_set<account_id_type> required_owner;
vector<authority> other;
trx.get_required_authorities( required_active, required_owner, other );
trx.get_required_authorities( required_active, required_owner, other, ignore_custom_op_reqd_auths );
for( const auto& auth : other )
for( const auto& key : auth.get_keys() )
result.insert( key );
Expand All @@ -2307,26 +2309,30 @@ set<public_key_type> database_api_impl::get_potential_signatures( const signed_t

set<address> database_api_impl::get_potential_address_signatures( const signed_transaction& trx )const
{
auto chain_time = _db.head_block_time();
bool allow_non_immediate_owner = ( chain_time >= HARDFORK_CORE_584_TIME );
bool ignore_custom_op_reqd_auths = MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( chain_time );

set<address> result;
trx.get_required_signatures(
_db.get_chain_id(),
flat_set<public_key_type>(),
[&]( account_id_type id )
{
const auto& auth = id(_db).active;
for( const auto& k : auth.get_addresses() )
result.insert(k);
return &auth;
},
[&]( account_id_type id )
{
const auto& auth = id(_db).owner;
for( const auto& k : auth.get_addresses() )
result.insert(k);
return &auth;
},
_db.get_global_properties().parameters.max_authority_depth
);
auto get_active = [this, &result]( account_id_type id ){
const auto& auth = id( _db ).active;
for( const auto& k : auth.get_addresses() )
result.insert( k );
return &auth;
};
auto get_owner = [this, &result]( account_id_type id ) {
const auto& auth = id( _db ).owner;
for (const auto& k : auth.get_addresses())
result.insert( k );
return &auth;
};

trx.get_required_signatures( _db.get_chain_id(),
flat_set<public_key_type>(),
get_active, get_owner,
allow_non_immediate_owner,
ignore_custom_op_reqd_auths,
_db.get_global_properties().parameters.max_authority_depth );
return result;
}

Expand Down Expand Up @@ -2365,7 +2371,7 @@ bool database_api_impl::verify_account_authority( const string& account_name_or_
graphene::chain::verify_authority(ops, keys,
[this]( account_id_type id ){ return &id(_db).active; },
[this]( account_id_type id ){ return &id(_db).owner; },
true );
true, MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(_db.head_block_time()) );
}
catch (fc::exception& ex)
{
Expand Down
13 changes: 6 additions & 7 deletions libraries/chain/db_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,13 +644,12 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
if( !(skip & skip_transaction_signatures) )
{
bool allow_non_immediate_owner = ( head_block_time() >= HARDFORK_CORE_584_TIME );
auto get_active = [&]( account_id_type id ) { return &id(*this).active; };
auto get_owner = [&]( account_id_type id ) { return &id(*this).owner; };
trx.verify_authority( chain_id,
get_active,
get_owner,
allow_non_immediate_owner,
get_global_properties().parameters.max_authority_depth );
auto get_active = [this]( account_id_type id ) { return &id(*this).active; };
auto get_owner = [this]( account_id_type id ) { return &id(*this).owner; };

trx.verify_authority(chain_id, get_active, get_owner, allow_non_immediate_owner,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(head_block_time()),
get_global_properties().parameters.max_authority_depth);
}

//Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is
Expand Down
48 changes: 30 additions & 18 deletions libraries/chain/db_notify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <graphene/chain/vesting_balance_object.hpp>
#include <graphene/chain/transaction_history_object.hpp>
#include <graphene/chain/impacted.hpp>
#include <graphene/chain/hardfork.hpp>

using namespace fc;
using namespace graphene::chain;
Expand All @@ -25,8 +26,13 @@ using namespace graphene::chain;
struct get_impacted_account_visitor
{
flat_set<account_id_type>& _impacted;
get_impacted_account_visitor( flat_set<account_id_type>& impact ):_impacted(impact) {}
typedef void result_type;
bool _ignore_custom_op_reqd_auths;

get_impacted_account_visitor( flat_set<account_id_type>& impact, bool ignore_custom_operation_required_auths )
: _impacted( impact ), _ignore_custom_op_reqd_auths( ignore_custom_operation_required_auths )
{}

using result_type = void;

void operator()( const transfer_operation& op )
{
Expand Down Expand Up @@ -154,7 +160,7 @@ struct get_impacted_account_visitor
_impacted.insert( op.fee_payer() ); // fee_paying_account
vector<authority> other;
for( const auto& proposed_op : op.proposed_ops )
operation_get_required_authorities( proposed_op.op, _impacted, _impacted, other );
operation_get_required_authorities( proposed_op.op, _impacted, _impacted, other, _ignore_custom_op_reqd_auths );
for( auto& o : other )
add_authority_accounts( _impacted, o );
}
Expand Down Expand Up @@ -214,6 +220,8 @@ struct get_impacted_account_visitor
void operator()( const custom_operation& op )
{
_impacted.insert( op.fee_payer() ); // payer
if( !_ignore_custom_op_reqd_auths )
_impacted.insert( op.required_auths.begin(), op.required_auths.end() );
}
void operator()( const assert_operation& op )
{
Expand Down Expand Up @@ -283,20 +291,17 @@ struct get_impacted_account_visitor
}
};

void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
{
get_impacted_account_visitor vtor = get_impacted_account_visitor( result );
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result, bool ignore_custom_operation_required_auths ) {
get_impacted_account_visitor vtor = get_impacted_account_visitor( result, ignore_custom_operation_required_auths );
op.visit( vtor );
}

void graphene::chain::transaction_get_impacted_accounts( const transaction& tx, flat_set<account_id_type>& result )
{
void graphene::chain::transaction_get_impacted_accounts( const transaction& tx, flat_set<account_id_type>& result, bool ignore_custom_operation_required_auths ) {
for( const auto& op : tx.operations )
operation_get_impacted_accounts( op, result );
operation_get_impacted_accounts( op, result, ignore_custom_operation_required_auths );
}

void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts )
{
void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts, bool ignore_custom_operation_required_auths ) {
if( obj->id.space() == protocol_ids )
{
switch( (object_type)obj->id.type() )
Expand Down Expand Up @@ -342,12 +347,14 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
} case proposal_object_type:{
const auto& aobj = dynamic_cast<const proposal_object*>(obj);
FC_ASSERT( aobj != nullptr );
transaction_get_impacted_accounts( aobj->proposed_transaction, accounts );
transaction_get_impacted_accounts( aobj->proposed_transaction, accounts,
ignore_custom_operation_required_auths );
break;
} case operation_history_object_type:{
const auto& aobj = dynamic_cast<const operation_history_object*>(obj);
FC_ASSERT( aobj != nullptr );
operation_get_impacted_accounts( aobj->op, accounts );
operation_get_impacted_accounts( aobj->op, accounts,
ignore_custom_operation_required_auths );
break;
} case withdraw_permission_object_type:{
const auto& aobj = dynamic_cast<const withdraw_permission_object*>(obj);
Expand Down Expand Up @@ -404,7 +411,8 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
} case impl_transaction_history_object_type:{
const auto& aobj = dynamic_cast<const transaction_history_object*>(obj);
FC_ASSERT( aobj != nullptr );
transaction_get_impacted_accounts( aobj->trx, accounts );
transaction_get_impacted_accounts( aobj->trx, accounts,
ignore_custom_operation_required_auths );
break;
} case impl_blinded_balance_object_type:{
const auto& aobj = dynamic_cast<const blinded_balance_object*>(obj);
Expand Down Expand Up @@ -458,6 +466,7 @@ void database::notify_changed_objects()
if( _undo_db.enabled() )
{
const auto& head_undo = _undo_db.head();
auto chain_time = head_block_time();

// New
if( !new_objects.empty() )
Expand All @@ -469,7 +478,8 @@ void database::notify_changed_objects()
new_ids.push_back(item);
auto obj = find_object(item);
if(obj != nullptr)
get_relevant_accounts(obj, new_accounts_impacted);
get_relevant_accounts(obj, new_accounts_impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time));
}

if( new_ids.size() )
Expand All @@ -484,7 +494,8 @@ void database::notify_changed_objects()
for( const auto& item : head_undo.old_values )
{
changed_ids.push_back(item.first);
get_relevant_accounts(item.second.get(), changed_accounts_impacted);
get_relevant_accounts(item.second.get(), changed_accounts_impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time));
}

if( changed_ids.size() )
Expand All @@ -502,11 +513,12 @@ void database::notify_changed_objects()
removed_ids.emplace_back( item.first );
auto obj = item.second.get();
removed.emplace_back( obj );
get_relevant_accounts(obj, removed_accounts_impacted);
get_relevant_accounts(obj, removed_accounts_impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time));
}

if( removed_ids.size() )
GRAPHENE_TRY_NOTIFY( removed_objects, removed_ids, removed, removed_accounts_impacted)
GRAPHENE_TRY_NOTIFY( removed_objects, removed_ids, removed, removed_accounts_impacted )
}
}
} FC_CAPTURE_AND_LOG( (0) ) }
Expand Down
6 changes: 6 additions & 0 deletions libraries/chain/hardfork.d/CORE_210.hf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// #210 Check authorities on custom_operation
#ifndef HARDFORK_CORE_210_TIME
#define HARDFORK_CORE_210_TIME (fc::time_point_sec(1893456000)) // Jan 1 00:00:00 2030 (Not yet scheduled)
// Bugfix: pre-HF 210, custom_operation's required_auths field was ignored.
#define MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time) (chain_time <= HARDFORK_CORE_210_TIME)
#endif
15 changes: 7 additions & 8 deletions libraries/chain/include/graphene/chain/impacted.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@

namespace graphene { namespace chain {

void operation_get_impacted_accounts(
const graphene::chain::operation& op,
fc::flat_set<graphene::chain::account_id_type>& result );
void operation_get_impacted_accounts( const graphene::chain::operation& op,
fc::flat_set<graphene::chain::account_id_type>& result,
bool ignore_custom_operation_required_auths );

void transaction_get_impacted_accounts(
const graphene::chain::transaction& tx,
fc::flat_set<graphene::chain::account_id_type>& result
);
void transaction_get_impacted_accounts( const graphene::chain::transaction& tx,
fc::flat_set<graphene::chain::account_id_type>& result,
bool ignore_custom_operation_required_auths );

} } // graphene::app
} } // graphene::app
2 changes: 2 additions & 0 deletions libraries/chain/include/graphene/chain/proposal_evaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ namespace graphene { namespace chain {
object_id_type do_apply( const proposal_create_operation& o );

transaction _proposed_trx;
flat_set<account_id_type> _required_active_auths;
flat_set<account_id_type> _required_owner_auths;

hardfork_visitor_1479 vtor_1479;
};
Expand Down
Loading