From 7dd0afe257cde1b8ea0679d8ce7b01636cf2b3e1 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Mon, 13 Apr 2020 06:08:45 +0200 Subject: [PATCH] Handle peerplays deposits with transaction settling --- .../sidechain_net_handler.cpp | 42 +++---- .../sidechain_net_handler_peerplays.cpp | 112 +++++++++++++++++- 2 files changed, 128 insertions(+), 26 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 0c7661ab..5fab7a9b 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -426,7 +426,7 @@ void sidechain_net_handler::settle_sidechain_transactions() { int64_t settle_amount = settle_sidechain_transaction(sto); - if (settle_amount == -1) { + if (settle_amount < 0) { wlog("Sidechain transaction not settled: ${sto}", ("sto", sto.id)); return; } @@ -437,29 +437,29 @@ void sidechain_net_handler::settle_sidechain_transactions() { sts_op.payer = gpo.parameters.son_account(); sts_op.sidechain_transaction_id = sto.id; - operation s_op; - - if (sto.object_id.is()) { - asset_issue_operation ai_op; - ai_op.fee = asset(2001000); - ai_op.issuer = gpo.parameters.son_account(); - ai_op.asset_to_issue = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); - ai_op.issue_to_account = database.get(sto.object_id).peerplays_from; - s_op = ai_op; - } - - if (sto.object_id.is()) { - asset_reserve_operation ar_op; - ar_op.fee = asset(2001000); - ar_op.payer = gpo.parameters.son_account(); - ar_op.amount_to_reserve = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); - s_op = ar_op; - } - proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; proposal_op.proposed_ops.emplace_back(sts_op); - proposal_op.proposed_ops.emplace_back(s_op); + + if (settle_amount != 0) { + if (sto.object_id.is()) { + asset_issue_operation ai_op; + ai_op.fee = asset(2001000); + ai_op.issuer = gpo.parameters.son_account(); + ai_op.asset_to_issue = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); + ai_op.issue_to_account = database.get(sto.object_id).peerplays_from; + proposal_op.proposed_ops.emplace_back(ai_op); + } + + if (sto.object_id.is()) { + asset_reserve_operation ar_op; + ar_op.fee = asset(2001000); + ar_op.payer = gpo.parameters.son_account(); + ar_op.amount_to_reserve = asset(settle_amount, database.get_global_properties().parameters.btc_asset()); + 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); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index 7ea2828e..72de3da5 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -15,12 +16,26 @@ #include #include #include +#include namespace graphene { namespace peerplays_sidechain { sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::peerplays; + + if (options.count("peerplays-private-key")) { + const std::vector pub_priv_keys = options["peerplays-private-key"].as>(); + for (const std::string &itr_key_pair : pub_priv_keys) { + auto key_pair = graphene::app::dejsonify>(itr_key_pair, 5); + ilog("Peerplays Public Key: ${public}", ("public", key_pair.first)); + if (!key_pair.first.length() || !key_pair.second.length()) { + FC_THROW("Invalid public private key pair."); + } + private_keys[key_pair.first] = key_pair.second; + } + } + database.applied_block.connect([&](const signed_block &b) { on_applied_block(b); }); @@ -115,7 +130,7 @@ bool sidechain_net_handler_peerplays::process_proposal(const proposal_object &po } case chain::operation::tag::value: { - should_approve = false; + should_approve = true; break; } @@ -139,7 +154,55 @@ void sidechain_net_handler_peerplays::process_primary_wallet() { } bool sidechain_net_handler_peerplays::process_deposit(const son_wallet_deposit_object &swdo) { - return true; + + const chain::global_property_object &gpo = database.get_global_properties(); + + asset_issue_operation ai_op; + 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; + + signed_transaction tx; + auto dyn_props = database.get_dynamic_global_properties(); + tx.set_reference_block(dyn_props.head_block_id); + tx.set_expiration(database.head_block_time() + gpo.parameters.maximum_time_until_expiration); + tx.operations.push_back(ai_op); + database.current_fee_schedule().set_fee(tx.operations.back()); + + std::stringstream ss; + fc::raw::pack(ss, tx, 1000); + std::string tx_str = boost::algorithm::hex(ss.str()); + + if (!tx_str.empty()) { + const chain::global_property_object &gpo = database.get_global_properties(); + + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = swdo.id; + stc_op.sidechain = sidechain; + stc_op.transaction = tx_str; + stc_op.signers = gpo.active_sons; + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + proposal_op.proposed_ops.emplace_back(stc_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); + + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + trx.validate(); + try { + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + return true; + } catch (fc::exception e) { + elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + return false; + } + } + return false; } bool sidechain_net_handler_peerplays::process_withdrawal(const son_wallet_withdraw_object &swwo) { @@ -147,15 +210,54 @@ bool sidechain_net_handler_peerplays::process_withdrawal(const son_wallet_withdr } std::string sidechain_net_handler_peerplays::process_sidechain_transaction(const sidechain_transaction_object &sto) { - return sto.transaction; + + std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); + signed_transaction trx; + fc::raw::unpack(ss_trx, trx, 1000); + + fc::optional privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))); + signature_type st = trx.sign(*privkey, database.get_chain_id()); + + std::stringstream ss_st; + fc::raw::pack(ss_st, st, 1000); + std::string st_str = boost::algorithm::hex(ss_st.str()); + + return st_str; } std::string sidechain_net_handler_peerplays::send_sidechain_transaction(const sidechain_transaction_object &sto) { - return sto.transaction; + + std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); + signed_transaction trx; + fc::raw::unpack(ss_trx, trx, 1000); + + for (auto signature : sto.signatures) { + if (!signature.second.empty()) { + std::stringstream ss_st(boost::algorithm::unhex(signature.second)); + signature_type st; + fc::raw::unpack(ss_st, st, 1000); + + trx.signatures.push_back(st); + trx.signees.clear(); + } + } + + trx.validate(); + try { + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + return trx.id().str(); + } catch (fc::exception e) { + elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + return ""; + } + + return ""; } int64_t sidechain_net_handler_peerplays::settle_sidechain_transaction(const sidechain_transaction_object &sto) { - int64_t settle_amount = -1; + int64_t settle_amount = 0; return settle_amount; }