@ -1392,6 +1392,58 @@ void wallet2::set_unspent(size_t idx)
td . m_spent_height = 0 ;
}
//----------------------------------------------------------------------------------------------------
void wallet2 : : freeze ( size_t idx )
{
CHECK_AND_ASSERT_THROW_MES ( idx < m_transfers . size ( ) , " Invalid transfer_details index " ) ;
transfer_details & td = m_transfers [ idx ] ;
td . m_frozen = true ;
}
//----------------------------------------------------------------------------------------------------
void wallet2 : : thaw ( size_t idx )
{
CHECK_AND_ASSERT_THROW_MES ( idx < m_transfers . size ( ) , " Invalid transfer_details index " ) ;
transfer_details & td = m_transfers [ idx ] ;
td . m_frozen = false ;
}
//----------------------------------------------------------------------------------------------------
bool wallet2 : : frozen ( size_t idx ) const
{
CHECK_AND_ASSERT_THROW_MES ( idx < m_transfers . size ( ) , " Invalid transfer_details index " ) ;
const transfer_details & td = m_transfers [ idx ] ;
return td . m_frozen ;
}
//----------------------------------------------------------------------------------------------------
void wallet2 : : freeze ( const crypto : : key_image & ki )
{
freeze ( get_transfer_details ( ki ) ) ;
}
//----------------------------------------------------------------------------------------------------
void wallet2 : : thaw ( const crypto : : key_image & ki )
{
thaw ( get_transfer_details ( ki ) ) ;
}
//----------------------------------------------------------------------------------------------------
bool wallet2 : : frozen ( const crypto : : key_image & ki ) const
{
return frozen ( get_transfer_details ( ki ) ) ;
}
//----------------------------------------------------------------------------------------------------
size_t wallet2 : : get_transfer_details ( const crypto : : key_image & ki ) const
{
for ( size_t idx = 0 ; idx < m_transfers . size ( ) ; + + idx )
{
const transfer_details & td = m_transfers [ idx ] ;
if ( td . m_key_image_known & & td . m_key_image = = ki )
return idx ;
}
CHECK_AND_ASSERT_THROW_MES ( false , " Key image not found " ) ;
}
//----------------------------------------------------------------------------------------------------
bool wallet2 : : frozen ( const transfer_details & td ) const
{
return td . m_frozen ;
}
//----------------------------------------------------------------------------------------------------
void wallet2 : : check_acc_out_precomp ( const tx_out & o , const crypto : : key_derivation & derivation , const std : : vector < crypto : : key_derivation > & additional_derivations , size_t i , tx_scan_info_t & tx_scan_info ) const
{
hw : : device & hwdev = m_account . get_device ( ) ;
@ -1809,6 +1861,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td . m_mask = rct : : identity ( ) ;
td . m_rct = false ;
}
td . m_frozen = false ;
set_unspent ( m_transfers . size ( ) - 1 ) ;
if ( td . m_key_image_known )
m_key_images [ td . m_key_image ] = m_transfers . size ( ) - 1 ;
@ -3156,8 +3209,9 @@ void wallet2::detach_blockchain(uint64_t height)
wallet2 : : transfer_details & td = m_transfers [ i ] ;
if ( td . m_spent & & td . m_spent_height > = height )
{
LOG_PRINT_L1 ( " Resetting spent status for output " < < i < < " : " < < td . m_key_image ) ;
LOG_PRINT_L1 ( " Resetting spent /frozen status for output " < < i < < " : " < < td . m_key_image ) ;
set_unspent ( i ) ;
thaw ( i ) ;
}
}
@ -5331,7 +5385,7 @@ std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_majo
std : : map < uint32_t , uint64_t > amount_per_subaddr ;
for ( const auto & td : m_transfers )
{
if ( td . m_subaddr_index . major = = index_major & & ! td . m_spent )
if ( td . m_subaddr_index . major = = index_major & & ! td . m_spent & & ! td . m_frozen )
{
auto found = amount_per_subaddr . find ( td . m_subaddr_index . minor ) ;
if ( found = = amount_per_subaddr . end ( ) )
@ -5360,7 +5414,7 @@ std::map<uint32_t, uint64_t> wallet2::unlocked_balance_per_subaddress(uint32_t i
std : : map < uint32_t , uint64_t > amount_per_subaddr ;
for ( const transfer_details & td : m_transfers )
{
if ( td . m_subaddr_index . major = = index_major & & ! td . m_spent & & is_transfer_unlocked ( td ) )
if ( td . m_subaddr_index . major = = index_major & & ! td . m_spent & & ! td . m_frozen & & is_transfer_unlocked ( td ) )
{
auto found = amount_per_subaddr . find ( td . m_subaddr_index . minor ) ;
if ( found = = amount_per_subaddr . end ( ) )
@ -8264,7 +8318,7 @@ 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 ( ! td . m_spent & & 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 . m_spent & & ! 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 )
{
LOG_PRINT_L2 ( " We can use " < < i < < " alone: " < < print_money ( td . amount ( ) ) ) ;
picks . push_back ( i ) ;
@ -8279,13 +8333,13 @@ 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 ( ! td . m_spent & & ! 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 . m_spent & & ! 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 )
{
LOG_PRINT_L2 ( " Considering input " < < i < < " , " < < print_money ( td . amount ( ) ) ) ;
for ( size_t j = i + 1 ; j < m_transfers . size ( ) ; + + j )
{
const transfer_details & td2 = m_transfers [ j ] ;
if ( ! td2 . m_spent & & ! td . m_key_image_partial & & td2 . is_rct ( ) & & td . amount ( ) + td2 . amount ( ) > = needed_money & & is_transfer_unlocked ( td2 ) & & td2 . m_subaddr_index = = td . m_subaddr_index )
if ( ! td2 . m_spent & & ! td 2. m_frozen & & ! td . m_key_image_partial & & td2 . is_rct ( ) & & td . amount ( ) + td2 . amount ( ) > = needed_money & & is_transfer_unlocked ( td2 ) & & td2 . m_subaddr_index = = td . m_subaddr_index )
{
// update our picks if those outputs are less related than any we
// already found. If the same, don't update, and oldest suitable outputs
@ -8512,6 +8566,7 @@ void wallet2::light_wallet_get_unspent_outs()
td . m_pk_index = 0 ;
td . m_internal_output_index = o . index ;
td . m_spent = spent ;
td . m_frozen = false ;
tx_out txout ;
txout . target = txout_to_key ( public_key ) ;
@ -8986,7 +9041,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
MDEBUG ( " Ignoring output " < < i < < " of amount " < < print_money ( td . amount ( ) ) < < " which is below threshold " < < print_money ( fractional_threshold ) ) ;
continue ;
}
if ( ! td . m_spent & & ! td . m_ key_image_partial & & ( use_rct ? true : ! 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 . m_spent & & ! td . m_ frozen & & ! td . m_ key_image_partial & & ( use_rct ? true : ! td . is_rct ( ) ) & & is_transfer_unlocked ( td ) & & td . m_subaddr_index . major = = subaddr_account & & subaddr_indices . count ( td . m_subaddr_index . minor ) = = 1 )
{
const uint32_t index_minor = td . m_subaddr_index . minor ;
auto find_predicate = [ & index_minor ] ( const std : : pair < uint32_t , std : : vector < size_t > > & x ) { return x . first = = index_minor ; } ;
@ -9466,7 +9521,7 @@ 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 ( ! td . m_spent & & ! td . m_ key_image_partial & & ( use_rct ? true : ! td . is_rct ( ) ) & & is_transfer_unlocked ( td ) & & td . m_subaddr_index . major = = subaddr_account & & ( subaddr_indices . empty ( ) | | subaddr_indices . count ( td . m_subaddr_index . minor ) = = 1 ) )
if ( ! td . m_spent & & ! td . m_ frozen & & ! td . m_ key_image_partial & & ( use_rct ? true : ! td . is_rct ( ) ) & & is_transfer_unlocked ( td ) & & td . m_subaddr_index . major = = subaddr_account & & ( subaddr_indices . empty ( ) | | subaddr_indices . count ( td . m_subaddr_index . minor ) = = 1 ) )
{
fund_found = true ;
if ( below = = 0 | | td . amount ( ) < below )
@ -9514,7 +9569,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
for ( size_t i = 0 ; i < m_transfers . size ( ) ; + + i )
{
const transfer_details & td = m_transfers [ i ] ;
if ( td . m_key_image_known & & td . m_key_image = = ki & & ! td . m_spent & & ( use_rct ? true : ! td . is_rct ( ) ) & & is_transfer_unlocked ( td ) )
if ( td . m_key_image_known & & td . m_key_image = = ki & & ! td . m_spent & & ! td . m_frozen & & ( use_rct ? true : ! td . is_rct ( ) ) & & is_transfer_unlocked ( td ) )
{
if ( td . is_rct ( ) | | is_valid_decomposed_amount ( td . amount ( ) ) )
unused_transfers_indices . push_back ( i ) ;
@ -9846,6 +9901,8 @@ std::vector<size_t> wallet2::select_available_outputs(const std::function<bool(c
{
if ( i - > m_spent )
continue ;
if ( i - > m_frozen )
continue ;
if ( i - > m_key_image_partial )
continue ;
if ( ! is_transfer_unlocked ( * i ) )
@ -9861,7 +9918,7 @@ std::vector<uint64_t> wallet2::get_unspent_amounts_vector() const
std : : set < uint64_t > set ;
for ( const auto & td : m_transfers )
{
if ( ! td . m_spent )
if ( ! td . m_spent & & ! td . m_frozen )
set . insert ( td . is_rct ( ) ? 0 : td . amount ( ) ) ;
}
std : : vector < uint64_t > vector ;
@ -9987,7 +10044,7 @@ void wallet2::discard_unmixable_outputs()
std : : vector < size_t > unmixable_outputs = select_available_unmixable_outputs ( ) ;
for ( size_t idx : unmixable_outputs )
{
m_transfers[ idx ] . m_spent = true ;
freeze( idx ) ;
}
}
@ -10770,7 +10827,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
for ( size_t i = 0 ; i < m_transfers . size ( ) ; + + i )
{
const transfer_details & td = m_transfers [ i ] ;
if ( ! td . m_spent & & ( ! account_minreserve | | account_minreserve - > first = = td . m_subaddr_index . major ) )
if ( ! td . m_spent & & ! td . m_frozen & & ( ! account_minreserve | | account_minreserve - > first = = td . m_subaddr_index . major ) )
selected_transfers . push_back ( i ) ;
}
@ -11517,6 +11574,8 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
for ( size_t i = 0 ; i < offset ; + + i )
{
const transfer_details & td = m_transfers [ i ] ;
if ( td . m_frozen )
continue ;
uint64_t amount = td . amount ( ) ;
if ( td . m_spent )
spent + = amount ;
@ -11528,6 +11587,8 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
for ( size_t i = 0 ; i < signed_key_images . size ( ) ; + + i )
{
const transfer_details & td = m_transfers [ i + offset ] ;
if ( td . m_frozen )
continue ;
uint64_t amount = td . amount ( ) ;
if ( td . m_spent )
spent + = amount ;