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

Feature/es voting stat plugin #1983

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 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
7 changes: 7 additions & 0 deletions libraries/chain/db_maint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <graphene/chain/vote_count.hpp>
#include <graphene/chain/witness_object.hpp>
#include <graphene/chain/worker_object.hpp>
#include <graphene/chain/voting_statistics_object.hpp>
pmconrad marked this conversation as resolved.
Show resolved Hide resolved

namespace graphene { namespace chain {

Expand Down Expand Up @@ -1150,6 +1151,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
distribute_fba_balances(*this);
create_buyback_orders(*this);

on_maintenance_begin( next_block.block_num() );

struct vote_tally_helper {
database& d;
const global_property_object& props;
Expand Down Expand Up @@ -1179,6 +1182,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
+ (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0)
+ stats.core_in_balance.value;

d.on_voting_stake_calculated( stake_account, opinion_account, voting_stake );

for( vote_id_type id : opinion_account.options.votes )
{
uint32_t offset = id.instance();
Expand Down Expand Up @@ -1327,6 +1332,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
// process_budget needs to run at the bottom because
// it needs to know the next_maintenance_time
process_budget();

on_maintenance_end();
}

} }
11 changes: 7 additions & 4 deletions libraries/chain/db_notify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ struct get_impacted_account_visitor
}
void operator()( const htlc_extend_operation& op )
{
_impacted.insert( op.fee_payer() );
_impacted.insert( op.fee_payer() );
}
void operator()( const htlc_refund_operation& op )
{
void operator()( const htlc_refund_operation& op )
{
_impacted.insert( op.fee_payer() );
}
};
Expand Down Expand Up @@ -375,6 +375,9 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
accounts.insert( htlc_obj->transfer.to );
break;
}
/*
add voting and voteable here?
*/
}
}
else if( obj->id.space() == implementation_ids )
Expand Down Expand Up @@ -455,7 +458,7 @@ void database::notify_on_pending_transaction( const signed_transaction& tx )

void database::notify_changed_objects()
{ try {
if( _undo_db.enabled() )
if( _undo_db.enabled() )
{
const auto& head_undo = _undo_db.head();

Expand Down
17 changes: 16 additions & 1 deletion libraries/chain/include/graphene/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,21 @@ namespace graphene { namespace chain {
*/
fc::signal<void(const vector<object_id_type>&, const vector<const object*>&, const flat_set<account_id_type>&)> removed_objects;

/**
* Emitted after the calculation of the voting_stake (occurs in the maintenance interval)
*/
fc::signal<void(const account_object&, const account_object&, const uint64_t)> on_voting_stake_calculated;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, unsure if we want to add such a specific signal. @abitmore @jmjatlanta?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a glance I don't like it. Is there any way to avoid this?

Copy link
Author

@Dimfred Dimfred Sep 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need all the data to properly feed the plugin, so AFAIK there is no way to avoid this. Everything is performed inside the vote_tally_helper and nothing is given outside.

What exactly do you don't like? Is the signal signature too specific?

To make it more generic I could switch the emission signature to emit an object with the data. This would make it extensible. It would be up to the signal receiver to use the data or not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understood correctly, void(const account_object&, const account_object&, const uint64_t) means we need to emit the signal once per account, which IMHO is too many. I think it's easier if we add the voting_stake data directly into account_statistics_object as a member variable, although this would need a bit more memory.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are right. The signal is emitted once per account.

Inserting data in account_statistics_object would mean double tracking of the data. Also it would then insert always (or make a check whether the plugin is active, but this seems weird IMHO). But the plugin kinda looses its purpose then.

What would be if I gathered the data first and then emit the signal with all the data? This would call the signal only once and wouldn't require more memory to be used. Though still would require a check whether the plugin is active or not.


/**
* Emitted after the beginning of the maintenance interval
*/
fc::signal<void(uint32_t)> on_maintenance_begin;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this resolves #211.


/**
* Emitted after the end of the maintenance interval
*/
fc::signal<void()> on_maintenance_end;

//////////////////// db_witness_schedule.cpp ////////////////////

/**
Expand Down Expand Up @@ -333,7 +348,7 @@ namespace graphene { namespace chain {
* to newly created VBID and return it.
*
* Otherwise, credit amount to ovbid.
*
*
* @return ID of newly created VBO, but only if VBO was created.
*/
optional< vesting_balance_id_type > deposit_lazy_vesting(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
pmconrad marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) 2019 Blockchain Projects B.V.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once

#include <boost/range/numeric.hpp>
#include <boost/range/adaptor/map.hpp>

#include <fc/optional.hpp>

#include <graphene/protocol/types.hpp>
#include <graphene/protocol/vote.hpp>

#include <graphene/db/generic_index.hpp>


namespace graphene { namespace chain {

/**
* @brief tracks the history of the voting stake for an account
* @ingroup object
* @ingroup implementation
*
* The calculation of the voting stake, performed in the maintenance interval, results
* in the creation or, if present, in the update of a voting_statistics_object.
*
* @note By default these objects are not tracked, the voting_stat_plugin must
* be loaded for these objects to be maintained.
*/
class voteable_statistics_object : public abstract_object<voteable_statistics_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = voteable_statistics_object_type;

voteable_statistics_object(){}

/* the block_num where the maintenance interval was performed */
uint32_t block_number;
/* vote_id of the voteable_object */
vote_id_type vote_id;
/* the accounts which this voteable is voted by with the number of votes */
flat_map< account_id_type, uint64_t > voted_by;

/* returns the total votes of this object */
uint64_t get_votes() const
{
return boost::accumulate( voted_by | boost::adaptors::map_values, 0 );
}
};


//struct by_block_number{}; // declared in voting_statistics_object just let it like this?
typedef multi_index_container< voteable_statistics_object,
indexed_by<
ordered_unique< tag<by_id>,
member< object, object_id_type, &object::id >
>,
ordered_unique< tag<by_block_number>,
composite_key< voteable_statistics_object,
member< voteable_statistics_object, uint32_t, &voteable_statistics_object::block_number >,
member< voteable_statistics_object, vote_id_type, &voteable_statistics_object::vote_id >
>
>
>
> voteable_statistics_multi_index_type;

typedef generic_index< voteable_statistics_object,
voteable_statistics_multi_index_type
> voteable_statistics_index;

}} // graphene::chain

FC_REFLECT_DERIVED( graphene::chain::voteable_statistics_object, (graphene::chain::object),
(block_number)(vote_id)(voted_by) )
105 changes: 105 additions & 0 deletions libraries/chain/include/graphene/chain/voting_statistics_object.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
pmconrad marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) 2019 Blockchain Projects B.V.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once

#include <boost/range/numeric.hpp>
#include <boost/range/adaptor/map.hpp>

#include <fc/optional.hpp>

#include <graphene/protocol/types.hpp>
#include <graphene/protocol/vote.hpp>

#include <graphene/db/generic_index.hpp>
#include <boost/multi_index/composite_key.hpp>

namespace graphene { namespace chain {

/**
* @brief tracks the history of the voting stake for an account
* @ingroup object
* @ingroup implementation
*
* The calculation of the voting stake, performed in the maintenance interval, results in the creation or,
* if present, in the update of a voting_statistics_object.
*
* @note By default these objects are not tracked, the voting_stat_plugin must be loaded for these objects to
* be maintained.
*/
class voting_statistics_object : public abstract_object<voting_statistics_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = voting_statistics_object_type;

voting_statistics_object(){}

/* the block number where the maintenance interval was performed */
uint32_t block_number;
/* the owner of the stake */
account_id_type account;
/* the stake which was generated by this account */
uint64_t stake = 0;
/* the proxy for this account */
account_id_type proxy = GRAPHENE_PROXY_TO_SELF_ACCOUNT;
/* the accounts which this account was a proxy for with the proxied stakes */
flat_map< account_id_type, uint64_t > proxy_for;
/* the vote_id's this account was voting for */
flat_set<vote_id_type> votes;

/* returns the total voting stake this account can vote with */
uint64_t get_total_voting_stake() const
{
uint64_t init = has_proxy() ? 0 : stake;
return boost::accumulate( proxy_for | boost::adaptors::map_values, init );
}

inline bool has_proxy() const
{
return GRAPHENE_PROXY_TO_SELF_ACCOUNT != proxy;
}
};


struct by_block_number{};
typedef multi_index_container< voting_statistics_object,
indexed_by<
ordered_unique< tag<by_id>,
member< object, object_id_type, &object::id >
>,
ordered_unique< tag<by_block_number>,
composite_key< voting_statistics_object,
member< voting_statistics_object, uint32_t, &voting_statistics_object::block_number >,
member< voting_statistics_object, account_id_type, &voting_statistics_object::account >
>
>
>
> voting_statistics_multi_index_type;

typedef generic_index< voting_statistics_object, voting_statistics_multi_index_type > voting_statistics_index;

}} // graphene::chain

FC_REFLECT_DERIVED( graphene::chain::voting_statistics_object, (graphene::chain::object),
(block_number)(account)(stake)(proxy)(proxy_for)(votes) )
5 changes: 5 additions & 0 deletions libraries/db/include/graphene/db/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ namespace graphene { namespace db {
}
virtual variant to_variant()const { return variant( static_cast<const DerivedClass&>(*this), MAX_NESTING ); }
virtual vector<char> pack()const { return fc::raw::pack( static_cast<const DerivedClass&>(*this) ); }

static constexpr uint16_t space_type()
{
return (uint16_t)DerivedClass::space_id << 8 | DerivedClass::type_id;
}
};

typedef flat_map<uint8_t, object_id_type> annotation_map;
Expand Down
1 change: 1 addition & 0 deletions libraries/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ add_subdirectory( debug_witness )
add_subdirectory( snapshot )
add_subdirectory( es_objects )
add_subdirectory( api_helper_indexes )
add_subdirectory( voting_stat )
Loading