diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 37a78c80..f8e3e4a5 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -343,6 +343,9 @@ struct get_impacted_account_visitor void operator()( const bitcoin_transaction_sign_operation& op ){ _impacted.insert( op.payer ); } + void operator()( const bitcoin_send_transaction_process_operation& op ){ + _impacted.insert( op.payer ); + } }; void operation_get_impacted_accounts( const operation& op, flat_set& result ) diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index a3a64ecb..19f47791 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -330,6 +330,9 @@ struct get_impacted_account_visitor void operator()( const bitcoin_transaction_sign_operation& op ) { _impacted.insert( op.payer ); } + void operator()( const bitcoin_send_transaction_process_operation& op ) { + _impacted.insert( op.payer ); + } }; void operation_get_impacted_accounts( const operation& op, flat_set& result ) diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index ef0188c6..ff63e763 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -155,7 +155,8 @@ namespace graphene { namespace chain { sidechain_address_update_operation, sidechain_address_delete_operation, bitcoin_transaction_send_operation, - bitcoin_transaction_sign_operation + bitcoin_transaction_sign_operation, + bitcoin_send_transaction_process_operation > operation; /// @} // operations group diff --git a/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp b/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp index e401f406..eb7e942d 100644 --- a/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp +++ b/libraries/chain/include/graphene/chain/protocol/sidechain_transaction.hpp @@ -34,6 +34,20 @@ namespace graphene { namespace chain { share_type calculate_fee( const fee_parameters_type& k )const { return 0; } }; + struct bitcoin_send_transaction_process_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 0; }; + + asset fee; + account_id_type payer; + + bitcoin_transaction_id_type bitcoin_transaction_id; + + account_id_type fee_payer()const { return payer; } + void validate()const {} + share_type calculate_fee( const fee_parameters_type& k )const { return 0; } + }; + } } // graphene::chain FC_REFLECT( graphene::chain::bitcoin_transaction_send_operation::fee_parameters_type, (fee) ) @@ -41,3 +55,6 @@ FC_REFLECT( graphene::chain::bitcoin_transaction_send_operation, (fee)(payer)(si FC_REFLECT( graphene::chain::bitcoin_transaction_sign_operation::fee_parameters_type, (fee) ) 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) ) \ No newline at end of file diff --git a/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp b/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp index 90390fb0..aac04698 100644 --- a/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/sidechain_transaction_evaluator.hpp @@ -23,4 +23,13 @@ public: void update_proposal( const bitcoin_transaction_sign_operation& o ); }; +class bitcoin_send_transaction_process_evaluator : public evaluator +{ +public: + typedef bitcoin_send_transaction_process_operation operation_type; + + void_result do_evaluate(const bitcoin_send_transaction_process_operation& o); + object_id_type do_apply(const bitcoin_send_transaction_process_operation& o); +}; + } } // namespace graphene::chain \ No newline at end of file diff --git a/libraries/chain/sidechain_transaction_evaluator.cpp b/libraries/chain/sidechain_transaction_evaluator.cpp index 292284ea..8b507e96 100644 --- a/libraries/chain/sidechain_transaction_evaluator.cpp +++ b/libraries/chain/sidechain_transaction_evaluator.cpp @@ -6,78 +6,131 @@ #include #include -namespace graphene { namespace chain { - -void_result bitcoin_transaction_send_evaluator::do_evaluate(const bitcoin_transaction_send_operation& op) -{ try{ - FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass - FC_ASSERT(op.payer == db().get_global_properties().parameters.get_son_btc_account_id(), "Payer should be the son btc account"); - return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } - -object_id_type bitcoin_transaction_send_evaluator::do_apply(const bitcoin_transaction_send_operation& op) -{ try { - const auto& new_bitcoin_transaction_object = db().create( [&]( bitcoin_transaction_object& obj ){ - obj.processed = false; - obj.signatures = op.signatures; - }); - return new_bitcoin_transaction_object.id; -} FC_CAPTURE_AND_RETHROW( (op) ) } - -void_result bitcoin_transaction_sign_evaluator::do_evaluate(const bitcoin_transaction_sign_operation& op) -{ try { - FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass - 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 - auto can_this_son_approve_this_proposal = [ & ]() { - const auto& sidx = db().get_index_type().indices().get(); - auto son_obj = sidx.find( op.payer ); - if( son_obj == sidx.end() ) { - return false; - } - // TODO: Check if the SON is included in the PW script. - return true; - }; - - FC_ASSERT(can_this_son_approve_this_proposal(), "Invalid approval received"); - return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } - -object_id_type bitcoin_transaction_sign_evaluator::do_apply(const bitcoin_transaction_sign_operation& op) -{ try { - 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( 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; - }); - - update_proposal( op ); -} FC_CAPTURE_AND_RETHROW( (op) ) } - -void bitcoin_transaction_sign_evaluator::update_proposal( const bitcoin_transaction_sign_operation& op ) +namespace graphene { - database& d = db(); +namespace chain +{ + +void_result bitcoin_transaction_send_evaluator::do_evaluate(const bitcoin_transaction_send_operation &op) +{ + try + { + FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass + FC_ASSERT(op.payer == db().get_global_properties().parameters.get_son_btc_account_id(), "Payer should be the son btc account"); + return void_result(); + } + FC_CAPTURE_AND_RETHROW((op)) +} + +object_id_type bitcoin_transaction_send_evaluator::do_apply(const bitcoin_transaction_send_operation &op) +{ + try + { + const auto &new_bitcoin_transaction_object = db().create([&](bitcoin_transaction_object &obj) { + obj.processed = false; + obj.signatures = op.signatures; + }); + return new_bitcoin_transaction_object.id; + } + FC_CAPTURE_AND_RETHROW((op)) +} + +void_result bitcoin_transaction_sign_evaluator::do_evaluate(const bitcoin_transaction_sign_operation &op) +{ + try + { + FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass + 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 + auto can_this_son_approve_this_proposal = [&]() { + const auto &sidx = db().get_index_type().indices().get(); + auto son_obj = sidx.find(op.payer); + if (son_obj == sidx.end()) + { + return false; + } + // TODO: Check if the SON is included in the PW script. + return true; + }; + + FC_ASSERT(can_this_son_approve_this_proposal(), "Invalid approval received"); + return void_result(); + } + FC_CAPTURE_AND_RETHROW((op)) +} + +object_id_type bitcoin_transaction_sign_evaluator::do_apply(const bitcoin_transaction_sign_operation &op) +{ + try + { + 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(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; + }); + + update_proposal(op); + } + 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 }; + 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 ); + 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; } -} } // namespace graphene::chain +void_result bitcoin_send_transaction_process_evaluator::do_evaluate(const bitcoin_send_transaction_process_operation &op) +{ + try + { + FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass + FC_ASSERT(op.payer == db().get_global_properties().parameters.get_son_btc_account_id(), "Payer should be the son btc account"); + const auto &btidx = db.get_index_type().indices().get(); + const auto btobj = btidx.find(op.bitcoin_transaction_id); + FC_ASSERT(btobj != btidx.end(), "Bitcoin Transaction Object not found"); + FC_ASSERT(btobj->processed == false, "Bitcoin Transaction already processed"); + return void_result(); + } + FC_CAPTURE_AND_RETHROW((op)) +} + +object_id_type bitcoin_send_transaction_process_evaluator::do_apply(const bitcoin_send_transaction_process_operation &op) +{ + try + { + const auto &btidx = db.get_index_type().indices().get(); + auto btobj = btidx.find(op.bitcoin_transaction_id); + if (btobj != btindx.end()) + { + db().modify(*btobj, [&op](bitcoin_transaction_object &bto) { + bto.processed = true; + }); + } + return op.bitcoin_transaction_id; + } + FC_CAPTURE_AND_RETHROW((op)) +} + +} // namespace chain +} // namespace graphene