Compare commits

...

5 commits

Author SHA1 Message Date
sierra19XX
df7f9c3783 compilation fix 2020-09-08 11:51:00 +00:00
sierra19XX
4c7e951d6b Merge remote-tracking branch 'origin/develop' into feature/bts-210 2020-09-08 11:22:18 +00:00
Nathan Hourt
406cc54299
Ref #381: Fix bad merge
During merge conflict resolution, I accidentally broke custom
authorities. This fixes it.
2020-09-03 17:16:06 -05:00
Nathan Hourt
5d48052da3
Ref #381: Fixes
Build and logic fixes for Pull Request #381
2020-09-02 14:18:44 -05:00
Nathan Hourt
133b41b65a
Resolve #210: [HF] Check authorities on custom_operation
The required_auths field on custom_operation was being ignored during authority checking. This commit causes it to be checked correctly, and adds a unit test verifying as much.
2020-09-02 13:14:11 -05:00
14 changed files with 164 additions and 87 deletions

View file

@ -789,12 +789,14 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
if( !(skip & (skip_transaction_signatures | skip_authority_check) ) )
{
auto get_active = [&]( account_id_type id ) { return &id(*this).active; };
auto get_owner = [&]( account_id_type id ) { return &id(*this).owner; };
auto get_custom = [&]( account_id_type id, const operation& op ) {
auto get_active = [this]( account_id_type id ) { return &id(*this).active; };
auto get_owner = [this]( account_id_type id ) { return &id(*this).owner; };
auto get_custom = [this]( account_id_type id, const operation& op ) {
return get_account_custom_authorities(id, op);
};
trx.verify_authority( chain_id, get_active, get_owner, get_custom, get_global_properties().parameters.max_authority_depth );
trx.verify_authority( chain_id, get_active, get_owner, get_custom,
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

View file

@ -40,6 +40,7 @@
#include <graphene/chain/vesting_balance_object.hpp>
#include <graphene/chain/transaction_object.hpp>
#include <graphene/chain/impacted.hpp>
#include <graphene/chain/hardfork.hpp>
using namespace fc;
@ -49,8 +50,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 )
{
@ -136,7 +142,7 @@ struct get_impacted_account_visitor
{
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 );
}
@ -346,20 +352,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() )
@ -406,12 +409,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);
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);
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);
@ -462,7 +467,8 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
} case impl_transaction_object_type:{
const auto& aobj = dynamic_cast<const transaction_object*>(obj);
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);
@ -507,6 +513,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() )
@ -518,7 +525,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));
}
GRAPHENE_TRY_NOTIFY( new_objects, new_ids, new_accounts_impacted)
@ -532,7 +540,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));
}
GRAPHENE_TRY_NOTIFY( changed_objects, changed_ids, changed_accounts_impacted)
@ -549,7 +558,8 @@ 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));
}
GRAPHENE_TRY_NOTIFY( removed_objects, removed_ids, removed, removed_accounts_impacted)

View file

@ -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

View file

@ -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

View file

@ -50,6 +50,9 @@ namespace graphene { namespace chain {
account_id_type fee_payer()const { return payer; }
void validate()const;
share_type calculate_fee(const fee_parameters_type& k)const;
void get_required_active_authorities( flat_set<account_id_type>& auths )const {
auths.insert( required_auths.begin(), required_auths.end() );
}
};
} } // namespace graphene::chain

View file

@ -166,10 +166,11 @@ namespace graphene { namespace chain {
*
* @return a set of required authorities for @ref op
*/
void operation_get_required_authorities( const operation& op,
void operation_get_required_authorities( const operation& op,
flat_set<account_id_type>& active,
flat_set<account_id_type>& owner,
vector<authority>& other );
vector<authority>& other,
bool ignore_custom_operation_required_auths );
void operation_validate( const operation& op );

View file

@ -112,7 +112,10 @@ namespace graphene { namespace chain {
return results;
}
void get_required_authorities( flat_set<account_id_type>& active, flat_set<account_id_type>& owner, vector<authority>& other )const;
void get_required_authorities( flat_set<account_id_type>& active,
flat_set<account_id_type>& owner,
vector<authority>& other,
bool ignore_custom_operation_required_auths )const;
};
/**
@ -142,6 +145,7 @@ namespace graphene { namespace chain {
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_authorities,
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
)const;
@ -150,6 +154,7 @@ namespace graphene { namespace chain {
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_auths,
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH )const;
/**
@ -158,13 +163,13 @@ namespace graphene { namespace chain {
* some cases where get_required_signatures() returns a
* non-minimal set.
*/
set<public_key_type> minimize_required_signatures(
const chain_id_type& chain_id,
const flat_set<public_key_type>& available_keys,
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_auths,
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
) const;
@ -198,10 +203,11 @@ namespace graphene { namespace chain {
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_auths,
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH,
bool allow_committe = false,
bool allow_committee = false,
const flat_set<account_id_type>& active_aprovals = flat_set<account_id_type>(),
const flat_set<account_id_type>& owner_approvals = flat_set<account_id_type>());
const flat_set<account_id_type>& owner_approvals = flat_set<account_id_type>() );
/**
* @brief captures the result of evaluating the operations contained in the transaction

View file

@ -204,19 +204,20 @@ struct proposal_operation_hardfork_visitor
}
};
void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o)
void_result proposal_create_evaluator::do_evaluate( const proposal_create_operation& o )
{ try {
const database& d = db();
auto block_time = d.head_block_time();
proposal_operation_hardfork_visitor vtor( d.head_block_time() );
proposal_operation_hardfork_visitor vtor( block_time );
vtor( o );
const auto& global_parameters = d.get_global_properties().parameters;
FC_ASSERT( o.expiration_time > d.head_block_time(), "Proposal has already expired on creation." );
FC_ASSERT( o.expiration_time <= d.head_block_time() + global_parameters.maximum_proposal_lifetime,
FC_ASSERT( o.expiration_time > block_time, "Proposal has already expired on creation." );
FC_ASSERT( o.expiration_time <= block_time + global_parameters.maximum_proposal_lifetime,
"Proposal expiration time is too far in the future.");
FC_ASSERT( !o.review_period_seconds || fc::seconds(*o.review_period_seconds) < (o.expiration_time - d.head_block_time()),
FC_ASSERT( !o.review_period_seconds || fc::seconds(*o.review_period_seconds) < (o.expiration_time - block_time),
"Proposal review period must be less than its overall lifetime." );
{
@ -225,7 +226,8 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
vector<authority> other;
for( auto& op : o.proposed_ops )
{
operation_get_required_authorities(op.op, auths, auths, other);
operation_get_required_authorities( op.op, auths, auths, other,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(block_time) );
}
FC_ASSERT( other.size() == 0 ); // TODO: what about other???
@ -248,18 +250,19 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
}
}
for( const op_wrapper& op : o.proposed_ops )
for (const op_wrapper& op : o.proposed_ops)
_proposed_trx.operations.push_back(op.op);
_proposed_trx.validate();
return void_result();
} FC_CAPTURE_AND_RETHROW( (o) ) }
object_id_type proposal_create_evaluator::do_apply(const proposal_create_operation& o)
object_id_type proposal_create_evaluator::do_apply( const proposal_create_operation& o )
{ try {
database& d = db();
auto chain_time = d.head_block_time();
const proposal_object& proposal = d.create<proposal_object>([&](proposal_object& proposal) {
const proposal_object& proposal = d.create<proposal_object>( [&o, this, chain_time](proposal_object& proposal) {
_proposed_trx.expiration = o.expiration_time;
proposal.proposed_transaction = _proposed_trx;
proposal.proposer = o.fee_paying_account;
@ -273,7 +276,8 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
// TODO: consider caching values from evaluate?
for( auto& op : _proposed_trx.operations )
operation_get_required_authorities(op, required_active, proposal.required_owner_approvals, other);
operation_get_required_authorities( op, required_active, proposal.required_owner_approvals, other,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(chain_time) );
//All accounts which must provide both owner and active authority should be omitted from the active authority set;
//owner authority approval implies active authority approval.
@ -285,7 +289,7 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
return proposal.id;
} FC_CAPTURE_AND_RETHROW( (o) ) }
void_result proposal_update_evaluator::do_evaluate(const proposal_update_operation& o)
void_result proposal_update_evaluator::do_evaluate( const proposal_update_operation& o )
{ try {
database& d = db();

View file

@ -24,12 +24,13 @@
#include <graphene/chain/database.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/hardfork.hpp>
namespace graphene { namespace chain {
bool proposal_object::is_authorized_to_execute(database& db) const
bool proposal_object::is_authorized_to_execute( database& db ) const
{
transaction_evaluation_state dry_run_eval(&db);
transaction_evaluation_state dry_run_eval( &db );
try {
verify_authority( proposed_transaction.operations,
@ -38,6 +39,7 @@ bool proposal_object::is_authorized_to_execute(database& db) const
[&]( account_id_type id ){ return &id(db).owner; },
[&]( account_id_type id, const operation& op ){
return db.get_account_custom_authorities(id, op); },
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ),
db.get_global_properties().parameters.max_authority_depth,
true, /* allow committee */
available_active_approvals,

View file

@ -53,25 +53,38 @@ struct operation_validator
struct operation_get_required_auth
{
typedef void result_type;
using result_type = void;
flat_set<account_id_type>& active;
flat_set<account_id_type>& owner;
vector<authority>& other;
bool ignore_custom_op_reqd_auths;
operation_get_required_auth( flat_set<account_id_type>& a,
flat_set<account_id_type>& own,
vector<authority>& oth ):active(a),owner(own),other(oth){}
flat_set<account_id_type>& own,
vector<authority>& oth,
bool ignore_custom_operation_required_auths )
: active( a ), owner( own ), other( oth ),
ignore_custom_op_reqd_auths( ignore_custom_operation_required_auths )
{}
template<typename T>
void operator()( const T& v )const
{
void operator()( const T& v ) const {
active.insert( v.fee_payer() );
v.get_required_active_authorities( active );
v.get_required_owner_authorities( owner );
v.get_required_active_authorities( active );
v.get_required_owner_authorities( owner );
v.get_required_authorities( other );
}
void operator()( const custom_operation& op ) const {
active.insert( op.fee_payer() );
if( !ignore_custom_op_reqd_auths ) {
op.get_required_active_authorities( active );
op.get_required_owner_authorities( owner );
op.get_required_authorities( other );
}
}
};
void operation_validate( const operation& op )
@ -79,12 +92,13 @@ void operation_validate( const operation& op )
op.visit( operation_validator() );
}
void operation_get_required_authorities( const operation& op,
void operation_get_required_authorities( const operation& op,
flat_set<account_id_type>& active,
flat_set<account_id_type>& owner,
vector<authority>& other )
vector<authority>& other,
bool ignore_custom_operation_required_auths )
{
op.visit( operation_get_required_auth( active, owner, other ) );
op.visit( operation_get_required_auth( active, owner, other, ignore_custom_operation_required_auths ) );
}
} } // namespace graphene::chain

View file

@ -95,10 +95,13 @@ void transaction::set_reference_block( const block_id_type& reference_block )
ref_block_prefix = reference_block._hash[1];
}
void transaction::get_required_authorities( flat_set<account_id_type>& active, flat_set<account_id_type>& owner, vector<authority>& other )const
void transaction::get_required_authorities( flat_set<account_id_type>& active,
flat_set<account_id_type>& owner,
vector<authority>& other,
bool ignore_custom_operation_required_auths )const
{
for( const auto& op : operations )
operation_get_required_authorities( op, active, owner, other );
for ( const auto& op : operations )
operation_get_required_authorities( op, active, owner, other, ignore_custom_operation_required_auths );
}
@ -249,8 +252,9 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_auths,
uint32_t max_recursion_depth,
bool allow_committe,
bool allow_committee,
const flat_set<account_id_type>& active_aprovals,
const flat_set<account_id_type>& owner_approvals )
{ try {
@ -276,7 +280,8 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
for( const auto& op : ops ) {
flat_set<account_id_type> operation_required_active;
operation_get_required_authorities( op, operation_required_active, required_owner, other );
operation_get_required_authorities( op, operation_required_active, required_owner, other,
ignore_custom_operation_required_auths );
auto itr = operation_required_active.begin();
while ( itr != operation_required_active.end() ) {
@ -289,7 +294,7 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
required_active.insert( operation_required_active.begin(), operation_required_active.end() );
}
if( !allow_committe )
if( !allow_committee )
GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(),
invalid_committee_approval, "Committee account may only propose transactions" );
@ -349,6 +354,7 @@ set<public_key_type> signed_transaction::get_required_signatures(
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_authorities,
uint32_t max_recursion_depth )const
{
flat_set<account_id_type> required_active;
@ -370,7 +376,7 @@ set<public_key_type> signed_transaction::get_required_signatures(
for( const auto& op : operations ) {
flat_set<account_id_type> operation_required_active;
operation_get_required_authorities( op, operation_required_active, required_owner, other );
operation_get_required_authorities( op, operation_required_active, required_owner, other, ignore_custom_operation_required_authorities );
auto itr = operation_required_active.begin();
while ( itr != operation_required_active.end() ) {
@ -383,7 +389,7 @@ set<public_key_type> signed_transaction::get_required_signatures(
required_active.insert( operation_required_active.begin(), operation_required_active.end() );
}
for( const auto& auth : other )
for (const auto& auth : other)
s.check_authority(&auth);
for( auto& owner : required_owner )
s.check_authority( get_owner( owner ) );
@ -407,10 +413,12 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_auths,
uint32_t max_recursion
) const
{
set< public_key_type > s = get_required_signatures( chain_id, available_keys, get_active, get_owner, get_custom, max_recursion );
set< public_key_type > s = get_required_signatures( chain_id, available_keys, get_active, get_owner, get_custom,
ignore_custom_operation_required_auths, max_recursion );
flat_set< public_key_type > result( s.begin(), s.end() );
for( const public_key_type& k : s )
@ -418,7 +426,8 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
result.erase( k );
try
{
graphene::chain::verify_authority( operations, result, get_active, get_owner, get_custom, max_recursion );
graphene::chain::verify_authority( operations, result, get_active, get_owner, get_custom,
ignore_custom_operation_required_auths, max_recursion );
continue; // element stays erased if verify_authority is ok
}
catch( const tx_missing_owner_auth& e ) {}
@ -434,6 +443,7 @@ void signed_transaction::verify_authority(
const std::function<const authority*(account_id_type)>& get_active,
const std::function<const authority*(account_id_type)>& get_owner,
const std::function<vector<authority>(account_id_type, const operation&)>& get_custom,
bool ignore_custom_operation_required_auths,
uint32_t max_recursion )const
{ try {
graphene::chain::verify_authority( operations, get_signature_keys( chain_id ), get_active, get_owner, get_custom, max_recursion );

View file

@ -33,6 +33,7 @@
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/transaction_evaluation_state.hpp>
#include <graphene/chain/hardfork.hpp>
#include <fc/smart_ref_impl.hpp>
#include <fc/thread/thread.hpp>
@ -123,12 +124,15 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
// get the set of accounts this operation applies to
flat_set<account_id_type> impacted;
vector<authority> other;
operation_get_required_authorities( op.op, impacted, impacted, other ); // fee_payer is added here
// fee payer is added here
operation_get_required_authorities( op.op, impacted, impacted, other,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) );
if( op.op.which() == operation::tag< account_create_operation >::value )
impacted.insert( op.result.get<object_id_type>() );
else
graphene::chain::operation_get_impacted_accounts( op.op, impacted );
graphene::chain::operation_get_impacted_accounts( op.op, impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(db.head_block_time()) );
if( op.op.which() == operation::tag< lottery_end_operation >::value )
{
auto lop = op.op.get< lottery_end_operation >();

View file

@ -25,7 +25,7 @@
#include <graphene/elasticsearch/elasticsearch_plugin.hpp>
#include <graphene/chain/impacted.hpp>
#include <graphene/chain/account_evaluator.hpp>
#include <fc/smart_ref_impl.hpp>
#include <graphene/chain/hardfork.hpp>
#include <curl/curl.h>
namespace graphene { namespace elasticsearch {
@ -157,12 +157,15 @@ bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b
// get the set of accounts this operation applies to
flat_set<account_id_type> impacted;
vector<authority> other;
operation_get_required_authorities( op.op, impacted, impacted, other ); // fee_payer is added here
// fee_payer is added here
operation_get_required_authorities( op.op, impacted, impacted, other,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) );
if( op.op.which() == operation::tag< account_create_operation >::value )
impacted.insert( op.result.get<object_id_type>() );
else
graphene::chain::operation_get_impacted_accounts( op.op, impacted );
operation_get_impacted_accounts( op.op, impacted,
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) );
for( auto& a : other )
for( auto& item : a.account_auths )

View file

@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE( proposed_single_account )
{
vector<authority> other;
flat_set<account_id_type> active_set, owner_set;
operation_get_required_authorities(op,active_set,owner_set,other);
operation_get_required_authorities(op, active_set, owner_set, other, false);
BOOST_CHECK_EQUAL(active_set.size(), 1lu);
BOOST_CHECK_EQUAL(owner_set.size(), 0lu);
BOOST_CHECK_EQUAL(other.size(), 0lu);
@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE( proposed_single_account )
active_set.clear();
other.clear();
operation_get_required_authorities(op.proposed_ops.front().op,active_set,owner_set,other);
operation_get_required_authorities(op.proposed_ops.front().op, active_set, owner_set, other, false);
BOOST_CHECK_EQUAL(active_set.size(), 1lu);
BOOST_CHECK_EQUAL(owner_set.size(), 0lu);
BOOST_CHECK_EQUAL(other.size(), 0lu);
@ -1055,7 +1055,7 @@ BOOST_FIXTURE_TEST_CASE( bogus_signature, database_fixture )
flat_set<account_id_type> active_set, owner_set;
vector<authority> others;
trx.get_required_authorities( active_set, owner_set, others );
trx.get_required_authorities(active_set, owner_set, others, false);
PUSH_TX( db, trx, skip );
@ -1204,9 +1204,12 @@ BOOST_FIXTURE_TEST_CASE( get_required_signatures_test, database_fixture )
) -> bool
{
//wdump( (tx)(available_keys) );
set<public_key_type> result_set = tx.get_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner, get_custom );
//wdump( (result_set)(ref_set) );
return result_set == ref_set;
set<public_key_type> result_set = tx.get_required_signatures(db.get_chain_id(), available_keys,
get_active, get_owner, get_custom, false);
set<public_key_type> result_set2 = tx.get_required_signatures(db.get_chain_id(), available_keys,
get_active, get_owner, get_custom, true);
//wdump( (result_set)(result_set2)(ref_set) );
return result_set == ref_set && result_set2 == ref_set;
} ;
set_auth( well_id, authority( 60, alice_id, 50, bob_id, 50 ) );
@ -1326,9 +1329,12 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
) -> bool
{
//wdump( (tx)(available_keys) );
set<public_key_type> result_set = tx.get_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner, get_custom );
//wdump( (result_set)(ref_set) );
return result_set == ref_set;
set<public_key_type> result_set = tx.get_required_signatures(db.get_chain_id(), available_keys,
get_active, get_owner, get_custom, false);
set<public_key_type> result_set2 = tx.get_required_signatures(db.get_chain_id(), available_keys,
get_active, get_owner, get_custom, true);
//wdump( (result_set)(result_set2)(ref_set) );
return result_set == ref_set && result_set2 == ref_set;
} ;
auto chk_min = [&](
@ -1338,9 +1344,12 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
) -> bool
{
//wdump( (tx)(available_keys) );
set<public_key_type> result_set = tx.minimize_required_signatures( db.get_chain_id(), available_keys, get_active, get_owner, get_custom );
//wdump( (result_set)(ref_set) );
return result_set == ref_set;
set<public_key_type> result_set = tx.minimize_required_signatures(db.get_chain_id(), available_keys,
get_active, get_owner, get_custom, false);
set<public_key_type> result_set2 = tx.minimize_required_signatures(db.get_chain_id(), available_keys,
get_active, get_owner, get_custom, true);
//wdump( (result_set)(result_set2)(ref_set) );
return result_set == ref_set && result_set2 == ref_set;
} ;
set_auth( roco_id, authority( 2, styx_id, 1, thud_id, 2 ) );
@ -1357,9 +1366,13 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
BOOST_CHECK( chk( tx, { alice_public_key, bob_public_key }, { alice_public_key, bob_public_key } ) );
BOOST_CHECK( chk_min( tx, { alice_public_key, bob_public_key }, { alice_public_key } ) );
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom ), fc::exception );
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom, false ),
fc::exception );
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom, true ),
fc::exception );
sign( tx, alice_private_key );
tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom );
tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom, false );
tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom, true );
}
catch(fc::exception& e)
{