rbac3 - tx auth verify changes
This commit is contained in:
parent
c74e83d088
commit
f376503ac6
9 changed files with 105 additions and 13 deletions
|
|
@ -1934,6 +1934,8 @@ bool database_api_impl::verify_authority( const signed_transaction& trx )const
|
|||
trx.verify_authority( _db.get_chain_id(),
|
||||
[this]( account_id_type id ){ return &id(_db).active; },
|
||||
[this]( account_id_type id ){ return &id(_db).owner; },
|
||||
[this]( account_id_type id, const operation& op ) {
|
||||
return _db.get_account_custom_authorities(id, op); },
|
||||
_db.get_global_properties().parameters.max_authority_depth );
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -790,7 +790,10 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx
|
|||
{
|
||||
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, get_global_properties().parameters.max_authority_depth );
|
||||
auto get_custom = [&]( 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 );
|
||||
}
|
||||
|
||||
//Skip all manner of expiration and TaPoS checking if we're on block 1; It's impossible that the transaction is
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/chain_property_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/custom_permission_object.hpp>
|
||||
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||
|
||||
#include <fc/smart_ref_impl.hpp>
|
||||
|
||||
|
|
@ -159,4 +161,24 @@ const witness_schedule_object& database::get_witness_schedule_object()const
|
|||
return *_p_witness_schedule_obj;
|
||||
}
|
||||
|
||||
vector<authority> database::get_account_custom_authorities(account_id_type account, const operation& op)const
|
||||
{
|
||||
const auto& pindex = get_index_type<custom_permission_index>().indices().get<by_account_and_permission>();
|
||||
const auto& cindex = get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
|
||||
auto prange = pindex.equal_range(boost::make_tuple(account));
|
||||
time_point_sec now = head_block_time();
|
||||
vector<authority> custom_auths;
|
||||
for(const custom_permission_object& pobj : boost::make_iterator_range(prange.first, prange.second))
|
||||
{
|
||||
auto crange = cindex.equal_range(boost::make_tuple(pobj.id, op.which()));
|
||||
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
|
||||
{
|
||||
if(now >= cobj.valid_from && now < cobj.valid_to)
|
||||
{
|
||||
custom_auths.push_back(pobj.auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
return custom_auths;
|
||||
}
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
|
||||
uint32_t last_non_undoable_block_num() const;
|
||||
vector<authority> get_account_custom_authorities(account_id_type account, const operation& op)const;
|
||||
//////////////////// db_init.cpp ////////////////////
|
||||
|
||||
void initialize_evaluators();
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ namespace graphene { namespace chain {
|
|||
const chain_id_type& chain_id,
|
||||
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,
|
||||
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH )const;
|
||||
|
||||
/**
|
||||
|
|
@ -162,6 +163,7 @@ namespace graphene { namespace chain {
|
|||
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,
|
||||
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH
|
||||
) const;
|
||||
|
||||
|
|
@ -194,6 +196,7 @@ namespace graphene { namespace chain {
|
|||
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
|
||||
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,
|
||||
uint32_t max_recursion = GRAPHENE_MAX_SIG_CHECK_DEPTH,
|
||||
bool allow_committe = false,
|
||||
const flat_set<account_id_type>& active_aprovals = flat_set<account_id_type>(),
|
||||
|
|
|
|||
|
|
@ -132,6 +132,30 @@ struct proposal_operation_hardfork_visitor
|
|||
FC_ASSERT( vbco.balance_type == vesting_balance_type::normal, "balance_type in vesting create not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const custom_permission_create_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_create_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const custom_permission_update_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_update_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const custom_permission_delete_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_permission_delete_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const custom_account_authority_create_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_create_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const custom_account_authority_update_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_update_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const custom_account_authority_delete_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_RBAC_TIME, "custom_account_authority_delete_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
// loop and self visit in proposals
|
||||
void operator()(const proposal_create_operation &v) const {
|
||||
for (const op_wrapper &op : v.proposed_ops)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ bool proposal_object::is_authorized_to_execute(database& db) const
|
|||
available_key_approvals,
|
||||
[&]( account_id_type id ){ return &id(db).active; },
|
||||
[&]( account_id_type id ){ return &id(db).owner; },
|
||||
[&]( account_id_type id, const operation& op ){
|
||||
return db.get_account_custom_authorities(id, op); },
|
||||
db.get_global_properties().parameters.max_authority_depth,
|
||||
true, /* allow committee */
|
||||
available_active_approvals,
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ struct sign_state
|
|||
void verify_authority( const vector<operation>& ops, const flat_set<public_key_type>& sigs,
|
||||
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,
|
||||
uint32_t max_recursion_depth,
|
||||
bool allow_committe,
|
||||
const flat_set<account_id_type>& active_aprovals,
|
||||
|
|
@ -257,13 +258,6 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
|
|||
flat_set<account_id_type> required_owner;
|
||||
vector<authority> other;
|
||||
|
||||
for( const auto& op : ops )
|
||||
operation_get_required_authorities( op, required_active, required_owner, other );
|
||||
|
||||
if( !allow_committe )
|
||||
GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(),
|
||||
invalid_committee_approval, "Committee account may only propose transactions" );
|
||||
|
||||
sign_state s(sigs,get_active);
|
||||
s.max_recursion = max_recursion_depth;
|
||||
for( auto& id : active_aprovals )
|
||||
|
|
@ -271,6 +265,37 @@ void verify_authority( const vector<operation>& ops, const flat_set<public_key_t
|
|||
for( auto& id : owner_approvals )
|
||||
s.approved_by.insert( id );
|
||||
|
||||
auto approved_by_custom_authority = [&s, &get_custom](
|
||||
account_id_type account,
|
||||
operation op ) mutable {
|
||||
auto custom_auths = get_custom( account, op );
|
||||
for( const auto& auth : custom_auths )
|
||||
if( s.check_authority( &auth ) ) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
for( const auto& op : ops )
|
||||
operation_get_required_authorities( op, required_active, required_owner, other );
|
||||
for( const auto& op : ops ) {
|
||||
flat_set<account_id_type> operation_required_active;
|
||||
operation_get_required_authorities( op, operation_required_active, required_owner, other );
|
||||
|
||||
auto itr = operation_required_active.begin();
|
||||
while ( itr != operation_required_active.end() ) {
|
||||
if ( approved_by_custom_authority( *itr, op ) )
|
||||
itr = operation_required_active.erase( itr );
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
|
||||
required_active.insert( operation_required_active.begin(), operation_required_active.end() );
|
||||
}
|
||||
|
||||
if( !allow_committe )
|
||||
GRAPHENE_ASSERT( required_active.find(GRAPHENE_COMMITTEE_ACCOUNT) == required_active.end(),
|
||||
invalid_committee_approval, "Committee account may only propose transactions" );
|
||||
|
||||
|
||||
for( const auto& auth : other )
|
||||
{
|
||||
GRAPHENE_ASSERT( s.check_authority(&auth), tx_missing_other_auth, "Missing Authority", ("auth",auth)("sigs",sigs) );
|
||||
|
|
@ -359,6 +384,7 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
|
|||
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,
|
||||
uint32_t max_recursion
|
||||
) const
|
||||
{
|
||||
|
|
@ -370,7 +396,7 @@ set<public_key_type> signed_transaction::minimize_required_signatures(
|
|||
result.erase( k );
|
||||
try
|
||||
{
|
||||
graphene::chain::verify_authority( operations, result, get_active, get_owner, max_recursion );
|
||||
graphene::chain::verify_authority( operations, result, get_active, get_owner, get_custom, max_recursion );
|
||||
continue; // element stays erased if verify_authority is ok
|
||||
}
|
||||
catch( const tx_missing_owner_auth& e ) {}
|
||||
|
|
@ -385,9 +411,10 @@ void signed_transaction::verify_authority(
|
|||
const chain_id_type& chain_id,
|
||||
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,
|
||||
uint32_t max_recursion )const
|
||||
{ try {
|
||||
graphene::chain::verify_authority( operations, get_signature_keys( chain_id ), get_active, get_owner, max_recursion );
|
||||
graphene::chain::verify_authority( operations, get_signature_keys( chain_id ), get_active, get_owner, get_custom, max_recursion );
|
||||
} FC_CAPTURE_AND_RETHROW( (*this) ) }
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -1303,6 +1303,14 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
|
|||
return &(aid(db).owner);
|
||||
} ;
|
||||
|
||||
auto get_custom = [&](
|
||||
account_id_type id,
|
||||
const operation& op
|
||||
) -> vector<authority>
|
||||
{
|
||||
return db.get_account_custom_authorities(id, op);
|
||||
} ;
|
||||
|
||||
auto chk = [&](
|
||||
const signed_transaction& tx,
|
||||
flat_set<public_key_type> available_keys,
|
||||
|
|
@ -1322,7 +1330,7 @@ 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 );
|
||||
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;
|
||||
} ;
|
||||
|
|
@ -1341,9 +1349,9 @@ 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 ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom ), fc::exception );
|
||||
sign( tx, alice_private_key );
|
||||
tx.verify_authority( db.get_chain_id(), get_active, get_owner );
|
||||
tx.verify_authority( db.get_chain_id(), get_active, get_owner, get_custom );
|
||||
}
|
||||
catch(fc::exception& e)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue