@ -40,6 +40,7 @@
# include <boost/asio/ip/address.hpp>
# include <boost/asio/ip/address.hpp>
# include <boost/range/adaptor/transformed.hpp>
# include <boost/range/adaptor/transformed.hpp>
# include <boost/preprocessor/stringize.hpp>
# include <boost/preprocessor/stringize.hpp>
# include <openssl/evp.h>
# include "include_base_utils.h"
# include "include_base_utils.h"
using namespace epee ;
using namespace epee ;
@ -138,6 +139,8 @@ using namespace cryptonote;
static const std : : string MULTISIG_SIGNATURE_MAGIC = " SigMultisigPkV1 " ;
static const std : : string MULTISIG_SIGNATURE_MAGIC = " SigMultisigPkV1 " ;
static const std : : string MULTISIG_EXTRA_INFO_MAGIC = " MultisigxV1 " ;
static const std : : string MULTISIG_EXTRA_INFO_MAGIC = " MultisigxV1 " ;
static const std : : string ASCII_OUTPUT_MAGIC = " MoneroAsciiDataV1 " ;
namespace
namespace
{
{
std : : string get_default_ringdb_path ( )
std : : string get_default_ringdb_path ( )
@ -1143,7 +1146,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_device_last_key_image_sync ( 0 ) ,
m_device_last_key_image_sync ( 0 ) ,
m_use_dns ( true ) ,
m_use_dns ( true ) ,
m_offline ( false ) ,
m_offline ( false ) ,
m_rpc_version ( 0 )
m_rpc_version ( 0 ) ,
m_export_format ( ExportFormat : : Binary )
{
{
}
}
@ -3647,6 +3651,9 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2 . SetInt ( m_original_keys_available ? 1 : 0 ) ;
value2 . SetInt ( m_original_keys_available ? 1 : 0 ) ;
json . AddMember ( " original_keys_available " , value2 , json . GetAllocator ( ) ) ;
json . AddMember ( " original_keys_available " , value2 , json . GetAllocator ( ) ) ;
value2 . SetInt ( m_export_format ) ;
json . AddMember ( " export_format " , value2 , json . GetAllocator ( ) ) ;
value2 . SetUint ( 1 ) ;
value2 . SetUint ( 1 ) ;
json . AddMember ( " encrypted_secret_keys " , value2 , json . GetAllocator ( ) ) ;
json . AddMember ( " encrypted_secret_keys " , value2 , json . GetAllocator ( ) ) ;
@ -3684,7 +3691,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
std : : string tmp_file_name = keys_file_name + " .new " ;
std : : string tmp_file_name = keys_file_name + " .new " ;
std : : string buf ;
std : : string buf ;
r = : : serialization : : dump_binary ( keys_file_data , buf ) ;
r = : : serialization : : dump_binary ( keys_file_data , buf ) ;
r = r & & epee: : file_io_utils : : save_string _to_file( tmp_file_name , buf ) ;
r = r & & save_to_file( tmp_file_name , buf ) ;
CHECK_AND_ASSERT_MES ( r , false , " failed to generate wallet keys file " < < tmp_file_name ) ;
CHECK_AND_ASSERT_MES ( r , false , " failed to generate wallet keys file " < < tmp_file_name ) ;
unlock_keys_file ( ) ;
unlock_keys_file ( ) ;
@ -3741,7 +3748,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
wallet2 : : keys_file_data keys_file_data ;
wallet2 : : keys_file_data keys_file_data ;
std : : string buf ;
std : : string buf ;
bool encrypted_secret_keys = false ;
bool encrypted_secret_keys = false ;
bool r = epee: : file_io_utils : : load_file_to_string ( keys_file_name , buf ) ;
bool r = load_from_file ( keys_file_name , buf ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , keys_file_name ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , keys_file_name ) ;
// Decrypt the contents
// Decrypt the contents
@ -3754,7 +3761,6 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
crypto : : chacha20 ( keys_file_data . account_data . data ( ) , keys_file_data . account_data . size ( ) , key , keys_file_data . iv , & account_data [ 0 ] ) ;
crypto : : chacha20 ( keys_file_data . account_data . data ( ) , keys_file_data . account_data . size ( ) , key , keys_file_data . iv , & account_data [ 0 ] ) ;
if ( json . Parse ( account_data . c_str ( ) ) . HasParseError ( ) | | ! json . IsObject ( ) )
if ( json . Parse ( account_data . c_str ( ) ) . HasParseError ( ) | | ! json . IsObject ( ) )
crypto : : chacha8 ( keys_file_data . account_data . data ( ) , keys_file_data . account_data . size ( ) , key , keys_file_data . iv , & account_data [ 0 ] ) ;
crypto : : chacha8 ( keys_file_data . account_data . data ( ) , keys_file_data . account_data . size ( ) , key , keys_file_data . iv , & account_data [ 0 ] ) ;
// The contents should be JSON if the wallet follows the new format.
// The contents should be JSON if the wallet follows the new format.
if ( json . Parse ( account_data . c_str ( ) ) . HasParseError ( ) )
if ( json . Parse ( account_data . c_str ( ) ) . HasParseError ( ) )
{
{
@ -3793,6 +3799,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR ;
m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR ;
m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR ;
m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR ;
m_original_keys_available = false ;
m_original_keys_available = false ;
m_export_format = ExportFormat : : Binary ;
m_device_name = " " ;
m_device_name = " " ;
m_device_derivation_path = " " ;
m_device_derivation_path = " " ;
m_key_device_type = hw : : device : : device_type : : SOFTWARE ;
m_key_device_type = hw : : device : : device_type : : SOFTWARE ;
@ -3954,6 +3961,9 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
GET_FIELD_FROM_JSON_RETURN_ON_ERROR ( json , encrypted_secret_keys , uint32_t , Uint , false , false ) ;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR ( json , encrypted_secret_keys , uint32_t , Uint , false , false ) ;
encrypted_secret_keys = field_encrypted_secret_keys ;
encrypted_secret_keys = field_encrypted_secret_keys ;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR ( json , export_format , ExportFormat , Int , false , Binary ) ;
m_export_format = field_export_format ;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR ( json , device_name , std : : string , String , false , std : : string ( ) ) ;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR ( json , device_name , std : : string , String , false , std : : string ( ) ) ;
if ( m_device_name . empty ( ) )
if ( m_device_name . empty ( ) )
{
{
@ -4101,7 +4111,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
wallet2 : : keys_file_data keys_file_data ;
wallet2 : : keys_file_data keys_file_data ;
std : : string buf ;
std : : string buf ;
bool encrypted_secret_keys = false ;
bool encrypted_secret_keys = false ;
bool r = epee: : file_io_utils : : load_file_to_string ( keys_file_name , buf ) ;
bool r = load_from_file ( keys_file_name , buf ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , keys_file_name ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , keys_file_name ) ;
// Decrypt the contents
// Decrypt the contents
@ -4186,7 +4196,7 @@ void wallet2::create_keys_file(const std::string &wallet_, bool watch_only, cons
if ( create_address_file )
if ( create_address_file )
{
{
r = file_io_utils: : save_string _to_file( m_wallet_file + " .address.txt " , m_account . get_public_address_str ( m_nettype ) ) ;
r = save_to_file( m_wallet_file + " .address.txt " , m_account . get_public_address_str ( m_nettype ) , true ) ;
if ( ! r ) MERROR ( " String with address text not saved " ) ;
if ( ! r ) MERROR ( " String with address text not saved " ) ;
}
}
}
}
@ -4208,7 +4218,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const std::stri
rapidjson : : Document json ;
rapidjson : : Document json ;
wallet2 : : keys_file_data keys_file_data ;
wallet2 : : keys_file_data keys_file_data ;
std : : string buf ;
std : : string buf ;
bool r = epee: : file_io_utils : : load_file_to_string ( keys_file_name , buf ) ;
bool r = load_from_file ( keys_file_name , buf ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , keys_file_name ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , keys_file_name ) ;
// Decrypt the contents
// Decrypt the contents
@ -4757,7 +4767,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
if ( boost : : filesystem : : exists ( m_wallet_file + " .address.txt " ) )
if ( boost : : filesystem : : exists ( m_wallet_file + " .address.txt " ) )
{
{
r = file_io_utils: : save_string _to_file( m_wallet_file + " .address.txt " , m_account . get_public_address_str ( m_nettype ) ) ;
r = save_to_file( m_wallet_file + " .address.txt " , m_account . get_public_address_str ( m_nettype ) , true ) ;
if ( ! r ) MERROR ( " String with address text not saved " ) ;
if ( ! r ) MERROR ( " String with address text not saved " ) ;
}
}
}
}
@ -5266,7 +5276,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{
{
wallet2 : : cache_file_data cache_file_data ;
wallet2 : : cache_file_data cache_file_data ;
std : : string buf ;
std : : string buf ;
bool r = epee: : file_io_utils : : load_file_to_string ( m_wallet_file , buf , std : : numeric_limits < size_t > : : max ( ) ) ;
bool r = load_from_file ( m_wallet_file , buf , std : : numeric_limits < size_t > : : max ( ) ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , m_wallet_file ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_read_error , m_wallet_file ) ;
// try to read it as an encrypted cache
// try to read it as an encrypted cache
@ -5501,7 +5511,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
{
{
// save address to the new file
// save address to the new file
const std : : string address_file = m_wallet_file + " .address.txt " ;
const std : : string address_file = m_wallet_file + " .address.txt " ;
r = file_io_utils: : save_string _to_file( address_file , m_account . get_public_address_str ( m_nettype ) ) ;
r = save_to_file( address_file , m_account . get_public_address_str ( m_nettype ) , true ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_save_error , m_wallet_file ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : file_save_error , m_wallet_file ) ;
}
}
// remove old wallet file
// remove old wallet file
@ -5536,7 +5546,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
binary_archive < true > oar ( oss ) ;
binary_archive < true > oar ( oss ) ;
bool success = : : serialization : : serialize ( oar , cache_file_data ) ;
bool success = : : serialization : : serialize ( oar , cache_file_data ) ;
if ( success ) {
if ( success ) {
success = epee: : file_io_utils : : save_string _to_file( new_file , oss . str ( ) ) ;
success = save_to_file( new_file , oss . str ( ) ) ;
}
}
THROW_WALLET_EXCEPTION_IF ( ! success , error : : file_save_error , new_file ) ;
THROW_WALLET_EXCEPTION_IF ( ! success , error : : file_save_error , new_file ) ;
# else
# else
@ -6164,7 +6174,7 @@ bool wallet2::save_tx(const std::vector<pending_tx>& ptx_vector, const std::stri
std : : string ciphertext = dump_tx_to_str ( ptx_vector ) ;
std : : string ciphertext = dump_tx_to_str ( ptx_vector ) ;
if ( ciphertext . empty ( ) )
if ( ciphertext . empty ( ) )
return false ;
return false ;
return epee : : file_io_utils : : save_string _to_file( filename , ciphertext ) ;
return save _to_file( filename , ciphertext ) ;
}
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
std : : string wallet2 : : dump_tx_to_str ( const std : : vector < pending_tx > & ptx_vector ) const
std : : string wallet2 : : dump_tx_to_str ( const std : : vector < pending_tx > & ptx_vector ) const
@ -6206,7 +6216,7 @@ bool wallet2::load_unsigned_tx(const std::string &unsigned_filename, unsigned_tx
LOG_PRINT_L0 ( " File " < < unsigned_filename < < " does not exist: " < < errcode ) ;
LOG_PRINT_L0 ( " File " < < unsigned_filename < < " does not exist: " < < errcode ) ;
return false ;
return false ;
}
}
if ( ! epee: : file_io_utils : : load_file_to_string ( unsigned_filename . c_str ( ) , s ) )
if ( ! load_from_file ( unsigned_filename . c_str ( ) , s ) )
{
{
LOG_PRINT_L0 ( " Failed to load from " < < unsigned_filename ) ;
LOG_PRINT_L0 ( " Failed to load from " < < unsigned_filename ) ;
return false ;
return false ;
@ -6427,7 +6437,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
return false ;
return false ;
}
}
if ( ! epee: : file_io_utils : : save_string _to_file( signed_filename , ciphertext ) )
if ( ! save_to_file( signed_filename , ciphertext ) )
{
{
LOG_PRINT_L0 ( " Failed to save file to " < < signed_filename ) ;
LOG_PRINT_L0 ( " Failed to save file to " < < signed_filename ) ;
return false ;
return false ;
@ -6439,7 +6449,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
{
{
std : : string tx_as_hex = epee : : string_tools : : buff_to_hex_nodelimer ( tx_to_blob ( signed_txes . ptx [ i ] . tx ) ) ;
std : : string tx_as_hex = epee : : string_tools : : buff_to_hex_nodelimer ( tx_to_blob ( signed_txes . ptx [ i ] . tx ) ) ;
std : : string raw_filename = signed_filename + " _raw " + ( signed_txes . ptx . size ( ) = = 1 ? " " : ( " _ " + std : : to_string ( i ) ) ) ;
std : : string raw_filename = signed_filename + " _raw " + ( signed_txes . ptx . size ( ) = = 1 ? " " : ( " _ " + std : : to_string ( i ) ) ) ;
if ( ! epee: : file_io_utils : : save_string _to_file( raw_filename , tx_as_hex ) )
if ( ! save_to_file( raw_filename , tx_as_hex ) )
{
{
LOG_PRINT_L0 ( " Failed to save file to " < < raw_filename ) ;
LOG_PRINT_L0 ( " Failed to save file to " < < raw_filename ) ;
return false ;
return false ;
@ -6487,7 +6497,7 @@ bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wal
return false ;
return false ;
}
}
if ( ! epee: : file_io_utils : : load_file_to_string ( signed_filename . c_str ( ) , s ) )
if ( ! load_from_file ( signed_filename . c_str ( ) , s ) )
{
{
LOG_PRINT_L0 ( " Failed to load from " < < signed_filename ) ;
LOG_PRINT_L0 ( " Failed to load from " < < signed_filename ) ;
return false ;
return false ;
@ -6618,7 +6628,7 @@ bool wallet2::save_multisig_tx(const multisig_tx_set &txs, const std::string &fi
std : : string ciphertext = save_multisig_tx ( txs ) ;
std : : string ciphertext = save_multisig_tx ( txs ) ;
if ( ciphertext . empty ( ) )
if ( ciphertext . empty ( ) )
return false ;
return false ;
return epee : : file_io_utils : : save_string _to_file( filename , ciphertext ) ;
return save _to_file( filename , ciphertext ) ;
}
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
wallet2 : : multisig_tx_set wallet2 : : make_multisig_tx_set ( const std : : vector < pending_tx > & ptx_vector ) const
wallet2 : : multisig_tx_set wallet2 : : make_multisig_tx_set ( const std : : vector < pending_tx > & ptx_vector ) const
@ -6646,7 +6656,7 @@ bool wallet2::save_multisig_tx(const std::vector<pending_tx>& ptx_vector, const
std : : string ciphertext = save_multisig_tx ( ptx_vector ) ;
std : : string ciphertext = save_multisig_tx ( ptx_vector ) ;
if ( ciphertext . empty ( ) )
if ( ciphertext . empty ( ) )
return false ;
return false ;
return epee : : file_io_utils : : save_string _to_file( filename , ciphertext ) ;
return save _to_file( filename , ciphertext ) ;
}
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
bool wallet2 : : parse_multisig_tx_from_str ( std : : string multisig_tx_st , multisig_tx_set & exported_txs ) const
bool wallet2 : : parse_multisig_tx_from_str ( std : : string multisig_tx_st , multisig_tx_set & exported_txs ) const
@ -6737,7 +6747,7 @@ bool wallet2::load_multisig_tx_from_file(const std::string &filename, multisig_t
LOG_PRINT_L0 ( " File " < < filename < < " does not exist: " < < errcode ) ;
LOG_PRINT_L0 ( " File " < < filename < < " does not exist: " < < errcode ) ;
return false ;
return false ;
}
}
if ( ! epee: : file_io_utils : : load_file_to_string ( filename . c_str ( ) , s ) )
if ( ! load_from_file ( filename . c_str ( ) , s ) )
{
{
LOG_PRINT_L0 ( " Failed to load from " < < filename ) ;
LOG_PRINT_L0 ( " Failed to load from " < < filename ) ;
return false ;
return false ;
@ -11633,7 +11643,7 @@ bool wallet2::export_key_images(const std::string &filename, bool all) const
// encrypt data, keep magic plaintext
// encrypt data, keep magic plaintext
PERF_TIMER ( export_key_images_encrypt ) ;
PERF_TIMER ( export_key_images_encrypt ) ;
std : : string ciphertext = encrypt_with_view_secret_key ( data ) ;
std : : string ciphertext = encrypt_with_view_secret_key ( data ) ;
return epee : : file_io_utils : : save_string _to_file( filename , magic + ciphertext ) ;
return save _to_file( filename , magic + ciphertext ) ;
}
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
@ -11698,7 +11708,7 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent
{
{
PERF_TIMER ( import_key_images_fsu ) ;
PERF_TIMER ( import_key_images_fsu ) ;
std : : string data ;
std : : string data ;
bool r = epee: : file_io_utils : : load_file_to_string ( filename , data ) ;
bool r = load_from_file ( filename , data ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : wallet_internal_error , std : : string ( tr ( " failed to read file " ) ) + filename ) ;
THROW_WALLET_EXCEPTION_IF ( ! r , error : : wallet_internal_error , std : : string ( tr ( " failed to read file " ) ) + filename ) ;
@ -13102,6 +13112,83 @@ void wallet2::throw_on_rpc_response_error(const boost::optional<std::string> &st
THROW_WALLET_EXCEPTION_IF ( * status ! = CORE_RPC_STATUS_OK , tools : : error : : wallet_generic_rpc_error , method , m_trusted_daemon ? * status : " daemon error " ) ;
THROW_WALLET_EXCEPTION_IF ( * status ! = CORE_RPC_STATUS_OK , tools : : error : : wallet_generic_rpc_error , method , m_trusted_daemon ? * status : " daemon error " ) ;
}
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
bool wallet2 : : save_to_file ( const std : : string & path_to_file , const std : : string & raw , bool is_printable ) const
{
if ( is_printable | | m_export_format = = ExportFormat : : Binary )
{
return epee : : file_io_utils : : save_string_to_file ( path_to_file , raw ) ;
}
FILE * fp = fopen ( path_to_file . c_str ( ) , " w+ " ) ;
// Save the result b/c we need to close the fp before returning success/failure.
int write_result = PEM_write ( fp , ASCII_OUTPUT_MAGIC . c_str ( ) , " " , ( const unsigned char * ) raw . c_str ( ) , raw . length ( ) ) ;
fclose ( fp ) ;
if ( write_result = = 0 )
{
return false ;
}
else
{
return true ;
}
}
//----------------------------------------------------------------------------------------------------
bool wallet2 : : load_from_file ( const std : : string & path_to_file , std : : string & target_str ,
size_t max_size )
{
std : : string data ;
bool r = epee : : file_io_utils : : load_file_to_string ( path_to_file , data , max_size ) ;
if ( ! r )
{
return false ;
}
if ( ! boost : : algorithm : : contains ( boost : : make_iterator_range ( data . begin ( ) , data . end ( ) ) , ASCII_OUTPUT_MAGIC ) )
{
// It's NOT our ascii dump.
target_str = std : : move ( data ) ;
return true ;
}
// Creating a BIO and calling PEM_read_bio instead of simpler PEM_read
// to avoid reading the file from disk twice.
BIO * b = BIO_new_mem_buf ( ( const void * ) data . data ( ) , data . length ( ) ) ;
char * name = NULL ;
char * header = NULL ;
unsigned char * openssl_data = NULL ;
long len = 0 ;
// Save the result b/c we need to free the data before returning success/failure.
int success = PEM_read_bio ( b , & name , & header , & openssl_data , & len ) ;
try
{
target_str = std : : string ( ( const char * ) openssl_data , len ) ;
}
catch ( . . . )
{
success = 0 ;
}
OPENSSL_free ( ( void * ) name ) ;
OPENSSL_free ( ( void * ) header ) ;
OPENSSL_free ( ( void * ) openssl_data ) ;
BIO_free ( b ) ;
if ( success = = 0 )
{
return false ;
}
else
{
return true ;
}
}
//----------------------------------------------------------------------------------------------------
void wallet2 : : hash_m_transfer ( const transfer_details & transfer , crypto : : hash & hash ) const
void wallet2 : : hash_m_transfer ( const transfer_details & transfer , crypto : : hash & hash ) const
{
{
KECCAK_CTX state ;
KECCAK_CTX state ;