@ -77,6 +77,8 @@ typedef cryptonote::simple_wallet sw;
# define DEFAULT_MIX 4
# define DEFAULT_MIX 4
# define KEY_IMAGE_EXPORT_FILE_MAGIC "Monero key image export\001"
// workaround for a suspected bug in pthread/kernel on MacOS X
// workaround for a suspected bug in pthread/kernel on MacOS X
# ifdef __APPLE__
# ifdef __APPLE__
# define DEFAULT_MAX_CONCURRENCY 1
# define DEFAULT_MAX_CONCURRENCY 1
@ -3583,11 +3585,14 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &args)
try
try
{
{
std : : vector < std : : pair < crypto : : key_image , crypto : : signature > > ski = m_wallet - > export_key_images ( ) ;
std : : vector < std : : pair < crypto : : key_image , crypto : : signature > > ski = m_wallet - > export_key_images ( ) ;
std : : string data ;
std : : string data ( KEY_IMAGE_EXPORT_FILE_MAGIC , strlen ( KEY_IMAGE_EXPORT_FILE_MAGIC ) ) ;
const cryptonote : : account_public_address & keys = m_wallet - > get_account ( ) . get_keys ( ) . m_account_address ;
data + = std : : string ( ( const char * ) & keys . m_spend_public_key , sizeof ( crypto : : public_key ) ) ;
data + = std : : string ( ( const char * ) & keys . m_view_public_key , sizeof ( crypto : : public_key ) ) ;
for ( const auto & i : ski )
for ( const auto & i : ski )
{
{
data + = epee : : string_tools : : pod_to_hex ( i . first ) ;
data + = std: : string ( ( const char * ) & i . first , sizeof ( crypto : : key_image ) ) ;
data + = epee: : string_tools : : pod_to_hex ( i . second ) ;
data + = std: : string ( ( const char * ) & i . second , sizeof ( crypto : : signature ) ) ;
}
}
bool r = epee : : file_io_utils : : save_string_to_file ( filename , data ) ;
bool r = epee : : file_io_utils : : save_string_to_file ( filename , data ) ;
if ( ! r )
if ( ! r )
@ -3623,34 +3628,41 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args)
fail_msg_writer ( ) < < tr ( " failed to read file " ) < < filename ;
fail_msg_writer ( ) < < tr ( " failed to read file " ) < < filename ;
return true ;
return true ;
}
}
const size_t magiclen = strlen ( KEY_IMAGE_EXPORT_FILE_MAGIC ) ;
if ( data . size ( ) < magiclen | | memcmp ( data . data ( ) , KEY_IMAGE_EXPORT_FILE_MAGIC , magiclen ) )
{
fail_msg_writer ( ) < < " Bad key image export file magic in " < < filename ;
return true ;
}
const size_t headerlen = magiclen + 2 * sizeof ( crypto : : public_key ) ;
if ( data . size ( ) < headerlen )
{
fail_msg_writer ( ) < < " Bad data size from file " < < filename ;
return true ;
}
const crypto : : public_key & public_spend_key = * ( const crypto : : public_key * ) & data [ magiclen ] ;
const crypto : : public_key & public_view_key = * ( const crypto : : public_key * ) & data [ magiclen + sizeof ( crypto : : public_key ) ] ;
const cryptonote : : account_public_address & keys = m_wallet - > get_account ( ) . get_keys ( ) . m_account_address ;
if ( public_spend_key ! = keys . m_spend_public_key | | public_view_key ! = keys . m_view_public_key )
{
fail_msg_writer ( ) < < " Key images from " < < filename < < " are for a different account " ;
return true ;
}
const size_t record_size = sizeof ( crypto : : key_image ) * 2 + sizeof ( crypto : : signature ) * 2 ;
const size_t record_size = sizeof ( crypto : : key_image ) + sizeof ( crypto : : signature ) ;
if ( data . size ( ) % record_size )
if ( ( data . size ( ) - headerlen ) % record_size )
{
{
fail_msg_writer ( ) < < " Bad data size from file " < < filename ;
fail_msg_writer ( ) < < " Bad data size from file " < < filename ;
return true ;
return true ;
}
}
size_t nki = data . size ( ) / record_size ;
size_t nki = ( data . size ( ) - headerlen ) / record_size ;
std : : vector < std : : pair < crypto : : key_image , crypto : : signature > > ski ;
std : : vector < std : : pair < crypto : : key_image , crypto : : signature > > ski ;
ski . reserve ( nki ) ;
ski . reserve ( nki ) ;
for ( size_t n = 0 ; n < nki ; + + n )
for ( size_t n = 0 ; n < nki ; + + n )
{
{
cryptonote : : blobdata bd ;
crypto : : key_image key_image = * reinterpret_cast < const crypto : : key_image * > ( & data [ headerlen + n * record_size ] ) ;
crypto : : signature signature = * reinterpret_cast < const crypto : : signature * > ( & data [ headerlen + n * record_size + sizeof ( crypto : : key_image ) ] ) ;
if ( ! epee : : string_tools : : parse_hexstr_to_binbuff ( std : : string ( & data [ n * record_size ] , sizeof ( crypto : : key_image ) * 2 ) , bd ) )
{
fail_msg_writer ( ) < < tr ( " failed to parse key image " ) ;
return false ;
}
crypto : : key_image key_image = * reinterpret_cast < const crypto : : key_image * > ( bd . data ( ) ) ;
if ( ! epee : : string_tools : : parse_hexstr_to_binbuff ( std : : string ( & data [ n * record_size + sizeof ( crypto : : key_image ) * 2 ] , sizeof ( crypto : : signature ) * 2 ) , bd ) )
{
fail_msg_writer ( ) < < tr ( " failed to parse signature " ) ;
return false ;
}
crypto : : signature signature = * reinterpret_cast < const crypto : : signature * > ( bd . data ( ) ) ;
ski . push_back ( std : : make_pair ( key_image , signature ) ) ;
ski . push_back ( std : : make_pair ( key_image , signature ) ) ;
}
}