From df369df4211365a36fd5ebb0ba18345e0cd329f0 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Mon, 10 Feb 2020 19:17:56 +0100 Subject: [PATCH] Move transfer inside son_wallet_transfer_process_operation --- .../chain/protocol/son_wallet_transfer.hpp | 3 +- .../chain/son_wallet_transfer_object.hpp | 3 +- .../chain/son_wallet_transfer_evaluator.cpp | 60 +++++++++++++++++-- .../peerplays_sidechain_plugin.cpp | 34 +++-------- .../sidechain_net_handler.cpp | 3 + .../sidechain_net_handler_bitcoin.cpp | 2 + 6 files changed, 73 insertions(+), 32 deletions(-) diff --git a/libraries/chain/include/graphene/chain/protocol/son_wallet_transfer.hpp b/libraries/chain/include/graphene/chain/protocol/son_wallet_transfer.hpp index f32eb2a5..38f8dac6 100644 --- a/libraries/chain/include/graphene/chain/protocol/son_wallet_transfer.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son_wallet_transfer.hpp @@ -19,6 +19,7 @@ namespace graphene { namespace chain { int64_t sidechain_amount; chain::account_id_type peerplays_from; chain::account_id_type peerplays_to; + chain::asset peerplays_amount; account_id_type fee_payer()const { return payer; } share_type calculate_fee(const fee_parameters_type& k)const { return 0; } @@ -41,7 +42,7 @@ namespace graphene { namespace chain { FC_REFLECT(graphene::chain::son_wallet_transfer_create_operation::fee_parameters_type, (fee) ) FC_REFLECT(graphene::chain::son_wallet_transfer_create_operation, (fee)(payer) - (timestamp) (sidechain) (sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_amount) (peerplays_from) (peerplays_to)) + (timestamp) (sidechain) (sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_amount) (peerplays_from) (peerplays_to) (peerplays_amount)) FC_REFLECT(graphene::chain::son_wallet_transfer_process_operation::fee_parameters_type, (fee) ) FC_REFLECT(graphene::chain::son_wallet_transfer_process_operation, (fee)(payer) (son_wallet_transfer_id)) diff --git a/libraries/chain/include/graphene/chain/son_wallet_transfer_object.hpp b/libraries/chain/include/graphene/chain/son_wallet_transfer_object.hpp index d5300588..68293784 100644 --- a/libraries/chain/include/graphene/chain/son_wallet_transfer_object.hpp +++ b/libraries/chain/include/graphene/chain/son_wallet_transfer_object.hpp @@ -26,6 +26,7 @@ namespace graphene { namespace chain { int64_t sidechain_amount; chain::account_id_type peerplays_from; chain::account_id_type peerplays_to; + chain::asset peerplays_amount; bool processed; }; @@ -63,5 +64,5 @@ namespace graphene { namespace chain { FC_REFLECT_DERIVED( graphene::chain::son_wallet_transfer_object, (graphene::db::object), (timestamp) (sidechain) (confirmations) (sidechain_uid) (sidechain_transaction_id) (sidechain_from) (sidechain_to) (sidechain_amount) - (peerplays_from) (peerplays_to) + (peerplays_from) (peerplays_to) (peerplays_amount) (processed) ) diff --git a/libraries/chain/son_wallet_transfer_evaluator.cpp b/libraries/chain/son_wallet_transfer_evaluator.cpp index 4a20f91b..6245efa8 100644 --- a/libraries/chain/son_wallet_transfer_evaluator.cpp +++ b/libraries/chain/son_wallet_transfer_evaluator.cpp @@ -1,6 +1,7 @@ #include #include +#include #include namespace graphene { namespace chain { @@ -32,6 +33,7 @@ object_id_type create_son_wallet_transfer_evaluator::do_apply(const son_wallet_t swto.sidechain_amount = op.sidechain_amount; swto.peerplays_from = op.peerplays_from; swto.peerplays_to = op.peerplays_to; + swto.peerplays_amount = op.peerplays_amount; swto.processed = false; }); return new_son_wallet_transfer_object.id; @@ -52,8 +54,48 @@ void_result process_son_wallet_transfer_evaluator::do_evaluate(const son_wallet_ const auto& idx = db().get_index_type().indices().get(); const auto& itr = idx.find(op.son_wallet_transfer_id); FC_ASSERT(itr != idx.end(), "Son wallet transfer not found"); - FC_ASSERT(itr->processed == false, "Son wallet transfer is already processed"); - return void_result(); + //FC_ASSERT(itr->processed == false, "Son wallet transfer is already processed"); + + const database& d = db(); + + const account_object& from_account = itr->peerplays_to(d); // reversed, for deposit + const account_object& to_account = itr->peerplays_from(d); // reversed, for deposit + const asset_object& asset_type = itr->peerplays_amount.asset_id(d); + + try { + + GRAPHENE_ASSERT( + is_authorized_asset( d, from_account, asset_type ), + transfer_from_account_not_whitelisted, + "'from' account ${from} is not whitelisted for asset ${asset}", + ("from",from_account.id) + ("asset",itr->peerplays_amount.asset_id) + ); + GRAPHENE_ASSERT( + is_authorized_asset( d, to_account, asset_type ), + transfer_to_account_not_whitelisted, + "'to' account ${to} is not whitelisted for asset ${asset}", + ("to",to_account.id) + ("asset",itr->peerplays_amount.asset_id) + ); + + if( asset_type.is_transfer_restricted() ) + { + GRAPHENE_ASSERT( + from_account.id == asset_type.issuer || to_account.id == asset_type.issuer, + transfer_restricted_transfer_asset, + "Asset {asset} has transfer_restricted flag enabled", + ("asset", itr->peerplays_amount.asset_id) + ); + } + + bool insufficient_balance = d.get_balance( from_account, asset_type ).amount >= itr->peerplays_amount.amount; + FC_ASSERT( insufficient_balance, + "Insufficient Balance: ${balance}, unable to transfer '${total_transfer}' from account '${a}' to '${t}'", + ("a",from_account.name)("t",to_account.name)("total_transfer",d.to_pretty_string(itr->peerplays_amount))("balance",d.to_pretty_string(d.get_balance(from_account, asset_type))) ); + + return void_result(); + } FC_RETHROW_EXCEPTIONS( error, "Unable to transfer ${a} from ${f} to ${t}", ("a",d.to_pretty_string(itr->peerplays_amount))("f",from_account.name)("t",to_account.name) ); } FC_CAPTURE_AND_RETHROW( (op) ) } object_id_type process_son_wallet_transfer_evaluator::do_apply(const son_wallet_transfer_process_operation& op) @@ -62,9 +104,17 @@ object_id_type process_son_wallet_transfer_evaluator::do_apply(const son_wallet_ auto itr = idx.find(op.son_wallet_transfer_id); if(itr != idx.end()) { - db().modify(*itr, [&op](son_wallet_transfer_object &swto) { - swto.processed = true; - }); + if (itr->processed == false) { + db().modify(*itr, [&op](son_wallet_transfer_object &swto) { + swto.processed = true; + }); + + const account_id_type from_account = itr->peerplays_to; // reversed, for deposit + const account_id_type to_account = itr->peerplays_from; // reversed, for deposit + + db().adjust_balance( from_account, -itr->peerplays_amount ); + db().adjust_balance( to_account, itr->peerplays_amount ); + } } return op.son_wallet_transfer_id; } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index da74ba26..e00f00d2 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -365,21 +365,16 @@ void peerplays_sidechain_plugin_impl::process_deposits() { const chain::global_property_object& gpo = plugin.database().get_global_properties(); - son_wallet_transfer_process_operation p_op; - p_op.payer = gpo.parameters.get_son_btc_account_id(); - p_op.son_wallet_transfer_id = swto.id; - - transfer_operation t_op; - t_op.from = gpo.parameters.get_son_btc_account_id();; - t_op.to = swto.peerplays_from; - t_op.amount = asset(swto.sidechain_amount / 1000000); // For Bitcoin, the exchange rate is 1:1, for others, get the exchange rate from market - for (son_id_type son_id : plugin.get_sons()) { if (plugin.is_active_son(son_id)) { + + son_wallet_transfer_process_operation p_op; + p_op.payer = gpo.parameters.get_son_btc_account_id(); + p_op.son_wallet_transfer_id = swto.id; + proposal_create_operation proposal_op; proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account; proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) ); - proposal_op.proposed_ops.emplace_back( op_wrapper( t_op ) ); uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; proposal_op.expiration_time = time_point_sec( plugin.database().head_block_time().sec_since_epoch() + lifetime ); @@ -389,6 +384,8 @@ void peerplays_sidechain_plugin_impl::process_deposits() { ilog("sidechain_net_handler: transaction validated ${swto} by ${son}", ("swto", swto.id) ("son", son_id)); try { plugin.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)); } catch(fc::exception e){ ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}",("e", e.what())); } @@ -484,21 +481,8 @@ void peerplays_sidechain_plugin_impl::on_objects_new(const vectorproposed_transaction.operations.size() == 1 - //&& proposal->proposed_transaction.operations[0].which() == chain::operation::tag::value) { - // approve_proposal( son_id, proposal->id ); - // continue; - //} - - //if(proposal->proposed_transaction.operations.size() == 1 - //&& proposal->proposed_transaction.operations[0].which() == chain::operation::tag::value) { - // approve_proposal( son_id, proposal->id ); - // continue; - //} - - if(proposal->proposed_transaction.operations.size() == 2 - && proposal->proposed_transaction.operations[0].which() == chain::operation::tag::value - && proposal->proposed_transaction.operations[1].which() == chain::operation::tag::value) { + if(proposal->proposed_transaction.operations.size() == 1 + && proposal->proposed_transaction.operations[0].which() == chain::operation::tag::value) { approve_proposal( son_id, proposal->id ); continue; } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index 90618929..ac50974c 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -66,6 +66,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ op.sidechain_amount = sed.sidechain_amount; op.peerplays_from = sed.peerplays_from; op.peerplays_to = sed.peerplays_to; + op.peerplays_amount = asset(sed.sidechain_amount / 1000); // For Bitcoin, the exchange rate is 1:1, for others, get the exchange rate from market for (son_id_type son_id : plugin.get_sons()) { if (plugin.is_active_son(son_id)) { @@ -79,6 +80,8 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op); 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)); } catch(fc::exception e){ ilog("sidechain_net_handler: sending proposal for son wallet transfer create operation by ${son} failed with exception ${e}", ("son", son_id) ("e", e.what())); } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index ee7a195a..cdd3611e 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -297,6 +297,8 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() { signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), proposal_op); 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)); } catch(fc::exception e){ ilog("sidechain_net_handler: sending proposal for son wallet update operation failed with exception ${e}",("e", e.what())); }