Added control to small input amount

This commit is contained in:
Anton Shkinder 2019-03-07 10:33:17 +03:00 committed by Anzhy Cherrnyavski
parent b747c7bb3c
commit 22826fd680
3 changed files with 94 additions and 2 deletions

View file

@ -202,6 +202,37 @@ full_btc_transaction database::create_btc_transaction( const std::vector<info_fo
return std::make_pair( ctx.get_transaction(), size_fee );
}
bool database::delete_invalid_amount_with_fee( sidechain::input_withdrawal_info& i_w_info, std::vector<info_for_vin> 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_for_vout>& 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_for_vin> 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<operation> 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<operation> 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<info_for_vin>
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<operation>();
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() );
}

View file

@ -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<info_for_vin> >;
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_for_vin> 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_for_vout>& info_vouts,
const info_for_vin& info_pw_vin );
sidechain::full_btc_transaction create_btc_transaction( const std::vector<info_for_vin>& info_vins,
const std::vector<info_for_vout>& info_vouts,

View file

@ -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()