@ -218,6 +218,17 @@ namespace
return reason ;
}
bool is_preferred_input ( const std : : vector < crypto : : key_image > & preferred_input_list , const crypto : : key_image & input ) {
bool res = true ;
if ( preferred_input_list . size ( ) > 0 ) {
auto it = std : : find ( preferred_input_list . begin ( ) , preferred_input_list . end ( ) , input ) ;
if ( it = = preferred_input_list . end ( ) ) {
res = false ;
}
}
return res ;
}
size_t get_num_outputs ( const std : : vector < cryptonote : : tx_destination_entry > & dsts , const std : : vector < tools : : wallet2 : : transfer_details > & transfers , const std : : vector < size_t > & selected_transfers )
{
size_t outputs = dsts . size ( ) ;
@ -10264,7 +10275,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
LOG_PRINT_L2 ( " transfer_selected_rct done " ) ;
}
std : : vector < size_t > wallet2 : : pick_preferred_rct_inputs ( uint64_t needed_money , uint32_t subaddr_account , const std : : set < uint32_t > & subaddr_indices )
std : : vector < size_t > wallet2 : : pick_preferred_rct_inputs ( uint64_t needed_money , uint32_t subaddr_account , const std : : set < uint32_t > & subaddr_indices , const std : : vector < crypto : : key_image > & preferred_input_list )
{
std : : vector < size_t > picks ;
float current_output_relatdness = 1.0f ;
@ -10275,6 +10286,10 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
for ( size_t i = 0 ; i < m_transfers . size ( ) ; + + i )
{
const transfer_details & td = m_transfers [ i ] ;
if ( ! is_preferred_input ( preferred_input_list , td . m_key_image ) ) {
continue ;
}
if ( ! is_spent ( td , false ) & & ! td . m_frozen & & td . is_rct ( ) & & td . amount ( ) > = needed_money & & is_transfer_unlocked ( td ) & & td . m_subaddr_index . major = = subaddr_account & & subaddr_indices . count ( td . m_subaddr_index . minor ) = = 1 )
{
if ( td . amount ( ) > m_ignore_outputs_above | | td . amount ( ) < m_ignore_outputs_below )
@ -10295,6 +10310,10 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
for ( size_t i = 0 ; i < m_transfers . size ( ) ; + + i )
{
const transfer_details & td = m_transfers [ i ] ;
if ( ! is_preferred_input ( preferred_input_list , td . m_key_image ) ) {
continue ;
}
if ( ! is_spent ( td , false ) & & ! td . m_frozen & & ! td . m_key_image_partial & & td . is_rct ( ) & & is_transfer_unlocked ( td ) & & td . m_subaddr_index . major = = subaddr_account & & subaddr_indices . count ( td . m_subaddr_index . minor ) = = 1 )
{
if ( td . amount ( ) > m_ignore_outputs_above | | td . amount ( ) < m_ignore_outputs_below )
@ -10306,6 +10325,10 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
for ( size_t j = i + 1 ; j < m_transfers . size ( ) ; + + j )
{
const transfer_details & td2 = m_transfers [ j ] ;
if ( ! is_preferred_input ( preferred_input_list , td . m_key_image ) ) {
continue ;
}
if ( td2 . amount ( ) > m_ignore_outputs_above | | td2 . amount ( ) < m_ignore_outputs_below )
{
MDEBUG ( " Ignoring output " < < j < < " of amount " < < print_money ( td2 . amount ( ) ) < < " which is outside prescribed range [ " < < print_money ( m_ignore_outputs_below ) < < " , " < < print_money ( m_ignore_outputs_above ) < < " ] " ) ;
@ -10878,7 +10901,7 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image,
// This system allows for sending (almost) the entire balance, since it does
// not generate spurious change in all txes, thus decreasing the instantaneous
// usable balance.
std : : vector < wallet2 : : pending_tx > wallet2 : : create_transactions_2 ( std : : vector < cryptonote : : tx_destination_entry > dsts , const size_t fake_outs_count , const uint64_t unlock_time , uint32_t priority , const std : : vector < uint8_t > & extra , uint32_t subaddr_account , std : : set < uint32_t > subaddr_indices )
std : : vector < wallet2 : : pending_tx > wallet2 : : create_transactions_2 ( std : : vector < cryptonote : : tx_destination_entry > dsts , const size_t fake_outs_count , const uint64_t unlock_time , uint32_t priority , const std : : vector < uint8_t > & extra , uint32_t subaddr_account , std : : set < uint32_t > subaddr_indices , const std : : vector < crypto : : key_image > & preferred_input_list )
{
//ensure device is let in NONE mode in any case
hw : : device & hwdev = m_account . get_device ( ) ;
@ -11019,6 +11042,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
for ( size_t i = 0 ; i < m_transfers . size ( ) ; + + i )
{
const transfer_details & td = m_transfers [ i ] ;
if ( ! is_preferred_input ( preferred_input_list , td . m_key_image ) ) {
continue ;
}
if ( m_ignore_fractional_outputs & & td . amount ( ) < fractional_threshold )
{
MDEBUG ( " Ignoring output " < < i < < " of amount " < < print_money ( td . amount ( ) ) < < " which is below fractional threshold " < < print_money ( fractional_threshold ) ) ;
@ -11103,7 +11130,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
// will get us a known fee.
uint64_t estimated_fee = estimate_fee ( use_per_byte_fee , use_rct , 2 , fake_outs_count , 2 , extra . size ( ) , bulletproof , clsag , bulletproof_plus , use_view_tags , base_fee , fee_quantization_mask ) ;
preferred_inputs = pick_preferred_rct_inputs ( needed_money + estimated_fee , subaddr_account , subaddr_indices );
preferred_inputs = pick_preferred_rct_inputs ( needed_money + estimated_fee , subaddr_account , subaddr_indices , preferred_input_list );
if ( ! preferred_inputs . empty ( ) )
{
string s ;
@ -11139,7 +11166,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
unsigned int original_output_index = 0 ;
std : : vector < size_t > * unused_transfers_indices = & unused_transfers_indices_per_subaddr [ 0 ] . second ;
std : : vector < size_t > * unused_dust_indices = & unused_dust_indices_per_subaddr [ 0 ] . second ;
hwdev . set_mode ( hw : : device : : TRANSACTION_CREATE_FAKE ) ;
while ( ( ! dsts . empty ( ) & & dsts [ 0 ] . amount > 0 ) | | adding_fee | | ! preferred_inputs . empty ( ) | | should_pick_a_second_output ( use_rct , txes . back ( ) . selected_transfers . size ( ) , * unused_transfers_indices , * unused_dust_indices ) ) {
TX & tx = txes . back ( ) ;
@ -11352,7 +11379,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
else
{
LOG_PRINT_L2 ( " We made a tx, adjusting fee and saving it, we need " < < print_money ( needed_fee ) < < " and we have " < < print_money ( test_ptx . fee ) ) ;
do {
while ( needed_fee > test_ptx . fee ) {
if ( use_rct )
transfer_selected_rct ( tx . dsts , tx . selected_transfers , fake_outs_count , outs , valid_public_keys_cache , unlock_time , needed_fee , extra ,
test_tx , test_ptx , rct_config , use_view_tags ) ;
@ -11363,7 +11390,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
needed_fee = calculate_fee ( use_per_byte_fee , test_ptx . tx , txBlob . size ( ) , base_fee , fee_quantization_mask ) ;
LOG_PRINT_L2 ( " Made an attempt at a final " < < get_weight_string ( test_ptx . tx , txBlob . size ( ) ) < < " tx, with " < < print_money ( test_ptx . fee ) < <
" fee and " < < print_money ( test_ptx . change_dts . amount ) < < " change " ) ;
} while ( needed_fee > test_ptx . fee ) ;
}
LOG_PRINT_L2 ( " Made a final " < < get_weight_string ( test_ptx . tx , txBlob . size ( ) ) < < " tx, with " < < print_money ( test_ptx . fee ) < <
" fee and " < < print_money ( test_ptx . change_dts . amount ) < < " change " ) ;
@ -11536,7 +11563,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, s
return true ;
}
std : : vector < wallet2 : : pending_tx > wallet2 : : create_transactions_all ( uint64_t below , const cryptonote : : account_public_address & address , bool is_subaddress , const size_t outputs , const size_t fake_outs_count , const uint64_t unlock_time , uint32_t priority , const std : : vector < uint8_t > & extra , uint32_t subaddr_account , std : : set < uint32_t > subaddr_indices )
std : : vector < wallet2 : : pending_tx > wallet2 : : create_transactions_all ( uint64_t below , const cryptonote : : account_public_address & address , bool is_subaddress , const size_t outputs , const size_t fake_outs_count , const uint64_t unlock_time , uint32_t priority , const std : : vector < uint8_t > & extra , uint32_t subaddr_account , std : : set < uint32_t > subaddr_indices , const std : : vector < crypto : : key_image > & preferred_input_list )
{
std : : vector < size_t > unused_transfers_indices ;
std : : vector < size_t > unused_dust_indices ;
@ -11565,6 +11592,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
for ( size_t i = 0 ; i < m_transfers . size ( ) ; + + i )
{
const transfer_details & td = m_transfers [ i ] ;
if ( ! is_preferred_input ( preferred_input_list , td . m_key_image ) ) {
continue ;
}
if ( m_ignore_fractional_outputs & & td . amount ( ) < fractional_threshold )
{
MDEBUG ( " Ignoring output " < < i < < " of amount " < < print_money ( td . amount ( ) ) < < " which is below threshold " < < print_money ( fractional_threshold ) ) ;