add secondary index to get proposals relevant to a particular account

This commit is contained in:
Daniel Larimer 2015-06-29 17:29:04 -04:00
parent 2ee9b01d3f
commit 681f0923fe
9 changed files with 97 additions and 30 deletions

2
docs

@ -1 +1 @@
Subproject commit b893895d05b4f0d448aabd4f1d2112a7e35e1354
Subproject commit 71ed2984b71d57cab13cdf12074cff150edc1d3d

View file

@ -122,7 +122,10 @@ void database::initialize_indexes()
add_index< primary_index<witness_index> >();
add_index< primary_index<limit_order_index > >();
add_index< primary_index<call_order_index > >();
add_index< primary_index<proposal_index > >();
auto prop_index = add_index< primary_index<proposal_index > >();
prop_index->add_secondary_index<required_approval_index>();
add_index< primary_index<withdraw_permission_index > >();
add_index< primary_index<simple_index<vesting_balance_object> > >();
add_index< primary_index<worker_index> >();

View file

@ -102,7 +102,7 @@ void database::clear_expired_proposals()
const proposal_object& proposal = *proposal_expiration_index.begin();
processed_transaction result;
try {
if( proposal.is_authorized_to_execute(this) )
if( proposal.is_authorized_to_execute(*this) )
{
result = push_proposal(proposal);
//TODO: Do something with result so plugins can process it.

View file

@ -46,7 +46,31 @@ class proposal_object : public abstract_object<proposal_object>
flat_set<account_id_type> available_owner_approvals;
flat_set<key_id_type> available_key_approvals;
bool is_authorized_to_execute(database* db)const;
bool is_authorized_to_execute(database& db)const;
};
/**
* @brief tracks all of the proposal objects that requrie approval of
* an individual account.
*
* @ingroup object
* @ingroup protocol
*
* This is a secondary index on the proposal_index
*
* @note the set of required approvals is constant
*/
class required_approval_index : public secondary_index
{
public:
virtual void object_inserted( const object& obj ) override;
virtual void object_removed( const object& obj ) override;
virtual void about_to_modify( const object& before ) override{};
virtual void object_modified( const object& after ) override{};
void remove( account_id_type a, proposal_id_type p );
map<account_id_type, set<proposal_id_type> > _account_to_proposals;
};
struct by_expiration{};

View file

@ -133,7 +133,7 @@ void_result proposal_update_evaluator::do_apply(const proposal_update_operation&
if( _proposal->review_period_time )
return void_result();
if( _proposal->is_authorized_to_execute(&d) )
if( _proposal->is_authorized_to_execute(d) )
{
// All required approvals are satisfied. Execute!
_executed_proposal = true;

View file

@ -21,9 +21,9 @@
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);
dry_run_eval._is_proposed_trx = true;
std::transform(available_active_approvals.begin(), available_active_approvals.end(),
std::inserter(dry_run_eval.approved_by, dry_run_eval.approved_by.end()), [](object_id_type id) {
@ -44,13 +44,53 @@ bool proposal_object::is_authorized_to_execute(database* db) const
// Check all required approvals. If any of them are unsatisfied, return false.
for( const auto& id : required_active_approvals )
if( !dry_run_eval.check_authority(id(*db), authority::active) )
if( !dry_run_eval.check_authority(id(db), authority::active) )
return false;
for( const auto& id : required_owner_approvals )
if( !dry_run_eval.check_authority(id(*db), authority::owner) )
if( !dry_run_eval.check_authority(id(db), authority::owner) )
return false;
return true;
}
void required_approval_index::object_inserted( const object& obj )
{
assert( dynamic_cast<const proposal_object*>(&obj) );
const proposal_object& p = static_cast<const proposal_object&>(obj);
for( const auto& a : p.required_active_approvals )
_account_to_proposals[a].insert( p.id );
for( const auto& a : p.required_owner_approvals )
_account_to_proposals[a].insert( p.id );
for( const auto& a : p.available_active_approvals )
_account_to_proposals[a].insert( p.id );
for( const auto& a : p.available_owner_approvals )
_account_to_proposals[a].insert( p.id );
}
void required_approval_index::remove( account_id_type a, proposal_id_type p )
{
auto itr = _account_to_proposals.find(a);
if( itr != _account_to_proposals.end() )
itr->second.erase(p);
if( itr->second.size() == 0 )
_account_to_proposals.erase(itr);
}
void required_approval_index::object_removed( const object& obj )
{
assert( dynamic_cast<const proposal_object*>(&obj) );
const proposal_object& p = static_cast<const proposal_object&>(obj);
for( const auto& a : p.required_active_approvals )
remove( a, p.id );
for( const auto& a : p.required_owner_approvals )
remove( a, p.id );
for( const auto& a : p.available_active_approvals )
remove( a, p.id );
for( const auto& a : p.available_owner_approvals )
remove( a, p.id );
}
} } // graphene::chain

@ -1 +1 @@
Subproject commit fe7eed6bebac28313e4e7350eb77f8da27f6a427
Subproject commit a8b85f6dcc4558b7a9913b59ef5dc19f3b5e62ca

View file

@ -383,12 +383,12 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
BOOST_CHECK(prop.review_period_time && *prop.review_period_time == pop.expiration_time - *pop.review_period_seconds);
BOOST_CHECK(prop.proposed_transaction.operations.size() == 1);
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 0);
BOOST_CHECK(!db.get<proposal_object>(prop.id).is_authorized_to_execute(&db));
BOOST_CHECK(!db.get<proposal_object>(prop.id).is_authorized_to_execute(db));
generate_block();
BOOST_REQUIRE(db.find_object(prop.id));
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 0);
BOOST_CHECK(!db.get<proposal_object>(prop.id).is_authorized_to_execute(&db));
BOOST_CHECK(!db.get<proposal_object>(prop.id).is_authorized_to_execute(db));
trx.operations.clear();
trx.signatures.clear();
proposal_update_operation uop;
@ -409,7 +409,7 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
trx.signatures[key_id_type(6)] = trx.signatures[key_id_type(1)];
db.push_transaction(trx);
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 0);
BOOST_CHECK(db.get<proposal_object>(prop.id).is_authorized_to_execute(&db));
BOOST_CHECK(db.get<proposal_object>(prop.id).is_authorized_to_execute(db));
generate_blocks(*prop.review_period_time);
uop.key_approvals_to_add = {key_id_type(7)};
@ -457,7 +457,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
sign(trx, key_id_type(), genesis_key);
const proposal_object& prop = db.get<proposal_object>(PUSH_TX( db, trx ).operation_results.front().get<object_id_type>());
proposal_id_type pid = prop.id;
BOOST_CHECK(!pid(db).is_authorized_to_execute(&db));
BOOST_CHECK(!pid(db).is_authorized_to_execute(db));
//Genesis key approves of the proposal.
proposal_update_operation uop;
@ -484,7 +484,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
trx.signatures[key_id_type(9)] = trx.signatures[key_id_type(1)];
trx.sign(key_id_type(), genesis_key);
PUSH_TX( db, trx );
BOOST_CHECK(pid(db).is_authorized_to_execute(&db));
BOOST_CHECK(pid(db).is_authorized_to_execute(db));
//Time passes... the proposal is now in its review period.
generate_blocks(*pid(db).review_period_time);
@ -492,7 +492,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
fc::time_point_sec maintenance_time = db.get_dynamic_global_properties().next_maintenance_time;
BOOST_CHECK_LT(maintenance_time.sec_since_epoch(), pid(db).expiration_time.sec_since_epoch());
//Yay! The proposal to give nathan more money is authorized.
BOOST_CHECK(pid(db).is_authorized_to_execute(&db));
BOOST_CHECK(pid(db).is_authorized_to_execute(db));
nathan = &get_account("nathan");
// no money yet
@ -515,7 +515,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
//Time passes... the set of active delegates gets updated.
generate_blocks(maintenance_time);
//The proposal is no longer authorized, because the active delegates got changed.
BOOST_CHECK(!pid(db).is_authorized_to_execute(&db));
BOOST_CHECK(!pid(db).is_authorized_to_execute(db));
// still no money
BOOST_CHECK_EQUAL(get_balance(*nathan, asset_id_type()(db)), 5000);
@ -563,7 +563,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_two_accounts, database_fixture )
const proposal_object& prop = *db.get_index_type<proposal_index>().indices().begin();
BOOST_CHECK(prop.required_active_approvals.size() == 2);
BOOST_CHECK(prop.required_owner_approvals.size() == 0);
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
{
proposal_id_type pid = prop.id;
@ -577,7 +577,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_two_accounts, database_fixture )
trx.clear();
BOOST_CHECK(db.find_object(pid) != nullptr);
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
uop.active_approvals_to_add = {dan.get_id()};
trx.operations.push_back(uop);
@ -627,7 +627,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_delete, database_fixture )
const proposal_object& prop = *db.get_index_type<proposal_index>().indices().begin();
BOOST_CHECK(prop.required_active_approvals.size() == 2);
BOOST_CHECK(prop.required_owner_approvals.size() == 0);
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
{
proposal_update_operation uop;
@ -638,7 +638,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_delete, database_fixture )
trx.sign(nathan_key_obj.id,nathan_key);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
BOOST_CHECK_EQUAL(prop.available_active_approvals.size(), 1);
std::swap(uop.active_approvals_to_add, uop.active_approvals_to_remove);
@ -646,7 +646,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_delete, database_fixture )
trx.sign(nathan_key_obj.id,nathan_key);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
BOOST_CHECK_EQUAL(prop.available_active_approvals.size(), 0);
}
@ -705,7 +705,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_delete, database_fixture )
const proposal_object& prop = *db.get_index_type<proposal_index>().indices().begin();
BOOST_CHECK_EQUAL(prop.required_active_approvals.size(), 1);
BOOST_CHECK_EQUAL(prop.required_owner_approvals.size(), 1);
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
{
proposal_update_operation uop;
@ -716,7 +716,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_delete, database_fixture )
trx.sign(nathan_key_obj.id,nathan_key);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
BOOST_CHECK_EQUAL(prop.available_owner_approvals.size(), 1);
std::swap(uop.owner_approvals_to_add, uop.owner_approvals_to_remove);
@ -724,7 +724,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_delete, database_fixture )
trx.sign(nathan_key_obj.id,nathan_key);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
BOOST_CHECK_EQUAL(prop.available_owner_approvals.size(), 0);
}
@ -784,7 +784,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
const proposal_object& prop = *db.get_index_type<proposal_index>().indices().begin();
BOOST_CHECK_EQUAL(prop.required_active_approvals.size(), 1);
BOOST_CHECK_EQUAL(prop.required_owner_approvals.size(), 1);
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
{
proposal_id_type pid = prop.id;
@ -797,7 +797,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
trx.sign(dan_key_obj.id,dan_key);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
BOOST_CHECK_EQUAL(prop.available_key_approvals.size(), 1);
std::swap(uop.key_approvals_to_add, uop.key_approvals_to_remove);
@ -806,7 +806,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
trx.sign(dan_key_obj.id,dan_key);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
BOOST_CHECK_EQUAL(prop.available_key_approvals.size(), 0);
std::swap(uop.key_approvals_to_add, uop.key_approvals_to_remove);
@ -817,7 +817,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
trx.sign(dan_key_obj.id,dan_key);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK(!prop.is_authorized_to_execute(db));
BOOST_CHECK_EQUAL(prop.available_key_approvals.size(), 1);
uop.key_approvals_to_add.clear();

View file

@ -611,7 +611,7 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
trx.sign(get_account("init6").active.get_keys().front(),delegate_priv_key);
trx.sign(get_account("init7").active.get_keys().front(),delegate_priv_key);
db.push_transaction(trx);
BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(&db));
BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(db));
}
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.block_interval, 5);