Merge remote-tracking branch 'glu/develop' into dapp-support

This commit is contained in:
Nathaniel 2022-02-13 08:37:15 -06:00
commit 659d135b9b
No known key found for this signature in database
GPG key ID: B4344309A110851E
15 changed files with 920 additions and 68 deletions

14
.gitmodules vendored
View file

@ -1,9 +1,9 @@
[submodule "docs"]
path = docs
url = https://github.com/bitshares/bitshares-core.wiki.git
ignore = dirty
path = docs
url = https://github.com/bitshares/bitshares-core.wiki.git
ignore = dirty
[submodule "libraries/fc"]
path = libraries/fc
url = https://github.com/nathanhourt/peerplays-fc
branch = latest-fc
ignore = dirty
path = libraries/fc
url = https://gitlab.com/PBSA/tools-libs/peerplays-fc.git
branch = dapp-support
ignore = dirty

2
docs

@ -1 +1 @@
Subproject commit 8df8f66389853df73ab8f6dd73981be2a6957df8
Subproject commit 1e924950c2f92b166c34ceb294e8b8c4997a6c4e

View file

@ -55,6 +55,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);
@ -149,18 +173,22 @@ public:
// Witnesses
vector<optional<witness_object>> get_witnesses(const vector<witness_id_type> &witness_ids) const;
fc::optional<witness_object> get_witness_by_account_id(account_id_type account) const;
fc::optional<witness_object> get_witness_by_account(const std::string account_id_or_name) const;
map<string, witness_id_type> lookup_witness_accounts(const string &lower_bound_name, uint32_t limit) const;
uint64_t get_witness_count() const;
// Committee members
vector<optional<committee_member_object>> get_committee_members(const vector<committee_member_id_type> &committee_member_ids) const;
fc::optional<committee_member_object> get_committee_member_by_account_id(account_id_type account) const;
fc::optional<committee_member_object> get_committee_member_by_account(const std::string account_id_or_name) const;
map<string, committee_member_id_type> lookup_committee_member_accounts(const string &lower_bound_name, uint32_t limit) const;
uint64_t get_committee_member_count() const;
// 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;
@ -176,8 +204,33 @@ 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_id(account_id_type account) const;
vector<worker_object> get_workers_by_account(const std::string account_id_or_name) const;
map<string, worker_id_type> lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const;
uint64_t get_worker_count() 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;
@ -237,6 +290,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,12 +301,11 @@ public:
uint32_t api_limit_lookup_accounts = 1000;
uint32_t api_limit_lookup_witness_accounts = 1000;
uint32_t api_limit_lookup_committee_member_accounts = 1000;
uint32_t api_limit_lookup_son_accounts = 1000;
uint32_t api_limit_lookup_worker_accounts = 1000;
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;
@ -1555,20 +1610,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());
@ -1581,17 +1622,25 @@ vector<optional<witness_object>> database_api_impl::get_witnesses(const vector<w
return result;
}
fc::optional<witness_object> database_api::get_witness_by_account_id(account_id_type account) const {
return my->get_witness_by_account_id(account);
}
fc::optional<witness_object> database_api_impl::get_witness_by_account_id(account_id_type account) const {
const auto &idx = _db.get_index_type<witness_index>().indices().get<by_account>();
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
}
fc::optional<witness_object> database_api::get_witness_by_account(const std::string account_id_or_name) const {
return my->get_witness_by_account(account_id_or_name);
}
fc::optional<witness_object> database_api_impl::get_witness_by_account(const std::string account_id_or_name) const {
const auto &idx = _db.get_index_type<witness_index>().indices().get<by_account>();
const account_id_type account = get_account_from_string(account_id_or_name)->id;
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
return get_witness_by_account_id(account);
}
map<string, witness_id_type> database_api::lookup_witness_accounts(const string &lower_bound_name, uint32_t limit) const {
@ -1652,17 +1701,25 @@ vector<optional<committee_member_object>> database_api_impl::get_committee_membe
return result;
}
fc::optional<committee_member_object> database_api::get_committee_member_by_account_id(account_id_type account) const {
return my->get_committee_member_by_account_id(account);
}
fc::optional<committee_member_object> database_api_impl::get_committee_member_by_account_id(account_id_type account) const {
const auto &idx = _db.get_index_type<committee_member_index>().indices().get<by_account>();
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
}
fc::optional<committee_member_object> database_api::get_committee_member_by_account(const std::string account_id_or_name) const {
return my->get_committee_member_by_account(account_id_or_name);
}
fc::optional<committee_member_object> database_api_impl::get_committee_member_by_account(const std::string account_id_or_name) const {
const auto &idx = _db.get_index_type<committee_member_index>().indices().get<by_account>();
const account_id_type account = get_account_from_string(account_id_or_name)->id;
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
return get_committee_member_by_account_id(account);
}
map<string, committee_member_id_type> database_api::lookup_committee_member_accounts(const string &lower_bound_name, uint32_t limit) const {
@ -1693,6 +1750,14 @@ map<string, committee_member_id_type> database_api_impl::lookup_committee_member
return committee_members_by_account_name;
}
uint64_t database_api::get_committee_member_count() const {
return my->get_committee_member_count();
}
uint64_t database_api_impl::get_committee_member_count() const {
return _db.get_index_type<committee_member_index>().indices().size();
}
//////////////////////////////////////////////////////////////////////
// //
// SON members //
@ -1715,11 +1780,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())
@ -1727,12 +1792,24 @@ 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);
}
map<string, son_id_type> database_api_impl::lookup_son_accounts(const string &lower_bound_name, uint32_t limit) const {
FC_ASSERT(limit <= 1000);
FC_ASSERT(limit <= api_limit_lookup_son_accounts,
"Number of querying accounts can not be greater than ${configured_limit}",
("configured_limit", api_limit_lookup_son_accounts));
const auto &sons_by_id = _db.get_index_type<son_index>().indices().get<by_id>();
// we want to order sons by account name, but that name is in the account object
@ -1878,6 +1955,91 @@ 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_id(account_id_type account) const {
return my->get_workers_by_account_id(account);
}
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);
}
map<string, worker_id_type> database_api::lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const {
return my->lookup_worker_accounts(lower_bound_name, limit);
}
uint64_t database_api::get_worker_count() const {
return my->get_worker_count();
}
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_id(account_id_type account) const {
const auto &idx = _db.get_index_type<worker_index>().indices().get<by_account>();
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<worker_object> database_api_impl::get_workers_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_workers_by_account_id(account);
}
map<string, worker_id_type> database_api_impl::lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const {
FC_ASSERT(limit <= api_limit_lookup_worker_accounts,
"Number of querying accounts can not be greater than ${configured_limit}",
("configured_limit", api_limit_lookup_worker_accounts));
const auto &workers_by_id = _db.get_index_type<worker_index>().indices().get<by_id>();
// we want to order workers by account name, but that name is in the account object
// so the worker_index doesn't have a quick way to access it.
// get all the names and look them all up, sort them, then figure out what
// records to return. This could be optimized, but we expect the
// number of witnesses to be few and the frequency of calls to be rare
std::map<std::string, worker_id_type> workers_by_account_name;
for (const worker_object &worker : workers_by_id)
if (auto account_iter = _db.find(worker.worker_account))
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
workers_by_account_name.insert(std::make_pair(account_iter->name, worker.id));
auto end_iter = workers_by_account_name.begin();
while (end_iter != workers_by_account_name.end() && limit--)
++end_iter;
workers_by_account_name.erase(end_iter, workers_by_account_name.end());
return workers_by_account_name;
}
uint64_t database_api_impl::get_worker_count() const {
return _db.get_index_type<worker_index>().indices().size();
}
//////////////////////////////////////////////////////////////////////
// //
// Votes //
@ -1888,6 +2050,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");
@ -1949,6 +2127,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>
@ -558,6 +560,13 @@ public:
* @param account The ID of the account whose witness should be retrieved
* @return The witness object, or null if the account does not have a witness
*/
fc::optional<witness_object> get_witness_by_account_id(account_id_type account) const;
/**
* @brief Get the witness owned by a given account
* @param account_id_or_name The ID or name of the account whose witness should be retrieved
* @return The witness object, or null if the account does not have a witness
*/
fc::optional<witness_object> get_witness_by_account(const std::string account_name_or_id) const;
/**
@ -586,6 +595,13 @@ public:
*/
vector<optional<committee_member_object>> get_committee_members(const vector<committee_member_id_type> &committee_member_ids) const;
/**
* @brief Get the committee_member owned by a given account
* @param account The ID of the account whose committee_member should be retrieved
* @return The committee_member object, or null if the account does not have a committee_member
*/
fc::optional<committee_member_object> get_committee_member_by_account_id(account_id_type account) const;
/**
* @brief Get the committee_member owned by a given account
* @param account_id_or_name The ID or name of the account whose committee_member should be retrieved
@ -601,6 +617,11 @@ public:
*/
map<string, committee_member_id_type> lookup_committee_member_accounts(const string &lower_bound_name, uint32_t limit) const;
/**
* @brief Get the total number of committee_members registered with the blockchain
*/
uint64_t get_committee_member_count() const;
/////////////////
// SON members //
/////////////////
@ -619,7 +640,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_id_or_name 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,15 +726,46 @@ 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.
* @param account_id_or_name The ID or name of the account whose worker should be retrieved
* @param account The ID of the account whose workers should be retrieved
* @return The worker object or null if the account does not have a worker
*/
vector<worker_object> get_workers_by_account_id(account_id_type account) const;
/**
* @brief Return the worker objects associated with this account.
* @param account_id_or_name The ID or name of the account whose workers should be retrieved
* @return The worker object or null if the account does not have a worker
*/
vector<worker_object> get_workers_by_account(const std::string account_id_or_name) const;
/**
* @brief Get names and IDs for registered workers
* @param lower_bound_name Lower bound of the first name to return
* @param limit Maximum number of results to return -- must not exceed 1000
* @return Map of worker names to corresponding IDs
*/
map<string, worker_id_type> lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const;
/**
* @brief Get the total number of workers registered with the blockchain
*/
uint64_t get_worker_count() const;
///////////
// Votes //
///////////
@ -721,6 +780,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 //
////////////////////////////
@ -1033,17 +1125,21 @@ FC_API(graphene::app::database_api,
// Witnesses
(get_witnesses)
(get_witness_by_account_id)
(get_witness_by_account)
(lookup_witness_accounts)
(get_witness_count)
// Committee members
(get_committee_members)
(get_committee_member_by_account_id)
(get_committee_member_by_account)
(lookup_committee_member_accounts)
(get_committee_member_count)
// SON members
(get_sons)
(get_son_by_account_id)
(get_son_by_account)
(lookup_son_accounts)
(get_son_count)
@ -1060,10 +1156,19 @@ 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_id)
(get_workers_by_account)
(lookup_worker_accounts)
(get_worker_count)
// 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/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/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) )

@ -1 +1 @@
Subproject commit a17b231acf3bbd448179ddffc63c655e9b326395
Subproject commit bff16bbc3dcecbb9ddec96ba0af99ae33a3bf528

View file

@ -23,19 +23,11 @@ add_library( peerplays_sidechain
)
if (ENABLE_DEV_FEATURES)
set(ENABLE_MULTIPLE_SONS 1)
set(ENABLE_PEERPLAYS_ASSET_DEPOSITS 1)
endif()
unset(ENABLE_DEV_FEATURES)
unset(ENABLE_DEV_FEATURES CACHE)
if (ENABLE_MULTIPLE_SONS)
message ("Multiple SONs per software instance are supported")
target_compile_definitions(peerplays_sidechain PRIVATE ENABLE_MULTIPLE_SONS)
endif()
unset(ENABLE_MULTIPLE_SONS)
unset(ENABLE_MULTIPLE_SONS CACHE)
if (ENABLE_PEERPLAYS_ASSET_DEPOSITS)
message ("Depositing Peerplays assets enabled")
target_compile_definitions(peerplays_sidechain PRIVATE ENABLE_PEERPLAYS_ASSET_DEPOSITS)

View file

@ -177,12 +177,6 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt
}
config_ready_son = config_ready_son && !sons.empty();
#ifndef ENABLE_MULTIPLE_SONS
if (sons.size() > 1) {
FC_THROW("Invalid configuration, multiple SON IDs provided");
}
#endif
if (options.count("peerplays-private-key")) {
const std::vector<std::string> key_id_to_wif_pair_strings = options["peerplays-private-key"].as<std::vector<std::string>>();
for (const std::string &key_id_to_wif_pair_string : key_id_to_wif_pair_strings) {

View file

@ -589,7 +589,7 @@ void sidechain_net_handler::settle_sidechain_transactions() {
if (settle_amount.amount != 0) {
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
asset_issue_operation ai_op;
ai_op.fee = asset(2001000);
ai_op.fee = database.current_fee_schedule().calculate_fee(ai_op);
ai_op.issuer = gpo.parameters.son_account();
ai_op.asset_to_issue = settle_amount;
ai_op.issue_to_account = database.get<son_wallet_deposit_object>(sto.object_id).peerplays_from;
@ -598,7 +598,7 @@ void sidechain_net_handler::settle_sidechain_transactions() {
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
asset_reserve_operation ar_op;
ar_op.fee = asset(2001000);
ar_op.fee = database.current_fee_schedule().calculate_fee(ar_op);
ar_op.payer = gpo.parameters.son_account();
ar_op.amount_to_reserve = settle_amount;
proposal_op.proposed_ops.emplace_back(ar_op);

View file

@ -626,7 +626,7 @@ bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object
proposal_op.proposed_ops.emplace_back(swdp_op);
asset_issue_operation ai_op;
ai_op.fee = asset(2001000);
ai_op.fee = database.current_fee_schedule().calculate_fee(ai_op);
ai_op.issuer = gpo.parameters.son_account();
ai_op.asset_to_issue = asset_to_issue;
ai_op.issue_to_account = swdo.peerplays_from;

View file

@ -1346,6 +1346,21 @@ class wallet_api
*/
map<string, committee_member_id_type> list_committee_members(const string& lowerbound, uint32_t limit);
/** Lists all workers in the blockchain.
* This returns a list of all account names that own worker, and the associated worker id,
* sorted by name. This lists workers whether they are currently voted in or not.
*
* Use the \c lowerbound and limit parameters to page through the list. To retrieve all workers,
* start by setting \c lowerbound to the empty string \c "", and then each iteration, pass
* the last worker name returned as the \c lowerbound for the next \c list_workers() call.
*
* @param lowerbound the name of the first worker to return. If the named worker does not exist,
* the list will start at the worker that comes after \c lowerbound
* @param limit the maximum number of worker to return (max: 1000)
* @returns a list of worker mapping worker names to worker ids
*/
map<string, worker_id_type> list_workers(const string& lowerbound, uint32_t limit);
/** Returns information about the given SON.
* @param owner_account the name or id of the SON account owner, or the id of the SON
* @returns the information about the SON stored in the block chain
@ -1370,6 +1385,12 @@ class wallet_api
*/
committee_member_object get_committee_member(string owner_account);
/** Returns information about the given worker.
* @param owner_account the name or id of the worker account owner, or the id of the worker
* @returns the information about the workers stored in the block chain
*/
vector<worker_object> get_workers(string owner_account);
/** Creates a SON object owned by the given account.
*
@ -2490,9 +2511,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();
@ -2629,8 +2682,10 @@ FC_API( graphene::wallet::wallet_api,
(get_witness)
(is_witness)
(get_committee_member)
(get_workers)
(list_witnesses)
(list_committee_members)
(list_workers)
(create_son)
(try_create_son)
(update_son)
@ -2799,4 +2854,8 @@ FC_API( graphene::wallet::wallet_api,
(get_custom_account_authorities_by_permission_name)
(get_active_custom_account_authorities_by_operation)
(run_custom_operation)
(get_votes_ids)
(get_votes)
(get_voters_by_id)
(get_voters)
)

View file

@ -1954,7 +1954,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
@ -1969,6 +1969,49 @@ public:
FC_CAPTURE_AND_RETHROW( (owner_account) )
}
vector<worker_object> get_workers(string owner_account)
{
try
{
fc::optional<worker_id_type> worker_id = maybe_id<worker_id_type>(owner_account);
if (worker_id)
{
std::vector<worker_id_type> ids_to_get;
ids_to_get.push_back(*worker_id);
std::vector<fc::optional<worker_object>> worker_objects = _remote_db->get_workers(ids_to_get);
if(!worker_objects.empty()) {
std::vector<worker_object> result;
for (const auto &worker_object : worker_objects) {
if (worker_object)
result.emplace_back(*worker_object);
}
return result;
}
else
FC_THROW("No workers is registered for id ${id}", ("id", owner_account));
}
else
{
// then maybe it's the owner account
try
{
std::string owner_account_id = account_id_to_string(get_account_id(owner_account));
auto workers = _remote_db->get_workers_by_account(owner_account_id);
if (!workers.empty())
return workers;
else
FC_THROW("No workers is registered for account ${account}", ("account", owner_account));
}
catch (const fc::exception&)
{
FC_THROW("No account or worker named ${account}", ("account", owner_account));
}
}
}
FC_CAPTURE_AND_RETHROW( (owner_account) )
}
bool is_witness(string owner_account)
{
try
@ -2083,7 +2126,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;
@ -2720,7 +2763,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)
@ -2765,7 +2808,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);
@ -2775,7 +2818,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);
@ -4090,6 +4133,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;
@ -4999,6 +5078,11 @@ map<string,committee_member_id_type> wallet_api::list_committee_members(const st
return my->_remote_db->lookup_committee_member_accounts(lowerbound, limit);
}
map<string, worker_id_type> wallet_api::list_workers(const string& lowerbound, uint32_t limit)
{
return my->_remote_db->lookup_worker_accounts(lowerbound, limit);
}
son_object wallet_api::get_son(string owner_account)
{
return my->get_son(owner_account);
@ -5019,6 +5103,11 @@ committee_member_object wallet_api::get_committee_member(string owner_account)
return my->get_committee_member(owner_account);
}
vector<worker_object> wallet_api::get_workers(string owner_account)
{
return my->get_workers(owner_account);
}
signed_transaction wallet_api::create_vesting_balance(string owner_account,
string amount,
string asset_symbol,
@ -7617,6 +7706,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()
}