Merge branch 'feature/SONs-base' into SON212
This commit is contained in:
commit
ef2041a8fb
13 changed files with 167 additions and 23 deletions
|
|
@ -19,6 +19,7 @@ if( GRAPHENE_DISABLE_UNITY_BUILD )
|
||||||
db_maint.cpp
|
db_maint.cpp
|
||||||
db_management.cpp
|
db_management.cpp
|
||||||
db_market.cpp
|
db_market.cpp
|
||||||
|
db_sidechain.cpp
|
||||||
db_update.cpp
|
db_update.cpp
|
||||||
db_witness_schedule.cpp
|
db_witness_schedule.cpp
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include "db_maint.cpp"
|
#include "db_maint.cpp"
|
||||||
#include "db_management.cpp"
|
#include "db_management.cpp"
|
||||||
#include "db_market.cpp"
|
#include "db_market.cpp"
|
||||||
|
#include "db_sidechain.cpp"
|
||||||
#include "db_update.cpp"
|
#include "db_update.cpp"
|
||||||
#include "db_witness_schedule.cpp"
|
#include "db_witness_schedule.cpp"
|
||||||
#include "db_notify.cpp"
|
#include "db_notify.cpp"
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#include <graphene/chain/global_property_object.hpp>
|
#include <graphene/chain/global_property_object.hpp>
|
||||||
#include <graphene/chain/market_object.hpp>
|
#include <graphene/chain/market_object.hpp>
|
||||||
#include <graphene/chain/special_authority_object.hpp>
|
#include <graphene/chain/special_authority_object.hpp>
|
||||||
|
#include <graphene/chain/son_object.hpp>
|
||||||
#include <graphene/chain/vesting_balance_object.hpp>
|
#include <graphene/chain/vesting_balance_object.hpp>
|
||||||
#include <graphene/chain/vote_count.hpp>
|
#include <graphene/chain/vote_count.hpp>
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
|
|
@ -445,20 +446,49 @@ void database::update_active_sons()
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// Compare current and to-be lists of active sons
|
||||||
|
//const global_property_object& gpo = get_global_properties();
|
||||||
|
auto cur_active_sons = gpo.active_sons;
|
||||||
|
vector<son_info> new_active_sons;
|
||||||
|
for( const son_object& son : sons ) {
|
||||||
|
son_info swi;
|
||||||
|
swi.son_id = son.id;
|
||||||
|
swi.total_votes = son.total_votes;
|
||||||
|
swi.signing_key = son.signing_key;
|
||||||
|
swi.sidechain_public_keys = son.sidechain_public_keys;
|
||||||
|
new_active_sons.push_back(swi);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool son_sets_equal = (cur_active_sons.size() == new_active_sons.size());
|
||||||
|
if (son_sets_equal) {
|
||||||
|
for( size_t i = 0; i < cur_active_sons.size(); i++ ) {
|
||||||
|
son_sets_equal = son_sets_equal && cur_active_sons.at(i) == new_active_sons.at(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (son_sets_equal) {
|
||||||
|
ilog( "Active SONs set NOT CHANGED" );
|
||||||
|
} else {
|
||||||
|
ilog( "Active SONs set CHANGED" );
|
||||||
|
// Store new SON info, initiate wallet recreation and transfer of funds
|
||||||
|
}
|
||||||
|
|
||||||
modify(gpo, [&]( global_property_object& gp ){
|
modify(gpo, [&]( global_property_object& gp ){
|
||||||
gp.active_sons.clear();
|
gp.active_sons.clear();
|
||||||
gp.active_sons.reserve(sons.size());
|
gp.active_sons.reserve(new_active_sons.size());
|
||||||
std::transform(sons.begin(), sons.end(),
|
gp.active_sons.insert(gp.active_sons.end(), new_active_sons.begin(), new_active_sons.end());
|
||||||
std::inserter(gp.active_sons, gp.active_sons.end()),
|
|
||||||
[](const son_object& s) {
|
|
||||||
return s.id;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const son_schedule_object& sso = son_schedule_id_type()(*this);
|
const son_schedule_object& sso = son_schedule_id_type()(*this);
|
||||||
modify(sso, [&](son_schedule_object& _sso)
|
modify(sso, [&](son_schedule_object& _sso)
|
||||||
{
|
{
|
||||||
flat_set<son_id_type> active_sons(gpo.active_sons.begin(), gpo.active_sons.end());
|
flat_set<son_id_type> active_sons;
|
||||||
|
active_sons.reserve(gpo.active_sons.size());
|
||||||
|
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
|
||||||
|
std::inserter(active_sons, active_sons.end()),
|
||||||
|
[](const son_info& swi) {
|
||||||
|
return swi.son_id;
|
||||||
|
});
|
||||||
_sso.scheduler.update(active_sons);
|
_sso.scheduler.update(active_sons);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -472,19 +502,19 @@ void database::update_active_sons()
|
||||||
obj.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
|
obj.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
|
||||||
obj.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
|
obj.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
|
||||||
|
|
||||||
for( const auto& son_id : gpo.active_sons )
|
for( const auto& son_info : gpo.active_sons )
|
||||||
{
|
{
|
||||||
const son_object& son = get(son_id);
|
const son_object& son = get(son_info.son_id);
|
||||||
total_votes += _vote_tally_buffer[son.vote_id];
|
total_votes += _vote_tally_buffer[son.vote_id];
|
||||||
}
|
}
|
||||||
// total_votes is 64 bits. Subtract the number of leading low bits from 64 to get the number of useful bits,
|
// total_votes is 64 bits. Subtract the number of leading low bits from 64 to get the number of useful bits,
|
||||||
// then I want to keep the most significant 16 bits of what's left.
|
// then I want to keep the most significant 16 bits of what's left.
|
||||||
int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0);
|
int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0);
|
||||||
|
|
||||||
for( const auto& son_id : gpo.active_sons )
|
for( const auto& son_info : gpo.active_sons )
|
||||||
{
|
{
|
||||||
// Ensure that everyone has at least one vote. Zero weights aren't allowed.
|
// Ensure that everyone has at least one vote. Zero weights aren't allowed.
|
||||||
const son_object& son = get(son_id);
|
const son_object& son = get(son_info.son_id);
|
||||||
uint16_t votes = std::max((_vote_tally_buffer[son.vote_id] >> bits_to_drop), uint64_t(1) );
|
uint16_t votes = std::max((_vote_tally_buffer[son.vote_id] >> bits_to_drop), uint64_t(1) );
|
||||||
obj.active.account_auths[son.son_account] += votes;
|
obj.active.account_auths[son.son_account] += votes;
|
||||||
obj.active.weight_threshold += votes;
|
obj.active.weight_threshold += votes;
|
||||||
|
|
@ -503,18 +533,18 @@ void database::update_active_sons()
|
||||||
modify( get(gpo.parameters.get_son_btc_account_id()), [&]( account_object& obj )
|
modify( get(gpo.parameters.get_son_btc_account_id()), [&]( account_object& obj )
|
||||||
{
|
{
|
||||||
uint64_t total_votes = 0;
|
uint64_t total_votes = 0;
|
||||||
for( const auto& son_id : gpo.active_sons )
|
for( const auto& son_info : gpo.active_sons )
|
||||||
{
|
{
|
||||||
const son_object& son = get(son_id);
|
const son_object& son = get(son_info.son_id);
|
||||||
total_votes += _vote_tally_buffer[son.vote_id];
|
total_votes += _vote_tally_buffer[son.vote_id];
|
||||||
}
|
}
|
||||||
// total_votes is 64 bits. Subtract the number of leading low bits from 64 to get the number of useful bits,
|
// total_votes is 64 bits. Subtract the number of leading low bits from 64 to get the number of useful bits,
|
||||||
// then I want to keep the most significant 16 bits of what's left.
|
// then I want to keep the most significant 16 bits of what's left.
|
||||||
int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0);
|
int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0);
|
||||||
for( const auto& son_id : gpo.active_sons )
|
for( const auto& son_info : gpo.active_sons )
|
||||||
{
|
{
|
||||||
// Ensure that everyone has at least one vote. Zero weights aren't allowed.
|
// Ensure that everyone has at least one vote. Zero weights aren't allowed.
|
||||||
const son_object& son = get(son_id);
|
const son_object& son = get(son_info.son_id);
|
||||||
uint16_t votes = std::max((_vote_tally_buffer[son.vote_id] >> bits_to_drop), uint64_t(1) );
|
uint16_t votes = std::max((_vote_tally_buffer[son.vote_id] >> bits_to_drop), uint64_t(1) );
|
||||||
obj.active.account_auths[son.son_account] += votes;
|
obj.active.account_auths[son.son_account] += votes;
|
||||||
obj.active.weight_threshold += votes;
|
obj.active.weight_threshold += votes;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ database::database() :
|
||||||
{
|
{
|
||||||
initialize_indexes();
|
initialize_indexes();
|
||||||
initialize_evaluators();
|
initialize_evaluators();
|
||||||
|
initialize_db_sidechain();
|
||||||
}
|
}
|
||||||
|
|
||||||
database::~database()
|
database::~database()
|
||||||
|
|
|
||||||
10
libraries/chain/db_sidechain.cpp
Normal file
10
libraries/chain/db_sidechain.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include <graphene/chain/database.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
void database::initialize_db_sidechain()
|
||||||
|
{
|
||||||
|
recreate_primary_wallet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
#include <graphene/chain/witness_schedule_object.hpp>
|
#include <graphene/chain/witness_schedule_object.hpp>
|
||||||
#include <graphene/chain/son_object.hpp>
|
#include <graphene/chain/son_object.hpp>
|
||||||
|
#include <graphene/chain/son_info.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
@ -200,8 +201,8 @@ void database::update_son_schedule()
|
||||||
_sso.current_shuffled_sons.clear();
|
_sso.current_shuffled_sons.clear();
|
||||||
_sso.current_shuffled_sons.reserve( gpo.active_sons.size() );
|
_sso.current_shuffled_sons.reserve( gpo.active_sons.size() );
|
||||||
|
|
||||||
for( const son_id_type& w : gpo.active_sons )
|
for( const son_info& w : gpo.active_sons )
|
||||||
_sso.current_shuffled_sons.push_back( w );
|
_sso.current_shuffled_sons.push_back( w.son_id );
|
||||||
|
|
||||||
auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32;
|
auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32;
|
||||||
for( uint32_t i = 0; i < _sso.current_shuffled_sons.size(); ++i )
|
for( uint32_t i = 0; i < _sso.current_shuffled_sons.size(); ++i )
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@
|
||||||
|
|
||||||
#include <graphene/chain/protocol/protocol.hpp>
|
#include <graphene/chain/protocol/protocol.hpp>
|
||||||
|
|
||||||
|
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||||
|
|
||||||
#include <fc/log/logger.hpp>
|
#include <fc/log/logger.hpp>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
@ -600,6 +602,13 @@ namespace graphene { namespace chain {
|
||||||
* database::close() has not been called, or failed during execution.
|
* database::close() has not been called, or failed during execution.
|
||||||
*/
|
*/
|
||||||
bool _opened = false;
|
bool _opened = false;
|
||||||
|
|
||||||
|
/////////////////////// db_sidechain.cpp ////////////////////
|
||||||
|
public:
|
||||||
|
bool recreate_primary_wallet;
|
||||||
|
void initialize_db_sidechain();
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <graphene/chain/protocol/chain_parameters.hpp>
|
#include <graphene/chain/protocol/chain_parameters.hpp>
|
||||||
#include <graphene/chain/protocol/types.hpp>
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
|
#include <graphene/chain/son_info.hpp>
|
||||||
#include <graphene/db/object.hpp>
|
#include <graphene/db/object.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
@ -51,7 +52,7 @@ namespace graphene { namespace chain {
|
||||||
uint32_t next_available_vote_id = 0;
|
uint32_t next_available_vote_id = 0;
|
||||||
vector<committee_member_id_type> active_committee_members; // updated once per maintenance interval
|
vector<committee_member_id_type> active_committee_members; // updated once per maintenance interval
|
||||||
flat_set<witness_id_type> active_witnesses; // updated once per maintenance interval
|
flat_set<witness_id_type> active_witnesses; // updated once per maintenance interval
|
||||||
vector<son_id_type> active_sons; // updated once per maintenance interval
|
vector<son_info> active_sons; // updated once per maintenance interval
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ namespace graphene { namespace chain {
|
||||||
bet_object_type,
|
bet_object_type,
|
||||||
son_object_type,
|
son_object_type,
|
||||||
son_proposal_object_type,
|
son_proposal_object_type,
|
||||||
|
son_wallet_object_type,
|
||||||
sidechain_address_object_type,
|
sidechain_address_object_type,
|
||||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||||
};
|
};
|
||||||
|
|
@ -211,6 +212,7 @@ namespace graphene { namespace chain {
|
||||||
class bet_object;
|
class bet_object;
|
||||||
class son_object;
|
class son_object;
|
||||||
class son_proposal_object;
|
class son_proposal_object;
|
||||||
|
class son_wallet_object;
|
||||||
class sidechain_address_object;
|
class sidechain_address_object;
|
||||||
|
|
||||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||||
|
|
@ -240,6 +242,7 @@ namespace graphene { namespace chain {
|
||||||
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
|
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
|
||||||
typedef object_id< protocol_ids, son_object_type, son_object> son_id_type;
|
typedef object_id< protocol_ids, son_object_type, son_object> son_id_type;
|
||||||
typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type;
|
typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type;
|
||||||
|
typedef object_id< protocol_ids, son_wallet_object_type, son_wallet_object> son_wallet_id_type;
|
||||||
typedef object_id< protocol_ids, sidechain_address_object_type, sidechain_address_object> sidechain_address_id_type;
|
typedef object_id< protocol_ids, sidechain_address_object_type, sidechain_address_object> sidechain_address_id_type;
|
||||||
|
|
||||||
// implementation types
|
// implementation types
|
||||||
|
|
|
||||||
36
libraries/chain/include/graphene/chain/son_info.hpp
Normal file
36
libraries/chain/include/graphene/chain/son_info.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
using namespace graphene::db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class son_info
|
||||||
|
* @brief tracks information about a SON info required to re/create primary wallet
|
||||||
|
* @ingroup object
|
||||||
|
*/
|
||||||
|
struct son_info {
|
||||||
|
son_id_type son_id;
|
||||||
|
uint64_t total_votes = 0;
|
||||||
|
public_key_type signing_key;
|
||||||
|
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||||
|
|
||||||
|
bool operator==(const son_info& rhs) {
|
||||||
|
bool son_sets_equal =
|
||||||
|
(son_id == rhs.son_id) &&
|
||||||
|
(total_votes == rhs.total_votes) &&
|
||||||
|
(signing_key == rhs.signing_key) &&
|
||||||
|
(sidechain_public_keys.size() == rhs.sidechain_public_keys.size());
|
||||||
|
|
||||||
|
if (son_sets_equal) {
|
||||||
|
// Compare sidechain public keys
|
||||||
|
}
|
||||||
|
return son_sets_equal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::chain::son_info,
|
||||||
|
(son_id)(total_votes)(signing_key)(sidechain_public_keys) )
|
||||||
36
libraries/chain/include/graphene/chain/son_wallet_object.hpp
Normal file
36
libraries/chain/include/graphene/chain/son_wallet_object.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
using namespace graphene::db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class son_wallet_object
|
||||||
|
* @brief tracks information about a SON wallet.
|
||||||
|
* @ingroup object
|
||||||
|
*/
|
||||||
|
class son_wallet_object : public abstract_object<son_wallet_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = son_wallet_object_type;
|
||||||
|
|
||||||
|
flat_map<peerplays_sidechain::sidechain_type, string> addresses;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_sidechain_type;
|
||||||
|
struct by_address;
|
||||||
|
using son_wallet_multi_index_type = multi_index_container<
|
||||||
|
son_wallet_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique< tag<by_id>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
using son_wallet_index = generic_index<son_wallet_object, son_wallet_multi_index_type>;
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::chain::son_wallet_object, (graphene::db::object),
|
||||||
|
(addresses) )
|
||||||
|
|
@ -186,9 +186,17 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop()
|
||||||
chain::database& d = plugin.database();
|
chain::database& d = plugin.database();
|
||||||
chain::son_id_type son_id = *(_sons.begin());
|
chain::son_id_type son_id = *(_sons.begin());
|
||||||
const chain::global_property_object& gpo = d.get_global_properties();
|
const chain::global_property_object& gpo = d.get_global_properties();
|
||||||
auto it = std::find(gpo.active_sons.begin(), gpo.active_sons.end(), son_id);
|
vector<son_id_type> active_son_ids;
|
||||||
if(it != gpo.active_sons.end()) {
|
active_son_ids.reserve(gpo.active_sons.size());
|
||||||
ilog("peerplays_sidechain_plugin_impl: sending heartbeat");
|
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
|
||||||
|
std::inserter(active_son_ids, active_son_ids.end()),
|
||||||
|
[](const son_info& swi) {
|
||||||
|
return swi.son_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto it = std::find(active_son_ids.begin(), active_son_ids.end(), son_id);
|
||||||
|
if(it != active_son_ids.end()) {
|
||||||
|
ilog("peerplays_sidechain_plugin: sending heartbeat");
|
||||||
chain::son_heartbeat_operation op;
|
chain::son_heartbeat_operation op;
|
||||||
const auto& idx = d.get_index_type<chain::son_index>().indices().get<by_id>();
|
const auto& idx = d.get_index_type<chain::son_index>().indices().get<by_id>();
|
||||||
auto son_obj = idx.find( son_id );
|
auto son_obj = idx.find( son_id );
|
||||||
|
|
|
||||||
|
|
@ -1942,7 +1942,14 @@ public:
|
||||||
map<string, son_id_type> list_active_sons()
|
map<string, son_id_type> list_active_sons()
|
||||||
{ try {
|
{ try {
|
||||||
global_property_object gpo = get_global_properties();
|
global_property_object gpo = get_global_properties();
|
||||||
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(gpo.active_sons);
|
vector<son_id_type> son_ids;
|
||||||
|
son_ids.reserve(gpo.active_sons.size());
|
||||||
|
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
|
||||||
|
std::inserter(son_ids, son_ids.end()),
|
||||||
|
[](const son_info& swi) {
|
||||||
|
return swi.son_id;
|
||||||
|
});
|
||||||
|
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(son_ids);
|
||||||
vector<account_id_type> owners;
|
vector<account_id_type> owners;
|
||||||
owners.resize(son_objects.size());
|
owners.resize(son_objects.size());
|
||||||
std::transform(son_objects.begin(), son_objects.end(), owners.begin(),
|
std::transform(son_objects.begin(), son_objects.end(), owners.begin(),
|
||||||
|
|
@ -1952,7 +1959,7 @@ public:
|
||||||
});
|
});
|
||||||
vector<fc::optional<account_object>> accs = _remote_db->get_accounts(owners);
|
vector<fc::optional<account_object>> accs = _remote_db->get_accounts(owners);
|
||||||
map<string, son_id_type> result;
|
map<string, son_id_type> result;
|
||||||
std::transform(accs.begin(), accs.end(), gpo.active_sons.begin(),
|
std::transform(accs.begin(), accs.end(), son_ids.begin(),
|
||||||
std::inserter(result, result.end()),
|
std::inserter(result, result.end()),
|
||||||
[](fc::optional<account_object>& acct, son_id_type& sid) {
|
[](fc::optional<account_object>& acct, son_id_type& sid) {
|
||||||
FC_ASSERT(acct, "Invalid active SONs list in global properties.");
|
FC_ASSERT(acct, "Invalid active SONs list in global properties.");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue