diff --git a/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp b/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp index 115d31ee..953cf3d0 100644 --- a/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp +++ b/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp @@ -28,7 +28,7 @@ namespace graphene { namespace chain { asset fee; account_id_type payer; - bitcoin_transaction_id_type tx_id; + proposal_id_type proposal_id; std::vector signatures; account_id_type fee_payer()const { return payer; } @@ -56,7 +56,7 @@ FC_REFLECT( graphene::chain::bitcoin_transaction_send_operation::fee_parameters_ FC_REFLECT( graphene::chain::bitcoin_transaction_send_operation, (fee)(payer)(unsigned_tx)(redeem_script)(in_amounts)(signatures) ) FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation, (fee)(payer)(tx_id)(signatures) ) +FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation, (fee)(payer)(proposal_id)(signatures) ) FC_REFLECT( graphene::chain::bitcoin_send_transaction_process_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::bitcoin_send_transaction_process_operation, (fee)(payer)(bitcoin_transaction_id) ) diff --git a/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp b/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp index 87a79a7d..315bd36b 100644 --- a/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp @@ -20,6 +20,7 @@ public: void_result do_evaluate(const bitcoin_transaction_sign_operation& o); object_id_type do_apply(const bitcoin_transaction_sign_operation& o); + void update_proposal(const bitcoin_transaction_sign_operation& o); }; class bitcoin_send_transaction_process_evaluator : public evaluator diff --git a/libraries/chain/sidechain_transaction_evaluator.cpp b/libraries/chain/sidechain_transaction_evaluator.cpp index 59a093a4..35740575 100644 --- a/libraries/chain/sidechain_transaction_evaluator.cpp +++ b/libraries/chain/sidechain_transaction_evaluator.cpp @@ -43,26 +43,24 @@ void_result bitcoin_transaction_sign_evaluator::do_evaluate(const bitcoin_transa try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass - const auto &tx_idx = db().get_index_type().indices().get(); - const auto &tx_itr = tx_idx.find(op.tx_id); - FC_ASSERT(tx_idx.end() != tx_itr, "bitcoin transaction not found"); + const auto &proposal_idx = db().get_index_type().indices().get(); + const auto &proposal_itr = proposal_idx.find(op.proposal_id); + FC_ASSERT(proposal_idx.end() != proposal_itr, "proposal not found"); + // Checks can this SON approve this proposal + const auto &sidx = db().get_index_type().indices().get(); + auto son_obj = sidx.find(op.payer); + FC_ASSERT(son_obj != sidx.end(), "Unknown SON as payer"); + // Get bitcoin tx from proposal + FC_ASSERT(proposal_itr->proposed_transaction.operations.size() == 1, "Invalid proposal"); + auto op = proposal_itr->proposed_transaction.operations[0]; + FC_ASSERT(op.which() == chain::operation::tag::value, "Invalid proposal"); + bitcoin_transaction_send_operation btx_op = op.get(); + // Find the SON among the tx signers + auto it = btx_op.signatures.find(son_obj->id); + FC_ASSERT(it != btx_op.signatures.end(), "SON is not tx signer"); + // tx is not signed with this son already + FC_ASSERT(it->second.empty(), "This SON has already signed this tx"); - // Checks can this SON sign this tx - auto can_this_son_sign_this_tx = [&]() { - const auto &sidx = db().get_index_type().indices().get(); - auto son_obj = sidx.find(op.payer); - if (son_obj == sidx.end()) - { - return false; - } - auto it = tx_itr->signatures.find(son_obj->id); - if (it == tx_itr->signatures.end()) - return false; - // tx is not signed with this son already - return it->second.empty(); - }; - - FC_ASSERT(can_this_son_sign_this_tx(), "Invalid approval received"); return void_result(); } FC_CAPTURE_AND_RETHROW((op)) @@ -72,23 +70,45 @@ object_id_type bitcoin_transaction_sign_evaluator::do_apply(const bitcoin_transa { try { - const auto &bitcoin_tx = op.tx_id(db()); + const auto &proposal = op.proposal_id(db()); const auto &sidx = db().get_index_type().indices().get(); auto son_obj = sidx.find(op.payer); - db().modify(bitcoin_tx, [&](bitcoin_transaction_object &btx) { - btx.signatures[son_obj->id] = op.signatures; + db().modify(proposal, [&](proposal_object &po) { + auto bitcoin_transaction_send_op = po.proposed_transaction.operations[0].get(); + bitcoin_transaction_send_op.signatures[son_obj->id] = op.signatures; + po.proposed_transaction.operations[0] = bitcoin_transaction_send_op; }); db().modify( son_obj->statistics( db() ), [&]( son_statistics_object& sso ) { sso.txs_signed += 1; } ); - return bitcoin_tx.id; + update_proposal(op); + return op.proposal_id; } FC_CAPTURE_AND_RETHROW((op)) } +void bitcoin_transaction_sign_evaluator::update_proposal(const bitcoin_transaction_sign_operation &op) +{ + database &d = db(); + proposal_update_operation update_op; + + update_op.fee_paying_account = op.payer; + update_op.proposal = op.proposal_id; + update_op.active_approvals_to_add = {op.payer}; + + bool skip_fee_old = trx_state->skip_fee; + bool skip_fee_schedule_check_old = trx_state->skip_fee_schedule_check; + trx_state->skip_fee = true; + trx_state->skip_fee_schedule_check = true; + + d.apply_operation(*trx_state, update_op); + + trx_state->skip_fee = skip_fee_old; + trx_state->skip_fee_schedule_check = skip_fee_schedule_check_old; +} void_result bitcoin_send_transaction_process_evaluator::do_evaluate(const bitcoin_send_transaction_process_operation &op) { diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 128e1c55..6080a940 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -445,11 +445,6 @@ void peerplays_sidechain_plugin_impl::approve_proposals() { 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() == 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_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index b748c8c8..bd76d96e 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -681,38 +682,44 @@ static bool has_enough_signatures(const bitcoin_transaction_object &tx_object) { return !has_empty; } -void sidechain_net_handler_bitcoin::process_signing() { - const auto &idx = plugin.database().get_index_type().indices().get(); - const auto &idx_range = idx.equal_range(false); - std::for_each(idx_range.first, idx_range.second, - [&](const bitcoin_transaction_object &tx_object) { - // collect signatures - auto sons = plugin.get_sons(); - for (son_id_type son_id : sons) { - auto it = tx_object.signatures.find(son_id); - if (it == tx_object.signatures.end()) - continue; - if (it->second.empty()) - { - bitcoin_transaction_sign_operation op; - son_object s_obj= plugin.get_son_object(son_id); - op.payer = s_obj.son_account; - op.tx_id = tx_object.id; - fc::ecc::private_key k = plugin.get_private_key(son_id); - op.signatures = signatures_for_raw_transaction(tx_object.unsigned_tx, tx_object.in_amounts, tx_object.redeem_script, k); +void sidechain_net_handler_bitcoin::process_signing() +{ + const auto &idx = plugin.database().get_index_type().indices().get(); + vector proposals; + for (const auto &proposal : idx) { + if (proposal.proposed_transaction.operations.size() != 1) + continue; + if (proposal.proposed_transaction.operations[0].which() != chain::operation::tag::value) { + continue; + } + bitcoin_transaction_send_operation tx_object = proposal.proposed_transaction.operations[0].get(); + // collect signatures + auto sons = plugin.get_sons(); + for (son_id_type son_id : sons) { + auto it = tx_object.signatures.find(son_id); + if (it == tx_object.signatures.end()) + continue; + if (it->second.empty()) + { + bitcoin_transaction_sign_operation op; + son_object s_obj= plugin.get_son_object(son_id); + op.payer = s_obj.son_account; + op.proposal_id = proposal.id; + fc::ecc::private_key k = plugin.get_private_key(son_id); + op.signatures = signatures_for_raw_transaction(tx_object.unsigned_tx, tx_object.in_amounts, tx_object.redeem_script, k); - signed_transaction trx = plugin.database().create_signed_transaction(k, op); - 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: bitcoin transaction signing failed with exception ${e}",("e", e.what())); - return; - } - } - } - }); + signed_transaction trx = plugin.database().create_signed_transaction(k, op); + 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: bitcoin transaction signing failed with exception ${e}",("e", e.what())); + return; + } + } + } + } } void sidechain_net_handler_bitcoin::complete_signing() diff --git a/tests/tests/sidechain_transaction_tests.cpp b/tests/tests/sidechain_transaction_tests.cpp index 2a827468..99f75dd6 100644 --- a/tests/tests/sidechain_transaction_tests.cpp +++ b/tests/tests/sidechain_transaction_tests.cpp @@ -231,7 +231,7 @@ BOOST_AUTO_TEST_CASE(bitcoin_transaction_send_test) bitcoin_transaction_sign_operation sign_op; sign_op.payer = alice_id; - //sign_op.proposal_id = proposal_id_type(0); + sign_op.proposal_id = proposal_id_type(0); sign_op.signatures.push_back(a1); sign_op.signatures.push_back(a2); sign_op.signatures.push_back(a3);