diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 68bb4f18..de4762fa 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1906,15 +1906,24 @@ void perform_son_tasks(database& db) const asset_object& btc_asset = db.create( [&gpo, &dyn_asset]( asset_object& a ) { a.symbol = "BTC"; - a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; a.precision = 8; - a.options.flags = 0; - a.options.issuer_permissions = 0; a.issuer = gpo.parameters.son_account(); - a.options.core_exchange_rate.base.amount = 1; + a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + a.options.market_fee_percent = 500; // 5% + a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK; + a.options.flags = asset_issuer_permission_flags::charge_market_fee | + //asset_issuer_permission_flags::white_list | + asset_issuer_permission_flags::override_authority | + asset_issuer_permission_flags::transfer_restricted | + asset_issuer_permission_flags::disable_confidential; + a.options.core_exchange_rate.base.amount = 100000; a.options.core_exchange_rate.base.asset_id = asset_id_type(0); - a.options.core_exchange_rate.quote.amount = 1; + a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value a.options.core_exchange_rate.quote.asset_id = asset_id_type(0); + a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty + a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set + a.options.whitelist_markets.clear(); // might be traded with + a.options.blacklist_markets.clear(); // might not be traded with a.dynamic_asset_data_id = dyn_asset.id; }); db.modify( gpo, [&btc_asset]( global_property_object& gpo ) { @@ -2137,6 +2146,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g p.pending_parameters->extensions.value.son_heartbeat_frequency = p.parameters.extensions.value.son_heartbeat_frequency; if( !p.pending_parameters->extensions.value.son_down_time.valid() ) p.pending_parameters->extensions.value.son_down_time = p.parameters.extensions.value.son_down_time; + if( !p.pending_parameters->extensions.value.son_bitcoin_min_tx_confirmations.valid() ) + p.pending_parameters->extensions.value.son_bitcoin_min_tx_confirmations = p.parameters.extensions.value.son_bitcoin_min_tx_confirmations; p.parameters = std::move(*p.pending_parameters); p.pending_parameters.reset(); } diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 14554ddc..d8b64028 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -234,6 +234,7 @@ #define SON_DEREGISTER_TIME (60*60*12) // 12 Hours in seconds #define SON_HEARTBEAT_FREQUENCY (60*3) // 3 minutes in seconds #define SON_DOWN_TIME (60*3*2) // 2 Heartbeats in seconds +#define SON_BITCOIN_MIN_TX_CONFIRMATIONS (1) #define SON_PAY_TIME (60*60*24) // 1 day #define SON_PAY_MAX (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(200)) #define SWEEPS_DEFAULT_DISTRIBUTION_PERCENTAGE (2*GRAPHENE_1_PERCENT) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index c13cd9a0..50408afc 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -57,6 +57,7 @@ namespace graphene { namespace chain { optional < uint32_t > son_deregister_time = SON_DEREGISTER_TIME; optional < uint32_t > son_heartbeat_frequency = SON_HEARTBEAT_FREQUENCY; optional < uint32_t > son_down_time = SON_DOWN_TIME; + optional < uint16_t > son_bitcoin_min_tx_confirmations = SON_BITCOIN_MIN_TX_CONFIRMATIONS; optional < account_id_type > son_account; optional < asset_id_type > btc_asset; @@ -161,6 +162,9 @@ namespace graphene { namespace chain { inline uint16_t son_down_time()const { return extensions.value.son_down_time.valid() ? *extensions.value.son_down_time : SON_DOWN_TIME; } + inline uint16_t son_bitcoin_min_tx_confirmations()const { + return extensions.value.son_bitcoin_min_tx_confirmations.valid() ? *extensions.value.son_bitcoin_min_tx_confirmations : SON_BITCOIN_MIN_TX_CONFIRMATIONS; + } inline uint32_t gpos_period()const { return extensions.value.gpos_period.valid() ? *extensions.value.gpos_period : GPOS_PERIOD; /// total seconds of current gpos period } @@ -203,6 +207,7 @@ FC_REFLECT( graphene::chain::parameter_extension, (son_deregister_time) (son_heartbeat_frequency) (son_down_time) + (son_bitcoin_min_tx_confirmations) (son_account) (btc_asset) ) diff --git a/libraries/chain/include/graphene/chain/protocol/son_wallet_deposit.hpp b/libraries/chain/include/graphene/chain/protocol/son_wallet_deposit.hpp index a1b44fac..1b6a02c7 100644 --- a/libraries/chain/include/graphene/chain/protocol/son_wallet_deposit.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son_wallet_deposit.hpp @@ -15,6 +15,7 @@ namespace graphene { namespace chain { son_id_type son_id; fc::time_point_sec timestamp; + uint32_t block_num; sidechain_type sidechain; std::string sidechain_uid; std::string sidechain_transaction_id; @@ -47,7 +48,7 @@ namespace graphene { namespace chain { FC_REFLECT(graphene::chain::son_wallet_deposit_create_operation::fee_parameters_type, (fee) ) FC_REFLECT(graphene::chain::son_wallet_deposit_create_operation, (fee)(payer) - (son_id) (timestamp) (sidechain) + (son_id) (timestamp) (block_num) (sidechain) (sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_currency) (sidechain_amount) (peerplays_from) (peerplays_to) (peerplays_asset) ) diff --git a/libraries/chain/include/graphene/chain/protocol/son_wallet_withdraw.hpp b/libraries/chain/include/graphene/chain/protocol/son_wallet_withdraw.hpp index 353d695e..0461d4b2 100644 --- a/libraries/chain/include/graphene/chain/protocol/son_wallet_withdraw.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son_wallet_withdraw.hpp @@ -15,6 +15,7 @@ namespace graphene { namespace chain { son_id_type son_id; fc::time_point_sec timestamp; + uint32_t block_num; sidechain_type sidechain; std::string peerplays_uid; std::string peerplays_transaction_id; @@ -46,7 +47,7 @@ namespace graphene { namespace chain { FC_REFLECT(graphene::chain::son_wallet_withdraw_create_operation::fee_parameters_type, (fee) ) FC_REFLECT(graphene::chain::son_wallet_withdraw_create_operation, (fee)(payer) - (son_id) (timestamp) (sidechain) + (son_id) (timestamp) (block_num) (sidechain) (peerplays_uid) (peerplays_transaction_id) (peerplays_from) (peerplays_asset) (withdraw_sidechain) (withdraw_address) (withdraw_currency) (withdraw_amount) ) diff --git a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp index d3fbe1b3..984a25a6 100644 --- a/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_transaction_object.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace graphene { namespace chain { using namespace graphene::db; diff --git a/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp b/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp index 80c749d2..ae68a64f 100644 --- a/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp +++ b/libraries/chain/include/graphene/chain/son_wallet_deposit_object.hpp @@ -18,6 +18,7 @@ namespace graphene { namespace chain { static const uint8_t type_id = son_wallet_deposit_object_type; time_point_sec timestamp; + uint32_t block_num; sidechain_type sidechain = sidechain_type::unknown; std::string sidechain_uid; std::string sidechain_transaction_id; @@ -61,7 +62,7 @@ namespace graphene { namespace chain { } } // graphene::chain FC_REFLECT_DERIVED( graphene::chain::son_wallet_deposit_object, (graphene::db::object), - (timestamp) (sidechain) + (timestamp) (block_num) (sidechain) (sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_currency) (sidechain_amount) (peerplays_from) (peerplays_to) (peerplays_asset) (expected_reports) (received_reports) diff --git a/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp b/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp index 1afbe8b6..d65f5cab 100644 --- a/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp +++ b/libraries/chain/include/graphene/chain/son_wallet_withdraw_object.hpp @@ -18,6 +18,7 @@ namespace graphene { namespace chain { static const uint8_t type_id = son_wallet_withdraw_object_type; time_point_sec timestamp; + uint32_t block_num; sidechain_type sidechain = sidechain_type::unknown; std::string peerplays_uid; std::string peerplays_transaction_id; @@ -60,7 +61,7 @@ namespace graphene { namespace chain { } } // graphene::chain FC_REFLECT_DERIVED( graphene::chain::son_wallet_withdraw_object, (graphene::db::object), - (timestamp) (sidechain) + (timestamp) (block_num) (sidechain) (peerplays_uid) (peerplays_transaction_id) (peerplays_from) (peerplays_asset) (withdraw_sidechain) (withdraw_address) (withdraw_currency) (withdraw_amount) (expected_reports) (received_reports) diff --git a/libraries/chain/son_wallet_deposit_evaluator.cpp b/libraries/chain/son_wallet_deposit_evaluator.cpp index 88336b2e..24a87e47 100644 --- a/libraries/chain/son_wallet_deposit_evaluator.cpp +++ b/libraries/chain/son_wallet_deposit_evaluator.cpp @@ -66,6 +66,7 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de if (itr == idx.end()) { const auto& new_son_wallet_deposit_object = db().create( [&]( son_wallet_deposit_object& swdo ){ swdo.timestamp = op.timestamp; + swdo.block_num = op.block_num; swdo.sidechain = op.sidechain; swdo.sidechain_uid = op.sidechain_uid; swdo.sidechain_transaction_id = op.sidechain_transaction_id; diff --git a/libraries/chain/son_wallet_withdraw_evaluator.cpp b/libraries/chain/son_wallet_withdraw_evaluator.cpp index 4552cc0f..bf6adaf9 100644 --- a/libraries/chain/son_wallet_withdraw_evaluator.cpp +++ b/libraries/chain/son_wallet_withdraw_evaluator.cpp @@ -65,6 +65,7 @@ object_id_type create_son_wallet_withdraw_evaluator::do_apply(const son_wallet_w if (itr == idx.end()) { const auto& new_son_wallet_withdraw_object = db().create( [&]( son_wallet_withdraw_object& swwo ){ swwo.timestamp = op.timestamp; + swwo.block_num = op.block_num; swwo.sidechain = op.sidechain; swwo.peerplays_uid = op.peerplays_uid; swwo.peerplays_transaction_id = op.peerplays_transaction_id; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/defs.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/defs.hpp index 95026c1b..70618236 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/defs.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/defs.hpp @@ -59,6 +59,7 @@ struct info_for_vin { struct sidechain_event_data { fc::time_point_sec timestamp; + uint32_t block_num; sidechain_type sidechain; std::string sidechain_uid; std::string sidechain_transaction_id; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 7cfb7469..9f718693 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -5,8 +5,7 @@ #include #include -#include -#include +#include #include #include #include @@ -26,13 +25,18 @@ public: std::vector get_sidechain_withdraw_addresses(); std::string get_private_key(std::string public_key); + bool approve_proposal(const proposal_id_type &proposal_id, const son_id_type &son_id); void sidechain_event_data_received(const sidechain_event_data &sed); + + void process_proposals(); + void process_active_sons_change(); void process_deposits(); void process_withdrawals(); void process_sidechain_transactions(); void send_sidechain_transactions(); - virtual void recreate_primary_wallet() = 0; + virtual bool process_proposal(const proposal_object &po) = 0; + virtual void process_primary_wallet() = 0; virtual bool process_deposit(const son_wallet_deposit_object &swdo) = 0; virtual bool process_withdrawal(const son_wallet_withdraw_object &swwo) = 0; virtual std::string process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete) = 0; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index 62363b15..65489598 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -29,13 +29,14 @@ public: std::string decodepsbt(std::string const &tx_psbt); std::string decoderawtransaction(std::string const &tx_hex); std::string encryptwallet(const std::string &passphrase); - uint64_t estimatesmartfee(); + uint64_t estimatesmartfee(uint16_t conf_target = 128); std::string finalizepsbt(std::string const &tx_psbt); std::string getaddressinfo(const std::string &address); std::string getblock(const std::string &block_hash, int32_t verbosity = 2); + std::string gettransaction(const std::string &txid, const bool include_watch_only = false); void importaddress(const std::string &address_or_script); - std::vector listunspent(); - std::vector listunspent_by_address_and_amount(const std::string &address, double transfer_amount); + std::vector listunspent(const uint32_t minconf = 1, const uint32_t maxconf = 9999999); + std::vector listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999); std::string loadwallet(const std::string &filename); bool sendrawtransaction(const std::string &tx_hex); std::string signrawtransactionwithwallet(const std::string &tx_hash); @@ -83,7 +84,8 @@ public: sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options); virtual ~sidechain_net_handler_bitcoin(); - void recreate_primary_wallet(); + bool process_proposal(const proposal_object &po); + void process_primary_wallet(); bool process_deposit(const son_wallet_deposit_object &swdo); bool process_withdrawal(const son_wallet_withdraw_object &swwo); std::string process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp index c2245c6f..f1b75629 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp @@ -13,7 +13,8 @@ public: sidechain_net_handler_peerplays(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options); virtual ~sidechain_net_handler_peerplays(); - void recreate_primary_wallet(); + bool process_proposal(const proposal_object &po); + void process_primary_wallet(); bool process_deposit(const son_wallet_deposit_object &swdo); bool process_withdrawal(const son_wallet_withdraw_object &swwo); std::string process_sidechain_transaction(const sidechain_transaction_object &sto, bool &complete); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp index 29d9c7f1..3e98c2b1 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp @@ -16,7 +16,8 @@ public: virtual ~sidechain_net_manager(); bool create_handler(sidechain_type sidechain, const boost::program_options::variables_map &options); - void recreate_primary_wallet(); + void process_proposals(); + void process_active_sons_change(); void process_deposits(); void process_withdrawals(); void process_sidechain_transactions(); diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index be34f7ca..026cb3b5 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -50,7 +50,9 @@ public: void approve_proposals(); void create_son_down_proposals(); void create_son_deregister_proposals(); - void recreate_primary_wallet(); + + void process_proposals(); + void process_active_sons_change(); void process_deposits(); void process_withdrawals(); void process_sidechain_transactions(); @@ -373,16 +375,16 @@ void peerplays_sidechain_plugin_impl::son_processing() { ("scheduled_son_id", scheduled_son_id)("now", now)); for (son_id_type son_id : plugin.get_sons()) { + current_son_id = son_id; + + // These tasks are executed by + // - All active SONs, no matter if scheduled + // - All previously active SONs + approve_proposals(); + process_proposals(); + process_sidechain_transactions(); if (plugin.is_active_son(son_id)) { - - current_son_id = son_id; - - // Tasks that are executed by all active SONs, no matter if scheduled - // E.g. sending approvals and signing (only signing that can be done in parallel) - approve_proposals(); - process_sidechain_transactions(); - // Tasks that are executed by scheduled and active SON only if (current_son_id == scheduled_son_id) { @@ -390,7 +392,7 @@ void peerplays_sidechain_plugin_impl::son_processing() { create_son_deregister_proposals(); - recreate_primary_wallet(); + process_active_sons_change(); process_deposits(); @@ -400,13 +402,6 @@ void peerplays_sidechain_plugin_impl::son_processing() { send_sidechain_transactions(); } - } else { - // Tasks that are executed by previously active SONs - // E.g. sending approvals and signing that SON was required to do while it was active - //approve_leftover_proposals(); ??? - //process_leftover_sidechain_transactions(); ??? - approve_proposals(); - process_sidechain_transactions(); } } } @@ -423,27 +418,6 @@ bool peerplays_sidechain_plugin_impl::is_valid_son_proposal(const chain::proposa if (op_idx_0 == chain::operation::tag::value) { return is_son_delete_op_valid(op); } - - if (op_idx_0 == chain::operation::tag::value) { - return true; - } - - if (op_idx_0 == chain::operation::tag::value) { - return true; - } - } else if (proposal.proposed_transaction.operations.size() == 2) { - int32_t op_idx_0 = proposal.proposed_transaction.operations[0].which(); - int32_t op_idx_1 = proposal.proposed_transaction.operations[1].which(); - - if ((op_idx_0 == chain::operation::tag::value) && - (op_idx_1 == chain::operation::tag::value)) { - return true; - } - if ((op_idx_0 == chain::operation::tag::value) && - (op_idx_1 == chain::operation::tag::value)) { - return true; - } - } return false; @@ -588,8 +562,12 @@ void peerplays_sidechain_plugin_impl::create_son_deregister_proposals() { } } -void peerplays_sidechain_plugin_impl::recreate_primary_wallet() { - net_manager->recreate_primary_wallet(); +void peerplays_sidechain_plugin_impl::process_proposals() { + net_manager->process_proposals(); +} + +void peerplays_sidechain_plugin_impl::process_active_sons_change() { + net_manager->process_active_sons_change(); } void peerplays_sidechain_plugin_impl::process_deposits() { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index be69f699..ca8a3637 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include namespace graphene { namespace peerplays_sidechain { @@ -51,9 +53,30 @@ std::string sidechain_net_handler::get_private_key(std::string public_key) { return std::string(); } +bool sidechain_net_handler::approve_proposal(const proposal_id_type &proposal_id, const son_id_type &son_id) { + + proposal_update_operation op; + op.fee_paying_account = plugin.get_son_object(son_id).son_account; + op.proposal = proposal_id; + op.active_approvals_to_add = {plugin.get_son_object(son_id).son_account}; + + signed_transaction tx = database.create_signed_transaction(plugin.get_private_key(son_id), op); + try { + database.push_transaction(tx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(tx)); + return true; + } catch (fc::exception e) { + elog("Sending approval from ${son_id} for proposal ${proposal_id} failed with exception ${e}", + ("son_id", son_id)("proposal_id", proposal_id)("e", e.what())); + return false; + } +} + void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_data &sed) { ilog("sidechain_event_data:"); ilog(" timestamp: ${timestamp}", ("timestamp", sed.timestamp)); + ilog(" block_num: ${block_num}", ("block_num", sed.block_num)); ilog(" sidechain: ${sidechain}", ("sidechain", sed.sidechain)); ilog(" sidechain_uid: ${uid}", ("uid", sed.sidechain_uid)); ilog(" sidechain_transaction_id: ${transaction_id}", ("transaction_id", sed.sidechain_transaction_id)); @@ -67,8 +90,13 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ const chain::global_property_object &gpo = database.get_global_properties(); + asset_id_type btc_asset_id = database.get_global_properties().parameters.btc_asset(); + std::string btc_asset_id_str = fc::to_string(btc_asset_id.space_id) + "." + + fc::to_string(btc_asset_id.type_id) + "." + + fc::to_string((uint64_t)btc_asset_id.instance); + // Deposit request - if ((sed.peerplays_from == gpo.parameters.son_account()) && (sed.sidechain_currency != fc::variant(gpo.parameters.btc_asset(), 1).as(1))) { + if ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) != 0)) { for (son_id_type son_id : plugin.get_sons()) { if (plugin.is_active_son(son_id)) { @@ -77,6 +105,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ op.payer = plugin.get_son_object(son_id).son_account; op.son_id = son_id; op.timestamp = sed.timestamp; + op.block_num = sed.block_num; op.sidechain = sed.sidechain; op.sidechain_uid = sed.sidechain_uid; op.sidechain_transaction_id = sed.sidechain_transaction_id; @@ -102,7 +131,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ } // Withdrawal request - if ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency == fc::variant(gpo.parameters.btc_asset(), 1).as(1))) { + if ((sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain_currency.compare(btc_asset_id_str) == 0)) { // BTC Payout only (for now) const auto &sidechain_addresses_idx = database.get_index_type().indices().get(); const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sed.peerplays_from, sidechain_type::bitcoin)); @@ -116,15 +145,18 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ op.payer = plugin.get_son_object(son_id).son_account; op.son_id = son_id; op.timestamp = sed.timestamp; + op.block_num = sed.block_num; op.sidechain = sed.sidechain; op.peerplays_uid = sed.sidechain_uid; op.peerplays_transaction_id = sed.sidechain_transaction_id; op.peerplays_from = sed.peerplays_from; op.peerplays_asset = sed.peerplays_asset; - op.withdraw_sidechain = sidechain_type::bitcoin; // BTC payout only (for now) - op.withdraw_address = addr_itr->withdraw_address; // BTC payout only (for now) - op.withdraw_currency = "BTC"; // BTC payout only (for now) - op.withdraw_amount = sed.peerplays_asset.amount; // BTC payout only (for now) + // BTC payout only (for now) + op.withdraw_sidechain = sidechain_type::bitcoin; + op.withdraw_address = addr_itr->withdraw_address; + op.withdraw_currency = "BTC"; + price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; + op.withdraw_amount = sed.peerplays_asset.amount * btc_price.quote.amount / btc_price.base.amount; signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), op); try { @@ -142,6 +174,100 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ FC_ASSERT(false, "Invalid sidechain event"); } +void sidechain_net_handler::process_proposals() { + const auto &idx = database.get_index_type().indices().get(); + vector proposals; + for (const auto &proposal : idx) { + proposals.push_back(proposal.id); + } + + for (const auto proposal_id : proposals) { + const auto &idx = database.get_index_type().indices().get(); + const auto po = idx.find(proposal_id); + if (po != idx.end()) { + + ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", (*po).id)("son_id", plugin.get_current_son_id())); + + if (po->available_active_approvals.find(plugin.get_current_son_object().son_account) != po->available_active_approvals.end()) { + continue; + } + + bool should_process = false; + + int32_t op_idx_0 = -1; + chain::operation op_obj_idx_0; + int32_t op_idx_1 = -1; + chain::operation op_obj_idx_1; + + if (po->proposed_transaction.operations.size() >= 1) { + op_idx_0 = po->proposed_transaction.operations[0].which(); + op_obj_idx_0 = po->proposed_transaction.operations[0]; + } + + if (po->proposed_transaction.operations.size() >= 2) { + op_idx_1 = po->proposed_transaction.operations[1].which(); + op_obj_idx_1 = po->proposed_transaction.operations[1]; + } + + switch (op_idx_0) { + case chain::operation::tag::value: { + should_process = true; + break; + } + + case chain::operation::tag::value: { + son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swdo = idx.find(swdo_id); + if (swdo != idx.end()) { + should_process = (swdo->sidechain == sidechain); + } + break; + } + + case chain::operation::tag::value: { + son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get().son_wallet_withdraw_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swwo = idx.find(swwo_id); + if (swwo != idx.end()) { + should_process = (swwo->sidechain == sidechain); + } + break; + } + + case chain::operation::tag::value: { + sidechain_type sc = op_obj_idx_0.get().sidechain; + should_process = (sc == sidechain); + break; + } + + default: + should_process = false; + ilog("=================================================="); + ilog("Proposal not processed ${po}", ("po", *po)); + ilog("=================================================="); + } + + if (should_process) { + ilog("Proposal ${po} will be processed by sidechain handler ${sidechain}", ("po", (*po).id)("sidechain", sidechain)); + bool should_approve = process_proposal(*po); + if (should_approve) { + ilog("Proposal ${po} will be approved", ("po", *po)); + approve_proposal(po->id, plugin.get_current_son_id()); + } else { + ilog("Proposal ${po} is not approved", ("po", (*po).id)); + } + } else { + ilog("Proposal ${po} will not be processed by sidechain handler ${sidechain}", ("po", (*po).id)("sidechain", sidechain)); + } + } + } +} + +void sidechain_net_handler::process_active_sons_change() { + process_primary_wallet(); +} + void sidechain_net_handler::process_deposits() { if (database.get_global_properties().active_sons.size() < database.get_chain_properties().immutable_parameters.min_son_count) { return; @@ -166,16 +292,17 @@ void sidechain_net_handler::process_deposits() { swdp_op.payer = gpo.parameters.son_account(); swdp_op.son_wallet_deposit_id = swdo.id; - asset_issue_operation i_op; - i_op.fee = asset(2001000); - i_op.issuer = gpo.parameters.son_account(); - i_op.asset_to_issue = swdo.peerplays_asset; - i_op.issue_to_account = swdo.peerplays_to; + asset_issue_operation ai_op; + ai_op.fee = asset(2001000); + ai_op.issuer = gpo.parameters.son_account(); + price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; + ai_op.asset_to_issue = asset(swdo.peerplays_asset.amount * btc_price.quote.amount / btc_price.base.amount, database.get_global_properties().parameters.btc_asset()); + ai_op.issue_to_account = swdo.peerplays_from; proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; proposal_op.proposed_ops.emplace_back(swdp_op); - proposal_op.proposed_ops.emplace_back(i_op); + proposal_op.proposed_ops.emplace_back(ai_op); uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); @@ -186,7 +313,7 @@ void sidechain_net_handler::process_deposits() { if (plugin.app().p2p_node()) plugin.app().p2p_node()->broadcast(net::trx_message(trx)); } catch (fc::exception e) { - elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + elog("Sending proposal for son wallet deposit process operation failed with exception ${e}", ("e", e.what())); } }); } @@ -215,16 +342,15 @@ void sidechain_net_handler::process_withdrawals() { swwp_op.payer = gpo.parameters.son_account(); swwp_op.son_wallet_withdraw_id = swwo.id; - asset_reserve_operation r_op; - r_op.fee = asset(2001000); - r_op.payer = gpo.parameters.son_account(); - asset_object btc_asset_obj = gpo.parameters.btc_asset()(database); - r_op.amount_to_reserve = btc_asset_obj.amount(swwo.withdraw_amount); + asset_reserve_operation ar_op; + ar_op.fee = asset(2001000); + ar_op.payer = gpo.parameters.son_account(); + ar_op.amount_to_reserve = asset(swwo.withdraw_amount, database.get_global_properties().parameters.btc_asset()); proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; proposal_op.proposed_ops.emplace_back(swwp_op); - proposal_op.proposed_ops.emplace_back(r_op); + proposal_op.proposed_ops.emplace_back(ar_op); uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); @@ -235,7 +361,7 @@ void sidechain_net_handler::process_withdrawals() { if (plugin.app().p2p_node()) plugin.app().p2p_node()->broadcast(net::trx_message(trx)); } catch (fc::exception e) { - elog("Sending proposal for withdraw sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + elog("Sending proposal for son wallet withdraw process operation failed with exception ${e}", ("e", e.what())); } }); } @@ -245,13 +371,13 @@ void sidechain_net_handler::process_sidechain_transactions() { const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, false)); std::for_each(idx_range.first, idx_range.second, [&](const sidechain_transaction_object &sto) { - ilog("Sidechain transaction to process: ${sto}", ("sto", sto)); + ilog("Sidechain transaction to process: ${sto}", ("sto", sto.id)); bool complete = false; std::string processed_sidechain_tx = process_sidechain_transaction(sto, complete); if (processed_sidechain_tx.empty()) { - wlog("Sidechain transaction not processed: ${sto}", ("sto", sto)); + wlog("Sidechain transaction not processed: ${sto}", ("sto", sto.id)); return; } @@ -278,13 +404,13 @@ void sidechain_net_handler::send_sidechain_transactions() { const auto &idx_range = idx.equal_range(std::make_tuple(sidechain, true, false)); std::for_each(idx_range.first, idx_range.second, [&](const sidechain_transaction_object &sto) { - ilog("Sidechain transaction to send: ${sto}", ("sto", sto)); + ilog("Sidechain transaction to send: ${sto}", ("sto", sto.id)); std::string sidechain_transaction = ""; bool sent = send_sidechain_transaction(sto, sidechain_transaction); if (!sent) { - wlog("Sidechain transaction not sent: ${sto}", ("sto", sto)); + wlog("Sidechain transaction not sent: ${sto}", ("sto", sto.id)); return; } @@ -305,8 +431,12 @@ void sidechain_net_handler::send_sidechain_transactions() { }); } -void sidechain_net_handler::recreate_primary_wallet() { - FC_ASSERT(false, "recreate_primary_wallet not implemented"); +bool sidechain_net_handler::process_proposal(const proposal_object &po) { + FC_ASSERT(false, "process_proposal not implemented"); +} + +void sidechain_net_handler::process_primary_wallet() { + FC_ASSERT(false, "process_primary_wallet not implemented"); } bool sidechain_net_handler::process_deposit(const son_wallet_deposit_object &swdo) { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 1e0c0191..92ce2acb 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -300,14 +300,12 @@ std::string bitcoin_rpc_client::encryptwallet(const std::string &passphrase) { return ""; } -uint64_t bitcoin_rpc_client::estimatesmartfee() { - static const auto confirmation_target_blocks = 6; - +uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) { const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"estimatesmartfee\", " - "\"method\": \"estimatesmartfee\", \"params\": [") + - std::to_string(confirmation_target_blocks) + std::string("] }"); + "\"method\": \"estimatesmartfee\", \"params\": [" + + std::to_string(conf_target) + std::string("] }")); - const auto reply = send_post_request(body); + const auto reply = send_post_request(body, true); if (reply.body.empty()) { wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); @@ -421,10 +419,36 @@ std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t return ""; } +std::string bitcoin_rpc_client::gettransaction(const std::string &txid, const bool include_watch_only) { + std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"gettransaction\", \"method\": " + "\"gettransaction\", \"params\": [\"" + + txid + "\"] }"); + + const auto reply = send_post_request(body, true); + + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return ""; + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + return ss.str(); + } + + if (json.count("error") && !json.get_child("error").empty()) { + wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str())); + } + return ""; +} + void bitcoin_rpc_client::importaddress(const std::string &address_or_script) { const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"importaddress\", " - "\"method\": \"importaddress\", \"params\": [") + - std::string("\"") + address_or_script + std::string("\"") + std::string("] }"); + "\"method\": \"importaddress\", \"params\": [" + + std::string("\"") + address_or_script + std::string("\"") + std::string("] }")); const auto reply = send_post_request(body); @@ -444,9 +468,10 @@ void bitcoin_rpc_client::importaddress(const std::string &address_or_script) { } } -std::vector bitcoin_rpc_client::listunspent() { +std::vector bitcoin_rpc_client::listunspent(const uint32_t minconf, const uint32_t maxconf) { const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": " - "\"listunspent\", \"params\": [] }"); + "\"listunspent\", \"params\": [" + + std::to_string(minconf) + "," + std::to_string(maxconf) + "] }"); const auto reply = send_post_request(body); @@ -477,14 +502,15 @@ std::vector bitcoin_rpc_client::listunspent() { return result; } -std::vector bitcoin_rpc_client::listunspent_by_address_and_amount(const std::string &address, double minimum_amount) { +std::vector bitcoin_rpc_client::listunspent_by_address_and_amount(const std::string &address, double minimum_amount, const uint32_t minconf, const uint32_t maxconf) { std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": " - "\"listunspent\", \"params\": ["); - body += std::string("1,999999,[\""); + "\"listunspent\", \"params\": [" + + std::to_string(minconf) + "," + std::to_string(maxconf) + ","); + body += std::string("[\""); body += address; body += std::string("\"],true,{\"minimumAmount\":"); body += std::to_string(minimum_amount); - body += std::string("}] }"); + body += std::string("} ] }"); const auto reply = send_post_request(body); @@ -840,7 +866,98 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() { } } -void sidechain_net_handler_bitcoin::recreate_primary_wallet() { +bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po) { + + ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); + + bool should_approve = false; + + const chain::global_property_object &gpo = database.get_global_properties(); + + int32_t op_idx_0 = -1; + chain::operation op_obj_idx_0; + //int32_t op_idx_1 = -1; + //chain::operation op_obj_idx_1; + + if (po.proposed_transaction.operations.size() >= 1) { + op_idx_0 = po.proposed_transaction.operations[0].which(); + op_obj_idx_0 = po.proposed_transaction.operations[0]; + } + + if (po.proposed_transaction.operations.size() >= 2) { + //op_idx_1 = po.proposed_transaction.operations[1].which(); + //op_obj_idx_1 = po.proposed_transaction.operations[1]; + } + + switch (op_idx_0) { + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + case chain::operation::tag::value: { + son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swdo = idx.find(swdo_id); + if (swdo != idx.end()) { + + std::string swdo_txid = swdo->sidechain_transaction_id; + std::string swdo_address = swdo->sidechain_to; + uint64_t swdo_amount = swdo->sidechain_amount.value; + uint64_t swdo_vout = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-") + 1)); + + std::string tx_str = bitcoin_client->gettransaction(swdo_txid); + std::stringstream tx_ss(tx_str); + boost::property_tree::ptree tx_json; + boost::property_tree::read_json(tx_ss, tx_json); + + if (tx_json.count("error") && tx_json.get_child("error").empty()) { + + std::string tx_txid = tx_json.get("result.txid"); + uint32_t tx_confirmations = tx_json.get("result.confirmations"); + std::string tx_address = ""; + uint64_t tx_amount = 0; + uint64_t tx_vout = 0; + + for (auto &input : tx_json.get_child("result.details")) { + tx_address = input.second.get("address"); + std::string tx_amount_s = input.second.get("amount"); + tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); + tx_amount = std::stoll(tx_amount_s); + std::string tx_vout_s = input.second.get("vout"); + tx_vout = std::stoll(tx_vout_s); + break; + } + + should_approve = (swdo_txid == tx_txid) && + (swdo_address == tx_address) && + (swdo_amount == tx_amount) && + (swdo_vout == tx_vout) && + (gpo.parameters.son_bitcoin_min_tx_confirmations() <= tx_confirmations); + } + } + break; + } + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + default: + should_approve = false; + } + + return should_approve; +} + +void sidechain_net_handler_bitcoin::process_primary_wallet() { const auto &swi = database.get_index_type().indices().get(); const auto &active_sw = swi.rbegin(); if (active_sw != swi.rend()) { @@ -1403,6 +1520,7 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) sidechain_event_data sed; sed.timestamp = database.head_block_time(); + sed.block_num = database.head_block_num(); sed.sidechain = addr_itr->sidechain; sed.sidechain_uid = sidechain_uid; sed.sidechain_transaction_id = v.out.hash_tx; @@ -1410,11 +1528,10 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data) sed.sidechain_to = v.address; sed.sidechain_currency = "BTC"; sed.sidechain_amount = v.out.amount; - sed.peerplays_from = database.get_global_properties().parameters.son_account(); - sed.peerplays_to = addr_itr->sidechain_address_account; - asset_id_type btc_asset_id = database.get_global_properties().parameters.btc_asset(); - asset_object btc_asset = btc_asset_id(database); - sed.peerplays_asset = btc_asset.amount(sed.sidechain_amount); + sed.peerplays_from = addr_itr->sidechain_address_account; + sed.peerplays_to = database.get_global_properties().parameters.son_account(); + price btc_price = database.get(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate; + sed.peerplays_asset = asset(sed.sidechain_amount * btc_price.base.amount / btc_price.quote.amount); sidechain_event_data_received(sed); } } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index 5d0315a5..42d1757d 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -29,7 +29,111 @@ sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidec sidechain_net_handler_peerplays::~sidechain_net_handler_peerplays() { } -void sidechain_net_handler_peerplays::recreate_primary_wallet() { +bool sidechain_net_handler_peerplays::process_proposal(const proposal_object &po) { + + ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); + + bool should_approve = false; + + const chain::global_property_object &gpo = database.get_global_properties(); + + int32_t op_idx_0 = -1; + chain::operation op_obj_idx_0; + //int32_t op_idx_1 = -1; + //chain::operation op_obj_idx_1; + + if (po.proposed_transaction.operations.size() >= 1) { + op_idx_0 = po.proposed_transaction.operations[0].which(); + op_obj_idx_0 = po.proposed_transaction.operations[0]; + } + + if (po.proposed_transaction.operations.size() >= 2) { + //op_idx_1 = po.proposed_transaction.operations[1].which(); + //op_obj_idx_1 = po.proposed_transaction.operations[1]; + } + + switch (op_idx_0) { + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + case chain::operation::tag::value: { + son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swdo = idx.find(swdo_id); + if (swdo != idx.end()) { + + uint32_t swdo_block_num = swdo->block_num; + std::string swdo_sidechain_transaction_id = swdo->sidechain_transaction_id; + uint32_t swdo_op_idx = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-") + 1)); + + const auto &block = database.fetch_block_by_number(swdo_block_num); + + for (const auto &tx : block->transactions) { + if (tx.id().str() == swdo_sidechain_transaction_id) { + operation op = tx.operations[swdo_op_idx]; + transfer_operation t_op = op.get(); + + asset sidechain_asset = asset(swdo->sidechain_amount, fc::variant(swdo->sidechain_currency, 1).as(1)); + price sidechain_asset_price = database.get(sidechain_asset.asset_id).options.core_exchange_rate; + asset peerplays_asset = asset(sidechain_asset.amount * sidechain_asset_price.base.amount / sidechain_asset_price.quote.amount); + + should_approve = (gpo.parameters.son_account() == t_op.to) && + (swdo->peerplays_from == t_op.from) && + (sidechain_asset == t_op.amount) && + (swdo->peerplays_asset == peerplays_asset); + break; + } + } + } + break; + } + + case chain::operation::tag::value: { + son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get().son_wallet_withdraw_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swwo = idx.find(swwo_id); + if (swwo != idx.end()) { + + uint32_t swwo_block_num = swwo->block_num; + std::string swwo_peerplays_transaction_id = swwo->peerplays_transaction_id; + uint32_t swwo_op_idx = std::stoll(swwo->peerplays_uid.substr(swwo->peerplays_uid.find_last_of("-") + 1)); + + const auto &block = database.fetch_block_by_number(swwo_block_num); + + for (const auto &tx : block->transactions) { + if (tx.id().str() == swwo_peerplays_transaction_id) { + operation op = tx.operations[swwo_op_idx]; + transfer_operation t_op = op.get(); + + price asset_price = database.get(t_op.amount.asset_id).options.core_exchange_rate; + asset peerplays_asset = asset(t_op.amount.amount * asset_price.base.amount / asset_price.quote.amount); + + should_approve = (t_op.to == gpo.parameters.son_account()) && + (swwo->peerplays_from == t_op.from) && + (swwo->peerplays_asset == peerplays_asset); + break; + } + } + } + break; + } + + case chain::operation::tag::value: { + should_approve = true; + break; + } + + default: + should_approve = false; + } + + return should_approve; +} + +void sidechain_net_handler_peerplays::process_primary_wallet() { return; } @@ -61,9 +165,6 @@ void sidechain_net_handler_peerplays::on_applied_block(const signed_block &b) { if (transfer_op.to != plugin.database().get_global_properties().parameters.son_account()) { continue; } - // only bitcoin withdraws acepted for now - if (transfer_op.amount.asset_id != plugin.database().get_global_properties().parameters.btc_asset()) - continue; std::stringstream ss; ss << "peerplays" @@ -72,16 +173,18 @@ void sidechain_net_handler_peerplays::on_applied_block(const signed_block &b) { sidechain_event_data sed; sed.timestamp = database.head_block_time(); + sed.block_num = database.head_block_num(); sed.sidechain = sidechain_type::peerplays; sed.sidechain_uid = sidechain_uid; sed.sidechain_transaction_id = trx.id().str(); sed.sidechain_from = fc::to_string(transfer_op.from.space_id) + "." + fc::to_string(transfer_op.from.type_id) + "." + fc::to_string((uint64_t)transfer_op.from.instance); sed.sidechain_to = fc::to_string(transfer_op.to.space_id) + "." + fc::to_string(transfer_op.to.type_id) + "." + fc::to_string((uint64_t)transfer_op.to.instance); - sed.sidechain_currency = fc::to_string(transfer_op.amount.asset_id.space_id) + "." + fc::to_string(transfer_op.amount.asset_id.type_id) + "." + fc::to_string((uint64_t)transfer_op.amount.asset_id.instance); //transfer_op.amount.asset_id(database).symbol; + sed.sidechain_currency = fc::to_string(transfer_op.amount.asset_id.space_id) + "." + fc::to_string(transfer_op.amount.asset_id.type_id) + "." + fc::to_string((uint64_t)transfer_op.amount.asset_id.instance); sed.sidechain_amount = transfer_op.amount.amount; sed.peerplays_from = transfer_op.from; sed.peerplays_to = transfer_op.to; - sed.peerplays_asset = transfer_op.amount; + price asset_price = database.get(transfer_op.amount.asset_id).options.core_exchange_rate; + sed.peerplays_asset = asset(transfer_op.amount.amount * asset_price.base.amount / asset_price.quote.amount); sidechain_event_data_received(sed); } } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp index 826e5d91..ede60bd4 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp @@ -39,9 +39,15 @@ bool sidechain_net_manager::create_handler(sidechain_type sidechain, const boost return ret_val; } -void sidechain_net_manager::recreate_primary_wallet() { +void sidechain_net_manager::process_proposals() { for (size_t i = 0; i < net_handlers.size(); i++) { - net_handlers.at(i)->recreate_primary_wallet(); + net_handlers.at(i)->process_proposals(); + } +} + +void sidechain_net_manager::process_active_sons_change() { + for (size_t i = 0; i < net_handlers.size(); i++) { + net_handlers.at(i)->process_active_sons_change(); } }