@ -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 ( ) ;
@ -10317,7 +10328,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 ;
@ -10328,6 +10339,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 )
@ -10348,6 +10363,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 )
@ -10359,6 +10378,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 ) < < " ] " ) ;
@ -10931,7 +10954,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 , const unique_index_container & subtract_fee_from_outputs )
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 unique_index_container & subtract_fee_from_outputs , 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 ( ) ;
@ -11139,6 +11162,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 ) ) ;
@ -11224,7 +11251,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// 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 ) ;
total_needed_money = needed_money + ( subtract_fee_from_outputs . size ( ) ? 0 : estimated_fee ) ;
preferred_inputs = pick_preferred_rct_inputs ( total_needed_money , subaddr_account , subaddr_indices );
preferred_inputs = pick_preferred_rct_inputs ( total_needed_money , subaddr_account , subaddr_indices , preferred_input_list );
if ( ! preferred_inputs . empty ( ) )
{
string s ;
@ -11260,7 +11287,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
unsigned int original_output_index = 0 , destination_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 ( ) ;
@ -11705,7 +11732,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
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 ;
@ -11734,6 +11761,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 ) ) ;