Compare commits

...

14 commits

Author SHA1 Message Date
Srdjan Obucina
5d67efa964 Fix crashing errors on bitcoin event received 2019-12-18 02:20:49 +01:00
Srdjan Obucina
4be5743d68 Remove short param for son-id 2019-12-17 15:06:24 +01:00
Srdjan Obucina
fb7c48fb20 Improved peerplays_sidechain_plugin_impl 2019-12-17 14:54:26 +01:00
Srdjan Obucina
c79b215aa0 Fix RPC, add CLI wallet commands for sidechain addresses 2019-12-16 01:56:53 +01:00
Srdjan Obucina
243a269f36 Fix build errors due to merge conflict 2019-12-12 19:35:27 +01:00
Srdjan Obucina
6efbf6c512 Merge branch 'feature/SONs-base' of https://github.com/peerplays-network/peerplays into feature/SON-203 2019-12-12 18:40:29 +01:00
Srdjan Obucina
5085167554 Enable RPC calls 2019-12-11 21:31:34 +01:00
Srdjan Obucina
9f5269e808 Merge branch 'feature/SONs-base' into feature/SON-203 2019-12-11 16:08:48 +01:00
Srdjan Obucina
e374cb16b7 Add sidechain address operation tests 2019-12-10 15:16:27 +01:00
Srdjan Obucina
8ac236e5f5 Reflect missing members of sidechain_address_update_operation 2019-12-09 20:56:07 +01:00
Srdjan Obucina
a2d71689c1 Fix reflection problem 2019-12-09 20:50:40 +01:00
Srdjan Obucina
0ecffdd4a8 WIP: User sidechain address mappings 2019-12-09 00:25:34 +01:00
Srdjan Obucina
4935246caf Revert "WIP: Sidechain objects"
This reverts commit 8676940a28.
2019-12-06 00:30:37 +01:00
Srdjan Obucina
8676940a28 WIP: Sidechain objects 2019-12-06 00:25:44 +01:00
29 changed files with 1004 additions and 228 deletions

View file

@ -14,7 +14,7 @@ add_library( graphene_app
# need to link graphene_debug_witness because plugins aren't sufficiently isolated #246 # 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_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 target_include_directories( graphene_app
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" ) "${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" )

View file

@ -443,6 +443,11 @@ namespace graphene { namespace app {
assert( aobj != nullptr ); assert( aobj != nullptr );
accounts.insert( aobj->son_account ); accounts.insert( aobj->son_account );
break; 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 sport_object_type:
case event_group_object_type: case event_group_object_type:

View file

@ -103,7 +103,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
uint64_t get_asset_count()const; uint64_t get_asset_count()const;
// Peerplays // 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_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<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; 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(), vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
unsigned limit = 100, unsigned limit = 100,
asset_id_type start = asset_id_type() )const; 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, asset_id_type stop,
unsigned limit, unsigned limit,
asset_id_type start )const; asset_id_type start )const;
asset get_lottery_balance( asset_id_type lottery_id )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; 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; asset get_sweeps_vesting_balance_available_for_claim( account_id_type account )const;
// Markets / feeds // Markets / feeds
vector<limit_order_object> get_limit_orders(asset_id_type a, asset_id_type b, uint32_t limit)const; 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; vector<call_order_object> get_call_orders(asset_id_type a, uint32_t limit)const;
@ -152,6 +152,14 @@ 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; map<string, son_id_type> lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const;
uint64_t get_son_count()const; uint64_t get_son_count()const;
// Sidechain addresses
vector<optional<sidechain_address_object>> get_all_sidechain_addresses()const;
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 // Votes
vector<variant> lookup_vote_ids( const vector<vote_id_type>& votes )const; vector<variant> lookup_vote_ids( const vector<vote_id_type>& votes )const;
@ -528,11 +536,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 vector<vector<account_id_type>> database_api_impl::get_key_references( vector<public_key_type> keys )const
{ {
wdump( (keys) ); wdump( (keys) );
const auto& idx = _db.get_index_type<account_index>(); const auto& idx = _db.get_index_type<account_index>();
const auto& aidx = dynamic_cast<const base_primary_index&>(idx); const auto& aidx = dynamic_cast<const base_primary_index&>(idx);
const auto& refs = aidx.get_secondary_index<graphene::chain::account_member_index>(); const auto& refs = aidx.get_secondary_index<graphene::chain::account_member_index>();
vector< vector<account_id_type> > final_result; vector< vector<account_id_type> > final_result;
final_result.reserve(keys.size()); final_result.reserve(keys.size());
@ -648,7 +656,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& proposal_idx = _db.get_index_type<proposal_index>();
const auto& pidx = dynamic_cast<const base_primary_index&>(proposal_idx); 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>(); const auto& proposals_by_account = pidx.get_secondary_index<graphene::chain::required_approval_index>();
std::map<std::string, full_account> results; std::map<std::string, full_account> results;
for (const std::string& account_name_or_id : names_or_ids) for (const std::string& account_name_or_id : names_or_ids)
@ -738,7 +746,7 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
acnt.withdraws.emplace_back(withdraw); 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)); _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)); std::copy(pending_payouts_range.first, pending_payouts_range.second, std::back_inserter(acnt.pending_dividend_payments));
@ -1058,7 +1066,7 @@ vector<asset_object> database_api_impl::get_lotteries( asset_id_type stop,
return result; 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, asset_id_type stop,
unsigned limit, unsigned limit,
asset_id_type start )const asset_id_type start )const
@ -1066,7 +1074,7 @@ vector<asset_object> database_api::get_account_lotteries( account_id_type issuer
return my->get_account_lotteries( issuer, stop, limit, start ); 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, asset_id_type stop,
unsigned limit, unsigned limit,
asset_id_type start )const asset_id_type start )const
@ -1763,6 +1771,101 @@ uint64_t database_api_impl::get_son_count()const
return _db.get_index_type<son_index>().indices().size(); return _db.get_index_type<son_index>().indices().size();
} }
//////////////////////////////////////////////////////////////////////
// //
// Sidechain Accounts //
// //
//////////////////////////////////////////////////////////////////////
vector<optional<sidechain_address_object>> database_api::get_all_sidechain_addresses()const
{
return my->get_all_sidechain_addresses();
}
vector<optional<sidechain_address_object>> database_api_impl::get_all_sidechain_addresses()const
{
vector<optional<sidechain_address_object>> result;
const auto& idx = _db.get_index_type<sidechain_address_index>().indices().get<by_id>();
std::for_each(idx.begin(), idx.end(),
[&result] (const sidechain_address_object& sao) {
result.push_back(sao);
});
return result;
}
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 // // Votes //
@ -2164,7 +2267,7 @@ vector<tournament_object> database_api::get_tournaments(tournament_id_type stop,
vector<tournament_object> database_api_impl::get_tournaments(tournament_id_type stop, vector<tournament_object> database_api_impl::get_tournaments(tournament_id_type stop,
unsigned limit, unsigned limit,
tournament_id_type start) tournament_id_type start)
{ {
vector<tournament_object> result; vector<tournament_object> result;
const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>(); const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>();
@ -2191,7 +2294,7 @@ vector<tournament_object> database_api_impl::get_tournaments_by_state(tournament
unsigned limit, unsigned limit,
tournament_id_type start, tournament_id_type start,
tournament_state state) tournament_state state)
{ {
vector<tournament_object> result; vector<tournament_object> result;
const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>(); const auto& tournament_idx = _db.get_index_type<tournament_index>().indices().get<by_id>();
for (auto elem: tournament_idx) { for (auto elem: tournament_idx) {
@ -2320,7 +2423,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 /// if a connection hangs then this could get backed up and result in
/// a failure to exit cleanly. /// a failure to exit cleanly.
//fc::async([capture_this,this,updates,market_broadcast_queue](){ //fc::async([capture_this,this,updates,market_broadcast_queue](){
//if( _subscribe_callback ) //if( _subscribe_callback )
// _subscribe_callback( updates ); // _subscribe_callback( updates );
for(auto id : ids) for(auto id : ids)

View file

@ -310,6 +310,15 @@ struct get_impacted_account_visitor
void operator()( const son_heartbeat_operation& op ){ void operator()( const son_heartbeat_operation& op ){
_impacted.insert( op.owner_account ); _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 ) void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )

View file

@ -44,6 +44,7 @@
#include <graphene/chain/betting_market_object.hpp> #include <graphene/chain/betting_market_object.hpp>
#include <graphene/chain/global_betting_statistics_object.hpp> #include <graphene/chain/global_betting_statistics_object.hpp>
#include <graphene/chain/son_object.hpp> #include <graphene/chain/son_object.hpp>
#include <graphene/chain/sidechain_address_object.hpp>
#include <graphene/chain/worker_object.hpp> #include <graphene/chain/worker_object.hpp>
#include <graphene/chain/witness_object.hpp> #include <graphene/chain/witness_object.hpp>
@ -602,6 +603,54 @@ class database_api
*/ */
uint64_t get_son_count()const; uint64_t get_son_count()const;
/////////////////////////
// Sidechain Addresses //
/////////////////////////
/**
* @brief Get a list of all sidechain addresses
* @return The list of all sidechain accounts
*
* This function has semantics identical to @ref get_objects
*/
vector<optional<sidechain_address_object>> get_all_sidechain_addresses()const;
/**
* @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 /// WORKERS
/** /**
@ -814,6 +863,14 @@ FC_API(graphene::app::database_api,
(lookup_son_accounts) (lookup_son_accounts)
(get_son_count) (get_son_count)
// Sidechain addresses
(get_all_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 // workers
(get_workers_by_account) (get_workers_by_account)
// Votes // Votes

View file

@ -116,13 +116,15 @@ add_library( graphene_chain
son_evaluator.cpp son_evaluator.cpp
son_object.cpp son_object.cpp
sidechain_address_evaluator.cpp
${HEADERS} ${HEADERS}
${PROTOCOL_HEADERS} ${PROTOCOL_HEADERS}
"${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp" "${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp"
) )
add_dependencies( graphene_chain build_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 target_include_directories( graphene_chain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" ) PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" )

View file

@ -56,6 +56,7 @@
#include <graphene/chain/global_betting_statistics_object.hpp> #include <graphene/chain/global_betting_statistics_object.hpp>
#include <graphene/chain/son_object.hpp> #include <graphene/chain/son_object.hpp>
#include <graphene/chain/son_proposal_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/account_evaluator.hpp>
#include <graphene/chain/asset_evaluator.hpp> #include <graphene/chain/asset_evaluator.hpp>
@ -78,6 +79,7 @@
#include <graphene/chain/betting_market_evaluator.hpp> #include <graphene/chain/betting_market_evaluator.hpp>
#include <graphene/chain/tournament_evaluator.hpp> #include <graphene/chain/tournament_evaluator.hpp>
#include <graphene/chain/son_evaluator.hpp> #include <graphene/chain/son_evaluator.hpp>
#include <graphene/chain/sidechain_address_evaluator.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp> #include <graphene/chain/protocol/fee_schedule.hpp>
@ -248,6 +250,9 @@ void database::initialize_evaluators()
register_evaluator<update_son_evaluator>(); register_evaluator<update_son_evaluator>();
register_evaluator<delete_son_evaluator>(); register_evaluator<delete_son_evaluator>();
register_evaluator<son_heartbeat_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() void database::initialize_indexes()
@ -292,6 +297,8 @@ void database::initialize_indexes()
add_index< primary_index<game_index> >(); add_index< primary_index<game_index> >();
add_index< primary_index<son_proposal_index> >(); add_index< primary_index<son_proposal_index> >();
add_index< primary_index<sidechain_address_index> >();
//Implementation object indexes //Implementation object indexes
add_index< primary_index<transaction_index > >(); add_index< primary_index<transaction_index > >();

View file

@ -297,6 +297,15 @@ struct get_impacted_account_visitor
void operator()( const son_heartbeat_operation& op ) { void operator()( const son_heartbeat_operation& op ) {
_impacted.insert( op.owner_account ); _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 ) 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 ); assert( aobj != nullptr );
accounts.insert( aobj->son_account ); accounts.insert( aobj->son_account );
break; 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;
} }
} }
} }

View file

@ -46,6 +46,7 @@
#include <graphene/chain/protocol/betting_market.hpp> #include <graphene/chain/protocol/betting_market.hpp>
#include <graphene/chain/protocol/tournament.hpp> #include <graphene/chain/protocol/tournament.hpp>
#include <graphene/chain/protocol/son.hpp> #include <graphene/chain/protocol/son.hpp>
#include <graphene/chain/protocol/sidechain_address.hpp>
namespace graphene { namespace chain { namespace graphene { namespace chain {
@ -140,7 +141,10 @@ namespace graphene { namespace chain {
son_create_operation, son_create_operation,
son_update_operation, son_update_operation,
son_delete_operation, son_delete_operation,
son_heartbeat_operation son_heartbeat_operation,
sidechain_address_add_operation,
sidechain_address_update_operation,
sidechain_address_delete_operation
> operation; > operation;
/// @} // operations group /// @} // operations group

View file

@ -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) )

View file

@ -147,6 +147,7 @@ namespace graphene { namespace chain {
bet_object_type, bet_object_type,
son_object_type, son_object_type,
son_proposal_object_type, son_proposal_object_type,
sidechain_address_object_type,
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
}; };
@ -209,6 +210,7 @@ namespace graphene { namespace chain {
class bet_object; class bet_object;
class son_object; class son_object;
class son_proposal_object; class son_proposal_object;
class sidechain_address_object;
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type; typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
@ -237,6 +239,7 @@ namespace graphene { namespace chain {
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type; typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
typedef object_id< protocol_ids, son_object_type, son_object> son_id_type; typedef object_id< protocol_ids, son_object_type, son_object> son_id_type;
typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type; typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type;
typedef object_id< protocol_ids, sidechain_address_object_type, sidechain_address_object> sidechain_address_id_type;
// implementation types // implementation types
class global_property_object; class global_property_object;
@ -421,6 +424,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
(bet_object_type) (bet_object_type)
(son_object_type) (son_object_type)
(son_proposal_object_type) (son_proposal_object_type)
(sidechain_address_object_type)
(OBJECT_TYPE_COUNT) (OBJECT_TYPE_COUNT)
) )
FC_REFLECT_ENUM( graphene::chain::impl_object_type, FC_REFLECT_ENUM( graphene::chain::impl_object_type,
@ -493,6 +497,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::tournament_details_id_type )
FC_REFLECT_TYPENAME( graphene::chain::son_id_type ) FC_REFLECT_TYPENAME( graphene::chain::son_id_type )
FC_REFLECT_TYPENAME( graphene::chain::son_proposal_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, ) FC_REFLECT( graphene::chain::void_t, )

View file

@ -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

View file

@ -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) )

View 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

View file

@ -8,9 +8,10 @@
namespace graphene { namespace peerplays_sidechain { namespace graphene { namespace peerplays_sidechain {
enum network { enum class sidechain_type {
bitcoin, bitcoin,
//ethereum //ethereum,
//eos
}; };
using bytes = std::vector<char>; using bytes = std::vector<char>;
@ -59,7 +60,7 @@ struct info_for_vin
}; };
struct sidechain_event_data { struct sidechain_event_data {
network sidechain; sidechain_type sidechain;
std::string transaction_id; std::string transaction_id;
std::string from; std::string from;
std::string to; std::string to;
@ -68,3 +69,4 @@ struct sidechain_event_data {
} } // graphene::peerplays_sidechain } } // graphene::peerplays_sidechain
FC_REFLECT_ENUM(graphene::peerplays_sidechain::sidechain_type, (bitcoin) )

View file

@ -5,6 +5,8 @@
#include <graphene/chain/account_object.hpp> #include <graphene/chain/account_object.hpp>
#include <graphene/chain/database.hpp> #include <graphene/chain/database.hpp>
#include <graphene/peerplays_sidechain/defs.hpp>
namespace graphene { namespace peerplays_sidechain { namespace graphene { namespace peerplays_sidechain {
using namespace chain; using namespace chain;

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <graphene/peerplays_sidechain/defs.hpp> #include <graphene/peerplays_sidechain/defs.hpp>
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
#include <vector> #include <vector>
@ -10,13 +11,16 @@ namespace graphene { namespace peerplays_sidechain {
class sidechain_net_handler { class sidechain_net_handler {
public: 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(); virtual ~sidechain_net_handler();
std::vector<std::string> get_user_sidechain_address_mapping(); std::vector<std::string> get_sidechain_addresses();
protected: 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 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; virtual std::string transfer( const std::string& from, const std::string& to, const uint64_t amount ) = 0;

View file

@ -56,17 +56,9 @@ private:
class sidechain_net_handler_bitcoin : public sidechain_net_handler { class sidechain_net_handler_bitcoin : public sidechain_net_handler {
public: 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(); 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; bool connection_is_not_defined() const;
std::string create_multisignature_wallet( const std::vector<std::string> public_keys ); 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<zmq_listener> listener;
std::unique_ptr<bitcoin_rpc_client> bitcoin_client; std::unique_ptr<bitcoin_rpc_client> bitcoin_client;
graphene::chain::database* db;
void handle_event( const std::string& event_data); void handle_event( const std::string& event_data);
std::vector<info_for_vin> extract_info_from_block( const std::string& _block ); 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 } } // graphene::peerplays_sidechain

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <graphene/peerplays_sidechain/defs.hpp> #include <graphene/peerplays_sidechain/defs.hpp>
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp> #include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
#include <vector> #include <vector>
@ -11,12 +12,12 @@ namespace graphene { namespace peerplays_sidechain {
class sidechain_net_manager { class sidechain_net_manager {
public: public:
sidechain_net_manager(); sidechain_net_manager(std::shared_ptr<graphene::chain::database> db);
virtual ~sidechain_net_manager(); 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: private:
std::shared_ptr<graphene::chain::database> database;
std::vector<std::unique_ptr<sidechain_net_handler>> net_handlers; std::vector<std::unique_ptr<sidechain_net_handler>> net_handlers;
}; };

View file

@ -1,6 +1,7 @@
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp> #include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
#include <fc/log/logger.hpp> #include <fc/log/logger.hpp>
#include <graphene/chain/sidechain_address_object.hpp>
#include <graphene/peerplays_sidechain/sidechain_net_manager.hpp> #include <graphene/peerplays_sidechain/sidechain_net_manager.hpp>
#include <graphene/utilities/key_conversion.hpp> #include <graphene/utilities/key_conversion.hpp>
@ -14,20 +15,105 @@ namespace detail
class peerplays_sidechain_plugin_impl class peerplays_sidechain_plugin_impl
{ {
public: public:
peerplays_sidechain_plugin_impl(peerplays_sidechain_plugin& _plugin) peerplays_sidechain_plugin_impl(peerplays_sidechain_plugin& _plugin);
: _self( _plugin )
{ }
virtual ~peerplays_sidechain_plugin_impl(); 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();
peerplays_sidechain::sidechain_net_manager _net_manager; private:
peerplays_sidechain_plugin& plugin;
bool config_ready_son;
bool config_ready_bitcoin;
std::unique_ptr<peerplays_sidechain::sidechain_net_manager> net_manager;
}; };
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() peerplays_sidechain_plugin_impl::~peerplays_sidechain_plugin_impl()
{ {
return; }
void peerplays_sidechain_plugin_impl::plugin_set_program_options(
boost::program_options::options_description& cli,
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", 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]")
("bitcoin-node-ip", bpo::value<string>()->default_value("99.79.189.95"), "IP address of Bitcoin node")
("bitcoin-node-zmq-port", bpo::value<uint32_t>()->default_value(11111), "ZMQ port of Bitcoin node")
("bitcoin-node-rpc-port", bpo::value<uint32_t>()->default_value(22222), "RPC port of Bitcoin node")
("bitcoin-node-rpc-user", bpo::value<string>()->default_value("1"), "Bitcoin RPC user")
("bitcoin-node-rpc-password", bpo::value<string>()->default_value("1"), "Bitcoin RPC password")
("bitcoin-address", bpo::value<string>()->default_value("2N911a7smwDzUGARg8s7Q1ViizFCw6gWcbR"), "Bitcoin address")
("bitcoin-public-key", bpo::value<string>()->default_value("02d0f137e717fb3aab7aff99904001d49a0a636c5e1342f8927a4ba2eaee8e9772"), "Bitcoin public key")
("bitcoin-private-key", bpo::value<string>()->default_value("cVN31uC9sTEr392DLVUEjrtMgLA8Yb3fpYmTRj7bomTm6nn2ANPr"), "Bitcoin private key")
;
cfg.add(cli);
}
void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_options::variables_map& options)
{
config_ready_son = options.count( "son-id" ) && options.count( "peerplays-private-key" );
if (config_ready_son) {
} else {
wlog("Haven't set up SON parameters");
}
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");
//}
}
void peerplays_sidechain_plugin_impl::plugin_startup()
{
if (config_ready_son) {
ilog("SON running");
}
if (config_ready_bitcoin) {
ilog("Bitcoin sidechain handler running");
}
//if (config_ready_ethereum) {
// ilog("Ethereum sidechain handler running");
//}
} }
} // end namespace detail } // end namespace detail
@ -49,47 +135,22 @@ std::string peerplays_sidechain_plugin::plugin_name()const
void peerplays_sidechain_plugin::plugin_set_program_options( void peerplays_sidechain_plugin::plugin_set_program_options(
boost::program_options::options_description& cli, 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"))); ilog("peerplays sidechain plugin: plugin_set_program_options()");
string son_id_example = fc::json::to_string(chain::son_id_type(5)); my->plugin_set_program_options(cli, cfg);
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())
("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]")
("bitcoin-node-ip", bpo::value<string>()->default_value("99.79.189.95"), "IP address of Bitcoin node")
("bitcoin-node-zmq-port", bpo::value<uint32_t>()->default_value(11111), "ZMQ port of Bitcoin node")
("bitcoin-node-rpc-port", bpo::value<uint32_t>()->default_value(22222), "RPC port of Bitcoin node")
("bitcoin-node-rpc-user", bpo::value<string>()->default_value("1"), "Bitcoin RPC user")
("bitcoin-node-rpc-password", bpo::value<string>()->default_value("1"), "Bitcoin RPC password")
("bitcoin-address", bpo::value<string>()->default_value("2N911a7smwDzUGARg8s7Q1ViizFCw6gWcbR"), "Bitcoin address")
("bitcoin-public-key", bpo::value<string>()->default_value("02d0f137e717fb3aab7aff99904001d49a0a636c5e1342f8927a4ba2eaee8e9772"), "Bitcoin public key")
("bitcoin-private-key", bpo::value<string>()->default_value("cVN31uC9sTEr392DLVUEjrtMgLA8Yb3fpYmTRj7bomTm6nn2ANPr"), "Bitcoin private key")
;
cfg.add(cli);
} }
void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options::variables_map& options) void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ {
ilog("peerplays sidechain plugin: plugin_initialize()"); ilog("peerplays sidechain plugin: plugin_initialize()");
my->plugin_initialize(options);
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);
} else {
wlog("Haven't set up bitcoin sidechain parameters");
}
} }
void peerplays_sidechain_plugin::plugin_startup() void peerplays_sidechain_plugin::plugin_startup()
{ {
ilog("peerplays sidechain plugin: plugin_startup()"); ilog("peerplays sidechain plugin: plugin_startup()");
my->plugin_startup();
} }
} } // graphene::peerplays_sidechain } } // graphene::peerplays_sidechain

View file

@ -1,29 +1,34 @@
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp> #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 { 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() { 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; std::vector<std::string> result;
switch (network) { switch (sidechain) {
case network::bitcoin: case sidechain_type::bitcoin:
result.push_back("2N5aFW5WFaYZLuJWx9RGziHBdEMj9Zf8s3J"); {
result.push_back("2MxAnE469fhhdvUqUB7daU997VSearb2mn7"); const auto& sidechain_addresses_idx = database->get_index_type<sidechain_address_index>();
result.push_back("2NAYptFvTU8vJ1pC7CxvVA9R7D3NdBJHpwL"); const auto& sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get<by_sidechain>();
result.push_back("2N9zPaLDfaJazUmVfr3wgn8BK75tid2kkzR"); const auto& sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain);
result.push_back("2NDN7cDH3E57E1B8TwTYvBgF7CndL4FTBPL"); std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second,
//result.push_back("2MzEmSiwrRzozxE6gfZ14LAyDHZ4DYP1zVG"); [&result] (const sidechain_address_object& sao) {
//result.push_back("2NDCdm1WVJVCMWJzRaSSy9NDvpNKiqkbrMg"); result.push_back(sao.address);
//result.push_back("2Mu2iz3Jfqjyv3hBQGQZSGmZGZxhJp91TNX"); });
//result.push_back("2N1sFbwcn4QVbvjp7yRsN4mg4mBFbvC8gKM"); break;
//result.push_back("2NDmxr6ufBE7Zgdgq9hShF2grx2YPEiTyNy"); }
default: default:
assert(false); assert(false);
} }
@ -31,5 +36,15 @@ std::vector<std::string> sidechain_net_handler::get_user_sidechain_address_mappi
return result; 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 } } // graphene::peerplays_sidechain

View file

@ -11,7 +11,7 @@
#include <fc/log/logger.hpp> #include <fc/log/logger.hpp>
#include <fc/network/ip.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 { namespace graphene { namespace peerplays_sidechain {
@ -178,17 +178,17 @@ void zmq_listener::handle_zmq() {
while ( true ) { while ( true ) {
auto msg = receive_multipart(); auto msg = receive_multipart();
const auto header = std::string( static_cast<char*>( msg[0].data() ), msg[0].size() ); 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_bitcoin::sidechain_net_handler_bitcoin(std::shared_ptr<graphene::chain::database> db, const boost::program_options::variables_map& options) :
sidechain_net_handler(options) { sidechain_net_handler(db, options) {
network = peerplays_sidechain::network::bitcoin; sidechain = sidechain_type::bitcoin;
ip = options.at("bitcoin-node-ip").as<std::string>(); ip = options.at("bitcoin-node-ip").as<std::string>();
zmq_port = options.at("bitcoin-node-zmq-port").as<uint32_t>(); 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 ) ); 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 ) ); 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 ) { listener->event_received.connect([this]( const std::string& event_data ) {
std::thread( &sidechain_net_handler_bitcoin::handle_event, this, event_data ).detach(); 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() { 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 bool sidechain_net_handler_bitcoin::connection_is_not_defined() const
{ {
return listener->connection_is_not_defined() && bitcoin_client->connection_is_not_defined(); 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 ) { void sidechain_net_handler_bitcoin::handle_event( const std::string& event_data ) {
ilog("peerplays sidechain plugin: sidechain_net_handler_bitcoin::handle_event"); ilog("peerplays sidechain plugin: sidechain_net_handler_bitcoin::handle_event");
ilog(" event_data: ${event_data}", ("event_data", event_data)); ilog(" event_data: ${event_data}", ("event_data", event_data));
//update_tx_approvals();
//update_estimated_fee(); std::string block = bitcoin_client->receive_full_block( event_data );
//update_tx_infos( block_hash ); 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 ) 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; 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")) { for (const auto& tx_child : block.get_child("tx")) {
const auto& tx = tx_child.second; 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? 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>(); 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; info_for_vin vin;
vin.out.hash_tx = tx.get_child("txid").get_value<std::string>(); 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.out.n_vout = o.second.get_child( "n" ).get_value<uint32_t>();
vin.address = address_base58; vin.address = address_base58;
result.push_back( vin ); result.push_back( vin );
@ -344,59 +299,6 @@ std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block
return result; 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 } } // graphene::peerplays_sidechain

View file

@ -5,7 +5,9 @@
namespace graphene { namespace peerplays_sidechain { 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__); ilog(__FUNCTION__);
} }
@ -13,16 +15,17 @@ sidechain_net_manager::~sidechain_net_manager() {
ilog(__FUNCTION__); 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__); ilog(__FUNCTION__);
bool ret_val = false; bool ret_val = false;
switch (network) { switch (sidechain) {
case network::bitcoin: { case sidechain_type::bitcoin: {
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_bitcoin(options)); 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)); net_handlers.push_back(std::move(h));
ret_val = true; ret_val = true;
break;
} }
default: default:
assert(false); assert(false);

View file

@ -23,7 +23,7 @@ else()
endif() endif()
add_library( graphene_wallet wallet.cpp ${CMAKE_CURRENT_BINARY_DIR}/api_documentation.cpp ${HEADERS} ) 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" ) target_include_directories( graphene_db PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
if(MSVC) if(MSVC)

View file

@ -1368,6 +1368,89 @@ class wallet_api
*/ */
map<string, son_id_type> list_active_sons(); 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 registered in the system.
*
* @returns the list of all sidechain addresses registered in the system
*/
vector<optional<sidechain_address_object>> get_all_sidechain_addresses ();
/** 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. /** Creates a witness object owned by the given account.
* *
* An account can have at most one witness object. * An account can have at most one witness object.
@ -2121,6 +2204,14 @@ FC_API( graphene::wallet::wallet_api,
(update_son) (update_son)
(delete_son) (delete_son)
(list_sons) (list_sons)
(add_sidechain_address)
(update_sidechain_address)
(delete_sidechain_address)
(get_all_sidechain_addresses)
(get_sidechain_addresses_by_account)
(get_sidechain_addresses_by_sidechain)
(get_sidechain_address_by_account_and_sidechain)
(get_sidechain_addresses_count)
(create_witness) (create_witness)
(update_witness) (update_witness)
(create_worker) (create_worker)

View file

@ -73,6 +73,7 @@
#include <graphene/chain/rock_paper_scissors.hpp> #include <graphene/chain/rock_paper_scissors.hpp>
#include <graphene/bookie/bookie_api.hpp> #include <graphene/bookie/bookie_api.hpp>
#include <graphene/peerplays_sidechain/defs.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp> #include <graphene/chain/protocol/fee_schedule.hpp>
#include <graphene/utilities/git_revision.hpp> #include <graphene/utilities/git_revision.hpp>
@ -1954,6 +1955,73 @@ public:
return result; return result;
} FC_CAPTURE_AND_RETHROW() } } 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, signed_transaction create_witness(string owner_account,
string url, string url,
bool broadcast /* = false */) bool broadcast /* = false */)
@ -4330,6 +4398,60 @@ map<string, son_id_type> wallet_api::list_active_sons()
return my->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_all_sidechain_addresses ()
{
return my->_remote_db->get_all_sidechain_addresses();
}
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, signed_transaction wallet_api::create_witness(string owner_account,
string url, string url,
bool broadcast /* = false */) bool broadcast /* = false */)

View file

@ -44,6 +44,7 @@
#include <graphene/chain/match_object.hpp> #include <graphene/chain/match_object.hpp>
#include <graphene/chain/game_object.hpp> #include <graphene/chain/game_object.hpp>
#include <graphene/chain/son_object.hpp> #include <graphene/chain/son_object.hpp>
#include <graphene/chain/sidechain_address_object.hpp>
#include <fc/smart_ref_impl.hpp> #include <fc/smart_ref_impl.hpp>
#include <iostream> #include <iostream>

View file

@ -8,7 +8,7 @@ endif()
file(GLOB UNIT_TESTS "tests/*.cpp") file(GLOB UNIT_TESTS "tests/*.cpp")
add_executable( chain_test ${UNIT_TESTS} ${COMMON_SOURCES} ) 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) if(MSVC)
set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
endif(MSVC) endif(MSVC)

View 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()