#260 Added functions get_votes() and get_voters()

This commit is contained in:
Vlad Dobromyslov 2022-02-10 21:11:08 +00:00 committed by serkixenos
parent 494482eba5
commit d7e24bfb07
8 changed files with 695 additions and 30 deletions

View file

@ -52,6 +52,30 @@ template class fc::api<graphene::app::database_api>;
namespace graphene { namespace app {
template<class T>
optional<T> maybe_id( const string& name_or_id )
{
if( std::isdigit( name_or_id.front() ) )
{
try
{
return fc::variant(name_or_id, 1).as<T>(1);
}
catch (const fc::exception&)
{ // not an ID
}
}
return optional<T>();
}
std::string object_id_to_string(object_id_type id)
{
std::string object_id = fc::to_string(id.space())
+ "." + fc::to_string(id.type())
+ "." + fc::to_string(id.instance());
return object_id;
}
class database_api_impl : public std::enable_shared_from_this<database_api_impl> {
public:
database_api_impl(graphene::chain::database &db);
@ -157,7 +181,8 @@ public:
// SON members
vector<optional<son_object>> get_sons(const vector<son_id_type> &son_ids) const;
fc::optional<son_object> get_son_by_account(account_id_type account) const;
fc::optional<son_object> get_son_by_account_id(account_id_type account) const;
fc::optional<son_object> get_son_by_account(const std::string account_id_or_name) const;
map<string, son_id_type> lookup_son_accounts(const string &lower_bound_name, uint32_t limit) const;
uint64_t get_son_count() const;
@ -173,8 +198,30 @@ public:
fc::optional<sidechain_address_object> get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain) const;
uint64_t get_sidechain_addresses_count() const;
// Workers
vector<optional<worker_object>> get_workers(const vector<worker_id_type> &witness_ids) const;
vector<worker_object> get_workers_by_account(const std::string account_id_or_name) const;
// Votes
vector<variant> lookup_vote_ids(const vector<vote_id_type> &votes) const;
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const;
template<typename IndexType, typename Tag>
vector<variant> get_votes_objects(const vector<vote_id_type> &votes, unsigned int variant_max_depth = 1) const
{
static_assert( std::is_base_of<index,IndexType>::value, "Type must be an index type" );
vector<variant> result;
const auto &idx = _db.get_index_type<IndexType>().indices().template get<Tag>();
for (auto id : votes) {
auto itr = idx.find(id);
if (itr != idx.end())
result.emplace_back(variant(*itr,variant_max_depth));
}
return result;
}
votes_info get_votes(const string &account_name_or_id) const;
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const;
voters_info get_voters(const string &account_name_or_id) const;
// Authority / validation
std::string get_transaction_hex(const signed_transaction &trx) const;
@ -234,6 +281,9 @@ public:
vector<offer_history_object> get_offer_history_by_item(const offer_history_id_type lower_id, const nft_id_type item, uint32_t limit) const;
vector<offer_history_object> get_offer_history_by_bidder(const offer_history_id_type lower_id, const account_id_type bidder_account_id, uint32_t limit) const;
// Account Role
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
uint32_t api_limit_get_lower_bound_symbol = 100;
uint32_t api_limit_get_limit_orders = 300;
uint32_t api_limit_get_limit_orders_by_account = 101;
@ -245,9 +295,6 @@ public:
uint32_t api_limit_get_trade_history = 100;
uint32_t api_limit_get_trade_history_by_sequence = 100;
// Account Role
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
//private:
const account_object *get_account_from_string(const std::string &name_or_id,
bool throw_if_not_found = true) const;
@ -1552,20 +1599,6 @@ vector<optional<witness_object>> database_api::get_witnesses(const vector<witnes
return my->get_witnesses(witness_ids);
}
vector<worker_object> database_api::get_workers_by_account(const std::string account_id_or_name) const {
const auto &idx = my->_db.get_index_type<worker_index>().indices().get<by_account>();
const account_id_type account = my->get_account_from_string(account_id_or_name)->id;
auto itr = idx.find(account);
vector<worker_object> result;
if (itr != idx.end() && itr->worker_account == account) {
result.emplace_back(*itr);
++itr;
}
return result;
}
vector<optional<witness_object>> database_api_impl::get_witnesses(const vector<witness_id_type> &witness_ids) const {
vector<optional<witness_object>> result;
result.reserve(witness_ids.size());
@ -1712,11 +1745,11 @@ vector<optional<son_object>> database_api_impl::get_sons(const vector<son_id_typ
return result;
}
fc::optional<son_object> database_api::get_son_by_account(account_id_type account) const {
return my->get_son_by_account(account);
fc::optional<son_object> database_api::get_son_by_account_id(account_id_type account) const {
return my->get_son_by_account_id(account);
}
fc::optional<son_object> database_api_impl::get_son_by_account(account_id_type account) const {
fc::optional<son_object> database_api_impl::get_son_by_account_id(account_id_type account) const {
const auto &idx = _db.get_index_type<son_index>().indices().get<by_account>();
auto itr = idx.find(account);
if (itr != idx.end())
@ -1724,6 +1757,15 @@ fc::optional<son_object> database_api_impl::get_son_by_account(account_id_type a
return {};
}
fc::optional<son_object> database_api::get_son_by_account(const std::string account_id_or_name) const {
return my->get_son_by_account(account_id_or_name);
}
fc::optional<son_object> database_api_impl::get_son_by_account(const std::string account_id_or_name) const {
const account_id_type account = get_account_from_string(account_id_or_name)->id;
return get_son_by_account_id(account);
}
map<string, son_id_type> database_api::lookup_son_accounts(const string &lower_bound_name, uint32_t limit) const {
return my->lookup_son_accounts(lower_bound_name, limit);
}
@ -1875,6 +1917,46 @@ uint64_t database_api_impl::get_sidechain_addresses_count() const {
return _db.get_index_type<sidechain_address_index>().indices().size();
}
//////////////////////////////////////////////////////////////////////
// //
// Workers //
// //
//////////////////////////////////////////////////////////////////////
vector<optional<worker_object>> database_api::get_workers(const vector<worker_id_type> &worker_ids) const {
return my->get_workers(worker_ids);
}
vector<worker_object> database_api::get_workers_by_account(const std::string account_id_or_name) const {
return my->get_workers_by_account(account_id_or_name);
}
vector<optional<worker_object>> database_api_impl::get_workers(const vector<worker_id_type> &worker_ids) const {
vector<optional<worker_object>> result;
result.reserve(worker_ids.size());
std::transform(worker_ids.begin(), worker_ids.end(), std::back_inserter(result),
[this](worker_id_type id) -> optional<worker_object> {
if (auto o = _db.find(id))
return *o;
return {};
});
return result;
}
vector<worker_object> database_api_impl::get_workers_by_account(const std::string account_id_or_name) const {
const auto &idx = _db.get_index_type<worker_index>().indices().get<by_account>();
const account_id_type account = get_account_from_string(account_id_or_name)->id;
auto itr = idx.find(account);
vector<worker_object> result;
if (itr != idx.end() && itr->worker_account == account) {
result.emplace_back(*itr);
++itr;
}
return result;
}
//////////////////////////////////////////////////////////////////////
// //
// Votes //
@ -1885,6 +1967,22 @@ vector<variant> database_api::lookup_vote_ids(const vector<vote_id_type> &votes)
return my->lookup_vote_ids(votes);
}
vector<vote_id_type> database_api::get_votes_ids(const string &account_name_or_id) const {
return my->get_votes_ids(account_name_or_id);
}
votes_info database_api::get_votes(const string &account_name_or_id) const {
return my->get_votes(account_name_or_id);
}
vector<account_object> database_api::get_voters_by_id(const vote_id_type &vote_id) const {
return my->get_voters_by_id(vote_id);
}
voters_info database_api::get_voters(const string &account_name_or_id) const {
return my->get_voters(account_name_or_id);
}
vector<variant> database_api_impl::lookup_vote_ids(const vector<vote_id_type> &votes) const {
FC_ASSERT(votes.size() < 1000, "Only 1000 votes can be queried at a time");
@ -1946,6 +2044,268 @@ vector<variant> database_api_impl::lookup_vote_ids(const vector<vote_id_type> &v
return result;
}
vector<vote_id_type> database_api_impl::get_votes_ids(const string &account_name_or_id) const {
vector<vote_id_type> result;
const account_object *account = get_account_from_string(account_name_or_id);
//! Iterate throug votes and fill vector
for( const auto& vote : account->options.votes )
{
result.emplace_back(vote);
}
return result;
}
votes_info database_api_impl::get_votes(const string &account_name_or_id) const {
votes_info result;
const auto& votes_ids = get_votes_ids(account_name_or_id);
const auto& committee_ids = get_votes_objects<committee_member_index, by_vote_id>(votes_ids);
const auto& witness_ids = get_votes_objects<witness_index, by_vote_id>(votes_ids);
const auto& for_worker_ids = get_votes_objects<worker_index, by_vote_for>(votes_ids);
const auto& against_worker_ids = get_votes_objects<worker_index, by_vote_against>(votes_ids);
const auto& son_ids = get_votes_objects<son_index, by_vote_id>(votes_ids, 5);
//! Fill votes info
if(!committee_ids.empty()) {
vector< votes_info_object<committee_member_id_type> > votes_for_committee_members;
votes_for_committee_members.reserve(committee_ids.size());
for (const auto &committee : committee_ids) {
const auto &committee_obj = committee.as<committee_member_object>(2);
votes_for_committee_members.emplace_back(votes_info_object<committee_member_id_type>{committee_obj.vote_id, committee_obj.id.instance()});
}
result.votes_for_committee_members = std::move(votes_for_committee_members);
}
if(!witness_ids.empty()) {
vector< votes_info_object<witness_id_type> > votes_for_witnesses;
votes_for_witnesses.reserve(witness_ids.size());
for (const auto &witness : witness_ids) {
const auto &witness_obj = witness.as<witness_object>(2);
votes_for_witnesses.emplace_back(votes_info_object<witness_id_type>{witness_obj.vote_id, witness_obj.id.instance()});
}
result.votes_for_witnesses = std::move(votes_for_witnesses);
}
if(!for_worker_ids.empty()) {
vector< votes_info_object<worker_id_type> > votes_for_workers;
votes_for_workers.reserve(for_worker_ids.size());
for (const auto &for_worker : for_worker_ids) {
const auto &for_worker_obj = for_worker.as<worker_object>(2);
votes_for_workers.emplace_back(votes_info_object<worker_id_type>{for_worker_obj.vote_for, for_worker_obj.id.instance()});
}
result.votes_for_workers = std::move(votes_for_workers);
}
if(!against_worker_ids.empty()) {
vector< votes_info_object<worker_id_type> > votes_against_workers;
votes_against_workers.reserve(against_worker_ids.size());
for (const auto &against_worker : against_worker_ids) {
const auto &against_worker_obj = against_worker.as<worker_object>(2);
votes_against_workers.emplace_back(votes_info_object<worker_id_type>{against_worker_obj.vote_against, against_worker_obj.id.instance()});
}
result.votes_against_workers = std::move(votes_against_workers);
}
if(!son_ids.empty()) {
vector< votes_info_object<son_id_type> > votes_for_sons;
votes_for_sons.reserve(son_ids.size());
for (const auto &son : son_ids) {
const auto &son_obj = son.as<son_object>(6);
votes_for_sons.emplace_back(votes_info_object<son_id_type>{son_obj.vote_id, son_obj.id.instance()});
}
result.votes_for_sons = std::move(votes_for_sons);
}
return result;
}
vector<account_object> database_api_impl::get_voters_by_id(const vote_id_type &vote_id) const {
vector<account_object> result;
//! We search all accounts that have voted for this vote_id
const auto& account_index = _db.get_index_type<graphene::chain::account_index>().indices().get<by_id>();
for( const auto& account: account_index )
{
if(account.options.votes.count(vote_id) != 0)
result.emplace_back(account);
}
return result;
}
voters_info database_api_impl::get_voters(const string &account_name_or_id) const {
voters_info result;
//! Find account name
bool owner_account_found = false;
std::string owner_account_id;
//! Check if we have account by name
const auto& account_object = get_account_by_name(account_name_or_id);
if(account_object) {
//! It is account
owner_account_id = object_id_to_string( account_object->get_id() );
owner_account_found = true;
}
else {
//! Check if we have account id
const auto& account_id = maybe_id<account_id_type>(account_name_or_id);
if(account_id) {
//! It may be account id
const auto& account_objects = get_accounts({account_name_or_id});
if(!account_objects.empty()){
const auto& account_object = account_objects.front();
if(account_object) {
//! It is account object
owner_account_id = object_id_to_string( account_object->get_id() );
owner_account_found = true;
}
}
}
else {
//! Check if we have committee member id
const auto& committee_member_id = maybe_id<committee_member_id_type>(account_name_or_id);
if(committee_member_id) {
//! It may be committee member id
const auto& committee_member_objects = get_committee_members({*committee_member_id});
if(!committee_member_objects.empty()){
const auto& committee_member_object = committee_member_objects.front();
if(committee_member_object) {
//! It is committee member object
owner_account_id = object_id_to_string( committee_member_object->committee_member_account );
owner_account_found = true;
}
}
}
else {
//! Check if we have witness id
const auto& witness_id = maybe_id<witness_id_type>(account_name_or_id);
if(witness_id) {
//! It may be witness id
const auto& witness_objects = get_witnesses({*witness_id});
if(!witness_objects.empty()){
const auto& witness_object = witness_objects.front();
if(witness_object) {
//! It is witness object
owner_account_id = object_id_to_string( witness_object->witness_account );
owner_account_found = true;
}
}
}
else {
//! Check if we have worker id
const auto& worker_id = maybe_id<worker_id_type>(account_name_or_id);
if(worker_id) {
//! It may be worker id
const auto& worker_objects = get_workers({*worker_id});
if(!worker_objects.empty()){
const auto& worker_object = worker_objects.front();
if(worker_object) {
//! It is worker object
owner_account_id = object_id_to_string( worker_object->worker_account );
owner_account_found = true;
}
}
}
else {
//! Check if we have son id
const auto& son_id = maybe_id<son_id_type>(account_name_or_id);
if(son_id) {
//! It may be son id
const auto& son_objects = get_sons({*son_id});
if(!son_objects.empty()){
const auto& son_object = son_objects.front();
if(son_object) {
//! It is son object
owner_account_id = object_id_to_string( son_object->son_account );
owner_account_found = true;
}
}
}
}
}
}
}
}
//! We didn't find who it was
if(!owner_account_found)
FC_THROW_EXCEPTION(database_query_exception, "Wrong account_name_or_id: ${account_name_or_id}", ("account_name_or_id", account_name_or_id));
//! Fill voters_info
const auto& committee_member_object = get_committee_member_by_account(owner_account_id);
const auto& witness_object = get_witness_by_account(owner_account_id);
const auto& worker_objects = get_workers_by_account(owner_account_id);
const auto& son_object = get_son_by_account(owner_account_id);
//! Info for committee member voters
if(committee_member_object) {
const auto& committee_member_voters = get_voters_by_id(committee_member_object->vote_id);
voters_info_object voters_for_committee_member;
voters_for_committee_member.vote_id = committee_member_object->vote_id;
voters_for_committee_member.voters.reserve(committee_member_voters.size());
for(const auto& voter: committee_member_voters) {
voters_for_committee_member.voters.emplace_back(voter.get_id());
}
result.voters_for_committee_member = std::move(voters_for_committee_member);
}
//! Info for witness voters
if(witness_object) {
const auto& witness_voters = get_voters_by_id(witness_object->vote_id);
voters_info_object voters_for_witness;
voters_for_witness.vote_id = witness_object->vote_id;
voters_for_witness.voters.reserve(witness_voters.size());
for(const auto& voter: witness_voters) {
voters_for_witness.voters.emplace_back(voter.get_id());
}
result.voters_for_witness = std::move(voters_for_witness);
}
//! Info for worker voters
if(!worker_objects.empty()) {
vector<voters_info_object> voters_for_workers(worker_objects.size());
vector<voters_info_object> voters_against_workers(worker_objects.size());
for (const auto &worker_object : worker_objects) {
voters_info_object voters_for_worker;
const auto &for_worker_voters = get_voters_by_id(worker_object.vote_for);
voters_for_worker.vote_id = worker_object.vote_for;
voters_for_worker.voters.reserve(for_worker_voters.size());
for (const auto &voter : for_worker_voters) {
voters_for_worker.voters.emplace_back(voter.get_id());
}
voters_for_workers.emplace_back(std::move(voters_for_worker));
voters_info_object voters_against_worker;
const auto &against_worker_voters = get_voters_by_id(worker_object.vote_against);
voters_against_worker.vote_id = worker_object.vote_against;
voters_against_worker.voters.reserve(against_worker_voters.size());
for (const auto &voter : against_worker_voters) {
voters_against_worker.voters.emplace_back(voter.get_id());
}
voters_against_workers.emplace_back(std::move(voters_against_worker));
}
result.voters_for_workers = std::move(voters_for_workers);
result.voters_against_workers = std::move(voters_against_workers);
}
//! Info for son voters
if(son_object) {
const auto& son_voters = get_voters_by_id(son_object->vote_id);
voters_info_object voters_for_son;
voters_for_son.vote_id = son_object->vote_id;
voters_for_son.voters.reserve(son_voters.size());
for(const auto& voter: son_voters) {
voters_for_son.voters.emplace_back(voter.get_id());
}
result.voters_for_son = std::move(voters_for_son);
}
return result;
}
//////////////////////////////////////////////////////////////////////
// //
// Authority / validation //

View file

@ -56,6 +56,8 @@
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/nft_object.hpp>
#include <graphene/chain/offer_object.hpp>
#include <graphene/chain/votes_info.hpp>
#include <graphene/chain/voters_info.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
@ -619,7 +621,14 @@ public:
* @param account The ID of the account whose SON should be retrieved
* @return The SON object, or null if the account does not have a SON
*/
fc::optional<son_object> get_son_by_account(account_id_type account) const;
fc::optional<son_object> get_son_by_account_id(account_id_type account) const;
/**
* @brief Get the SON owned by a given account
* @param account The ID of the account whose SON should be retrieved
* @return The SON object, or null if the account does not have a SON
*/
fc::optional<son_object> get_son_by_account(const std::string account_id_or_name) const;
/**
* @brief Get names and IDs for registered SONs
@ -698,7 +707,18 @@ public:
*/
uint64_t get_sidechain_addresses_count() const;
/// WORKERS
/////////////
// Workers //
/////////////
/**
* @brief Get a list of workers by ID
* @param worker_ids IDs of the workers to retrieve
* @return The workers corresponding to the provided IDs
*
* This function has semantics identical to @ref get_objects
*/
vector<optional<worker_object>> get_workers(const vector<worker_id_type> &worker_ids) const;
/**
* @brief Return the worker objects associated with this account.
@ -721,6 +741,39 @@ public:
*/
vector<variant> lookup_vote_ids(const vector<vote_id_type> &votes) const;
/**
* @brief Get a list of vote_id_type that ID votes for
* @param account_name_or_id ID or name of the account to get votes for
* @return The list of vote_id_type ID votes for
*
*/
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const;
/**
* @brief Return the objects account_name_or_id votes for
* @param account_name_or_id ID or name of the account to get votes for
* @return The votes_info account_name_or_id votes for
*
*/
votes_info get_votes(const string &account_name_or_id) const;
/**
*
* @brief Get a list of accounts that votes for vote_id
* @param vote_id We search accounts that vote for this ID
* @return The accounts that votes for provided ID
*
*/
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const;
/**
* @brief Return the accounts that votes for account_name_or_id
* @param account_name_or_id ID or name of the account to get voters for
* @return The voters_info for account_name_or_id
*
*/
voters_info get_voters(const string &account_name_or_id) const;
////////////////////////////
// Authority / validation //
////////////////////////////
@ -1044,6 +1097,7 @@ FC_API(graphene::app::database_api,
// SON members
(get_sons)
(get_son_by_account_id)
(get_son_by_account)
(lookup_son_accounts)
(get_son_count)
@ -1060,10 +1114,16 @@ FC_API(graphene::app::database_api,
(get_sidechain_address_by_account_and_sidechain)
(get_sidechain_addresses_count)
// workers
// Workers
(get_workers)
(get_workers_by_account)
// Votes
(lookup_vote_ids)
(get_votes_ids)
(get_votes)
(get_voters_by_id)
(get_voters)
// Authority / validation
(get_transaction_hex)

View file

@ -0,0 +1,40 @@
#pragma once
#include <graphene/chain/protocol/vote.hpp>
namespace graphene { namespace chain {
/**
* @class voters_info_object
* @ingroup object
*/
struct voters_info_object {
vote_id_type vote_id;
vector<account_id_type> voters;
};
/**
* @class voters_info
* @brief tracks information about a voters info
* @ingroup object
*/
struct voters_info {
optional<voters_info_object> voters_for_committee_member;
optional<voters_info_object> voters_for_witness;
optional<vector<voters_info_object> > voters_for_workers;
optional<vector<voters_info_object> > voters_against_workers;
optional<voters_info_object> voters_for_son;
};
} } // graphene::chain
FC_REFLECT( graphene::chain::voters_info_object,
(vote_id)
(voters) )
FC_REFLECT( graphene::chain::voters_info,
(voters_for_committee_member)
(voters_for_witness)
(voters_for_workers)
(voters_against_workers)
(voters_for_son) )

View file

@ -0,0 +1,48 @@
#pragma once
#include <graphene/chain/protocol/vote.hpp>
namespace graphene { namespace chain {
/**
* @class votes_info_object
* @tparam IdType id type of the object
* @ingroup object
*/
template<typename IdType>
struct votes_info_object {
votes_info_object() = default;
votes_info_object(const vote_id_type& vote_id_, uint64_t id_)
: vote_id{vote_id_}
, id{id_}
{}
vote_id_type vote_id;
IdType id;
};
/**
* @class votes_info
* @brief tracks information about a votes info
* @ingroup object
*/
struct votes_info {
optional< vector< votes_info_object<committee_member_id_type> > > votes_for_committee_members;
optional< vector< votes_info_object<witness_id_type> > > votes_for_witnesses;
optional< vector< votes_info_object<worker_id_type> > > votes_for_workers;
optional< vector< votes_info_object<worker_id_type> > > votes_against_workers;
optional< vector< votes_info_object<son_id_type> > > votes_for_sons;
};
} } // graphene::chain
FC_REFLECT_TEMPLATE( (typename IdType), graphene::chain::votes_info_object<IdType>,
(vote_id)
(id) )
FC_REFLECT( graphene::chain::votes_info,
(votes_for_committee_members)
(votes_for_witnesses)
(votes_for_workers)
(votes_against_workers)
(votes_for_sons) )

View file

@ -2487,9 +2487,41 @@ class wallet_api
bool broadcast = false,
bool to_temp = false );
std::map<string,std::function<string(fc::variant,const fc::variants&)>> get_result_formatters() const;
/**
* @brief Get a list of vote_id_type that ID votes for
* @param account_name_or_id ID or name of the account to get votes for
* @return The list of vote_id_type ID votes for
*
*/
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const;
/**
* @brief Return the objects account_name_or_id votes for
* @param account_name_or_id ID or name of the account to get votes for
* @return The votes_info account_name_or_id votes for
*
*/
votes_info get_votes(const string &account_name_or_id) const;
/**
* @brief Get a list of accounts that votes for vote_id
* @param vote_id We search accounts that vote for this ID
* @return The accounts that votes for provided ID
*
*/
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const;
/**
* @brief Return the accounts that votes for account_name_or_id
* @param account_name_or_id ID or name of the account to get voters for
* @return The voters_info for account_name_or_id
*
*/
voters_info get_voters(const string &account_name_or_id) const;
fc::signal<void(bool)> lock_changed;
std::shared_ptr<detail::wallet_api_impl> my;
void encrypt_keys();
@ -2795,4 +2827,8 @@ FC_API( graphene::wallet::wallet_api,
(get_custom_account_authorities_by_permission_id)
(get_custom_account_authorities_by_permission_name)
(get_active_custom_account_authorities_by_operation)
(get_votes_ids)
(get_votes)
(get_voters_by_id)
(get_voters)
)

View file

@ -1946,7 +1946,7 @@ public:
try
{
account_id_type owner_account_id = get_account_id(owner_account);
fc::optional<son_object> son = _remote_db->get_son_by_account(owner_account_id);
fc::optional<son_object> son = _remote_db->get_son_by_account_id(owner_account_id);
if (son)
return *son;
else
@ -2075,7 +2075,7 @@ public:
son_create_op.pay_vb = pay_vb_id;
son_create_op.sidechain_public_keys = sidechain_public_keys;
if (_remote_db->get_son_by_account(son_create_op.owner_account))
if (_remote_db->get_son_by_account_id(son_create_op.owner_account))
FC_THROW("Account ${owner_account} is already a SON", ("owner_account", owner_account));
signed_transaction tx;
@ -2712,7 +2712,7 @@ public:
account_object voting_account_object = get_account(voting_account);
account_id_type son_account_id = get_account_id(son);
fc::optional<son_object> son_obj = _remote_db->get_son_by_account(son_account_id);
fc::optional<son_object> son_obj = _remote_db->get_son_by_account_id(son_account_id);
if (!son_obj)
FC_THROW("Account ${son} is not registered as a son", ("son", son));
if (approve)
@ -2756,7 +2756,7 @@ public:
for (const std::string& son : sons_to_approve)
{
account_id_type son_owner_account_id = get_account_id(son);
fc::optional<son_object> son_obj = _remote_db->get_son_by_account(son_owner_account_id);
fc::optional<son_object> son_obj = _remote_db->get_son_by_account_id(son_owner_account_id);
if (!son_obj)
FC_THROW("Account ${son} is not registered as a SON", ("son", son));
auto insert_result = voting_account_object.options.votes.insert(son_obj->vote_id);
@ -2766,7 +2766,7 @@ public:
for (const std::string& son : sons_to_reject)
{
account_id_type son_owner_account_id = get_account_id(son);
fc::optional<son_object> son_obj = _remote_db->get_son_by_account(son_owner_account_id);
fc::optional<son_object> son_obj = _remote_db->get_son_by_account_id(son_owner_account_id);
if (!son_obj)
FC_THROW("Account ${son} is not registered as a SON", ("son", son));
unsigned votes_removed = voting_account_object.options.votes.erase(son_obj->vote_id);
@ -4082,6 +4082,42 @@ public:
return it->second;
}
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const
{
try
{
return _remote_db->get_votes_ids(account_name_or_id);
}
FC_CAPTURE_AND_RETHROW( (account_name_or_id) )
}
votes_info get_votes(const string &account_name_or_id) const
{
try
{
return _remote_db->get_votes(account_name_or_id);
}
FC_CAPTURE_AND_RETHROW( (account_name_or_id) )
}
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const
{
try
{
return _remote_db->get_voters_by_id(vote_id);
}
FC_CAPTURE_AND_RETHROW( (vote_id) )
}
voters_info get_voters(const string &account_name_or_id) const
{
try
{
return _remote_db->get_voters(account_name_or_id);
}
FC_CAPTURE_AND_RETHROW( (account_name_or_id) )
}
string _wallet_filename;
wallet_data _wallet;
@ -7583,6 +7619,26 @@ std::vector<matched_bet_object> wallet_api::get_all_matched_bets_for_bettor(acco
return( my->_remote_bookie->get_all_matched_bets_for_bettor(bettor_id, start, limit) );
}
vector<vote_id_type> wallet_api::get_votes_ids(const string &account_name_or_id) const
{
return my->get_votes_ids(account_name_or_id);
}
votes_info wallet_api::get_votes(const string &account_name_or_id) const
{
return my->get_votes(account_name_or_id);
}
vector<account_object> wallet_api::get_voters_by_id(const vote_id_type &vote_id) const
{
return my->get_voters_by_id(vote_id);
}
voters_info wallet_api::get_voters(const string &account_name_or_id) const
{
return my->get_voters(account_name_or_id);
}
// default ctor necessary for FC_REFLECT
signed_block_with_info::signed_block_with_info( const signed_block& block )
: signed_block( block )

View file

@ -244,6 +244,28 @@ BOOST_AUTO_TEST_CASE( son_voting )
son2_end_votes = son2_obj.total_votes;
BOOST_CHECK(son2_end_votes > son2_start_votes);
//! Get nathan account
const auto nathan_account_object = con.wallet_api_ptr->get_account("nathan");
//! Check son1account voters
auto voters_for_son1account = con.wallet_api_ptr->get_voters("son1account");
BOOST_REQUIRE(voters_for_son1account.voters_for_son);
BOOST_CHECK_EQUAL(voters_for_son1account.voters_for_son->voters.size(), 1);
BOOST_CHECK_EQUAL((uint32_t)voters_for_son1account.voters_for_son->voters[0].instance, nathan_account_object.id.instance());
//! Check son2account voters
auto voters_for_son2account = con.wallet_api_ptr->get_voters("son2account");
BOOST_REQUIRE(voters_for_son2account.voters_for_son);
BOOST_CHECK_EQUAL(voters_for_son2account.voters_for_son->voters.size(), 1);
BOOST_CHECK_EQUAL((uint32_t)voters_for_son2account.voters_for_son->voters[0].instance, nathan_account_object.id.instance());
//! Check votes of nathan
auto nathan_votes = con.wallet_api_ptr->get_votes("nathan");
BOOST_REQUIRE(nathan_votes.votes_for_sons);
BOOST_CHECK_EQUAL(nathan_votes.votes_for_sons->size(), 2);
BOOST_CHECK_EQUAL((uint32_t)nathan_votes.votes_for_sons->at(0).id.instance, son1_obj.id.instance());
BOOST_CHECK_EQUAL((uint32_t)nathan_votes.votes_for_sons->at(1).id.instance, son2_obj.id.instance());
// Withdraw vote for a son1account
BOOST_TEST_MESSAGE("Withdraw vote for a son1account");
vote_son1_tx = con.wallet_api_ptr->vote_for_son("nathan", "son1account", false, true);
@ -254,6 +276,17 @@ BOOST_AUTO_TEST_CASE( son_voting )
son1_end_votes = son1_obj.total_votes;
BOOST_CHECK(son1_end_votes == son1_start_votes);
//! Check son1account voters
voters_for_son1account = con.wallet_api_ptr->get_voters("son1account");
BOOST_REQUIRE(voters_for_son1account.voters_for_son);
BOOST_CHECK_EQUAL(voters_for_son1account.voters_for_son->voters.size(), 0);
//! Check votes of nathan
nathan_votes = con.wallet_api_ptr->get_votes("nathan");
BOOST_REQUIRE(nathan_votes.votes_for_sons);
BOOST_CHECK_EQUAL(nathan_votes.votes_for_sons->size(), 1);
BOOST_CHECK_EQUAL((uint32_t)nathan_votes.votes_for_sons->at(0).id.instance, son2_obj.id.instance());
// Withdraw vote for a son2account
BOOST_TEST_MESSAGE("Withdraw vote for a son2account");
vote_son2_tx = con.wallet_api_ptr->vote_for_son("nathan", "son2account", false, true);
@ -264,6 +297,15 @@ BOOST_AUTO_TEST_CASE( son_voting )
son2_end_votes = son2_obj.total_votes;
BOOST_CHECK(son2_end_votes == son2_start_votes);
//! Check son2account voters
voters_for_son2account = con.wallet_api_ptr->get_voters("son2account");
BOOST_REQUIRE(voters_for_son2account.voters_for_son);
BOOST_CHECK_EQUAL(voters_for_son2account.voters_for_son->voters.size(), 0);
//! Check votes of nathan
nathan_votes = con.wallet_api_ptr->get_votes("nathan");
BOOST_CHECK(!nathan_votes.votes_for_sons.valid());
} catch( fc::exception& e ) {
BOOST_TEST_MESSAGE("SON cli wallet tests exception");
edump((e.to_detail_string()));

View file

@ -322,6 +322,18 @@ BOOST_AUTO_TEST_CASE(track_votes_witnesses_enabled)
auto witness1_object = db_api1.get_witness_by_account(witness1_id(db).name);
BOOST_CHECK_EQUAL(witness1_object->total_votes, 111);
//! Check witness1 voters
const auto voters_for_witness1 = db_api1.get_voters("witness1");
BOOST_REQUIRE(voters_for_witness1.voters_for_witness);
BOOST_CHECK_EQUAL(voters_for_witness1.voters_for_witness->voters.size(), 1);
BOOST_CHECK_EQUAL((uint32_t)voters_for_witness1.voters_for_witness->voters[0].instance, 18);
//! Check votes of account
const auto account_votes = db_api1.get_votes("1.2.18");
BOOST_REQUIRE(account_votes.votes_for_witnesses);
BOOST_CHECK_EQUAL(account_votes.votes_for_witnesses->size(), 1);
BOOST_CHECK_EQUAL((uint32_t)account_votes.votes_for_witnesses->at(0).id.instance, witness1_object->id.instance());
} FC_LOG_AND_RETHROW()
}
@ -501,6 +513,17 @@ BOOST_AUTO_TEST_CASE(track_votes_committee_enabled)
auto committee1_object = db_api1.get_committee_member_by_account(committee1_id(db).name);
BOOST_CHECK_EQUAL(committee1_object->total_votes, 111);
//! Check committee1 voters
const auto voters_for_committee1 = db_api1.get_voters("committee1");
BOOST_REQUIRE(voters_for_committee1.voters_for_committee_member);
BOOST_CHECK_EQUAL(voters_for_committee1.voters_for_committee_member->voters.size(), 1);
BOOST_CHECK_EQUAL((uint32_t)voters_for_committee1.voters_for_committee_member->voters[0].instance, 18);
//! Check votes of account
const auto account_votes = db_api1.get_votes("1.2.18");
BOOST_REQUIRE(account_votes.votes_for_committee_members);
BOOST_CHECK_EQUAL((uint32_t)account_votes.votes_for_committee_members->back().id.instance, committee1_object->id.instance());
} FC_LOG_AND_RETHROW()
}