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 16 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
14 changes: 10 additions & 4 deletions libraries/chain/db_maint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ void database::update_active_witnesses()
/// accounts that vote for 0 or 1 witness do not get to express an opinion on
/// the number of witnesses to have (they abstain and are non-voting accounts)

share_type stake_tally = 0;
share_type stake_tally = 0;

size_t witness_count = 0;
if( stake_target > 0 )
Expand Down Expand Up @@ -959,8 +959,8 @@ void process_hf_1465( database& db )
graphene::chain::share_type max_supply = current_asset.options.max_supply;
if (current_supply > max_supply && max_supply != GRAPHENE_MAX_SHARE_SUPPLY)
{
wlog( "Adjusting max_supply of ${asset} because current_supply (${current_supply}) is greater than ${old}.",
("asset", current_asset.symbol)
wlog( "Adjusting max_supply of ${asset} because current_supply (${current_supply}) is greater than ${old}.",
("asset", current_asset.symbol)
("current_supply", current_supply.value)
("old", max_supply));
db.modify<asset_object>( current_asset, [current_supply](asset_object& obj) {
Expand Down Expand Up @@ -1150,6 +1150,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 +1181,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 @@ -1233,7 +1237,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
update_worker_votes();

const auto& dgpo = get_dynamic_global_properties();

modify(gpo, [&dgpo](global_property_object& p) {
// Remove scaling of account registration fee
p.parameters.get_mutable_fees().get<account_create_operation>().basic_fee >>= p.parameters.account_fee_scale_bitshifts *
Expand Down Expand Up @@ -1327,6 +1331,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();
}

} }
8 changes: 4 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 @@ -455,7 +455,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
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 )
9 changes: 5 additions & 4 deletions libraries/plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ Plugins are optional to run by node operator according to their needs. However,

# Available Plugins

Folder | Name | Description | Category | Status | SpaceID
Folder | Name | Description | Category | Status | SpaceID
-----------------------------------|--------------------------|-----------------------------------------------------------------------------|----------------|---------------|--------------|
[account_history](account_history) | Account History | Save account history data | History | Stable | 4
[api_helper_indexes](api_helper_indexes) | API Helper Indexes | Provides some helper indexes used by various API calls | Database API | Stable |
[api_helper_indexes](api_helper_indexes) | API Helper Indexes | Provides some helper indexes used by various API calls | Database API | Stable |
[debug_witness](debug_witness) | Debug Witness | Run "what-if" tests | Debug | Stable |
[delayed_node](delayed_node) | Delayed Node | Avoid forks by running a several times confirmed and delayed blockchain | Business | Stable |
[elasticsearch](elasticsearch) | ElasticSearch Operations | Save account history data into elasticsearch database | History | Experimental | 6
[es_objects](es_objects) | ElasticSearch Objects | Save selected objects into elasticsearch database | History | Experimental |
[grouped_orders](grouped_orders) | Grouped Orders | Expose api to create a grouped order book of bitshares markets | Market data | Experimental |
[market_history](market_history) | Market History | Save market history data | Market data | Stable | 5
[snapshot](snapshot) | Snapshot | Get a json of all objects in blockchain at a specificed time or block | Debug | Stable |
[witness](witness) | Witness | Generate and sign blocks | Block producer | Stable |
[snapshot](snapshot) | Snapshot | Get a json of all objects in blockchain at a specificed time or block | Debug | Stable |
[witness](witness) | Witness | Generate and sign blocks | Block producer | Stable |
[voting_stat](voting_stat) | Voting Statistics | Generate objects from voting related data (works together with es objects) | History | Experimental | 7
2 changes: 1 addition & 1 deletion libraries/plugins/es_objects/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if(MSVC)
set_source_files_properties(es_objects.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
endif(MSVC)

target_link_libraries( graphene_es_objects graphene_chain graphene_app ${CURL_LIBRARIES} )
target_link_libraries( graphene_es_objects graphene_chain graphene_app graphene_voting_stat ${CURL_LIBRARIES} )
target_include_directories( graphene_es_objects
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )

Expand Down
191 changes: 139 additions & 52 deletions libraries/plugins/es_objects/es_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@
#include <graphene/chain/market_object.hpp>
#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/voting_stat/voting_statistics_object.hpp>
#include <graphene/voting_stat/voteable_statistics_object.hpp>

#include <graphene/utilities/elasticsearch.hpp>

namespace graphene { namespace es_objects {

using voting_stat::voting_statistics_object;
using voting_stat::voteable_statistics_object;

namespace detail
{

Expand All @@ -61,6 +66,10 @@ class es_objects_plugin_impl
bool _es_objects_balances = true;
bool _es_objects_limit_orders = true;
bool _es_objects_asset_bitasset = true;
bool _es_objects_voting_statistics = true;
bool _es_objects_voteable_statistics = true;
bool _es_objects_statistics_delete_allowed = true;

std::string _es_objects_index_prefix = "objects-";
uint32_t _es_objects_start_es_after_block = 0;
CURL *curl; // curl handler
Expand Down Expand Up @@ -141,61 +150,126 @@ bool es_objects_plugin_impl::index_database(const vector<object_id_type>& ids, s
limit_documents = _es_objects_bulk_replay;


for (auto const &value: ids) {
if (value.is<proposal_object>() && _es_objects_proposals) {
auto obj = db.find_object(value);
auto p = static_cast<const proposal_object *>(obj);
if (p != nullptr) {
if (action == "delete")
remove_from_database(p->id, "proposal");
else
prepareTemplate<proposal_object>(*p, "proposal");
for (auto const &value: ids)
{
switch( value.space_type() )
pmconrad marked this conversation as resolved.
Show resolved Hide resolved
{
case( proposal_object::space_type() ):
{
if( _es_objects_proposals ) {
auto obj = db.find_object(value);
auto p = static_cast<const proposal_object *>(obj);
if (p != nullptr) {
if (action == "delete")
remove_from_database(p->id, "proposal");
else
prepareTemplate<proposal_object>(*p, "proposal");
}
}
break;
}
case( account_object::space_type() ):
{
if( _es_objects_accounts ) {
auto obj = db.find_object(value);
auto a = static_cast<const account_object *>(obj);
if (a != nullptr) {
if (action == "delete")
remove_from_database(a->id, "account");
else
prepareTemplate<account_object>(*a, "account");
}
}
break;
}
} else if (value.is<account_object>() && _es_objects_accounts) {
auto obj = db.find_object(value);
auto a = static_cast<const account_object *>(obj);
if (a != nullptr) {
if (action == "delete")
remove_from_database(a->id, "account");
else
prepareTemplate<account_object>(*a, "account");
case( asset_object::space_type() ):
{
if( _es_objects_assets ) {
auto obj = db.find_object(value);
auto a = static_cast<const asset_object *>(obj);
if (a != nullptr) {
if (action == "delete")
remove_from_database(a->id, "asset");
else
prepareTemplate<asset_object>(*a, "asset");
}
}
break;
}
} else if (value.is<asset_object>() && _es_objects_assets) {
auto obj = db.find_object(value);
auto a = static_cast<const asset_object *>(obj);
if (a != nullptr) {
if (action == "delete")
remove_from_database(a->id, "asset");
else
prepareTemplate<asset_object>(*a, "asset");
case( account_balance_object::space_type() ):
{
if( _es_objects_balances ) {
auto obj = db.find_object(value);
auto b = static_cast<const account_balance_object *>(obj);
if (b != nullptr) {
if (action == "delete")
remove_from_database(b->id, "balance");
else
prepareTemplate<account_balance_object>(*b, "balance");
}
}
break;
}
} else if (value.is<account_balance_object>() && _es_objects_balances) {
auto obj = db.find_object(value);
auto b = static_cast<const account_balance_object *>(obj);
if (b != nullptr) {
if (action == "delete")
remove_from_database(b->id, "balance");
else
prepareTemplate<account_balance_object>(*b, "balance");
case( limit_order_object::space_type() ):
{
if( _es_objects_limit_orders ) {
auto obj = db.find_object(value);
auto l = static_cast<const limit_order_object *>(obj);
if (l != nullptr) {
if (action == "delete")
remove_from_database(l->id, "limitorder");
else
prepareTemplate<limit_order_object>(*l, "limitorder");
}
}
break;
}
} else if (value.is<limit_order_object>() && _es_objects_limit_orders) {
auto obj = db.find_object(value);
auto l = static_cast<const limit_order_object *>(obj);
if (l != nullptr) {
if (action == "delete")
remove_from_database(l->id, "limitorder");
else
prepareTemplate<limit_order_object>(*l, "limitorder");
case( asset_bitasset_data_object::space_type() ):
{
if( _es_objects_asset_bitasset ) {
auto obj = db.find_object(value);
auto ba = static_cast<const asset_bitasset_data_object *>(obj);
if (ba != nullptr) {
if (action == "delete")
remove_from_database(ba->id, "bitasset");
else
prepareTemplate<asset_bitasset_data_object>(*ba, "bitasset");
}
}
break;
}
} else if (value.is<asset_bitasset_data_object>() && _es_objects_asset_bitasset) {
auto obj = db.find_object(value);
auto ba = static_cast<const asset_bitasset_data_object *>(obj);
if (ba != nullptr) {
if (action == "delete")
remove_from_database(ba->id, "bitasset");
else
prepareTemplate<asset_bitasset_data_object>(*ba, "bitasset");
case( voting_statistics_object::space_type() ):
{
if( _es_objects_voting_statistics ) {
auto obj = db.find_object(value);
auto vs = static_cast<const voting_statistics_object *>(obj);

if (vs != nullptr) {
if (action == "delete" && _es_objects_statistics_delete_allowed ) // TODO will lead to error when false
remove_from_database(vs->id, "voting-statistics");
else
prepareTemplate<voting_statistics_object>(*vs, "voting-statistics");
}
}
break;
}
case( voteable_statistics_object::space_type() ):
{
if( _es_objects_voteable_statistics ) {
auto obj = db.find_object(value);
auto vs = static_cast<const voteable_statistics_object *>(obj);

if (vs != nullptr) {
if (action == "delete" && _es_objects_statistics_delete_allowed ) // TODO will lead to error when false
remove_from_database(vs->id, "voteable-statistics");
else
prepareTemplate<voteable_statistics_object>(*vs, "voteable-statistics");
}
}
break;
}
default:
break;
}
}

Expand Down Expand Up @@ -308,12 +382,16 @@ void es_objects_plugin::plugin_set_program_options(
("es-objects-balances", boost::program_options::value<bool>(), "Store balances objects(true)")
("es-objects-limit-orders", boost::program_options::value<bool>(), "Store limit order objects(true)")
("es-objects-asset-bitasset", boost::program_options::value<bool>(), "Store feed data(true)")
("es-objects-voting-statistics", boost::program_options::value<bool>(), "Store voting statistcs(true)")
("es-objects-voteable-statistics", boost::program_options::value<bool>(), "Store voteable statistcs(true)")
("es-objects-statistics-delete-allowed", boost::program_options::value<bool>(),
"Allows the deletion of statistics objects from es(true)")
("es-objects-index-prefix", boost::program_options::value<std::string>(),
"Add a prefix to the index(objects-)")
"Add a prefix to the index(objects-)")
("es-objects-keep-only-current", boost::program_options::value<bool>(),
"Keep only current state of the objects(true)")
"Keep only current state of the objects(true)")
("es-objects-start-es-after-block", boost::program_options::value<uint32_t>(),
"Start doing ES job after block(0)")
"Start doing ES job after block(0)")
;
cfg.add(cli);
}
Expand Down Expand Up @@ -350,6 +428,15 @@ void es_objects_plugin::plugin_initialize(const boost::program_options::variable
if (options.count("es-objects-asset-bitasset")) {
my->_es_objects_asset_bitasset = options["es-objects-asset-bitasset"].as<bool>();
}
if (options.count("es-objects-voting-statistics")) {
my->_es_objects_voting_statistics = options["es-objects-voting-statistics"].as<bool>();
}
if (options.count("es-objects-voteable-statistics")) {
my->_es_objects_voteable_statistics = options["es-objects-voteable-statistics"].as<bool>();
}
if (options.count("es-objects-statistics-delete-allowed")) {
my->_es_objects_statistics_delete_allowed = options["es-objects-statistics-delete-allowed"].as<bool>();
}
if (options.count("es-objects-index-prefix")) {
my->_es_objects_index_prefix = options["es-objects-index-prefix"].as<std::string>();
}
Expand Down
Loading