rbac5 - clear expired and deleted permission linked auths
This commit is contained in:
parent
4c2efdb871
commit
88a8753a60
3 changed files with 110 additions and 60 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
#include <graphene/chain/custom_permission_object.hpp>
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
#include <graphene/chain/hardfork.hpp>
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
|
||||||
namespace graphene
|
namespace graphene
|
||||||
|
|
@ -105,7 +106,21 @@ void_result delete_custom_permission_evaluator::do_apply(const custom_permission
|
||||||
{
|
{
|
||||||
database &d = db();
|
database &d = db();
|
||||||
const custom_permission_object &pobj = op.permission_id(d);
|
const custom_permission_object &pobj = op.permission_id(d);
|
||||||
// TODO: Remove all the custom_account_authority_object linked to this permission object.
|
// Remove the account authority objects linked to this permission
|
||||||
|
const auto& cindex = d.get_index_type<custom_account_authority_index>().indices().get<by_permission_and_op>();
|
||||||
|
vector<std::reference_wrapper<const custom_account_authority_object>> custom_auths;
|
||||||
|
auto crange = cindex.equal_range(boost::make_tuple(pobj.id));
|
||||||
|
// Store the references to the account authorities
|
||||||
|
for(const custom_account_authority_object& cobj : boost::make_iterator_range(crange.first, crange.second))
|
||||||
|
{
|
||||||
|
custom_auths.push_back(cobj);
|
||||||
|
}
|
||||||
|
// Now remove the account authorities
|
||||||
|
for(const auto& cauth : custom_auths)
|
||||||
|
{
|
||||||
|
d.remove(cauth);
|
||||||
|
}
|
||||||
|
// Now finally remove the permission
|
||||||
d.remove(pobj);
|
d.remove(pobj);
|
||||||
return void_result();
|
return void_result();
|
||||||
}
|
}
|
||||||
|
|
@ -113,4 +128,4 @@ void_result delete_custom_permission_evaluator::do_apply(const custom_permission
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chain
|
} // namespace chain
|
||||||
} // namespace graphene
|
} // namespace graphene
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
#include <graphene/chain/witness_schedule_object.hpp>
|
#include <graphene/chain/witness_schedule_object.hpp>
|
||||||
#include <graphene/chain/worker_object.hpp>
|
#include <graphene/chain/worker_object.hpp>
|
||||||
|
#include <graphene/chain/custom_account_authority_object.hpp>
|
||||||
|
|
||||||
#define USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX // vesting_balance_object by_asset_balance index needed
|
#define USE_VESTING_OBJECT_BY_ASSET_BALANCE_INDEX // vesting_balance_object by_asset_balance index needed
|
||||||
|
|
||||||
|
|
@ -933,6 +934,15 @@ void rolling_period_start(database& db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear_expired_custom_account_authorities(database& db)
|
||||||
|
{
|
||||||
|
const auto& cindex = db.get_index_type<custom_account_authority_index>().indices().get<by_expiration>();
|
||||||
|
while(!cindex.empty() && cindex.begin()->valid_to < db.head_block_time())
|
||||||
|
{
|
||||||
|
db.remove(*cindex.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Schedules payouts from a dividend distribution account to the current holders of the
|
// Schedules payouts from a dividend distribution account to the current holders of the
|
||||||
// dividend-paying asset. This takes any deposits made to the dividend distribution account
|
// dividend-paying asset. This takes any deposits made to the dividend distribution account
|
||||||
// since the last time it was called, and distributes them to the current owners of the
|
// since the last time it was called, and distributes them to the current owners of the
|
||||||
|
|
@ -1707,7 +1717,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
||||||
//for( const asset_bitasset_data_object* d : get_index_type<asset_bitasset_data_index>() )
|
//for( const asset_bitasset_data_object* d : get_index_type<asset_bitasset_data_index>() )
|
||||||
for( const auto& d : get_index_type<asset_bitasset_data_index>().indices() )
|
for( const auto& d : get_index_type<asset_bitasset_data_index>().indices() )
|
||||||
modify( d, [](asset_bitasset_data_object& o) { o.force_settled_volume = 0; });
|
modify( d, [](asset_bitasset_data_object& o) { o.force_settled_volume = 0; });
|
||||||
|
// Ideally we have to do this after every block but that leads to longer block applicaiton/replay times.
|
||||||
|
// So keep it here as it is not critical. valid_to check ensures
|
||||||
|
// these custom account auths are not usable.
|
||||||
|
clear_expired_custom_account_authorities(*this);
|
||||||
// process_budget needs to run at the bottom because
|
// process_budget needs to run at the bottom because
|
||||||
// it needs to know the next_maintenance_time
|
// it needs to know the next_maintenance_time
|
||||||
process_budget();
|
process_budget();
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,17 @@ BOOST_AUTO_TEST_CASE(permission_create_success_test)
|
||||||
generate_blocks(HARDFORK_RBAC_TIME);
|
generate_blocks(HARDFORK_RBAC_TIME);
|
||||||
generate_block();
|
generate_block();
|
||||||
set_expiration(db, trx);
|
set_expiration(db, trx);
|
||||||
ACTORS((alice)(bob));
|
ACTORS((alice)(bob)(charlie)(dave)(erin));
|
||||||
upgrade_to_lifetime_member(alice);
|
upgrade_to_lifetime_member(alice);
|
||||||
upgrade_to_lifetime_member(bob);
|
upgrade_to_lifetime_member(bob);
|
||||||
|
upgrade_to_lifetime_member(charlie);
|
||||||
|
upgrade_to_lifetime_member(dave);
|
||||||
|
upgrade_to_lifetime_member(erin);
|
||||||
transfer(committee_account, alice_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
transfer(committee_account, alice_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
||||||
transfer(committee_account, bob_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
transfer(committee_account, bob_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
||||||
|
transfer(committee_account, charlie_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
||||||
|
transfer(committee_account, dave_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
||||||
|
transfer(committee_account, erin_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
||||||
const auto &pidx = db.get_index_type<custom_permission_index>().indices().get<by_id>();
|
const auto &pidx = db.get_index_type<custom_permission_index>().indices().get<by_id>();
|
||||||
// Alice creates a permission abc
|
// Alice creates a permission abc
|
||||||
{
|
{
|
||||||
|
|
@ -138,7 +144,7 @@ BOOST_AUTO_TEST_CASE(permission_update_test)
|
||||||
INVOKE(permission_create_success_test);
|
INVOKE(permission_create_success_test);
|
||||||
GET_ACTOR(alice);
|
GET_ACTOR(alice);
|
||||||
GET_ACTOR(bob);
|
GET_ACTOR(bob);
|
||||||
ACTORS((charlie));
|
GET_ACTOR(charlie);
|
||||||
const auto &pidx = db.get_index_type<custom_permission_index>().indices().get<by_id>();
|
const auto &pidx = db.get_index_type<custom_permission_index>().indices().get<by_id>();
|
||||||
BOOST_REQUIRE(pidx.size() == 1);
|
BOOST_REQUIRE(pidx.size() == 1);
|
||||||
BOOST_REQUIRE(custom_permission_id_type(0)(db).permission_name == "abc");
|
BOOST_REQUIRE(custom_permission_id_type(0)(db).permission_name == "abc");
|
||||||
|
|
@ -210,56 +216,6 @@ BOOST_AUTO_TEST_CASE(permission_update_test)
|
||||||
FC_LOG_AND_RETHROW()
|
FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(permission_delete_test)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
INVOKE(permission_create_success_test);
|
|
||||||
GET_ACTOR(alice);
|
|
||||||
GET_ACTOR(bob);
|
|
||||||
const auto &pidx = db.get_index_type<custom_permission_index>().indices().get<by_id>();
|
|
||||||
BOOST_REQUIRE(pidx.size() == 1);
|
|
||||||
BOOST_REQUIRE(custom_permission_id_type(0)(db).permission_name == "abc");
|
|
||||||
BOOST_REQUIRE(custom_permission_id_type(0)(db).auth == authority(1, bob_id, 1));
|
|
||||||
// Alice tries to delete permission abc with wrong owner_account
|
|
||||||
{
|
|
||||||
custom_permission_delete_operation op;
|
|
||||||
op.permission_id = custom_permission_id_type(0);
|
|
||||||
op.owner_account = bob_id;
|
|
||||||
trx.operations.push_back(op);
|
|
||||||
sign(trx, bob_private_key);
|
|
||||||
BOOST_CHECK_THROW(PUSH_TX(db, trx), fc::exception);
|
|
||||||
trx.clear();
|
|
||||||
BOOST_REQUIRE(pidx.size() == 1);
|
|
||||||
}
|
|
||||||
// Alice tries to delete permission abc with wrong permission_id
|
|
||||||
{
|
|
||||||
custom_permission_delete_operation op;
|
|
||||||
op.permission_id = custom_permission_id_type(1);
|
|
||||||
op.owner_account = alice_id;
|
|
||||||
trx.operations.push_back(op);
|
|
||||||
sign(trx, alice_private_key);
|
|
||||||
BOOST_CHECK_THROW(PUSH_TX(db, trx), fc::exception);
|
|
||||||
trx.clear();
|
|
||||||
BOOST_REQUIRE(pidx.size() == 1);
|
|
||||||
}
|
|
||||||
// Alice deletes permission abc
|
|
||||||
{
|
|
||||||
BOOST_REQUIRE(custom_permission_id_type(0)(db).permission_name == "abc");
|
|
||||||
BOOST_REQUIRE(custom_permission_id_type(0)(db).auth == authority(1, bob_id, 1));
|
|
||||||
custom_permission_delete_operation op;
|
|
||||||
op.permission_id = custom_permission_id_type(0);
|
|
||||||
op.owner_account = alice_id;
|
|
||||||
trx.operations.push_back(op);
|
|
||||||
sign(trx, alice_private_key);
|
|
||||||
PUSH_TX(db, trx);
|
|
||||||
trx.clear();
|
|
||||||
BOOST_REQUIRE(pidx.size() == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FC_LOG_AND_RETHROW()
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(account_authority_create_test)
|
BOOST_AUTO_TEST_CASE(account_authority_create_test)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -279,7 +235,7 @@ BOOST_AUTO_TEST_CASE(account_authority_create_test)
|
||||||
op.permission_id = custom_permission_id_type(0);
|
op.permission_id = custom_permission_id_type(0);
|
||||||
op.valid_from = db.head_block_time();
|
op.valid_from = db.head_block_time();
|
||||||
op.valid_to = db.head_block_time() + fc::seconds(10 * db.block_interval());
|
op.valid_to = db.head_block_time() + fc::seconds(10 * db.block_interval());
|
||||||
op.operation_type = 0;
|
op.operation_type = operation::tag<transfer_operation>::value;
|
||||||
op.owner_account = alice_id;
|
op.owner_account = alice_id;
|
||||||
trx.operations.push_back(op);
|
trx.operations.push_back(op);
|
||||||
sign(trx, alice_private_key);
|
sign(trx, alice_private_key);
|
||||||
|
|
@ -294,7 +250,7 @@ BOOST_AUTO_TEST_CASE(account_authority_create_test)
|
||||||
op.permission_id = custom_permission_id_type(0);
|
op.permission_id = custom_permission_id_type(0);
|
||||||
op.valid_from = db.head_block_time();
|
op.valid_from = db.head_block_time();
|
||||||
op.valid_to = db.head_block_time() + fc::seconds(11 * db.block_interval());
|
op.valid_to = db.head_block_time() + fc::seconds(11 * db.block_interval());
|
||||||
op.operation_type = 0;
|
op.operation_type = operation::tag<transfer_operation>::value;
|
||||||
op.owner_account = alice_id;
|
op.owner_account = alice_id;
|
||||||
trx.operations.push_back(op);
|
trx.operations.push_back(op);
|
||||||
sign(trx, alice_private_key);
|
sign(trx, alice_private_key);
|
||||||
|
|
@ -379,6 +335,57 @@ BOOST_AUTO_TEST_CASE(account_authority_delete_test)
|
||||||
FC_LOG_AND_RETHROW()
|
FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(permission_delete_test)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
INVOKE(account_authority_create_test);
|
||||||
|
GET_ACTOR(alice);
|
||||||
|
GET_ACTOR(bob);
|
||||||
|
const auto &pidx = db.get_index_type<custom_permission_index>().indices().get<by_id>();
|
||||||
|
const auto &cidx = db.get_index_type<custom_account_authority_index>().indices().get<by_id>();
|
||||||
|
BOOST_REQUIRE(pidx.size() == 1);
|
||||||
|
BOOST_REQUIRE(custom_permission_id_type(0)(db).permission_name == "abc");
|
||||||
|
BOOST_REQUIRE(custom_permission_id_type(0)(db).auth == authority(1, bob_id, 1));
|
||||||
|
BOOST_REQUIRE(cidx.size() == 2);
|
||||||
|
// Alice tries to delete permission abc with wrong owner_account
|
||||||
|
{
|
||||||
|
custom_permission_delete_operation op;
|
||||||
|
op.permission_id = custom_permission_id_type(0);
|
||||||
|
op.owner_account = bob_id;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, bob_private_key);
|
||||||
|
BOOST_CHECK_THROW(PUSH_TX(db, trx), fc::exception);
|
||||||
|
trx.clear();
|
||||||
|
BOOST_REQUIRE(pidx.size() == 1);
|
||||||
|
}
|
||||||
|
// Alice tries to delete permission abc with wrong permission_id
|
||||||
|
{
|
||||||
|
custom_permission_delete_operation op;
|
||||||
|
op.permission_id = custom_permission_id_type(1);
|
||||||
|
op.owner_account = alice_id;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, alice_private_key);
|
||||||
|
BOOST_CHECK_THROW(PUSH_TX(db, trx), fc::exception);
|
||||||
|
trx.clear();
|
||||||
|
BOOST_REQUIRE(pidx.size() == 1);
|
||||||
|
}
|
||||||
|
// Alice deletes permission abc
|
||||||
|
{
|
||||||
|
custom_permission_delete_operation op;
|
||||||
|
op.permission_id = custom_permission_id_type(0);
|
||||||
|
op.owner_account = alice_id;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, alice_private_key);
|
||||||
|
PUSH_TX(db, trx);
|
||||||
|
trx.clear();
|
||||||
|
BOOST_REQUIRE(pidx.size() == 0);
|
||||||
|
BOOST_REQUIRE(cidx.size() == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FC_LOG_AND_RETHROW()
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(transfer_op_custom_permission_test)
|
BOOST_AUTO_TEST_CASE(transfer_op_custom_permission_test)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -390,6 +397,7 @@ BOOST_AUTO_TEST_CASE(transfer_op_custom_permission_test)
|
||||||
const auto &cidx = db.get_index_type<custom_account_authority_index>().indices().get<by_id>();
|
const auto &cidx = db.get_index_type<custom_account_authority_index>().indices().get<by_id>();
|
||||||
BOOST_REQUIRE(pidx.size() == 1);
|
BOOST_REQUIRE(pidx.size() == 1);
|
||||||
BOOST_REQUIRE(cidx.size() == 2);
|
BOOST_REQUIRE(cidx.size() == 2);
|
||||||
|
// alice->bob transfer_operation op with active auth, success
|
||||||
generate_block();
|
generate_block();
|
||||||
{
|
{
|
||||||
transfer_operation op;
|
transfer_operation op;
|
||||||
|
|
@ -404,7 +412,7 @@ BOOST_AUTO_TEST_CASE(transfer_op_custom_permission_test)
|
||||||
trx.clear();
|
trx.clear();
|
||||||
generate_block();
|
generate_block();
|
||||||
}
|
}
|
||||||
|
// alice->bob transfer_operation op with the created custom account auth, success
|
||||||
{
|
{
|
||||||
transfer_operation op;
|
transfer_operation op;
|
||||||
op.amount.asset_id = asset_id_type(0);
|
op.amount.asset_id = asset_id_type(0);
|
||||||
|
|
@ -418,7 +426,7 @@ BOOST_AUTO_TEST_CASE(transfer_op_custom_permission_test)
|
||||||
trx.clear();
|
trx.clear();
|
||||||
generate_block();
|
generate_block();
|
||||||
}
|
}
|
||||||
|
// alice->bob transfer_operation op with extra unnecessary sigs (both active and the custom auth), fails
|
||||||
{
|
{
|
||||||
transfer_operation op;
|
transfer_operation op;
|
||||||
op.amount.asset_id = asset_id_type(0);
|
op.amount.asset_id = asset_id_type(0);
|
||||||
|
|
@ -433,7 +441,7 @@ BOOST_AUTO_TEST_CASE(transfer_op_custom_permission_test)
|
||||||
trx.clear();
|
trx.clear();
|
||||||
generate_block();
|
generate_block();
|
||||||
}
|
}
|
||||||
|
// bob->alice transfer_operation op with alice active auth sig, fails
|
||||||
{
|
{
|
||||||
transfer_operation op;
|
transfer_operation op;
|
||||||
op.amount.asset_id = asset_id_type(0);
|
op.amount.asset_id = asset_id_type(0);
|
||||||
|
|
@ -447,6 +455,20 @@ BOOST_AUTO_TEST_CASE(transfer_op_custom_permission_test)
|
||||||
trx.clear();
|
trx.clear();
|
||||||
generate_block();
|
generate_block();
|
||||||
}
|
}
|
||||||
|
// bob->alice transfer_operation op with bob active auth sig, success
|
||||||
|
{
|
||||||
|
transfer_operation op;
|
||||||
|
op.amount.asset_id = asset_id_type(0);
|
||||||
|
op.amount.amount = 100 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||||
|
op.from = bob_id;
|
||||||
|
op.to = alice_id;
|
||||||
|
op.fee.asset_id = asset_id_type(0);
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, bob_private_key);
|
||||||
|
PUSH_TX(db, trx);
|
||||||
|
trx.clear();
|
||||||
|
generate_block();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FC_LOG_AND_RETHROW()
|
FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue