From 22826fd68005e24b825bf17d891495cd1e9b36e8 Mon Sep 17 00:00:00 2001 From: Anton Shkinder Date: Thu, 7 Mar 2019 10:33:17 +0300 Subject: [PATCH] Added control to small input amount --- libraries/chain/db_sidechain.cpp | 40 ++++++++++++++- .../chain/include/graphene/chain/database.hpp | 7 +++ tests/sidechain_tests/db_sidechain_tests.cpp | 49 +++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/libraries/chain/db_sidechain.cpp b/libraries/chain/db_sidechain.cpp index d4e1016b..ad386e81 100644 --- a/libraries/chain/db_sidechain.cpp +++ b/libraries/chain/db_sidechain.cpp @@ -202,6 +202,37 @@ full_btc_transaction database::create_btc_transaction( const std::vector info_vins, const uint64_t& fee, const uint64_t& count_transfer_vout ) +{ + uint64_t size_fee = fee / ( info_vins.size() + count_transfer_vout ); + bool deleted = false; + for( auto info: info_vins ) { + if( info.out.amount < size_fee ) { + wlog("Amount is too small, vin will be ignored (prevout hash tx = ${hash_tx})",("hash_tx", info.out.hash_tx)); + i_w_info.remove_info_for_vin( info ); + deleted = true; + } + } + return deleted; +}; + +database::full_btc_tx_and_new_vins database::create_tx_with_valid_vin( const std::vector& info_vouts, + const info_for_vin& info_pw_vin ) +{ + // we have to be sure, that we have enough BTC on vin to pay size_fee + full_btc_transaction btc_tx_and_fee; + std::vector info_vins = i_w_info.get_info_for_vins(); + bool deleted = true; + + while( info_vins.size() && deleted ) { + btc_tx_and_fee = create_btc_transaction( info_vins, info_vouts, info_pw_vin ); + deleted = delete_invalid_amount_with_fee( i_w_info, info_vins, btc_tx_and_fee.second, info_vouts.size() ); + info_vins = i_w_info.get_info_for_vins(); + } + + return std::make_pair( btc_tx_and_fee, info_vins ); +} + fc::optional database::create_send_btc_tx_proposal( const witness_object& current_witness ) { const auto& info_vins = i_w_info.get_info_for_vins(); @@ -209,12 +240,17 @@ fc::optional database::create_send_btc_tx_proposal( const witness_obj const auto& info_pw_vin = i_w_info.get_info_for_pw_vin(); if( info_pw_vin.valid() && ( info_vins.size() || info_vouts.size() ) ) { - const auto& btc_tx_and_size_fee = create_btc_transaction( info_vins, info_vouts, *info_pw_vin ); + // tx_and_new_vins.first = sidechain::full_btc_transaction; tx_and_new_vins.second = std::vector + const auto& tx_and_new_vins = create_tx_with_valid_vin( info_vouts, *info_pw_vin ); + if( !tx_and_new_vins.second.size() && !info_vouts.size() ) + return fc::optional(); + + const auto& btc_tx_and_size_fee = tx_and_new_vins.first; bitcoin_transaction_send_operation btc_send_op; btc_send_op.payer = get_sidechain_account_id(); btc_send_op.pw_vin = *info_pw_vin; - btc_send_op.vins = info_vins; + btc_send_op.vins = tx_and_new_vins.second; for( auto& out : info_vouts ) { btc_send_op.vouts.push_back( out.get_id() ); } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index f11a3e08..a38ed5b8 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -519,6 +519,8 @@ namespace graphene { namespace chain { //////////////////// db_sidechain.cpp //////////////////// public: + using full_btc_tx_and_new_vins = std::pair< sidechain::full_btc_transaction, std::vector >; + std::map< account_id_type, public_key_type> get_active_witnesses_keys() const; bool is_sidechain_fork_needed() const; void perform_sidechain_fork(); @@ -530,6 +532,11 @@ namespace graphene { namespace chain { int64_t get_estimated_fee( size_t tx_vsize, uint64_t estimated_feerate ); void processing_sidechain_proposals( const witness_object& current_witness, const private_key& signing_private_key ); + + inline bool delete_invalid_amount_with_fee( sidechain::input_withdrawal_info& i_w_info, std::vector info_vins, const uint64_t& fee, const uint64_t& count_transfer_vout ); + + full_btc_tx_and_new_vins create_tx_with_valid_vin( const std::vector& info_vouts, + const info_for_vin& info_pw_vin ); sidechain::full_btc_transaction create_btc_transaction( const std::vector& info_vins, const std::vector& info_vouts, diff --git a/tests/sidechain_tests/db_sidechain_tests.cpp b/tests/sidechain_tests/db_sidechain_tests.cpp index 99ed9a3b..55b7953c 100644 --- a/tests/sidechain_tests/db_sidechain_tests.cpp +++ b/tests/sidechain_tests/db_sidechain_tests.cpp @@ -259,4 +259,53 @@ BOOST_AUTO_TEST_CASE( roll_back_part_test ) } } +BOOST_AUTO_TEST_CASE( not_enough_amount_for_fee ) +{ + test_environment env( db ); + + auto vins = env.vins; + for( auto& vin: vins ) { + db.i_w_info.modify_info_for_vin( vin, [&]( info_for_vin& obj ) { + obj.out.amount = 1; + obj.identifier = fc::sha256::hash( obj.out.hash_tx + std::to_string( obj.out.n_vout ) ); + } ); + vin.out.amount = 1; + } + + auto tx_and_new_infos = db.create_tx_with_valid_vin( env.vouts, env.pw_vin ); + + BOOST_CHECK_EQUAL( tx_and_new_infos.second.size(), 0 ); + BOOST_CHECK_EQUAL( db.i_w_info.get_info_for_vins().size(), 0 ); +} + +BOOST_AUTO_TEST_CASE( not_enough_amount_for_fee_tree_of_five ) +{ + test_environment env( db ); + + auto vins = env.vins; + + for( uint32_t i = 0; i < 3; ++i ) { + db.i_w_info.modify_info_for_vin( vins[i], [&]( info_for_vin& obj ) { + obj.out.amount = 100 + i; + obj.identifier = fc::sha256::hash( obj.out.hash_tx + std::to_string( obj.out.n_vout ) ); + } ); + vins[i].out.amount = 100 + i; + } + + auto tx_and_new_infos = db.create_tx_with_valid_vin( env.vouts, env.pw_vin ); + + BOOST_CHECK_EQUAL( tx_and_new_infos.second.size(), 2 ); + BOOST_CHECK_EQUAL( db.i_w_info.get_info_for_vins().size(), 2 ); +} + +BOOST_AUTO_TEST_CASE( enough_amount_for_fee ) +{ + test_environment env( db ); + + auto tx_and_new_infos = db.create_tx_with_valid_vin( env.vouts, env.pw_vin ); + + BOOST_CHECK_EQUAL( tx_and_new_infos.second.size(), 5 ); + BOOST_CHECK_EQUAL( db.i_w_info.get_info_for_vins().size(), 5 ); +} + BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file