Resolve conflicts
This commit is contained in:
commit
958429ce39
39 changed files with 1401 additions and 302 deletions
|
|
@ -14,7 +14,7 @@ add_library( graphene_app
|
|||
|
||||
# need to link graphene_debug_witness because plugins aren't sufficiently isolated #246
|
||||
#target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness )
|
||||
target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_accounts_list graphene_affiliate_stats graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities graphene_debug_witness graphene_bookie )
|
||||
target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_accounts_list graphene_affiliate_stats graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities graphene_debug_witness graphene_bookie peerplays_sidechain )
|
||||
target_include_directories( graphene_app
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" )
|
||||
|
|
|
|||
|
|
@ -443,6 +443,11 @@ namespace graphene { namespace app {
|
|||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->son_account );
|
||||
break;
|
||||
} case sidechain_address_object_type:{
|
||||
const auto& aobj = dynamic_cast<const sidechain_address_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->sidechain_address_account );
|
||||
break;
|
||||
}
|
||||
case sport_object_type:
|
||||
case event_group_object_type:
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
uint64_t get_asset_count()const;
|
||||
|
||||
// Peerplays
|
||||
vector<sport_object> list_sports() const;
|
||||
vector<sport_object> list_sports() const;
|
||||
vector<event_group_object> list_event_groups(sport_id_type sport_id) const;
|
||||
vector<event_object> list_events_in_group(event_group_id_type event_group_id) const;
|
||||
vector<betting_market_group_object> list_betting_market_groups(event_id_type) const;
|
||||
|
|
@ -115,14 +115,14 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
|
||||
unsigned limit = 100,
|
||||
asset_id_type start = asset_id_type() )const;
|
||||
vector<asset_object> get_account_lotteries( account_id_type issuer,
|
||||
vector<asset_object> get_account_lotteries( account_id_type issuer,
|
||||
asset_id_type stop,
|
||||
unsigned limit,
|
||||
asset_id_type start )const;
|
||||
asset get_lottery_balance( asset_id_type lottery_id )const;
|
||||
sweeps_vesting_balance_object get_sweeps_vesting_balance_object( account_id_type account )const;
|
||||
asset get_sweeps_vesting_balance_available_for_claim( account_id_type account )const;
|
||||
|
||||
|
||||
// Markets / feeds
|
||||
vector<limit_order_object> get_limit_orders(asset_id_type a, asset_id_type b, uint32_t limit)const;
|
||||
vector<call_order_object> get_call_orders(asset_id_type a, uint32_t limit)const;
|
||||
|
|
@ -152,6 +152,13 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
map<string, son_id_type> lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const;
|
||||
uint64_t get_son_count()const;
|
||||
|
||||
// Sidechain addresses
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const;
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_account(account_id_type account)const;
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_sidechain(peerplays_sidechain::sidechain_type sidechain)const;
|
||||
fc::optional<sidechain_address_object> get_sidechain_address_by_account_and_sidechain(account_id_type account, peerplays_sidechain::sidechain_type sidechain)const;
|
||||
uint64_t get_sidechain_addresses_count()const;
|
||||
|
||||
// Votes
|
||||
vector<variant> lookup_vote_ids( const vector<vote_id_type>& votes )const;
|
||||
|
||||
|
|
@ -528,11 +535,11 @@ vector<vector<account_id_type>> database_api::get_key_references( vector<public_
|
|||
vector<vector<account_id_type>> database_api_impl::get_key_references( vector<public_key_type> keys )const
|
||||
{
|
||||
wdump( (keys) );
|
||||
|
||||
|
||||
const auto& idx = _db.get_index_type<account_index>();
|
||||
const auto& aidx = dynamic_cast<const base_primary_index&>(idx);
|
||||
const auto& refs = aidx.get_secondary_index<graphene::chain::account_member_index>();
|
||||
|
||||
|
||||
vector< vector<account_id_type> > final_result;
|
||||
final_result.reserve(keys.size());
|
||||
|
||||
|
|
@ -648,7 +655,7 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
|
|||
const auto& proposal_idx = _db.get_index_type<proposal_index>();
|
||||
const auto& pidx = dynamic_cast<const base_primary_index&>(proposal_idx);
|
||||
const auto& proposals_by_account = pidx.get_secondary_index<graphene::chain::required_approval_index>();
|
||||
|
||||
|
||||
std::map<std::string, full_account> results;
|
||||
|
||||
for (const std::string& account_name_or_id : names_or_ids)
|
||||
|
|
@ -738,7 +745,7 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
|
|||
acnt.withdraws.emplace_back(withdraw);
|
||||
});
|
||||
|
||||
auto pending_payouts_range =
|
||||
auto pending_payouts_range =
|
||||
_db.get_index_type<pending_dividend_payout_balance_for_holder_object_index>().indices().get<by_account_dividend_payout>().equal_range(boost::make_tuple(account->id));
|
||||
|
||||
std::copy(pending_payouts_range.first, pending_payouts_range.second, std::back_inserter(acnt.pending_dividend_payments));
|
||||
|
|
@ -1058,7 +1065,7 @@ vector<asset_object> database_api_impl::get_lotteries( asset_id_type stop,
|
|||
|
||||
return result;
|
||||
}
|
||||
vector<asset_object> database_api::get_account_lotteries( account_id_type issuer,
|
||||
vector<asset_object> database_api::get_account_lotteries( account_id_type issuer,
|
||||
asset_id_type stop,
|
||||
unsigned limit,
|
||||
asset_id_type start )const
|
||||
|
|
@ -1066,7 +1073,7 @@ vector<asset_object> database_api::get_account_lotteries( account_id_type issuer
|
|||
return my->get_account_lotteries( issuer, stop, limit, start );
|
||||
}
|
||||
|
||||
vector<asset_object> database_api_impl::get_account_lotteries( account_id_type issuer,
|
||||
vector<asset_object> database_api_impl::get_account_lotteries( account_id_type issuer,
|
||||
asset_id_type stop,
|
||||
unsigned limit,
|
||||
asset_id_type start )const
|
||||
|
|
@ -1763,6 +1770,85 @@ uint64_t database_api_impl::get_son_count()const
|
|||
return _db.get_index_type<son_index>().indices().size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Sidechain Accounts //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<optional<sidechain_address_object>> database_api::get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const
|
||||
{
|
||||
return my->get_sidechain_addresses( sidechain_address_ids );
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const
|
||||
{
|
||||
vector<optional<sidechain_address_object>> result; result.reserve(sidechain_address_ids.size());
|
||||
std::transform(sidechain_address_ids.begin(), sidechain_address_ids.end(), std::back_inserter(result),
|
||||
[this](sidechain_address_id_type id) -> optional<sidechain_address_object> {
|
||||
if(auto o = _db.find(id))
|
||||
return *o;
|
||||
return {};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> database_api::get_sidechain_addresses_by_account(account_id_type account)const
|
||||
{
|
||||
return my->get_sidechain_addresses_by_account( account );
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addresses_by_account(account_id_type account)const
|
||||
{
|
||||
vector<optional<sidechain_address_object>> result;
|
||||
const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_account>().equal_range(account);
|
||||
std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second,
|
||||
[&result] (const sidechain_address_object& sao) {
|
||||
result.push_back(sao);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> database_api::get_sidechain_addresses_by_sidechain(peerplays_sidechain::sidechain_type sidechain)const
|
||||
{
|
||||
return my->get_sidechain_addresses_by_sidechain( sidechain );
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> database_api_impl::get_sidechain_addresses_by_sidechain(peerplays_sidechain::sidechain_type sidechain)const
|
||||
{
|
||||
vector<optional<sidechain_address_object>> result;
|
||||
const auto& sidechain_addresses_range = _db.get_index_type<sidechain_address_index>().indices().get<by_sidechain>().equal_range(sidechain);
|
||||
std::for_each(sidechain_addresses_range.first, sidechain_addresses_range.second,
|
||||
[&result] (const sidechain_address_object& sao) {
|
||||
result.push_back(sao);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
fc::optional<sidechain_address_object> database_api::get_sidechain_address_by_account_and_sidechain(account_id_type account, peerplays_sidechain::sidechain_type sidechain)const
|
||||
{
|
||||
return my->get_sidechain_address_by_account_and_sidechain( account, sidechain );
|
||||
}
|
||||
|
||||
fc::optional<sidechain_address_object> database_api_impl::get_sidechain_address_by_account_and_sidechain(account_id_type account, peerplays_sidechain::sidechain_type sidechain)const
|
||||
{
|
||||
const auto& idx = _db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>();
|
||||
auto itr = idx.find( boost::make_tuple( account, sidechain ) );
|
||||
if( itr != idx.end() )
|
||||
return *itr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t database_api::get_sidechain_addresses_count()const
|
||||
{
|
||||
return my->get_sidechain_addresses_count();
|
||||
}
|
||||
|
||||
uint64_t database_api_impl::get_sidechain_addresses_count()const
|
||||
{
|
||||
return _db.get_index_type<sidechain_address_index>().indices().size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Votes //
|
||||
|
|
@ -2164,7 +2250,7 @@ vector<tournament_object> database_api::get_tournaments(tournament_id_type stop,
|
|||
|
||||
vector<tournament_object> database_api_impl::get_tournaments(tournament_id_type stop,
|
||||
unsigned limit,
|
||||
tournament_id_type start)
|
||||
tournament_id_type start)
|
||||
{
|
||||
vector<tournament_object> result;
|
||||
const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>();
|
||||
|
|
@ -2191,7 +2277,7 @@ vector<tournament_object> database_api_impl::get_tournaments_by_state(tournament
|
|||
unsigned limit,
|
||||
tournament_id_type start,
|
||||
tournament_state state)
|
||||
{
|
||||
{
|
||||
vector<tournament_object> result;
|
||||
const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>();
|
||||
for (auto elem: tournament_idx) {
|
||||
|
|
@ -2320,7 +2406,7 @@ void database_api_impl::handle_object_changed(bool force_notify, bool full_objec
|
|||
/// if a connection hangs then this could get backed up and result in
|
||||
/// a failure to exit cleanly.
|
||||
//fc::async([capture_this,this,updates,market_broadcast_queue](){
|
||||
//if( _subscribe_callback )
|
||||
//if( _subscribe_callback )
|
||||
// _subscribe_callback( updates );
|
||||
|
||||
for(auto id : ids)
|
||||
|
|
|
|||
|
|
@ -310,6 +310,15 @@ struct get_impacted_account_visitor
|
|||
void operator()( const son_heartbeat_operation& op ){
|
||||
_impacted.insert( op.owner_account );
|
||||
}
|
||||
void operator()( const sidechain_address_add_operation& op ){
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
void operator()( const sidechain_address_update_operation& op ){
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
void operator()( const sidechain_address_delete_operation& op ){
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
};
|
||||
|
||||
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include <graphene/chain/betting_market_object.hpp>
|
||||
#include <graphene/chain/global_betting_statistics_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
|
||||
#include <graphene/chain/worker_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
|
|
@ -602,6 +603,46 @@ class database_api
|
|||
*/
|
||||
uint64_t get_son_count()const;
|
||||
|
||||
/////////////////////////
|
||||
// Sidechain Addresses //
|
||||
/////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Get a list of sidechain addresses
|
||||
* @param sidechain_address_ids IDs of the sidechain addresses to retrieve
|
||||
* @return The sidechain accounts corresponding to the provided IDs
|
||||
*
|
||||
* This function has semantics identical to @ref get_objects
|
||||
*/
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses(const vector<sidechain_address_id_type>& sidechain_address_ids)const;
|
||||
|
||||
/**
|
||||
* @brief Get the sidechain addresses for a given account
|
||||
* @param account The ID of the account whose sidechain addresses should be retrieved
|
||||
* @return The sidechain addresses objects, or null if the account does not have a sidechain addresses
|
||||
*/
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_account(account_id_type account)const;
|
||||
|
||||
/**
|
||||
* @brief Get the sidechain addresses for a given sidechain
|
||||
* @param sidechain Sidechain for which addresses should be retrieved
|
||||
* @return The sidechain addresses objects, or null if the sidechain does not have any addresses
|
||||
*/
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_sidechain(peerplays_sidechain::sidechain_type sidechain)const;
|
||||
|
||||
/**
|
||||
* @brief Get the sidechain addresses for a given account and sidechain
|
||||
* @param account The ID of the account whose sidechain addresses should be retrieved
|
||||
* @param sidechain Sidechain for which address should be retrieved
|
||||
* @return The sidechain addresses objects, or null if the account does not have a sidechain addresses for a given sidechain
|
||||
*/
|
||||
fc::optional<sidechain_address_object> get_sidechain_address_by_account_and_sidechain(account_id_type account, peerplays_sidechain::sidechain_type sidechain)const;
|
||||
|
||||
/**
|
||||
* @brief Get the total number of sidechain addresses registered with the blockchain
|
||||
*/
|
||||
uint64_t get_sidechain_addresses_count()const;
|
||||
|
||||
/// WORKERS
|
||||
|
||||
/**
|
||||
|
|
@ -814,6 +855,13 @@ FC_API(graphene::app::database_api,
|
|||
(lookup_son_accounts)
|
||||
(get_son_count)
|
||||
|
||||
// Sidechain addresses
|
||||
(get_sidechain_addresses)
|
||||
(get_sidechain_addresses_by_account)
|
||||
(get_sidechain_addresses_by_sidechain)
|
||||
(get_sidechain_address_by_account_and_sidechain)
|
||||
(get_sidechain_addresses_count)
|
||||
|
||||
// workers
|
||||
(get_workers_by_account)
|
||||
// Votes
|
||||
|
|
|
|||
|
|
@ -116,13 +116,15 @@ add_library( graphene_chain
|
|||
son_evaluator.cpp
|
||||
son_object.cpp
|
||||
|
||||
sidechain_address_evaluator.cpp
|
||||
|
||||
${HEADERS}
|
||||
${PROTOCOL_HEADERS}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp"
|
||||
)
|
||||
|
||||
add_dependencies( graphene_chain build_hardfork_hpp )
|
||||
target_link_libraries( graphene_chain fc graphene_db )
|
||||
target_link_libraries( graphene_chain fc graphene_db peerplays_sidechain )
|
||||
target_include_directories( graphene_chain
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -649,8 +649,13 @@ void database::_apply_block( const signed_block& next_block )
|
|||
_current_virtual_op = 0;
|
||||
}
|
||||
|
||||
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM)
|
||||
update_witness_schedule(next_block);
|
||||
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM) {
|
||||
update_witness_schedule(next_block);
|
||||
if(global_props.active_sons.size() > 0) {
|
||||
update_son_schedule(next_block);
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t missed = update_witness_missed_blocks( next_block );
|
||||
update_global_dynamic_data( next_block, missed );
|
||||
update_signing_witness(signing_witness, next_block);
|
||||
|
|
@ -678,8 +683,13 @@ void database::_apply_block( const signed_block& next_block )
|
|||
// update_global_dynamic_data() as perhaps these methods only need
|
||||
// to be called for header validation?
|
||||
update_maintenance_flag( maint_needed );
|
||||
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM)
|
||||
update_witness_schedule();
|
||||
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM) {
|
||||
update_witness_schedule();
|
||||
if(global_props.active_sons.size() > 0) {
|
||||
update_son_schedule();
|
||||
}
|
||||
}
|
||||
|
||||
if( !_node_property_object.debug_updates.empty() )
|
||||
apply_debug_updates();
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include <graphene/chain/global_betting_statistics_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/son_proposal_object.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
|
||||
#include <graphene/chain/account_evaluator.hpp>
|
||||
#include <graphene/chain/asset_evaluator.hpp>
|
||||
|
|
@ -78,6 +79,7 @@
|
|||
#include <graphene/chain/betting_market_evaluator.hpp>
|
||||
#include <graphene/chain/tournament_evaluator.hpp>
|
||||
#include <graphene/chain/son_evaluator.hpp>
|
||||
#include <graphene/chain/sidechain_address_evaluator.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
|
|
@ -248,6 +250,9 @@ void database::initialize_evaluators()
|
|||
register_evaluator<update_son_evaluator>();
|
||||
register_evaluator<delete_son_evaluator>();
|
||||
register_evaluator<son_heartbeat_evaluator>();
|
||||
register_evaluator<add_sidechain_address_evaluator>();
|
||||
register_evaluator<update_sidechain_address_evaluator>();
|
||||
register_evaluator<delete_sidechain_address_evaluator>();
|
||||
}
|
||||
|
||||
void database::initialize_indexes()
|
||||
|
|
@ -292,6 +297,8 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<game_index> >();
|
||||
add_index< primary_index<son_proposal_index> >();
|
||||
|
||||
add_index< primary_index<sidechain_address_index> >();
|
||||
|
||||
//Implementation object indexes
|
||||
add_index< primary_index<transaction_index > >();
|
||||
|
||||
|
|
@ -307,6 +314,7 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<flat_index< block_summary_object >> >();
|
||||
add_index< primary_index<simple_index<chain_property_object > > >();
|
||||
add_index< primary_index<simple_index<witness_schedule_object > > >();
|
||||
add_index< primary_index<simple_index<son_schedule_object > > >();
|
||||
add_index< primary_index<simple_index<budget_record_object > > >();
|
||||
add_index< primary_index< special_authority_index > >();
|
||||
add_index< primary_index< buyback_index > >();
|
||||
|
|
@ -940,6 +948,29 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
});
|
||||
assert( wso.id == witness_schedule_id_type() );
|
||||
|
||||
// Initialize witness schedule
|
||||
#ifndef NDEBUG
|
||||
const son_schedule_object& sso =
|
||||
#endif
|
||||
create<son_schedule_object>([&](son_schedule_object& _sso)
|
||||
{
|
||||
// for scheduled
|
||||
memset(_sso.rng_seed.begin(), 0, _sso.rng_seed.size());
|
||||
|
||||
witness_scheduler_rng rng(_sso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
|
||||
|
||||
auto init_witnesses = get_global_properties().active_witnesses;
|
||||
|
||||
_sso.scheduler = son_scheduler();
|
||||
_sso.scheduler._min_token_count = std::max(int(init_witnesses.size()) / 2, 1);
|
||||
|
||||
|
||||
_sso.last_scheduling_block = 0;
|
||||
|
||||
_sso.recent_slots_filled = fc::uint128::max_value();
|
||||
});
|
||||
assert( sso.id == son_schedule_id_type() );
|
||||
|
||||
// Enable fees
|
||||
modify(get_global_properties(), [&genesis_state](global_property_object& p) {
|
||||
p.parameters.current_fees = genesis_state.initial_parameters.current_fees;
|
||||
|
|
|
|||
|
|
@ -455,11 +455,12 @@ void database::update_active_sons()
|
|||
});
|
||||
});
|
||||
|
||||
//const witness_schedule_object& wso = witness_schedule_id_type()(*this);
|
||||
//modify(wso, [&](witness_schedule_object& _wso)
|
||||
//{
|
||||
// _wso.scheduler.update(gpo.active_witnesses);
|
||||
//});
|
||||
const son_schedule_object& sso = son_schedule_id_type()(*this);
|
||||
modify(sso, [&](son_schedule_object& _sso)
|
||||
{
|
||||
flat_set<son_id_type> active_sons(gpo.active_sons.begin(), gpo.active_sons.end());
|
||||
_sso.scheduler.update(active_sons);
|
||||
});
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const
|
||||
|
|
|
|||
|
|
@ -297,6 +297,15 @@ struct get_impacted_account_visitor
|
|||
void operator()( const son_heartbeat_operation& op ) {
|
||||
_impacted.insert( op.owner_account );
|
||||
}
|
||||
void operator()( const sidechain_address_add_operation& op ) {
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
void operator()( const sidechain_address_update_operation& op ) {
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
void operator()( const sidechain_address_delete_operation& op ) {
|
||||
_impacted.insert( op.sidechain_address_account );
|
||||
}
|
||||
};
|
||||
|
||||
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||
|
|
@ -390,6 +399,11 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
|
|||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->son_account );
|
||||
break;
|
||||
} case sidechain_address_object_type:{
|
||||
const auto& aobj = dynamic_cast<const sidechain_address_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->sidechain_address_account );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/witness_schedule_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -72,6 +73,47 @@ witness_id_type database::get_scheduled_witness( uint32_t slot_num )const
|
|||
return wid;
|
||||
}
|
||||
|
||||
son_id_type database::get_scheduled_son( uint32_t slot_num )const
|
||||
{
|
||||
son_id_type sid;
|
||||
const global_property_object& gpo = get_global_properties();
|
||||
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM)
|
||||
{
|
||||
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
|
||||
const son_schedule_object& sso = son_schedule_id_type()(*this);
|
||||
uint64_t current_aslot = dpo.current_aslot + slot_num;
|
||||
return sso.current_shuffled_sons[ current_aslot % sso.current_shuffled_sons.size() ];
|
||||
}
|
||||
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM &&
|
||||
slot_num != 0 )
|
||||
{
|
||||
const son_schedule_object& sso = son_schedule_id_type()(*this);
|
||||
// ask the near scheduler who goes in the given slot
|
||||
bool slot_is_near = sso.scheduler.get_slot(slot_num-1, sid);
|
||||
if(! slot_is_near)
|
||||
{
|
||||
// if the near scheduler doesn't know, we have to extend it to
|
||||
// a far scheduler.
|
||||
// n.b. instantiating it is slow, but block gaps long enough to
|
||||
// need it are likely pretty rare.
|
||||
|
||||
witness_scheduler_rng far_rng(sso.rng_seed.begin(), GRAPHENE_FAR_SCHEDULE_CTR_IV);
|
||||
|
||||
far_future_son_scheduler far_scheduler =
|
||||
far_future_son_scheduler(sso.scheduler, far_rng);
|
||||
if(!far_scheduler.get_slot(slot_num-1, sid))
|
||||
{
|
||||
// no scheduled son -- somebody set up us the bomb
|
||||
// n.b. this code path is impossible, the present
|
||||
// implementation of far_future_son_scheduler
|
||||
// returns true unconditionally
|
||||
assert( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
return sid;
|
||||
}
|
||||
|
||||
fc::time_point_sec database::get_slot_time(uint32_t slot_num)const
|
||||
{
|
||||
if( slot_num == 0 )
|
||||
|
|
@ -146,6 +188,41 @@ void database::update_witness_schedule()
|
|||
}
|
||||
}
|
||||
|
||||
void database::update_son_schedule()
|
||||
{
|
||||
const son_schedule_object& sso = son_schedule_id_type()(*this);
|
||||
const global_property_object& gpo = get_global_properties();
|
||||
|
||||
if( head_block_num() % gpo.active_sons.size() == 0 )
|
||||
{
|
||||
modify( sso, [&]( son_schedule_object& _sso )
|
||||
{
|
||||
_sso.current_shuffled_sons.clear();
|
||||
_sso.current_shuffled_sons.reserve( gpo.active_sons.size() );
|
||||
|
||||
for( const son_id_type& w : gpo.active_sons )
|
||||
_sso.current_shuffled_sons.push_back( w );
|
||||
|
||||
auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32;
|
||||
for( uint32_t i = 0; i < _sso.current_shuffled_sons.size(); ++i )
|
||||
{
|
||||
/// High performance random generator
|
||||
/// http://xorshift.di.unimi.it/
|
||||
uint64_t k = now_hi + uint64_t(i)*2685821657736338717ULL;
|
||||
k ^= (k >> 12);
|
||||
k ^= (k << 25);
|
||||
k ^= (k >> 27);
|
||||
k *= 2685821657736338717ULL;
|
||||
|
||||
uint32_t jmax = _sso.current_shuffled_sons.size() - i;
|
||||
uint32_t j = i + k%jmax;
|
||||
std::swap( _sso.current_shuffled_sons[i],
|
||||
_sso.current_shuffled_sons[j] );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
vector<witness_id_type> database::get_near_witness_schedule()const
|
||||
{
|
||||
const witness_schedule_object& wso = witness_schedule_id_type()(*this);
|
||||
|
|
@ -226,6 +303,71 @@ void database::update_witness_schedule(const signed_block& next_block)
|
|||
idump( ( double(total_time/1000000.0)/calls) );
|
||||
}
|
||||
|
||||
void database::update_son_schedule(const signed_block& next_block)
|
||||
{
|
||||
auto start = fc::time_point::now();
|
||||
const global_property_object& gpo = get_global_properties();
|
||||
const son_schedule_object& sso = get(son_schedule_id_type());
|
||||
uint32_t schedule_needs_filled = gpo.active_sons.size();
|
||||
uint32_t schedule_slot = get_slot_at_time(next_block.timestamp);
|
||||
|
||||
// We shouldn't be able to generate _pending_block with timestamp
|
||||
// in the past, and incoming blocks from the network with timestamp
|
||||
// in the past shouldn't be able to make it this far without
|
||||
// triggering FC_ASSERT elsewhere
|
||||
|
||||
assert( schedule_slot > 0 );
|
||||
|
||||
son_id_type first_son;
|
||||
bool slot_is_near = sso.scheduler.get_slot( schedule_slot-1, first_son );
|
||||
|
||||
son_id_type son;
|
||||
|
||||
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
|
||||
|
||||
assert( dpo.random.data_size() == witness_scheduler_rng::seed_length );
|
||||
assert( witness_scheduler_rng::seed_length == sso.rng_seed.size() );
|
||||
|
||||
modify(sso, [&](son_schedule_object& _sso)
|
||||
{
|
||||
_sso.slots_since_genesis += schedule_slot;
|
||||
witness_scheduler_rng rng(sso.rng_seed.data, _sso.slots_since_genesis);
|
||||
|
||||
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.size()) / 2, 1);
|
||||
|
||||
if( slot_is_near )
|
||||
{
|
||||
uint32_t drain = schedule_slot;
|
||||
while( drain > 0 )
|
||||
{
|
||||
if( _sso.scheduler.size() == 0 )
|
||||
break;
|
||||
_sso.scheduler.consume_schedule();
|
||||
--drain;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_sso.scheduler.reset_schedule( first_son );
|
||||
}
|
||||
while( !_sso.scheduler.get_slot(schedule_needs_filled, son) )
|
||||
{
|
||||
if( _sso.scheduler.produce_schedule(rng) & emit_turn )
|
||||
memcpy(_sso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
|
||||
}
|
||||
_sso.last_scheduling_block = next_block.block_num();
|
||||
_sso.recent_slots_filled = (
|
||||
(_sso.recent_slots_filled << 1)
|
||||
+ 1) << (schedule_slot - 1);
|
||||
});
|
||||
auto end = fc::time_point::now();
|
||||
static uint64_t total_time = 0;
|
||||
static uint64_t calls = 0;
|
||||
total_time += (end - start).count();
|
||||
if( ++calls % 1000 == 0 )
|
||||
idump( ( double(total_time/1000000.0)/calls) );
|
||||
}
|
||||
|
||||
uint32_t database::update_witness_missed_blocks( const signed_block& b )
|
||||
{
|
||||
uint32_t missed_blocks = get_slot_at_time( b.timestamp );
|
||||
|
|
|
|||
|
|
@ -240,6 +240,22 @@ namespace graphene { namespace chain {
|
|||
*/
|
||||
witness_id_type get_scheduled_witness(uint32_t slot_num)const;
|
||||
|
||||
/**
|
||||
* @brief Get the son scheduled for block production in a slot.
|
||||
*
|
||||
* slot_num always corresponds to a time in the future.
|
||||
*
|
||||
* If slot_num == 1, returns the next scheduled son.
|
||||
* If slot_num == 2, returns the next scheduled son after
|
||||
* 1 block gap.
|
||||
*
|
||||
* Use the get_slot_time() and get_slot_at_time() functions
|
||||
* to convert between slot_num and timestamp.
|
||||
*
|
||||
* Passing slot_num == 0 returns GRAPHENE_NULL_WITNESS
|
||||
*/
|
||||
son_id_type get_scheduled_son(uint32_t slot_num)const;
|
||||
|
||||
/**
|
||||
* Get the time at which the given slot occurs.
|
||||
*
|
||||
|
|
@ -263,6 +279,8 @@ namespace graphene { namespace chain {
|
|||
vector<witness_id_type> get_near_witness_schedule()const;
|
||||
void update_witness_schedule();
|
||||
void update_witness_schedule(const signed_block& next_block);
|
||||
void update_son_schedule();
|
||||
void update_son_schedule(const signed_block& next_block);
|
||||
|
||||
void check_lottery_end_by_participants( asset_id_type asset_id );
|
||||
void check_ending_lotteries();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include <graphene/chain/protocol/betting_market.hpp>
|
||||
#include <graphene/chain/protocol/tournament.hpp>
|
||||
#include <graphene/chain/protocol/son.hpp>
|
||||
#include <graphene/chain/protocol/sidechain_address.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -140,7 +141,10 @@ namespace graphene { namespace chain {
|
|||
son_create_operation,
|
||||
son_update_operation,
|
||||
son_delete_operation,
|
||||
son_heartbeat_operation
|
||||
son_heartbeat_operation,
|
||||
sidechain_address_add_operation,
|
||||
sidechain_address_update_operation,
|
||||
sidechain_address_delete_operation
|
||||
> operation;
|
||||
|
||||
/// @} // operations group
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct sidechain_address_add_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
account_id_type sidechain_address_account;
|
||||
graphene::peerplays_sidechain::sidechain_type sidechain;
|
||||
string address;
|
||||
string private_key;
|
||||
string public_key;
|
||||
|
||||
account_id_type fee_payer()const { return sidechain_address_account; }
|
||||
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||
};
|
||||
|
||||
struct sidechain_address_update_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
sidechain_address_id_type sidechain_address_id;
|
||||
account_id_type sidechain_address_account;
|
||||
graphene::peerplays_sidechain::sidechain_type sidechain;
|
||||
optional<string> address;
|
||||
optional<string> private_key;
|
||||
optional<string> public_key;
|
||||
|
||||
account_id_type fee_payer()const { return sidechain_address_account; }
|
||||
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||
};
|
||||
|
||||
struct sidechain_address_delete_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
sidechain_address_id_type sidechain_address_id;
|
||||
account_id_type sidechain_address_account;
|
||||
graphene::peerplays_sidechain::sidechain_type sidechain;
|
||||
|
||||
account_id_type fee_payer()const { return sidechain_address_account; }
|
||||
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||
};
|
||||
|
||||
} } // namespace graphene::chain
|
||||
|
||||
FC_REFLECT(graphene::chain::sidechain_address_add_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::sidechain_address_add_operation, (fee)
|
||||
(sidechain_address_account)(sidechain)(address)(private_key)(public_key) )
|
||||
|
||||
FC_REFLECT(graphene::chain::sidechain_address_update_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::sidechain_address_update_operation, (fee)
|
||||
(sidechain_address_id)
|
||||
(sidechain_address_account)(sidechain)(address)(private_key)(public_key) )
|
||||
|
||||
FC_REFLECT(graphene::chain::sidechain_address_delete_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::sidechain_address_delete_operation, (fee)
|
||||
(sidechain_address_id)
|
||||
(sidechain_address_account)(sidechain) )
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -12,6 +13,7 @@ namespace graphene { namespace chain {
|
|||
std::string url;
|
||||
vesting_balance_id_type deposit;
|
||||
public_key_type signing_key;
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
vesting_balance_id_type pay_vb;
|
||||
|
||||
account_id_type fee_payer()const { return owner_account; }
|
||||
|
|
@ -28,6 +30,7 @@ namespace graphene { namespace chain {
|
|||
optional<std::string> new_url;
|
||||
optional<vesting_balance_id_type> new_deposit;
|
||||
optional<public_key_type> new_signing_key;
|
||||
optional<flat_map<peerplays_sidechain::sidechain_type, string>> new_sidechain_public_keys;
|
||||
optional<vesting_balance_id_type> new_pay_vb;
|
||||
|
||||
account_id_type fee_payer()const { return owner_account; }
|
||||
|
|
@ -63,12 +66,12 @@ namespace graphene { namespace chain {
|
|||
} } // namespace graphene::chain
|
||||
|
||||
FC_REFLECT(graphene::chain::son_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::son_create_operation, (fee)(owner_account)(url)(deposit)(signing_key)
|
||||
FC_REFLECT(graphene::chain::son_create_operation, (fee)(owner_account)(url)(deposit)(signing_key)(sidechain_public_keys)
|
||||
(pay_vb) )
|
||||
|
||||
FC_REFLECT(graphene::chain::son_update_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::son_update_operation, (fee)(son_id)(owner_account)(new_url)(new_deposit)
|
||||
(new_signing_key)(new_pay_vb) )
|
||||
(new_signing_key)(new_sidechain_public_keys)(new_pay_vb) )
|
||||
|
||||
FC_REFLECT(graphene::chain::son_delete_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT(graphene::chain::son_delete_operation, (fee)(son_id)(payer)(owner_account) )
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ namespace graphene { namespace chain {
|
|||
bet_object_type,
|
||||
son_object_type,
|
||||
son_proposal_object_type,
|
||||
sidechain_address_object_type,
|
||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||
};
|
||||
|
||||
|
|
@ -176,7 +177,8 @@ namespace graphene { namespace chain {
|
|||
impl_global_betting_statistics_object_type,
|
||||
impl_lottery_balance_object_type,
|
||||
impl_sweeps_vesting_balance_object_type,
|
||||
impl_son_statistics_object_type
|
||||
impl_son_statistics_object_type,
|
||||
impl_son_schedule_object_type
|
||||
};
|
||||
|
||||
//typedef fc::unsigned_int object_id_type;
|
||||
|
|
@ -209,6 +211,7 @@ namespace graphene { namespace chain {
|
|||
class bet_object;
|
||||
class son_object;
|
||||
class son_proposal_object;
|
||||
class sidechain_address_object;
|
||||
|
||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
||||
|
|
@ -237,6 +240,7 @@ namespace graphene { namespace chain {
|
|||
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_proposal_object_type, son_proposal_object> son_proposal_id_type;
|
||||
typedef object_id< protocol_ids, sidechain_address_object_type, sidechain_address_object> sidechain_address_id_type;
|
||||
|
||||
// implementation types
|
||||
class global_property_object;
|
||||
|
|
@ -261,6 +265,7 @@ namespace graphene { namespace chain {
|
|||
class lottery_balance_object;
|
||||
class sweeps_vesting_balance_object;
|
||||
class son_statistics_object;
|
||||
class son_schedule_object;
|
||||
|
||||
typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type;
|
||||
typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type;
|
||||
|
|
@ -290,6 +295,7 @@ namespace graphene { namespace chain {
|
|||
typedef object_id< implementation_ids, impl_lottery_balance_object_type, lottery_balance_object > lottery_balance_id_type;
|
||||
typedef object_id< implementation_ids, impl_sweeps_vesting_balance_object_type, sweeps_vesting_balance_object> sweeps_vesting_balance_id_type;
|
||||
typedef object_id< implementation_ids, impl_son_statistics_object_type, son_statistics_object > son_statistics_id_type;
|
||||
typedef object_id< implementation_ids, impl_son_schedule_object_type, son_schedule_object> son_schedule_id_type;
|
||||
|
||||
typedef fc::array<char, GRAPHENE_MAX_ASSET_SYMBOL_LENGTH> symbol_type;
|
||||
typedef fc::ripemd160 block_id_type;
|
||||
|
|
@ -421,6 +427,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
|||
(bet_object_type)
|
||||
(son_object_type)
|
||||
(son_proposal_object_type)
|
||||
(sidechain_address_object_type)
|
||||
(OBJECT_TYPE_COUNT)
|
||||
)
|
||||
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||
|
|
@ -449,6 +456,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
|||
(impl_lottery_balance_object_type)
|
||||
(impl_sweeps_vesting_balance_object_type)
|
||||
(impl_son_statistics_object_type)
|
||||
(impl_son_schedule_object_type)
|
||||
)
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::share_type )
|
||||
|
|
@ -493,6 +501,7 @@ FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
|
|||
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_proposal_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::sidechain_address_id_type )
|
||||
|
||||
|
||||
FC_REFLECT( graphene::chain::void_t, )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/protocol/sidechain_address.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class add_sidechain_address_evaluator : public evaluator<add_sidechain_address_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef sidechain_address_add_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const sidechain_address_add_operation& o);
|
||||
object_id_type do_apply(const sidechain_address_add_operation& o);
|
||||
};
|
||||
|
||||
class update_sidechain_address_evaluator : public evaluator<update_sidechain_address_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef sidechain_address_update_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const sidechain_address_update_operation& o);
|
||||
object_id_type do_apply(const sidechain_address_update_operation& o);
|
||||
};
|
||||
|
||||
class delete_sidechain_address_evaluator : public evaluator<delete_sidechain_address_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef sidechain_address_delete_operation operation_type;
|
||||
|
||||
void_result do_evaluate(const sidechain_address_delete_operation& o);
|
||||
void_result do_apply(const sidechain_address_delete_operation& o);
|
||||
};
|
||||
|
||||
} } // namespace graphene::chain
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
||||
/**
|
||||
* @class sidechain_address_object
|
||||
* @brief tracks information about a sidechain addresses for user accounts.
|
||||
* @ingroup object
|
||||
*/
|
||||
class sidechain_address_object : public abstract_object<sidechain_address_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = sidechain_address_object_type;
|
||||
|
||||
account_id_type sidechain_address_account;
|
||||
graphene::peerplays_sidechain::sidechain_type sidechain;
|
||||
string address;
|
||||
string private_key;
|
||||
string public_key;
|
||||
|
||||
sidechain_address_object() :
|
||||
sidechain(graphene::peerplays_sidechain::sidechain_type::bitcoin),
|
||||
address(""),
|
||||
private_key(""),
|
||||
public_key("") {}
|
||||
};
|
||||
|
||||
struct by_account;
|
||||
struct by_sidechain;
|
||||
struct by_account_and_sidechain;
|
||||
struct by_sidechain_and_address;
|
||||
using sidechain_address_multi_index_type = multi_index_container<
|
||||
sidechain_address_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>,
|
||||
member<object, object_id_type, &object::id>
|
||||
>,
|
||||
ordered_non_unique< tag<by_account>,
|
||||
member<sidechain_address_object, account_id_type, &sidechain_address_object::sidechain_address_account>
|
||||
>,
|
||||
ordered_non_unique< tag<by_sidechain>,
|
||||
member<sidechain_address_object, peerplays_sidechain::sidechain_type, &sidechain_address_object::sidechain>
|
||||
>,
|
||||
ordered_unique< tag<by_account_and_sidechain>,
|
||||
composite_key<sidechain_address_object,
|
||||
member<sidechain_address_object, account_id_type, &sidechain_address_object::sidechain_address_account>,
|
||||
member<sidechain_address_object, peerplays_sidechain::sidechain_type, &sidechain_address_object::sidechain>
|
||||
>
|
||||
>,
|
||||
ordered_unique< tag<by_sidechain_and_address>,
|
||||
composite_key<sidechain_address_object,
|
||||
member<sidechain_address_object, peerplays_sidechain::sidechain_type, &sidechain_address_object::sidechain>,
|
||||
member<sidechain_address_object, std::string, &sidechain_address_object::address>
|
||||
>
|
||||
>
|
||||
>
|
||||
>;
|
||||
using sidechain_address_index = generic_index<sidechain_address_object, sidechain_address_multi_index_type>;
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::sidechain_address_object, (graphene::db::object),
|
||||
(sidechain_address_account)(sidechain)(address)(private_key)(public_key) )
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
@ -60,6 +61,7 @@ namespace graphene { namespace chain {
|
|||
vesting_balance_id_type pay_vb;
|
||||
son_statistics_id_type statistics;
|
||||
son_status status = son_status::inactive;
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
void pay_son_fee(share_type pay, database& db);
|
||||
};
|
||||
|
|
@ -95,7 +97,7 @@ namespace graphene { namespace chain {
|
|||
FC_REFLECT_ENUM(graphene::chain::son_status, (inactive)(active)(in_maintenance)(deregistered) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object),
|
||||
(son_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb) )
|
||||
(son_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb)(sidechain_public_keys) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::son_statistics_object,
|
||||
(graphene::db::object),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
namespace graphene { namespace chain {
|
||||
|
||||
class witness_schedule_object;
|
||||
class son_schedule_object;
|
||||
|
||||
typedef hash_ctr_rng<
|
||||
/* HashClass = */ fc::sha256,
|
||||
|
|
@ -53,6 +54,22 @@ typedef generic_far_future_witness_scheduler<
|
|||
/* debug = */ true
|
||||
> far_future_witness_scheduler;
|
||||
|
||||
typedef generic_witness_scheduler<
|
||||
/* WitnessID = */ son_id_type,
|
||||
/* RNG = */ witness_scheduler_rng,
|
||||
/* CountType = */ decltype( chain_parameters::maximum_son_count ),
|
||||
/* OffsetType = */ uint32_t,
|
||||
/* debug = */ true
|
||||
> son_scheduler;
|
||||
|
||||
typedef generic_far_future_witness_scheduler<
|
||||
/* WitnessID = */ son_id_type,
|
||||
/* RNG = */ witness_scheduler_rng,
|
||||
/* CountType = */ decltype( chain_parameters::maximum_son_count ),
|
||||
/* OffsetType = */ uint32_t,
|
||||
/* debug = */ true
|
||||
> far_future_son_scheduler;
|
||||
|
||||
class witness_schedule_object : public graphene::db::abstract_object<witness_schedule_object>
|
||||
{
|
||||
public:
|
||||
|
|
@ -73,6 +90,26 @@ class witness_schedule_object : public graphene::db::abstract_object<witness_sch
|
|||
fc::uint128 recent_slots_filled;
|
||||
};
|
||||
|
||||
class son_schedule_object : public graphene::db::abstract_object<son_schedule_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = implementation_ids;
|
||||
static const uint8_t type_id = impl_son_schedule_object_type;
|
||||
|
||||
vector< son_id_type > current_shuffled_sons;
|
||||
|
||||
son_scheduler scheduler;
|
||||
uint32_t last_scheduling_block;
|
||||
uint64_t slots_since_genesis = 0;
|
||||
fc::array< char, sizeof(secret_hash_type) > rng_seed;
|
||||
|
||||
/**
|
||||
* Not necessary for consensus, but used for figuring out the participation rate.
|
||||
* The nth bit is 0 if the nth slot was unfilled, else it is 1.
|
||||
*/
|
||||
fc::uint128 recent_slots_filled;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
|
||||
|
|
@ -96,3 +133,23 @@ FC_REFLECT_DERIVED(
|
|||
(recent_slots_filled)
|
||||
(current_shuffled_witnesses)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::son_scheduler,
|
||||
(_turns)
|
||||
(_tokens)
|
||||
(_min_token_count)
|
||||
(_ineligible_waiting_for_token)
|
||||
(_ineligible_no_turn)
|
||||
(_eligible)
|
||||
(_schedule)
|
||||
(_lame_duck)
|
||||
)
|
||||
FC_REFLECT_DERIVED(
|
||||
graphene::chain::son_schedule_object,
|
||||
(graphene::db::object),
|
||||
(scheduler)
|
||||
(last_scheduling_block)
|
||||
(slots_since_genesis)
|
||||
(rng_seed)
|
||||
(recent_slots_filled)
|
||||
(current_shuffled_sons)
|
||||
)
|
||||
|
|
|
|||
70
libraries/chain/sidechain_address_evaluator.cpp
Normal file
70
libraries/chain/sidechain_address_evaluator.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include <graphene/chain/sidechain_address_evaluator.hpp>
|
||||
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void_result add_sidechain_address_evaluator::do_evaluate(const sidechain_address_add_operation& op)
|
||||
{ try{
|
||||
|
||||
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>();
|
||||
FC_ASSERT( idx.find(boost::make_tuple(op.sidechain_address_account, op.sidechain)) == idx.end(), "Duplicated item" );
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type add_sidechain_address_evaluator::do_apply(const sidechain_address_add_operation& op)
|
||||
{ try {
|
||||
const auto& new_sidechain_address_object = db().create<sidechain_address_object>( [&]( sidechain_address_object& obj ){
|
||||
obj.sidechain_address_account = op.sidechain_address_account;
|
||||
obj.sidechain = op.sidechain;
|
||||
obj.address = op.address;
|
||||
obj.private_key = op.private_key;
|
||||
obj.public_key = op.public_key;
|
||||
});
|
||||
return new_sidechain_address_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result update_sidechain_address_evaluator::do_evaluate(const sidechain_address_update_operation& op)
|
||||
{ try {
|
||||
FC_ASSERT(db().get(op.sidechain_address_id).sidechain_address_account == op.sidechain_address_account);
|
||||
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>();
|
||||
FC_ASSERT( idx.find(op.sidechain_address_id) != idx.end() );
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type update_sidechain_address_evaluator::do_apply(const sidechain_address_update_operation& op)
|
||||
{ try {
|
||||
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>();
|
||||
auto itr = idx.find(op.sidechain_address_id);
|
||||
if(itr != idx.end())
|
||||
{
|
||||
db().modify(*itr, [&op](sidechain_address_object &sao) {
|
||||
if(op.address.valid()) sao.address = *op.address;
|
||||
if(op.private_key.valid()) sao.private_key = *op.private_key;
|
||||
if(op.public_key.valid()) sao.public_key = *op.public_key;
|
||||
});
|
||||
}
|
||||
return op.sidechain_address_id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result delete_sidechain_address_evaluator::do_evaluate(const sidechain_address_delete_operation& op)
|
||||
{ try {
|
||||
FC_ASSERT(db().get(op.sidechain_address_id).sidechain_address_account == op.sidechain_address_account);
|
||||
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>();
|
||||
FC_ASSERT( idx.find(op.sidechain_address_id) != idx.end() );
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result delete_sidechain_address_evaluator::do_apply(const sidechain_address_delete_operation& op)
|
||||
{ try {
|
||||
const auto& idx = db().get_index_type<sidechain_address_index>().indices().get<by_id>();
|
||||
auto sidechain_address = idx.find(op.sidechain_address_id);
|
||||
if(sidechain_address != idx.end()) {
|
||||
db().remove(*sidechain_address);
|
||||
}
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
} } // namespace graphene::chain
|
||||
|
|
@ -30,6 +30,7 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op)
|
|||
obj.url = op.url;
|
||||
obj.deposit = op.deposit;
|
||||
obj.signing_key = op.signing_key;
|
||||
obj.sidechain_public_keys = op.sidechain_public_keys;
|
||||
obj.pay_vb = op.pay_vb;
|
||||
obj.statistics = db().create<son_statistics_object>([&](son_statistics_object& s){s.owner = obj.id;}).id;
|
||||
});
|
||||
|
|
@ -55,6 +56,7 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op)
|
|||
if(op.new_url.valid()) so.url = *op.new_url;
|
||||
if(op.new_deposit.valid()) so.deposit = *op.new_deposit;
|
||||
if(op.new_signing_key.valid()) so.signing_key = *op.new_signing_key;
|
||||
if(op.new_sidechain_public_keys.valid()) so.sidechain_public_keys = *op.new_sidechain_public_keys;
|
||||
if(op.new_pay_vb.valid()) so.pay_vb = *op.new_pay_vb;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
enum network {
|
||||
enum class sidechain_type {
|
||||
bitcoin,
|
||||
//ethereum
|
||||
ethereum,
|
||||
eos,
|
||||
peerplays
|
||||
};
|
||||
|
||||
using bytes = std::vector<char>;
|
||||
|
|
@ -59,7 +61,7 @@ struct info_for_vin
|
|||
};
|
||||
|
||||
struct sidechain_event_data {
|
||||
network sidechain;
|
||||
sidechain_type sidechain;
|
||||
std::string transaction_id;
|
||||
std::string from;
|
||||
std::string to;
|
||||
|
|
@ -68,3 +70,4 @@ struct sidechain_event_data {
|
|||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
FC_REFLECT_ENUM(graphene::peerplays_sidechain::sidechain_type, (bitcoin)(ethereum)(eos)(peerplays) )
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
using namespace chain;
|
||||
|
||||
|
|
@ -26,13 +28,8 @@ class peerplays_sidechain_plugin : public graphene::app::plugin
|
|||
boost::program_options::options_description& cfg) override;
|
||||
virtual void plugin_initialize(const boost::program_options::variables_map& options) override;
|
||||
virtual void plugin_startup() override;
|
||||
void schedule_heartbeat_loop();
|
||||
void heartbeat_loop();
|
||||
|
||||
std::unique_ptr<detail::peerplays_sidechain_plugin_impl> my;
|
||||
std::map<chain::public_key_type, fc::ecc::private_key> _private_keys;
|
||||
std::set<chain::son_id_type> _sons;
|
||||
fc::future<void> _heartbeat_task;
|
||||
};
|
||||
|
||||
} } //graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -10,13 +11,16 @@ namespace graphene { namespace peerplays_sidechain {
|
|||
|
||||
class sidechain_net_handler {
|
||||
public:
|
||||
sidechain_net_handler(const boost::program_options::variables_map& options);
|
||||
sidechain_net_handler(std::shared_ptr<graphene::chain::database> db, const boost::program_options::variables_map& options);
|
||||
virtual ~sidechain_net_handler();
|
||||
|
||||
std::vector<std::string> get_user_sidechain_address_mapping();
|
||||
std::vector<std::string> get_sidechain_addresses();
|
||||
|
||||
protected:
|
||||
graphene::peerplays_sidechain::network network;
|
||||
std::shared_ptr<graphene::chain::database> database;
|
||||
graphene::peerplays_sidechain::sidechain_type sidechain;
|
||||
|
||||
void sidechain_event_data_received(const sidechain_event_data& sed);
|
||||
|
||||
virtual std::string create_multisignature_wallet( const std::vector<std::string> public_keys ) = 0;
|
||||
virtual std::string transfer( const std::string& from, const std::string& to, const uint64_t amount ) = 0;
|
||||
|
|
|
|||
|
|
@ -56,17 +56,9 @@ private:
|
|||
|
||||
class sidechain_net_handler_bitcoin : public sidechain_net_handler {
|
||||
public:
|
||||
sidechain_net_handler_bitcoin(const boost::program_options::variables_map& options);
|
||||
sidechain_net_handler_bitcoin(std::shared_ptr<graphene::chain::database> db, const boost::program_options::variables_map& options);
|
||||
virtual ~sidechain_net_handler_bitcoin();
|
||||
|
||||
void update_tx_infos( const std::string& block_hash );
|
||||
|
||||
//void update_tx_approvals();
|
||||
|
||||
//void update_estimated_fee();
|
||||
|
||||
//void send_btc_tx( const sidechain::bitcoin_transaction& trx );
|
||||
|
||||
bool connection_is_not_defined() const;
|
||||
|
||||
std::string create_multisignature_wallet( const std::vector<std::string> public_keys );
|
||||
|
|
@ -83,18 +75,9 @@ private:
|
|||
|
||||
std::unique_ptr<zmq_listener> listener;
|
||||
std::unique_ptr<bitcoin_rpc_client> bitcoin_client;
|
||||
graphene::chain::database* db;
|
||||
|
||||
void handle_event( const std::string& event_data);
|
||||
|
||||
std::vector<info_for_vin> extract_info_from_block( const std::string& _block );
|
||||
|
||||
void update_transaction_status( std::vector<fc::sha256> trx_for_check );
|
||||
|
||||
std::set<fc::sha256> get_valid_vins( const std::string tx_hash );
|
||||
|
||||
inline uint64_t parse_amount(std::string raw);
|
||||
|
||||
};
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -11,12 +12,12 @@ namespace graphene { namespace peerplays_sidechain {
|
|||
|
||||
class sidechain_net_manager {
|
||||
public:
|
||||
sidechain_net_manager();
|
||||
sidechain_net_manager(std::shared_ptr<graphene::chain::database> db);
|
||||
virtual ~sidechain_net_manager();
|
||||
|
||||
bool create_handler(peerplays_sidechain::network network, const boost::program_options::variables_map& options);
|
||||
bool create_handler(peerplays_sidechain::sidechain_type sidechain, const boost::program_options::variables_map& options);
|
||||
private:
|
||||
|
||||
std::shared_ptr<graphene::chain::database> database;
|
||||
std::vector<std::unique_ptr<sidechain_net_handler>> net_handlers;
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
|
||||
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_manager.hpp>
|
||||
#include <graphene/utilities/key_conversion.hpp>
|
||||
|
||||
|
|
@ -14,30 +15,37 @@ namespace detail
|
|||
class peerplays_sidechain_plugin_impl
|
||||
{
|
||||
public:
|
||||
peerplays_sidechain_plugin_impl(peerplays_sidechain_plugin& _plugin)
|
||||
: _self( _plugin )
|
||||
{ }
|
||||
peerplays_sidechain_plugin_impl(peerplays_sidechain_plugin& _plugin);
|
||||
virtual ~peerplays_sidechain_plugin_impl();
|
||||
|
||||
peerplays_sidechain_plugin& _self;
|
||||
void plugin_set_program_options(
|
||||
boost::program_options::options_description& cli,
|
||||
boost::program_options::options_description& cfg);
|
||||
void plugin_initialize(const boost::program_options::variables_map& options);
|
||||
void plugin_startup();
|
||||
void schedule_heartbeat_loop();
|
||||
void heartbeat_loop();
|
||||
private:
|
||||
peerplays_sidechain_plugin& plugin;
|
||||
|
||||
peerplays_sidechain::sidechain_net_manager _net_manager;
|
||||
bool config_ready_son;
|
||||
bool config_ready_bitcoin;
|
||||
|
||||
std::unique_ptr<peerplays_sidechain::sidechain_net_manager> net_manager;
|
||||
std::map<chain::public_key_type, fc::ecc::private_key> _private_keys;
|
||||
std::set<chain::son_id_type> _sons;
|
||||
fc::future<void> _heartbeat_task;
|
||||
};
|
||||
|
||||
peerplays_sidechain_plugin_impl::peerplays_sidechain_plugin_impl(peerplays_sidechain_plugin& _plugin) :
|
||||
plugin( _plugin ),
|
||||
config_ready_son(false),
|
||||
config_ready_bitcoin(false),
|
||||
net_manager(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
peerplays_sidechain_plugin_impl::~peerplays_sidechain_plugin_impl()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
peerplays_sidechain_plugin::peerplays_sidechain_plugin() :
|
||||
my( new detail::peerplays_sidechain_plugin_impl(*this) )
|
||||
{
|
||||
}
|
||||
|
||||
peerplays_sidechain_plugin::~peerplays_sidechain_plugin()
|
||||
{
|
||||
try {
|
||||
if( _heartbeat_task.valid() )
|
||||
|
|
@ -47,24 +55,17 @@ peerplays_sidechain_plugin::~peerplays_sidechain_plugin()
|
|||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::string peerplays_sidechain_plugin::plugin_name()const
|
||||
{
|
||||
return "peerplays_sidechain";
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_set_program_options(
|
||||
void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
||||
boost::program_options::options_description& cli,
|
||||
boost::program_options::options_description& cfg
|
||||
)
|
||||
boost::program_options::options_description& cfg)
|
||||
{
|
||||
auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
|
||||
string son_id_example = fc::json::to_string(chain::son_id_type(5));
|
||||
|
||||
cli.add_options()
|
||||
("son-id,w", bpo::value<vector<string>>(), ("ID of SON controlled by this node (e.g. " + son_id_example + ", quotes are required)").c_str())
|
||||
("son-id", bpo::value<vector<string>>(), ("ID of SON controlled by this node (e.g. " + son_id_example + ", quotes are required)").c_str())
|
||||
("peerplays-private-key", bpo::value<vector<string>>()->composing()->multitoken()->
|
||||
DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
|
||||
"Tuple of [PublicKey, WIF private key]")
|
||||
|
|
@ -81,49 +82,77 @@ void peerplays_sidechain_plugin::plugin_set_program_options(
|
|||
cfg.add(cli);
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{
|
||||
ilog("peerplays sidechain plugin: plugin_initialize()");
|
||||
|
||||
if( options.count( "bitcoin-node-ip" ) && options.count( "bitcoin-node-zmq-port" ) && options.count( "bitcoin-node-rpc-port" )
|
||||
&& options.count( "bitcoin-node-rpc-user" ) && options.count( "bitcoin-node-rpc-password" )
|
||||
&& options.count( "bitcoin-address" ) && options.count( "bitcoin-public-key" ) && options.count( "bitcoin-private-key" ) )
|
||||
{
|
||||
my->_net_manager.create_handler(network::bitcoin, options);
|
||||
config_ready_son = options.count( "son-id" ) && options.count( "peerplays-private-key" );
|
||||
if (config_ready_son) {
|
||||
LOAD_VALUE_SET(options, "son-id", _sons, chain::son_id_type)
|
||||
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)
|
||||
{
|
||||
auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >(key_id_to_wif_pair_string, 5);
|
||||
ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first));
|
||||
fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
|
||||
if (!private_key)
|
||||
{
|
||||
// the key isn't in WIF format; see if they are still passing the old native private key format. This is
|
||||
// just here to ease the transition, can be removed soon
|
||||
try
|
||||
{
|
||||
private_key = fc::variant(key_id_to_wif_pair.second, 2).as<fc::ecc::private_key>(1);
|
||||
}
|
||||
catch (const fc::exception&)
|
||||
{
|
||||
FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second));
|
||||
}
|
||||
}
|
||||
_private_keys[key_id_to_wif_pair.first] = *private_key;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wlog("Haven't set up bitcoin sidechain parameters");
|
||||
wlog("Haven't set up SON parameters");
|
||||
throw;
|
||||
}
|
||||
|
||||
LOAD_VALUE_SET(options, "son-id", _sons, chain::son_id_type)
|
||||
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)
|
||||
{
|
||||
auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >(key_id_to_wif_pair_string, 5);
|
||||
ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first));
|
||||
fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
|
||||
if (!private_key)
|
||||
{
|
||||
// the key isn't in WIF format; see if they are still passing the old native private key format. This is
|
||||
// just here to ease the transition, can be removed soon
|
||||
try
|
||||
{
|
||||
private_key = fc::variant(key_id_to_wif_pair.second, 2).as<fc::ecc::private_key>(1);
|
||||
}
|
||||
catch (const fc::exception&)
|
||||
{
|
||||
FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second));
|
||||
}
|
||||
}
|
||||
_private_keys[key_id_to_wif_pair.first] = *private_key;
|
||||
}
|
||||
net_manager = std::unique_ptr<sidechain_net_manager>(new sidechain_net_manager(plugin.app().chain_database()));
|
||||
|
||||
config_ready_bitcoin = options.count( "bitcoin-node-ip" ) &&
|
||||
options.count( "bitcoin-node-zmq-port" ) && options.count( "bitcoin-node-rpc-port" ) &&
|
||||
options.count( "bitcoin-node-rpc-user" ) && options.count( "bitcoin-node-rpc-password" ) &&
|
||||
options.count( "bitcoin-address" ) && options.count( "bitcoin-public-key" ) && options.count( "bitcoin-private-key" );
|
||||
if (config_ready_bitcoin) {
|
||||
net_manager->create_handler(sidechain_type::bitcoin, options);
|
||||
ilog("Bitcoin sidechain handler created");
|
||||
} else {
|
||||
wlog("Haven't set up Bitcoin sidechain parameters");
|
||||
}
|
||||
|
||||
//config_ready_ethereum = options.count( "ethereum-node-ip" ) &&
|
||||
// options.count( "ethereum-address" ) && options.count( "ethereum-public-key" ) && options.count( "ethereum-private-key" );
|
||||
//if (config_ready_ethereum) {
|
||||
// net_manager->create_handler(sidechain_type::ethereum, options);
|
||||
// ilog("Ethereum sidechain handler created");
|
||||
//} else {
|
||||
// wlog("Haven't set up Ethereum sidechain parameters");
|
||||
//}
|
||||
|
||||
if (!(config_ready_bitcoin /*&& config_ready_ethereum*/)) {
|
||||
wlog("Haven't set up any sidechain parameters");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_startup()
|
||||
void peerplays_sidechain_plugin_impl::plugin_startup()
|
||||
{
|
||||
ilog("peerplays sidechain plugin: plugin_startup()");
|
||||
if (config_ready_son) {
|
||||
ilog("SON running");
|
||||
}
|
||||
|
||||
if (config_ready_bitcoin) {
|
||||
ilog("Bitcoin sidechain handler running");
|
||||
}
|
||||
|
||||
if( !_sons.empty() && !_private_keys.empty() )
|
||||
{
|
||||
|
|
@ -131,10 +160,13 @@ void peerplays_sidechain_plugin::plugin_startup()
|
|||
schedule_heartbeat_loop();
|
||||
} else
|
||||
elog("No sons configured! Please add SON IDs and private keys to configuration.");
|
||||
ilog("peerplays sidechain plugin: plugin_startup() end");
|
||||
|
||||
//if (config_ready_ethereum) {
|
||||
// ilog("Ethereum sidechain handler running");
|
||||
//}
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::schedule_heartbeat_loop()
|
||||
void peerplays_sidechain_plugin_impl::schedule_heartbeat_loop()
|
||||
{
|
||||
fc::time_point now = fc::time_point::now();
|
||||
int64_t time_to_next_heartbeat = 180000000;
|
||||
|
|
@ -145,9 +177,9 @@ void peerplays_sidechain_plugin::schedule_heartbeat_loop()
|
|||
next_wakeup, "SON Heartbeat Production");
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::heartbeat_loop()
|
||||
void peerplays_sidechain_plugin_impl::heartbeat_loop()
|
||||
{
|
||||
chain::database& d = database();
|
||||
chain::database& d = plugin.database();
|
||||
chain::son_id_type son_id = *(_sons.begin());
|
||||
const chain::global_property_object& gpo = d.get_global_properties();
|
||||
auto it = std::find(gpo.active_sons.begin(), gpo.active_sons.end(), son_id);
|
||||
|
|
@ -163,7 +195,7 @@ void peerplays_sidechain_plugin::heartbeat_loop()
|
|||
fc::future<bool> fut = fc::async( [&](){
|
||||
try {
|
||||
d.push_transaction(trx);
|
||||
p2p_node().broadcast(net::trx_message(trx));
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch(fc::exception e){
|
||||
ilog("peerplays_sidechain_plugin: sending heartbeat failed with exception ${e}",("e", e.what()));
|
||||
|
|
@ -174,5 +206,43 @@ void peerplays_sidechain_plugin::heartbeat_loop()
|
|||
}
|
||||
schedule_heartbeat_loop();
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
peerplays_sidechain_plugin::peerplays_sidechain_plugin() :
|
||||
my( new detail::peerplays_sidechain_plugin_impl(*this) )
|
||||
{
|
||||
}
|
||||
|
||||
peerplays_sidechain_plugin::~peerplays_sidechain_plugin()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string peerplays_sidechain_plugin::plugin_name()const
|
||||
{
|
||||
return "peerplays_sidechain";
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_set_program_options(
|
||||
boost::program_options::options_description& cli,
|
||||
boost::program_options::options_description& cfg)
|
||||
{
|
||||
ilog("peerplays sidechain plugin: plugin_set_program_options()");
|
||||
my->plugin_set_program_options(cli, cfg);
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{
|
||||
ilog("peerplays sidechain plugin: plugin_initialize()");
|
||||
my->plugin_initialize(options);
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin::plugin_startup()
|
||||
{
|
||||
ilog("peerplays sidechain plugin: plugin_startup()");
|
||||
my->plugin_startup();
|
||||
}
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,34 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
|
||||
#include <fc/log/logger.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
sidechain_net_handler::sidechain_net_handler(const boost::program_options::variables_map& options) {
|
||||
sidechain_net_handler::sidechain_net_handler(std::shared_ptr<graphene::chain::database> db, const boost::program_options::variables_map& options) :
|
||||
database(db)
|
||||
{
|
||||
}
|
||||
|
||||
sidechain_net_handler::~sidechain_net_handler() {
|
||||
}
|
||||
|
||||
std::vector<std::string> sidechain_net_handler::get_user_sidechain_address_mapping() {
|
||||
std::vector<std::string> sidechain_net_handler::get_sidechain_addresses() {
|
||||
std::vector<std::string> result;
|
||||
|
||||
switch (network) {
|
||||
case network::bitcoin:
|
||||
result.push_back("2N5aFW5WFaYZLuJWx9RGziHBdEMj9Zf8s3J");
|
||||
result.push_back("2MxAnE469fhhdvUqUB7daU997VSearb2mn7");
|
||||
result.push_back("2NAYptFvTU8vJ1pC7CxvVA9R7D3NdBJHpwL");
|
||||
result.push_back("2N9zPaLDfaJazUmVfr3wgn8BK75tid2kkzR");
|
||||
result.push_back("2NDN7cDH3E57E1B8TwTYvBgF7CndL4FTBPL");
|
||||
//result.push_back("2MzEmSiwrRzozxE6gfZ14LAyDHZ4DYP1zVG");
|
||||
//result.push_back("2NDCdm1WVJVCMWJzRaSSy9NDvpNKiqkbrMg");
|
||||
//result.push_back("2Mu2iz3Jfqjyv3hBQGQZSGmZGZxhJp91TNX");
|
||||
//result.push_back("2N1sFbwcn4QVbvjp7yRsN4mg4mBFbvC8gKM");
|
||||
//result.push_back("2NDmxr6ufBE7Zgdgq9hShF2grx2YPEiTyNy");
|
||||
|
||||
switch (sidechain) {
|
||||
case sidechain_type::bitcoin:
|
||||
{
|
||||
const auto& sidechain_addresses_idx = database->get_index_type<sidechain_address_index>();
|
||||
const auto& sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get<by_sidechain>();
|
||||
const auto& sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain);
|
||||
std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second,
|
||||
[&result] (const sidechain_address_object& sao) {
|
||||
result.push_back(sao.address);
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
|
@ -31,5 +36,15 @@ std::vector<std::string> sidechain_net_handler::get_user_sidechain_address_mappi
|
|||
return result;
|
||||
}
|
||||
|
||||
void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_data& sed) {
|
||||
ilog( __FUNCTION__ );
|
||||
ilog( "sidechain_event_data:" );
|
||||
ilog( " sidechain: ${sidechain}", ( "sidechain", sed.sidechain ) );
|
||||
ilog( " transaction_id: ${transaction_id}", ( "transaction_id", sed.transaction_id ) );
|
||||
ilog( " from: ${from}", ( "from", sed.from ) );
|
||||
ilog( " to: ${to}", ( "to", sed.to ) );
|
||||
ilog( " amount: ${amount}", ( "amount", sed.amount ) );
|
||||
}
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include <fc/log/logger.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
|
||||
#include "graphene/peerplays_sidechain/sidechain_net_manager.hpp"
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
|
|
@ -178,17 +178,17 @@ void zmq_listener::handle_zmq() {
|
|||
while ( true ) {
|
||||
auto msg = receive_multipart();
|
||||
const auto header = std::string( static_cast<char*>( msg[0].data() ), msg[0].size() );
|
||||
const auto hash = boost::algorithm::hex( std::string( static_cast<char*>( msg[1].data() ), msg[1].size() ) );
|
||||
const auto block_hash = boost::algorithm::hex( std::string( static_cast<char*>( msg[1].data() ), msg[1].size() ) );
|
||||
|
||||
event_received( hash );
|
||||
event_received( block_hash );
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(const boost::program_options::variables_map& options) :
|
||||
sidechain_net_handler(options) {
|
||||
network = peerplays_sidechain::network::bitcoin;
|
||||
sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(std::shared_ptr<graphene::chain::database> db, const boost::program_options::variables_map& options) :
|
||||
sidechain_net_handler(db, options) {
|
||||
sidechain = sidechain_type::bitcoin;
|
||||
|
||||
ip = options.at("bitcoin-node-ip").as<std::string>();
|
||||
zmq_port = options.at("bitcoin-node-zmq-port").as<uint32_t>();
|
||||
|
|
@ -206,74 +206,15 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(const boost::progra
|
|||
|
||||
listener = std::unique_ptr<zmq_listener>( new zmq_listener( ip, zmq_port ) );
|
||||
bitcoin_client = std::unique_ptr<bitcoin_rpc_client>( new bitcoin_rpc_client( ip, rpc_port, rpc_user, rpc_password ) );
|
||||
//db = _db;
|
||||
|
||||
listener->event_received.connect([this]( const std::string& event_data ) {
|
||||
std::thread( &sidechain_net_handler_bitcoin::handle_event, this, event_data ).detach();
|
||||
} );
|
||||
|
||||
//db->send_btc_tx.connect([this]( const sidechain::bitcoin_transaction& trx ) {
|
||||
// std::thread( &sidechain_net_handler_bitcoin::send_btc_tx, this, trx ).detach();
|
||||
//} );
|
||||
}
|
||||
|
||||
sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() {
|
||||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::update_tx_infos( const std::string& block_hash )
|
||||
{
|
||||
std::string block = bitcoin_client->receive_full_block( block_hash );
|
||||
if( block != "" ) {
|
||||
const auto& vins = extract_info_from_block( block );
|
||||
// const auto& addr_idx = db->get_index_type<bitcoin_address_index>().indices().get<by_address>();
|
||||
// for( const auto& v : vins ) {
|
||||
// const auto& addr_itr = addr_idx.find( v.address );
|
||||
// FC_ASSERT( addr_itr != addr_idx.end() );
|
||||
// db->i_w_info.insert_info_for_vin( prev_out{ v.out.hash_tx, v.out.n_vout, v.out.amount }, v.address, addr_itr->address.get_witness_script() );
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::update_tx_approvals()
|
||||
//{
|
||||
// std::vector<fc::sha256> trx_for_check;
|
||||
// const auto& confirmations_num = db->get_sidechain_params().confirmations_num;
|
||||
//
|
||||
// db->bitcoin_confirmations.safe_for<by_hash>([&]( btc_tx_confirmations_index::iterator itr_b, btc_tx_confirmations_index::iterator itr_e ){
|
||||
// for(auto iter = itr_b; iter != itr_e; iter++) {
|
||||
// db->bitcoin_confirmations.modify<by_hash>( iter->transaction_id, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.count_block++;
|
||||
// });
|
||||
//
|
||||
// if( iter->count_block == confirmations_num ) {
|
||||
// trx_for_check.push_back( iter->transaction_id );
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// update_transaction_status( trx_for_check );
|
||||
//
|
||||
//}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::update_estimated_fee()
|
||||
//{
|
||||
// db->estimated_feerate = bitcoin_client->receive_estimated_fee();
|
||||
//}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::send_btc_tx( const sidechain::bitcoin_transaction& trx )
|
||||
//{
|
||||
// std::set<fc::sha256> valid_vins;
|
||||
// for( const auto& v : trx.vin ) {
|
||||
// valid_vins.insert( v.prevout.hash );
|
||||
// }
|
||||
// db->bitcoin_confirmations.insert( bitcoin_transaction_confirmations( trx.get_txid(), valid_vins ) );
|
||||
//
|
||||
// FC_ASSERT( !bitcoin_client->connection_is_not_defined() );
|
||||
// const auto tx_hex = fc::to_hex( pack( trx ) );
|
||||
//
|
||||
// bitcoin_client->send_btc_tx( tx_hex );
|
||||
//}
|
||||
|
||||
bool sidechain_net_handler_bitcoin::connection_is_not_defined() const
|
||||
{
|
||||
return listener->connection_is_not_defined() && bitcoin_client->connection_is_not_defined();
|
||||
|
|
@ -302,9 +243,27 @@ std::string sidechain_net_handler_bitcoin::send_transaction( const std::string&
|
|||
void sidechain_net_handler_bitcoin::handle_event( const std::string& event_data ) {
|
||||
ilog("peerplays sidechain plugin: sidechain_net_handler_bitcoin::handle_event");
|
||||
ilog(" event_data: ${event_data}", ("event_data", event_data));
|
||||
//update_tx_approvals();
|
||||
//update_estimated_fee();
|
||||
//update_tx_infos( block_hash );
|
||||
|
||||
std::string block = bitcoin_client->receive_full_block( event_data );
|
||||
if( block != "" ) {
|
||||
const auto& vins = extract_info_from_block( block );
|
||||
|
||||
const auto& sidechain_addresses_idx = database->get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_address>();
|
||||
|
||||
for( const auto& v : vins ) {
|
||||
const auto& addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain_type::bitcoin, v.address));
|
||||
if ( addr_itr == sidechain_addresses_idx.end() )
|
||||
continue;
|
||||
|
||||
sidechain_event_data sed;
|
||||
sed.sidechain = addr_itr->sidechain;
|
||||
sed.transaction_id = v.out.hash_tx;
|
||||
sed.from = "";
|
||||
sed.to = v.address;
|
||||
sed.amount = v.out.amount;
|
||||
sidechain_event_data_received(sed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block( const std::string& _block )
|
||||
|
|
@ -315,8 +274,6 @@ std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block
|
|||
|
||||
std::vector<info_for_vin> result;
|
||||
|
||||
const auto& addr_idx = get_user_sidechain_address_mapping();// db->get_index_type<bitcoin_address_index>().indices().get<by_address>();
|
||||
|
||||
for (const auto& tx_child : block.get_child("tx")) {
|
||||
const auto& tx = tx_child.second;
|
||||
|
||||
|
|
@ -327,13 +284,11 @@ std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block
|
|||
|
||||
for (const auto& addr : script.get_child("addresses")) { // in which cases there can be more addresses?
|
||||
const auto address_base58 = addr.second.get_value<std::string>();
|
||||
|
||||
auto it = find(addr_idx.begin(), addr_idx.end(), address_base58);
|
||||
if (it == addr_idx.end()) continue;
|
||||
|
||||
info_for_vin vin;
|
||||
vin.out.hash_tx = tx.get_child("txid").get_value<std::string>();
|
||||
vin.out.amount = parse_amount( o.second.get_child( "value" ).get_value<std::string>() );
|
||||
string amount = o.second.get_child( "value" ).get_value<std::string>();
|
||||
amount.erase(std::remove(amount.begin(), amount.end(), '.'), amount.end());
|
||||
vin.out.amount = std::stoll(amount);
|
||||
vin.out.n_vout = o.second.get_child( "n" ).get_value<uint32_t>();
|
||||
vin.address = address_base58;
|
||||
result.push_back( vin );
|
||||
|
|
@ -344,59 +299,6 @@ std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block
|
|||
return result;
|
||||
}
|
||||
|
||||
//void sidechain_net_handler_bitcoin::update_transaction_status( std::vector<fc::sha256> trx_for_check )
|
||||
//{
|
||||
// const auto& confirmations_num = db->get_sidechain_params().confirmations_num;
|
||||
//
|
||||
// for( const auto& trx : trx_for_check ) {
|
||||
// auto confirmations = bitcoin_client->receive_confirmations_tx( trx.str() );
|
||||
// db->bitcoin_confirmations.modify<by_hash>( trx, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.count_block = confirmations;
|
||||
// });
|
||||
//
|
||||
// if( confirmations >= confirmations_num ) {
|
||||
// db->bitcoin_confirmations.modify<by_hash>( trx, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.confirmed = true;
|
||||
// });
|
||||
//
|
||||
// } else if( confirmations == 0 ) {
|
||||
// auto is_in_mempool = bitcoin_client->receive_mempool_entry_tx( trx.str() );
|
||||
//
|
||||
// std::set<fc::sha256> valid_vins;
|
||||
// if( !is_in_mempool ) {
|
||||
// valid_vins = get_valid_vins( trx.str() );
|
||||
// }
|
||||
//
|
||||
// db->bitcoin_confirmations.modify<by_hash>( trx, [&]( bitcoin_transaction_confirmations& obj ) {
|
||||
// obj.missing = !is_in_mempool;
|
||||
// obj.valid_vins = valid_vins;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//std::set<fc::sha256> sidechain_net_handler_bitcoin::get_valid_vins( const std::string tx_hash )
|
||||
//{
|
||||
// const auto& confirmations_obj = db->bitcoin_confirmations.find<sidechain::by_hash>( fc::sha256( tx_hash ) );
|
||||
// FC_ASSERT( confirmations_obj.valid() );
|
||||
//
|
||||
// std::set<fc::sha256> valid_vins;
|
||||
// for( const auto& v : confirmations_obj->valid_vins ) {
|
||||
// auto confirmations = bitcoin_client->receive_confirmations_tx( v.str() );
|
||||
// if( confirmations == 0 ) {
|
||||
// continue;
|
||||
// }
|
||||
// valid_vins.insert( v );
|
||||
// }
|
||||
// return valid_vins;
|
||||
//}
|
||||
|
||||
// Removes dot from amount output: "50.00000000"
|
||||
inline uint64_t sidechain_net_handler_bitcoin::parse_amount(std::string raw) {
|
||||
raw.erase(std::remove(raw.begin(), raw.end(), '.'), raw.end());
|
||||
return std::stoll(raw);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
} } // graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
sidechain_net_manager::sidechain_net_manager() {
|
||||
sidechain_net_manager::sidechain_net_manager(std::shared_ptr<graphene::chain::database> db) :
|
||||
database(db)
|
||||
{
|
||||
ilog(__FUNCTION__);
|
||||
}
|
||||
|
||||
|
|
@ -13,16 +15,17 @@ sidechain_net_manager::~sidechain_net_manager() {
|
|||
ilog(__FUNCTION__);
|
||||
}
|
||||
|
||||
bool sidechain_net_manager::create_handler(peerplays_sidechain::network network, const boost::program_options::variables_map& options) {
|
||||
bool sidechain_net_manager::create_handler(peerplays_sidechain::sidechain_type sidechain, const boost::program_options::variables_map& options) {
|
||||
ilog(__FUNCTION__);
|
||||
|
||||
bool ret_val = false;
|
||||
|
||||
switch (network) {
|
||||
case network::bitcoin: {
|
||||
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_bitcoin(options));
|
||||
switch (sidechain) {
|
||||
case sidechain_type::bitcoin: {
|
||||
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_bitcoin(database, options));
|
||||
net_handlers.push_back(std::move(h));
|
||||
ret_val = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ else()
|
|||
endif()
|
||||
|
||||
add_library( graphene_wallet wallet.cpp ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp ${HEADERS} )
|
||||
target_link_libraries( graphene_wallet PRIVATE graphene_app graphene_net graphene_chain graphene_utilities fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( graphene_wallet PRIVATE graphene_app graphene_net graphene_chain graphene_utilities fc peerplays_sidechain ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_include_directories( graphene_db PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
if(MSVC)
|
||||
|
|
|
|||
|
|
@ -1312,6 +1312,7 @@ class wallet_api
|
|||
* display this when showing a list of SONs. May be blank.
|
||||
* @param deposit_id vesting balance id for SON deposit
|
||||
* @param pay_vb_id vesting balance id for SON pay_vb
|
||||
* @param sidechain_public_keys The new set of sidechain public keys.
|
||||
* @param broadcast true to broadcast the transaction on the network
|
||||
* @returns the signed transaction registering a SON
|
||||
*/
|
||||
|
|
@ -1319,6 +1320,7 @@ class wallet_api
|
|||
string url,
|
||||
vesting_balance_id_type deposit_id,
|
||||
vesting_balance_id_type pay_vb_id,
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys,
|
||||
bool broadcast = false);
|
||||
|
||||
/**
|
||||
|
|
@ -1327,11 +1329,13 @@ class wallet_api
|
|||
* @param witness The name of the SON's owner account. Also accepts the ID of the owner account or the ID of the SON.
|
||||
* @param url Same as for create_son. The empty string makes it remain the same.
|
||||
* @param block_signing_key The new block signing public key. The empty string makes it remain the same.
|
||||
* @param sidechain_public_keys The new set of sidechain public keys. The empty string makes it remain the same.
|
||||
* @param broadcast true if you wish to broadcast the transaction.
|
||||
*/
|
||||
signed_transaction update_son(string owner_account,
|
||||
string url,
|
||||
string block_signing_key,
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
|
|
@ -1368,6 +1372,83 @@ class wallet_api
|
|||
*/
|
||||
map<string, son_id_type> list_active_sons();
|
||||
|
||||
/** Adds sidechain address owned by the given account for a given sidechain.
|
||||
*
|
||||
* An account can have at most one sidechain address for one sidechain.
|
||||
*
|
||||
* @param account the name or id of the account who owns the address
|
||||
* @param sidechain a sidechain to whom address belongs
|
||||
* @param address sidechain address
|
||||
* @param private_key private key for sidechain address
|
||||
* @param public_key public key for sidechain address
|
||||
* @param broadcast true to broadcast the transaction on the network
|
||||
* @returns the signed transaction adding sidechain address
|
||||
*/
|
||||
signed_transaction add_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
string address,
|
||||
string private_key,
|
||||
string public_key,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Updates existing sidechain address owned by the given account for a given sidechain.
|
||||
*
|
||||
* Only address, private key and public key might be updated.
|
||||
*
|
||||
* @param account the name or id of the account who owns the address
|
||||
* @param sidechain a sidechain to whom address belongs
|
||||
* @param address sidechain address
|
||||
* @param private_key private key for sidechain address
|
||||
* @param public_key public key for sidechain address
|
||||
* @param broadcast true to broadcast the transaction on the network
|
||||
* @returns the signed transaction updating sidechain address
|
||||
*/
|
||||
signed_transaction update_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
string address,
|
||||
string private_key,
|
||||
string public_key,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Deletes existing sidechain address owned by the given account for a given sidechain.
|
||||
*
|
||||
* @param account the name or id of the account who owns the address
|
||||
* @param sidechain a sidechain to whom address belongs
|
||||
* @param broadcast true to broadcast the transaction on the network
|
||||
* @returns the signed transaction updating sidechain address
|
||||
*/
|
||||
signed_transaction delete_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Retrieves all sidechain addresses owned by given account.
|
||||
*
|
||||
* @param account the name or id of the account who owns the address
|
||||
* @returns the list of all sidechain addresses owned by given account.
|
||||
*/
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_account(string account);
|
||||
|
||||
/** Retrieves all sidechain addresses registered for a given sidechain.
|
||||
*
|
||||
* @param sidechain the name of the sidechain
|
||||
* @returns the list of all sidechain addresses registered for a given sidechain.
|
||||
*/
|
||||
vector<optional<sidechain_address_object>> get_sidechain_addresses_by_sidechain(peerplays_sidechain::sidechain_type sidechain);
|
||||
|
||||
/** Retrieves sidechain address owned by given account for a given sidechain.
|
||||
*
|
||||
* @param account the name or id of the account who owns the address
|
||||
* @param sidechain the name of the sidechain
|
||||
* @returns the sidechain address owned by given account for a given sidechain.
|
||||
*/
|
||||
fc::optional<sidechain_address_object> get_sidechain_address_by_account_and_sidechain(string account, peerplays_sidechain::sidechain_type sidechain);
|
||||
|
||||
/** Retrieves the total number of sidechain addresses registered in the system.
|
||||
*
|
||||
* @returns the total number of sidechain addresses registered in the system.
|
||||
*/
|
||||
uint64_t get_sidechain_addresses_count();
|
||||
|
||||
/** Creates a witness object owned by the given account.
|
||||
*
|
||||
* An account can have at most one witness object.
|
||||
|
|
@ -2121,6 +2202,13 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(update_son)
|
||||
(delete_son)
|
||||
(list_sons)
|
||||
(add_sidechain_address)
|
||||
(update_sidechain_address)
|
||||
(delete_sidechain_address)
|
||||
(get_sidechain_addresses_by_account)
|
||||
(get_sidechain_addresses_by_sidechain)
|
||||
(get_sidechain_address_by_account_and_sidechain)
|
||||
(get_sidechain_addresses_count)
|
||||
(create_witness)
|
||||
(update_witness)
|
||||
(create_worker)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
#include <graphene/chain/rock_paper_scissors.hpp>
|
||||
|
||||
#include <graphene/bookie/bookie_api.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <graphene/utilities/git_revision.hpp>
|
||||
|
|
@ -1862,6 +1863,7 @@ public:
|
|||
string url,
|
||||
vesting_balance_id_type deposit_id,
|
||||
vesting_balance_id_type pay_vb_id,
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
account_object son_account = get_account(owner_account);
|
||||
|
|
@ -1876,6 +1878,7 @@ public:
|
|||
son_create_op.url = url;
|
||||
son_create_op.deposit = deposit_id;
|
||||
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))
|
||||
FC_THROW("Account ${owner_account} is already a SON", ("owner_account", owner_account));
|
||||
|
|
@ -1893,6 +1896,7 @@ public:
|
|||
signed_transaction update_son(string owner_account,
|
||||
string url,
|
||||
string block_signing_key,
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
son_object son = get_son(owner_account);
|
||||
|
|
@ -1905,6 +1909,9 @@ public:
|
|||
if( block_signing_key != "" ) {
|
||||
son_update_op.new_signing_key = public_key_type( block_signing_key );
|
||||
}
|
||||
if( !sidechain_public_keys.empty() ) {
|
||||
son_update_op.new_sidechain_public_keys = sidechain_public_keys;
|
||||
}
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( son_update_op );
|
||||
|
|
@ -1954,6 +1961,73 @@ public:
|
|||
return result;
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
signed_transaction add_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
string address,
|
||||
string private_key,
|
||||
string public_key,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
account_id_type sidechain_address_account_id = get_account_id(account);
|
||||
|
||||
sidechain_address_add_operation op;
|
||||
op.sidechain_address_account = sidechain_address_account_id;
|
||||
op.sidechain = sidechain;
|
||||
op.address = address;
|
||||
op.private_key = private_key;
|
||||
op.public_key = public_key;
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( op );
|
||||
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees);
|
||||
tx.validate();
|
||||
|
||||
return sign_transaction( tx, broadcast );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
signed_transaction update_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
string address,
|
||||
string private_key,
|
||||
string public_key,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
account_id_type sidechain_address_account_id = get_account_id(account);
|
||||
|
||||
sidechain_address_update_operation op;
|
||||
op.sidechain_address_account = sidechain_address_account_id;
|
||||
op.sidechain = sidechain;
|
||||
op.address = address;
|
||||
op.private_key = private_key;
|
||||
op.public_key = public_key;
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( op );
|
||||
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees);
|
||||
tx.validate();
|
||||
|
||||
return sign_transaction( tx, broadcast );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
signed_transaction delete_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
bool broadcast /* = false */)
|
||||
{ try {
|
||||
account_id_type sidechain_address_account_id = get_account_id(account);
|
||||
|
||||
sidechain_address_delete_operation op;
|
||||
op.sidechain_address_account = sidechain_address_account_id;
|
||||
op.sidechain = sidechain;
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( op );
|
||||
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees);
|
||||
tx.validate();
|
||||
|
||||
return sign_transaction( tx, broadcast );
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
signed_transaction create_witness(string owner_account,
|
||||
string url,
|
||||
bool broadcast /* = false */)
|
||||
|
|
@ -4301,17 +4375,19 @@ signed_transaction wallet_api::create_son(string owner_account,
|
|||
string url,
|
||||
vesting_balance_id_type deposit_id,
|
||||
vesting_balance_id_type pay_vb_id,
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
return my->create_son(owner_account, url, deposit_id, pay_vb_id, broadcast);
|
||||
return my->create_son(owner_account, url, deposit_id, pay_vb_id, sidechain_public_keys, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::update_son(string owner_account,
|
||||
string url,
|
||||
string block_signing_key,
|
||||
flat_map<peerplays_sidechain::sidechain_type, string> sidechain_public_keys,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
return my->update_son(owner_account, url, block_signing_key, broadcast);
|
||||
return my->update_son(owner_account, url, block_signing_key, sidechain_public_keys, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::delete_son(string owner_account,
|
||||
|
|
@ -4330,6 +4406,55 @@ map<string, son_id_type> wallet_api::list_active_sons()
|
|||
return my->list_active_sons();
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::add_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
string address,
|
||||
string private_key,
|
||||
string public_key,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
return my->add_sidechain_address(account, sidechain, address, private_key, public_key, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::update_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
string address,
|
||||
string private_key,
|
||||
string public_key,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
return my->update_sidechain_address(account, sidechain, address, private_key, public_key, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::delete_sidechain_address(string account,
|
||||
peerplays_sidechain::sidechain_type sidechain,
|
||||
bool broadcast /* = false */)
|
||||
{
|
||||
return my->delete_sidechain_address(account, sidechain, broadcast);
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> wallet_api::get_sidechain_addresses_by_account(string account)
|
||||
{
|
||||
account_id_type account_id = get_account_id(account);
|
||||
return my->_remote_db->get_sidechain_addresses_by_account(account_id);
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> wallet_api::get_sidechain_addresses_by_sidechain(peerplays_sidechain::sidechain_type sidechain)
|
||||
{
|
||||
return my->_remote_db->get_sidechain_addresses_by_sidechain(sidechain);
|
||||
}
|
||||
|
||||
fc::optional<sidechain_address_object> wallet_api::get_sidechain_address_by_account_and_sidechain(string account, peerplays_sidechain::sidechain_type sidechain)
|
||||
{
|
||||
account_id_type account_id = get_account_id(account);
|
||||
return my->_remote_db->get_sidechain_address_by_account_and_sidechain(account_id, sidechain);
|
||||
}
|
||||
|
||||
uint64_t wallet_api::get_sidechain_addresses_count()
|
||||
{
|
||||
return my->_remote_db->get_sidechain_addresses_count();
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::create_witness(string owner_account,
|
||||
string url,
|
||||
bool broadcast /* = false */)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include <graphene/chain/match_object.hpp>
|
||||
#include <graphene/chain/game_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
|
||||
#include <fc/smart_ref_impl.hpp>
|
||||
#include <iostream>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ endif()
|
|||
|
||||
file(GLOB UNIT_TESTS "tests/*.cpp")
|
||||
add_executable( chain_test ${UNIT_TESTS} ${COMMON_SOURCES} )
|
||||
target_link_libraries( chain_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc graphene_wallet ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( chain_test graphene_chain graphene_app graphene_account_history graphene_bookie peerplays_sidechain graphene_egenesis_none fc graphene_wallet ${PLATFORM_SPECIFIC_LIBS} )
|
||||
if(MSVC)
|
||||
set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
endif(MSVC)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public:
|
|||
}
|
||||
|
||||
void create_son(const std::string& account_name, const std::string& son_url,
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string>& sidechain_public_keys,
|
||||
bool generate_maintenance = true)
|
||||
{
|
||||
graphene::wallet::brain_key_info bki;
|
||||
|
|
@ -92,6 +93,7 @@ public:
|
|||
|
||||
create_tx = fixture_.con.wallet_api_ptr->create_son(account_name, son_url,
|
||||
deposits[0].id, deposits[1].id,
|
||||
sidechain_public_keys,
|
||||
true);
|
||||
|
||||
if (generate_maintenance)
|
||||
|
|
@ -110,9 +112,17 @@ BOOST_AUTO_TEST_CASE( create_sons )
|
|||
BOOST_TEST_MESSAGE("SON cli wallet tests begin");
|
||||
try
|
||||
{
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
son_test_helper sth(*this);
|
||||
sth.create_son("son1account", "http://son1");
|
||||
sth.create_son("son2account", "http://son2");
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 1";
|
||||
sth.create_son("son1account", "http://son1", sidechain_public_keys);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 2";
|
||||
sth.create_son("son2account", "http://son2", sidechain_public_keys);
|
||||
|
||||
auto son1_obj = con.wallet_api_ptr->get_son("son1account");
|
||||
BOOST_CHECK(son1_obj.son_account == con.wallet_api_ptr->get_account_id("son1account"));
|
||||
|
|
@ -136,8 +146,13 @@ BOOST_AUTO_TEST_CASE( cli_update_son )
|
|||
{
|
||||
BOOST_TEST_MESSAGE("Cli get_son and update_son Test");
|
||||
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 1";
|
||||
|
||||
son_test_helper sth(*this);
|
||||
sth.create_son("sonmember", "http://sonmember");
|
||||
sth.create_son("sonmember", "http://sonmember", sidechain_public_keys);
|
||||
|
||||
auto sonmember_acct = con.wallet_api_ptr->get_account("sonmember");
|
||||
|
||||
|
|
@ -147,12 +162,16 @@ BOOST_AUTO_TEST_CASE( cli_update_son )
|
|||
BOOST_CHECK(son_data.son_account == sonmember_acct.get_id());
|
||||
|
||||
// update SON
|
||||
con.wallet_api_ptr->update_son("sonmember", "http://sonmember_updated", "", true);
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 2";
|
||||
|
||||
con.wallet_api_ptr->update_son("sonmember", "http://sonmember_updated", "", sidechain_public_keys, true);
|
||||
son_data = con.wallet_api_ptr->get_son("sonmember");
|
||||
BOOST_CHECK(son_data.url == "http://sonmember_updated");
|
||||
|
||||
// update SON signing key
|
||||
con.wallet_api_ptr->update_son("sonmember", "http://sonmember_updated2", "TEST6Yaq5ZNTTkMM2kBBzV5jktr8ETsniCC3bnVD7eFmegRrLXfGGG", true);
|
||||
sidechain_public_keys.clear();
|
||||
con.wallet_api_ptr->update_son("sonmember", "http://sonmember_updated2", "TEST6Yaq5ZNTTkMM2kBBzV5jktr8ETsniCC3bnVD7eFmegRrLXfGGG", sidechain_public_keys, true);
|
||||
son_data = con.wallet_api_ptr->get_son("sonmember");
|
||||
BOOST_CHECK(son_data.url == "http://sonmember_updated2");
|
||||
BOOST_CHECK(std::string(son_data.signing_key) == "TEST6Yaq5ZNTTkMM2kBBzV5jktr8ETsniCC3bnVD7eFmegRrLXfGGG");
|
||||
|
|
@ -168,9 +187,17 @@ BOOST_AUTO_TEST_CASE( son_voting )
|
|||
BOOST_TEST_MESSAGE("SON Vote cli wallet tests begin");
|
||||
try
|
||||
{
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
son_test_helper sth(*this);
|
||||
sth.create_son("son1account", "http://son1");
|
||||
sth.create_son("son2account", "http://son2");
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 1";
|
||||
sth.create_son("son1account", "http://son1", sidechain_public_keys);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 2";
|
||||
sth.create_son("son2account", "http://son2", sidechain_public_keys);
|
||||
|
||||
BOOST_TEST_MESSAGE("Voting for SONs");
|
||||
|
||||
|
|
@ -239,9 +266,17 @@ BOOST_AUTO_TEST_CASE( delete_son )
|
|||
BOOST_TEST_MESSAGE("SON delete cli wallet tests begin");
|
||||
try
|
||||
{
|
||||
son_test_helper sth(*this);
|
||||
sth.create_son("son1account", "http://son1");
|
||||
sth.create_son("son2account", "http://son2");
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
son_test_helper sth(*this);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 1";
|
||||
sth.create_son("son1account", "http://son1", sidechain_public_keys);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 2";
|
||||
sth.create_son("son2account", "http://son2", sidechain_public_keys);
|
||||
|
||||
BOOST_TEST_MESSAGE("Deleting SONs");
|
||||
signed_transaction delete_tx;
|
||||
|
|
@ -279,11 +314,17 @@ BOOST_FIXTURE_TEST_CASE( select_top_fifteen_sons, cli_fixture )
|
|||
gpo = con.wallet_api_ptr->get_global_properties();
|
||||
unsigned int son_number = gpo.parameters.maximum_son_count;
|
||||
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
// create son accounts
|
||||
for(unsigned int i = 0; i < son_number + 1; i++)
|
||||
{
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i);
|
||||
sth.create_son("sonaccount" + fc::to_pretty_string(i),
|
||||
"http://son" + fc::to_pretty_string(i), false);
|
||||
"http://son" + fc::to_pretty_string(i),
|
||||
sidechain_public_keys,
|
||||
false);
|
||||
}
|
||||
BOOST_CHECK(generate_maintenance_block());
|
||||
|
||||
|
|
@ -344,9 +385,17 @@ BOOST_AUTO_TEST_CASE( list_son )
|
|||
BOOST_TEST_MESSAGE("List SONs cli wallet tests begin");
|
||||
try
|
||||
{
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
son_test_helper sth(*this);
|
||||
sth.create_son("son1account", "http://son1");
|
||||
sth.create_son("son2account", "http://son2");
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 1";
|
||||
sth.create_son("son1account", "http://son1", sidechain_public_keys);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 2";
|
||||
sth.create_son("son2account", "http://son2", sidechain_public_keys);
|
||||
|
||||
auto res = con.wallet_api_ptr->list_sons("", 100);
|
||||
BOOST_REQUIRE(res.size() == 2);
|
||||
|
|
@ -366,9 +415,17 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test )
|
|||
BOOST_TEST_MESSAGE("SON update_son_votes cli wallet tests begin");
|
||||
try
|
||||
{
|
||||
son_test_helper sth(*this);
|
||||
sth.create_son("son1account", "http://son1");
|
||||
sth.create_son("son2account", "http://son2");
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
son_test_helper sth(*this);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 1";
|
||||
sth.create_son("son1account", "http://son1", sidechain_public_keys);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 2";
|
||||
sth.create_son("son2account", "http://son2", sidechain_public_keys);
|
||||
|
||||
BOOST_TEST_MESSAGE("Vote for 2 accounts with update_son_votes");
|
||||
|
||||
|
|
@ -515,9 +572,17 @@ BOOST_AUTO_TEST_CASE( related_functions )
|
|||
global_property_object gpo = con.wallet_api_ptr->get_global_properties();
|
||||
BOOST_CHECK(gpo.active_sons.size() == 0);
|
||||
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
son_test_helper sth(*this);
|
||||
sth.create_son("son1account", "http://son1");
|
||||
sth.create_son("son2account", "http://son2");
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 1";
|
||||
sth.create_son("son1account", "http://son1", sidechain_public_keys);
|
||||
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address 2";
|
||||
sth.create_son("son2account", "http://son2", sidechain_public_keys);
|
||||
|
||||
gpo = con.wallet_api_ptr->get_global_properties();
|
||||
BOOST_CHECK(gpo.active_sons.size() == 2);
|
||||
|
|
@ -543,11 +608,17 @@ BOOST_FIXTURE_TEST_CASE( cli_list_active_sons, cli_fixture )
|
|||
gpo = con.wallet_api_ptr->get_global_properties();
|
||||
unsigned int son_number = gpo.parameters.maximum_son_count;
|
||||
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
|
||||
// create son accounts
|
||||
for(unsigned int i = 0; i < son_number + 1; i++)
|
||||
{
|
||||
sidechain_public_keys.clear();
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin_address " + fc::to_pretty_string(i);
|
||||
sth.create_son("sonaccount" + fc::to_pretty_string(i),
|
||||
"http://son" + fc::to_pretty_string(i), false);
|
||||
"http://son" + fc::to_pretty_string(i),
|
||||
sidechain_public_keys,
|
||||
false);
|
||||
}
|
||||
BOOST_CHECK(generate_maintenance_block());
|
||||
|
||||
|
|
|
|||
143
tests/tests/sidechain_addresses_test.cpp
Normal file
143
tests/tests/sidechain_addresses_test.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "../common/database_fixture.hpp"
|
||||
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/defs.hpp>
|
||||
|
||||
using namespace graphene::chain;
|
||||
using namespace graphene::chain::test;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE( sidechain_addresses_tests, database_fixture )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( sidechain_address_add_test ) {
|
||||
|
||||
BOOST_TEST_MESSAGE("sidechain_address_add_test");
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
ACTORS((alice));
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send sidechain_address_add_operation");
|
||||
|
||||
sidechain_address_add_operation op;
|
||||
|
||||
op.sidechain_address_account = alice_id;
|
||||
op.sidechain = graphene::peerplays_sidechain::sidechain_type::bitcoin;
|
||||
op.address = "address";
|
||||
op.private_key = "private_key";
|
||||
op.public_key = "public_key";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE("Check sidechain_address_add_operation results");
|
||||
|
||||
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>();
|
||||
BOOST_REQUIRE( idx.size() == 1 );
|
||||
auto obj = idx.find( boost::make_tuple( alice_id, graphene::peerplays_sidechain::sidechain_type::bitcoin ) );
|
||||
BOOST_REQUIRE( obj != idx.end() );
|
||||
BOOST_CHECK( obj->sidechain_address_account == alice_id );
|
||||
BOOST_CHECK( obj->sidechain == graphene::peerplays_sidechain::sidechain_type::bitcoin );
|
||||
BOOST_CHECK( obj->address == "address" );
|
||||
BOOST_CHECK( obj->private_key == "private_key" );
|
||||
BOOST_CHECK( obj->public_key == "public_key" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( sidechain_address_update_test ) {
|
||||
|
||||
BOOST_TEST_MESSAGE("sidechain_address_update_test");
|
||||
|
||||
INVOKE(sidechain_address_add_test);
|
||||
|
||||
GET_ACTOR(alice);
|
||||
|
||||
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>();
|
||||
BOOST_REQUIRE( idx.size() == 1 );
|
||||
auto obj = idx.find( boost::make_tuple( alice_id, graphene::peerplays_sidechain::sidechain_type::bitcoin ) );
|
||||
BOOST_REQUIRE( obj != idx.end() );
|
||||
|
||||
std::string new_address = "new_address";
|
||||
std::string new_private_key = "new_private_key";
|
||||
std::string new_public_key = "new_public_key";
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send sidechain_address_update_operation");
|
||||
|
||||
sidechain_address_update_operation op;
|
||||
op.sidechain_address_id = sidechain_address_id_type(0);
|
||||
op.sidechain_address_account = obj->sidechain_address_account;
|
||||
op.sidechain = obj->sidechain;
|
||||
op.address = new_address;
|
||||
op.private_key = new_private_key;
|
||||
op.public_key = new_public_key;
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Check sidechain_address_update_operation results");
|
||||
|
||||
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>();
|
||||
BOOST_REQUIRE( idx.size() == 1 );
|
||||
auto obj = idx.find( boost::make_tuple( alice_id, graphene::peerplays_sidechain::sidechain_type::bitcoin ) );
|
||||
BOOST_REQUIRE( obj != idx.end() );
|
||||
BOOST_CHECK( obj->sidechain_address_account == obj->sidechain_address_account );
|
||||
BOOST_CHECK( obj->sidechain == obj->sidechain );
|
||||
BOOST_CHECK( obj->address == new_address );
|
||||
BOOST_CHECK( obj->private_key == new_private_key );
|
||||
BOOST_CHECK( obj->public_key == new_public_key );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( sidechain_address_delete_test ) {
|
||||
|
||||
BOOST_TEST_MESSAGE("sidechain_address_delete_test");
|
||||
|
||||
INVOKE(sidechain_address_add_test);
|
||||
|
||||
GET_ACTOR(alice);
|
||||
|
||||
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>();
|
||||
BOOST_REQUIRE( idx.size() == 1 );
|
||||
auto obj = idx.find( boost::make_tuple( alice_id, graphene::peerplays_sidechain::sidechain_type::bitcoin ) );
|
||||
BOOST_REQUIRE( obj != idx.end() );
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send sidechain_address_delete_operation");
|
||||
|
||||
sidechain_address_delete_operation op;
|
||||
op.sidechain_address_id = sidechain_address_id_type(0);
|
||||
op.sidechain_address_account = obj->sidechain_address_account;
|
||||
op.sidechain = obj->sidechain;
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Check sidechain_address_delete_operation results");
|
||||
|
||||
const auto& idx = db.get_index_type<sidechain_address_index>().indices().get<by_account_and_sidechain>();
|
||||
BOOST_REQUIRE( idx.size() == 0 );
|
||||
auto obj = idx.find( boost::make_tuple( alice_id, graphene::peerplays_sidechain::sidechain_type::bitcoin ) );
|
||||
BOOST_REQUIRE( obj == idx.end() );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
|
@ -83,12 +83,16 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
|
|||
|
||||
// alice became son
|
||||
{
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "bitcoin address";
|
||||
|
||||
son_create_operation op;
|
||||
op.owner_account = alice_id;
|
||||
op.url = test_url;
|
||||
op.deposit = deposit;
|
||||
op.pay_vb = payment;
|
||||
op.signing_key = alice_public_key;
|
||||
op.sidechain_public_keys = sidechain_public_keys;
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
|
|
@ -101,6 +105,7 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
|
|||
BOOST_REQUIRE( obj != idx.end() );
|
||||
BOOST_CHECK( obj->url == test_url );
|
||||
BOOST_CHECK( obj->signing_key == alice_public_key );
|
||||
BOOST_CHECK( obj->sidechain_public_keys.at(graphene::peerplays_sidechain::sidechain_type::bitcoin) == "bitcoin address" );
|
||||
BOOST_CHECK( obj->deposit.instance == deposit.instance.value );
|
||||
BOOST_CHECK( obj->pay_vb.instance == payment.instance.value );
|
||||
}
|
||||
|
|
@ -113,10 +118,14 @@ BOOST_AUTO_TEST_CASE( update_son_test ) {
|
|||
std::string new_url = "https://anewurl.com";
|
||||
|
||||
{
|
||||
flat_map<graphene::peerplays_sidechain::sidechain_type, string> sidechain_public_keys;
|
||||
sidechain_public_keys[graphene::peerplays_sidechain::sidechain_type::bitcoin] = "new bitcoin address";
|
||||
|
||||
son_update_operation op;
|
||||
op.son_id = son_id_type(0);
|
||||
op.owner_account = alice_id;
|
||||
op.new_url = new_url;
|
||||
op.son_id = son_id_type(0);
|
||||
op.new_sidechain_public_keys = sidechain_public_keys;
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
|
|
@ -129,6 +138,7 @@ BOOST_AUTO_TEST_CASE( update_son_test ) {
|
|||
auto obj = idx.find( alice_id );
|
||||
BOOST_REQUIRE( obj != idx.end() );
|
||||
BOOST_CHECK( obj->url == new_url );
|
||||
BOOST_CHECK( obj->sidechain_public_keys.at(graphene::peerplays_sidechain::sidechain_type::bitcoin) == "new bitcoin address" );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( delete_son_test ) {
|
||||
|
|
@ -335,7 +345,7 @@ BOOST_AUTO_TEST_CASE( son_pay_test )
|
|||
op.amount = asset(50*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::son;
|
||||
op.policy = dormant_vesting_policy_initializer {};
|
||||
|
||||
|
||||
trx.operations.push_back(op);
|
||||
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||
set_expiration(db, trx);
|
||||
|
|
@ -352,7 +362,7 @@ BOOST_AUTO_TEST_CASE( son_pay_test )
|
|||
op.owner = bob_id;
|
||||
op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
op.balance_type = vesting_balance_type::normal;
|
||||
|
||||
|
||||
trx.operations.push_back(op);
|
||||
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||
set_expiration(db, trx);
|
||||
|
|
@ -652,7 +662,7 @@ BOOST_AUTO_TEST_CASE( son_witness_proposal_test )
|
|||
generate_block();
|
||||
} FC_LOG_AND_RETHROW()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue