@ -66,6 +66,9 @@
# include "version.h"
# include <stdexcept>
# include "wallet/message_store.h"
# include <unistd.h>
# include <stdlib.h>
# include <time.h>
# ifdef WIN32
# include <boost/locale.hpp>
@ -3225,8 +3228,14 @@ simple_wallet::simple_wallet()
tr ( " Show simplified help section. " ) ) ;
m_cmd_binder . set_handler ( " help_advanced " ,
boost : : bind ( & simple_wallet : : help_advanced , this , _1 ) ,
tr ( " help_advanced [<command>] " ) ,
tr ( " Show the advanced help section or the documentation about a <command>. " ) ) ;
tr ( " help_advanced " ) ,
tr ( " Show the help section or the documentation about a <command>. " ) ) ;
m_cmd_binder . set_handler ( " churn " ,
boost : : bind ( & simple_wallet : : churn , this , _1 ) ,
tr ( " churn " ) ,
tr ( " Churning can enhance privacy by increasing the distance of your funds from the source. This is especially \n "
" important if your funds come from an exchange or a pool that shares public mining data. Each churn also helps \n "
" create more decoy outputs, which is good for constructing stronger ring signatures. " ) ) ;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet : : set_variable ( const std : : vector < std : : string > & args )
@ -4983,10 +4992,12 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid,
( m_long_payment_id_support ? tr ( " WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead. " ) : tr ( " WARNING: this transaction uses an unencrypted payment ID: these are obsolete. Support will be withdrawn in the future. Use subaddresses instead. " ) ) ;
}
}
if ( m_wallet - > auto_confirm_churn ( ) = = 0 ) {
if ( m_auto_refresh_refreshing )
m_cmd_binder . print_prompt ( ) ;
else
m_refresh_progress_reporter . update ( height , true ) ;
}
}
//----------------------------------------------------------------------------------------------------
void simple_wallet : : on_unconfirmed_money_received ( uint64_t height , const crypto : : hash & txid , const cryptonote : : transaction & tx , uint64_t amount , const cryptonote : : subaddress_index & subaddr_index )
@ -4996,15 +5007,18 @@ void simple_wallet::on_unconfirmed_money_received(uint64_t height, const crypto:
//----------------------------------------------------------------------------------------------------
void simple_wallet : : on_money_spent ( uint64_t height , const crypto : : hash & txid , const cryptonote : : transaction & in_tx , uint64_t amount , const cryptonote : : transaction & spend_tx , const cryptonote : : subaddress_index & subaddr_index )
{
message_writer ( console_color_magenta , false ) < < " \r " < <
tr ( " Height " ) < < height < < " , " < <
tr ( " txid " ) < < txid < < " , " < <
tr ( " spent " ) < < print_money ( amount ) < < " , " < <
tr ( " idx " ) < < subaddr_index ;
if ( m_wallet - > auto_confirm_churn ( ) = = 0 ) {
if ( m_auto_refresh_refreshing )
m_cmd_binder . print_prompt ( ) ;
else
m_refresh_progress_reporter . update ( height , true ) ;
}
}
//----------------------------------------------------------------------------------------------------
void simple_wallet : : on_skip_transaction ( uint64_t height , const crypto : : hash & txid , const cryptonote : : transaction & tx )
@ -5210,6 +5224,7 @@ bool simple_wallet::show_balance_unlocked(bool detailed)
extra = tr ( " (Some owned outputs have partial key images - import_multisig_info needed) " ) ;
else if ( m_wallet - > has_unknown_key_images ( ) )
extra + = tr ( " (Some owned outputs have missing key images - import_key_images needed) " ) ;
if ( m_wallet - > auto_confirm_churn ( ) = = 0 ) {
success_msg_writer ( ) < < tr ( " Currently selected account: [ " ) < < m_current_subaddress_account < < tr ( " ] " ) < < m_wallet - > get_subaddress_label ( { m_current_subaddress_account , 0 } ) ;
const std : : string tag = m_wallet - > get_account_tags ( ) . second [ m_current_subaddress_account ] ;
success_msg_writer ( ) < < tr ( " Tag: " ) < < ( tag . empty ( ) ? std : : string { tr ( " (No tag assigned) " ) } : tag ) ;
@ -5219,7 +5234,7 @@ bool simple_wallet::show_balance_unlocked(bool detailed)
if ( blocks_to_unlock > 0 )
unlock_time_message = ( boost : : format ( " (%lu block(s) to unlock) " ) % blocks_to_unlock ) . str ( ) ;
success_msg_writer ( ) < < tr ( " Balance: " ) < < print_money ( m_wallet - > balance ( m_current_subaddress_account ) ) < < " , "
< < tr ( " unlocked balance: " ) < < print_money ( unlocked_balance ) < < unlock_time_message < < extra ;
< < tr ( " unlocked balance: " ) < < print_money ( unlocked_balance ) < < unlock_time_message < < extra ; }
std : : map < uint32_t , uint64_t > balance_per_subaddress = m_wallet - > balance_per_subaddress ( m_current_subaddress_account ) ;
std : : map < uint32_t , std : : pair < uint64_t , uint64_t > > unlocked_balance_per_subaddress = m_wallet - > unlocked_balance_per_subaddress ( m_current_subaddress_account ) ;
if ( ! detailed | | balance_per_subaddress . empty ( ) )
@ -6410,6 +6425,8 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector<st
payment_id_seen = true ;
}
const bool is_wallet_address = m_wallet - > get_address ( ) = = info . address ;
// prompt is there is no payment id and confirmation is required
if ( m_long_payment_id_support & & ! payment_id_seen & & m_wallet - > confirm_missing_payment_id ( ) & & ! info . is_subaddress & & ! is_wallet_address )
{
@ -6438,6 +6455,9 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector<st
}
// give user total and fee, and prompt to confirm
if ( m_wallet - > auto_confirm_churn ( ) = = 0 )
{
uint64_t total_fee = 0 , total_sent = 0 ;
for ( size_t n = 0 ; n < ptx_vector . size ( ) ; + + n )
{
@ -6480,6 +6500,7 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector<st
return true ;
}
}
// actually commit the transactions
if ( m_wallet - > multisig ( ) )
@ -9323,6 +9344,89 @@ bool simple_wallet::process_command(const std::vector<std::string> &args)
return m_cmd_binder . process_command_vec ( args ) ;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet : : churn ( const std : : vector < std : : string > & args_ )
{
// Check if wallet is on MAINNET
if ( m_wallet - > nettype ( ) ! = cryptonote : : MAINNET )
{
fail_msg_writer ( ) < < tr ( " Churning is only possible on Mainnet, operation cancelled. " ) ;
return true ;
}
// Check balance
if ( m_wallet - > unlocked_balance ( m_current_subaddress_account ) < 2 )
{
fail_msg_writer ( ) < < tr ( " You need to have an unlocked balance of more than 2 WOW, operation cancelled. " ) ;
return true ;
}
// Warning
std : : string warning = input_line ( tr ( " Warning: Churning requires your wallet to be open for a few hours. If wallet is left unattended, make sure your computer is in a secure location. Continue? " ) ) ;
if ( std : : cin . eof ( ) | | ! command_line : : is_yes ( warning ) )
{
message_writer ( ) < < tr ( " Operation cancelled. " ) ;
return true ;
}
// Generate pseudo-random integers for the number of churns and interval pause
int churn_number , pause_time , i ;
srand ( time ( NULL ) ) ; // seed RNG with current time
churn_number = rand ( ) % ( 8 + 1 - 2 ) + 2 ; // churn between 2 to 8 times
pause_time = rand ( ) % ( 120 + 1 - 60 ) + 60 ; // wait between 1 to 2 hours per interval
float total_time = static_cast < float > ( churn_number * pause_time ) / 60 ; // calculate how long churning will take in hours
// Calculate fee
float churn_fee = m_wallet - > use_fork_rules ( HF_VERSION_PER_BYTE_FEE ) ? static_cast < float > ( churn_number * 0.015 ) : static_cast < float > ( churn_number * 0.032654 ) ; // usual 2/2 tx fee
// Prompt confirmation
printf ( " ---------------- \n Number of churns: %d \n Total duration: %.2f hours \n Estimated cost: %.2f WOW \n ---------------- \n " , churn_number , total_time , churn_fee ) ;
std : : string confirm_churn = input_line ( tr ( " Continue? " ) ) ;
if ( std : : cin . eof ( ) | | ! command_line : : is_yes ( confirm_churn ) )
{
message_writer ( ) < < tr ( " Operation cancelled. " ) ;
return true ;
}
// Get main address
std : : vector < std : : string > local_args = args_ ;
std : : string address_str ;
address_str = m_wallet - > get_account ( ) . get_public_address_str ( m_wallet - > nettype ( ) ) ;
local_args . push_back ( address_str ) ;
message_writer ( ) < < tr ( " Sweeping entire wallet balance to your main address: " ) ;
message_writer ( console_color_white , true ) < < address_str ;
// Disable wallet confirmations to allow for automation
m_wallet - > auto_confirm_churn ( 1 ) ;
m_wallet - > ask_password ( tools : : wallet2 : : AskPasswordNever ) ;
m_wallet - > always_confirm_transfers ( 0 ) ;
m_wallet - > auto_refresh ( 0 ) ;
// Loop sweep_all to main address for churn_number times with pause_time each interval
for ( i = 1 ; i < = churn_number ; + + i ) {
refresh ( local_args ) ;
sweep_all ( local_args ) ;
message_writer ( console_color_magenta , true ) < < tr ( " \n ---------------- " ) < < i < < tr ( " out of " ) < < churn_number < < tr ( " churns ---------------- " ) ;
if ( i = = churn_number )
{
success_msg_writer ( ) < < tr ( " \n Churning compete. " ) ;
// Re-enable confirmations
m_wallet - > auto_confirm_churn ( 0 ) ;
m_wallet - > ask_password ( tools : : wallet2 : : AskPasswordOnAction ) ;
m_wallet - > always_confirm_transfers ( 1 ) ;
m_wallet - > auto_refresh ( 1 ) ;
}
else
{
message_writer ( ) < < tr ( " \n Interval pause, please wait... \n " ) ;
sleep ( pause_time * 60 ) ;
}
}
return true ;
}
//----------------------------------------------------------------------------------------------------
void simple_wallet : : interrupt ( )
{
if ( m_in_manual_refresh . load ( std : : memory_order_relaxed ) )
@ -9355,9 +9459,14 @@ void simple_wallet::commit_or_save(std::vector<tools::wallet2::pending_tx>& ptx_
}
else
{
if ( m_wallet - > auto_confirm_churn ( ) = = 0 ) {
m_wallet - > commit_tx ( ptx ) ;
success_msg_writer ( true ) < < tr ( " Transaction successfully submitted, transaction " ) < < txid < < ENDL
< < tr ( " You can check its status by using the `show_transfers` command. " ) ;
} else {
m_wallet - > commit_tx ( ptx ) ;
success_msg_writer ( true ) < < tr ( " Churn successfully executed, transaction " ) < < txid ;
}
}
// if no exception, remove element from vector
ptx_vector . pop_back ( ) ;