Electroneum
tools::wallet2 Class Reference

#include <wallet2.h>

Classes

struct  address_book_row
 
struct  address_tx
 
struct  cache_file_data
 
struct  confirmed_transfer_details
 
struct  is_out_data
 
struct  keys_file_data
 
struct  multisig_info
 
struct  multisig_sig
 
struct  multisig_tx_set
 
struct  parsed_block
 
struct  payment_details
 
struct  pending_tx
 
struct  pool_payment_details
 
struct  reserve_proof_entry
 
struct  signed_tx_set
 
struct  transfer_details
 
struct  tx_cache_data
 
struct  tx_construction_data
 
struct  tx_scan_info_t
 
struct  unconfirmed_transfer_details
 
struct  unsigned_tx_set
 

Public Types

enum  RefreshType { RefreshFull, RefreshOptimizeCoinbase, RefreshNoCoinbase, RefreshDefault = RefreshOptimizeCoinbase }
 
enum  AskPasswordType { AskPasswordNever = 0, AskPasswordOnAction = 1, AskPasswordToDecrypt = 2 }
 
enum  BackgroundMiningSetupType { BackgroundMiningMaybe = 0, BackgroundMiningYes = 1, BackgroundMiningNo = 2 }
 
typedef std::vector< transfer_detailstransfer_container
 
typedef std::unordered_multimap< crypto::hash, payment_detailspayment_container
 
typedef std::tuple< uint64_t, crypto::public_key, rct::keyget_outs_entry
 

Public Member Functions

 wallet2 (cryptonote::network_type nettype=cryptonote::MAINNET, uint64_t kdf_rounds=1, bool unattended=false)
 
 ~wallet2 ()
 
void generate (const std::string &wallet_, const epee::wipeable_string &password, const epee::wipeable_string &multisig_data, bool create_address_file=false)
 Generates a wallet or restores one. More...
 
crypto::secret_key generate (const std::string &wallet, const epee::wipeable_string &password, const crypto::secret_key &recovery_param=crypto::secret_key(), bool recover=false, bool two_random=false, bool create_address_file=false)
 Generates a wallet or restores one. More...
 
void generate (const std::string &wallet, const epee::wipeable_string &password, const cryptonote::account_public_address &account_public_address, const crypto::secret_key &spendkey, const crypto::secret_key &viewkey, bool create_address_file=false)
 Creates a wallet from a public address and a spend/view secret key pair. More...
 
void generate (const std::string &wallet, const epee::wipeable_string &password, const cryptonote::account_public_address &account_public_address, const crypto::secret_key &viewkey=crypto::secret_key(), bool create_address_file=false)
 Creates a watch only wallet from a public address and a view secret key. More...
 
void restore (const std::string &wallet_, const epee::wipeable_string &password, const std::string &device_name, bool create_address_file=false)
 Restore a wallet hold by an HW. More...
 
std::string make_multisig (const epee::wipeable_string &password, const std::vector< std::string > &info, uint32_t threshold)
 Creates a multisig wallet. More...
 
std::string make_multisig (const epee::wipeable_string &password, const std::vector< crypto::secret_key > &view_keys, const std::vector< crypto::public_key > &spend_keys, uint32_t threshold)
 Creates a multisig wallet. More...
 
std::string exchange_multisig_keys (const epee::wipeable_string &password, const std::vector< std::string > &info)
 
std::string exchange_multisig_keys (const epee::wipeable_string &password, std::unordered_set< crypto::public_key > pkeys, std::vector< crypto::public_key > signers)
 Any but first round of keys exchange. More...
 
bool finalize_multisig (const epee::wipeable_string &password, const std::vector< std::string > &info)
 Finalizes creation of a multisig wallet. More...
 
bool finalize_multisig (const epee::wipeable_string &password, const std::unordered_set< crypto::public_key > &pkeys, std::vector< crypto::public_key > signers)
 Finalizes creation of a multisig wallet. More...
 
std::string get_multisig_info () const
 
cryptonote::blobdata export_multisig ()
 
size_t import_multisig (std::vector< cryptonote::blobdata > info)
 
void rewrite (const std::string &wallet_name, const epee::wipeable_string &password)
 Rewrites to the wallet file for wallet upgrade (doesn't generate key, assumes it's already there) More...
 
void write_watch_only_wallet (const std::string &wallet_name, const epee::wipeable_string &password, std::string &new_keys_filename)
 Writes to a file named based on the normal wallet (doesn't generate key, assumes it's already there) More...
 
void load (const std::string &wallet, const epee::wipeable_string &password)
 
void store ()
 
void store_to (const std::string &path, const epee::wipeable_string &password)
 store_to Stores wallet to another file(s), deleting old ones More...
 
std::string path () const
 
bool verify_password (const epee::wipeable_string &password)
 verifies given password is correct for default wallet keys file More...
 
cryptonote::account_baseget_account ()
 
const cryptonote::account_baseget_account () const
 
void encrypt_keys (const crypto::chacha_key &key)
 
void encrypt_keys (const epee::wipeable_string &password)
 
void decrypt_keys (const crypto::chacha_key &key)
 
void decrypt_keys (const epee::wipeable_string &password)
 
void set_refresh_from_block_height (uint64_t height)
 
uint64_t get_refresh_from_block_height () const
 
void explicit_refresh_from_block_height (bool expl)
 
bool explicit_refresh_from_block_height () const
 
bool deinit ()
 
bool init (std::string daemon_address="http://localhost:8080", boost::optional< epee::net_utils::http::login > daemon_login=boost::none, boost::asio::ip::tcp::endpoint proxy={}, uint64_t upper_transaction_weight_limit=0, bool trusted_daemon=true, epee::net_utils::ssl_options_t ssl_options=epee::net_utils::ssl_support_t::e_ssl_support_autodetect, std::string blockchain_db_path="")
 
bool set_daemon (std::string daemon_address="http://localhost:8080", boost::optional< epee::net_utils::http::login > daemon_login=boost::none, bool trusted_daemon=true, epee::net_utils::ssl_options_t ssl_options=epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
 
void stop ()
 
i_wallet2_callbackcallback () const
 
void callback (i_wallet2_callback *callback)
 
bool is_trusted_daemon () const
 
void set_trusted_daemon (bool trusted)
 
bool is_deterministic () const
 Checks if deterministic wallet. More...
 
bool get_seed (epee::wipeable_string &electrum_words, const epee::wipeable_string &passphrase=epee::wipeable_string()) const
 
bool light_wallet () const
 Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned. More...
 
void set_light_wallet (bool light_wallet)
 
uint64_t get_light_wallet_scanned_block_height () const
 
uint64_t get_light_wallet_blockchain_height () const
 
const std::string & get_seed_language () const
 Gets the seed language. More...
 
void set_seed_language (const std::string &language)
 Sets the seed language. More...
 
cryptonote::account_public_address get_subaddress (const cryptonote::subaddress_index &index) const
 
cryptonote::account_public_address get_address () const
 
boost::optional< cryptonote::subaddress_indexget_subaddress_index (const cryptonote::account_public_address &address) const
 
crypto::public_key get_subaddress_spend_public_key (const cryptonote::subaddress_index &index) const
 
std::vector< crypto::public_keyget_subaddress_spend_public_keys (uint32_t account, uint32_t begin, uint32_t end) const
 
std::string get_subaddress_as_str (const cryptonote::subaddress_index &index) const
 
std::string get_address_as_str () const
 
std::string get_integrated_address_as_str (const crypto::hash8 &payment_id) const
 
void add_subaddress_account (const std::string &label, const bool update_account_tags=true)
 
size_t get_num_subaddress_accounts () const
 
size_t get_num_subaddresses (uint32_t index_major) const
 
void add_subaddress (uint32_t index_major, const std::string &label)
 
void expand_subaddresses (const cryptonote::subaddress_index &index, const bool udpate_account_tags=true)
 
std::string get_subaddress_label (const cryptonote::subaddress_index &index) const
 
void set_subaddress_label (const cryptonote::subaddress_index &index, const std::string &label)
 
void set_subaddress_lookahead (size_t major, size_t minor)
 
std::pair< size_t, size_t > get_subaddress_lookahead () const
 
void account_major_offset (uint32_t offset)
 
uint32_t account_major_offset () const
 
bool is_deprecated () const
 Tells if the wallet file is deprecated. More...
 
void refresh (bool trusted_daemon)
 
void refresh (bool trusted_daemon, uint64_t start_height, uint64_t &blocks_fetched)
 
void refresh (bool trusted_daemon, uint64_t start_height, uint64_t &blocks_fetched, bool &received_etn, bool check_pool=true)
 
bool refresh (bool trusted_daemon, uint64_t &blocks_fetched, bool &received_etn, bool &ok)
 
void set_refresh_type (RefreshType refresh_type)
 
RefreshType get_refresh_type () const
 
cryptonote::network_type nettype () const
 
bool watch_only () const
 
bool multisig (bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
 
bool has_multisig_partial_key_images () const
 
bool has_unknown_key_images () const
 
bool get_multisig_seed (epee::wipeable_string &seed, const epee::wipeable_string &passphrase=std::string(), bool raw=true) const
 
bool key_on_device () const
 
hw::device::device_type get_device_type () const
 
bool reconnect_device ()
 
uint64_t balance (uint32_t subaddr_index_major, bool public_blockchain) const
 
uint64_t unlocked_balance (uint32_t subaddr_index_major, bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
 
std::map< uint32_t, uint64_tbalance_per_subaddress (uint32_t subaddr_index_major, bool public_blockchain=false) const
 
std::map< uint32_t, std::pair< uint64_t, uint64_t > > unlocked_balance_per_subaddress (uint32_t subaddr_index_major, bool public_blockchain=false) const
 
uint64_t balance_all (bool public_blockchain) const
 
uint64_t unlocked_balance_all (bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
 
template<typename T >
void transfer_selected (const std::vector< cryptonote::tx_destination_entry > &dsts, const std::vector< size_t > &selected_transfers, size_t fake_outputs_count, std::vector< std::vector< tools::wallet2::get_outs_entry >> &outs, uint64_t unlock_time, uint64_t fee, const std::vector< uint8_t > &extra, T destination_split_strategy, const tx_dust_policy &dust_policy, cryptonote::transaction &tx, pending_tx &ptx)
 
void commit_tx (pending_tx &ptx_vector)
 
void commit_tx (std::vector< pending_tx > &ptx_vector)
 
bool save_tx (const std::vector< pending_tx > &ptx_vector, const std::string &filename) const
 
std::string dump_tx_to_str (const std::vector< pending_tx > &ptx_vector) const
 
std::string save_multisig_tx (multisig_tx_set txs)
 
bool save_multisig_tx (const multisig_tx_set &txs, const std::string &filename)
 
std::string save_multisig_tx (const std::vector< pending_tx > &ptx_vector)
 
bool save_multisig_tx (const std::vector< pending_tx > &ptx_vector, const std::string &filename)
 
multisig_tx_set make_multisig_tx_set (const std::vector< pending_tx > &ptx_vector) const
 
bool sign_tx (const std::string &unsigned_filename, const std::string &signed_filename, std::vector< wallet2::pending_tx > &ptx, std::function< bool(const unsigned_tx_set &)> accept_func=NULL, bool export_raw=false)
 
bool sign_tx (unsigned_tx_set &exported_txs, const std::string &signed_filename, std::vector< wallet2::pending_tx > &ptx, bool export_raw=false)
 
bool sign_tx (unsigned_tx_set &exported_txs, std::vector< wallet2::pending_tx > &ptx, signed_tx_set &signed_txs)
 
std::string sign_tx_dump_to_str (unsigned_tx_set &exported_txs, std::vector< wallet2::pending_tx > &ptx, signed_tx_set &signed_txes)
 
bool load_unsigned_tx (const std::string &unsigned_filename, unsigned_tx_set &exported_txs) const
 
bool parse_unsigned_tx_from_str (const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const
 
bool load_tx (const std::string &signed_filename, std::vector< tools::wallet2::pending_tx > &ptx, std::function< bool(const signed_tx_set &)> accept_func=NULL)
 
bool parse_tx_from_str (const std::string &signed_tx_st, std::vector< tools::wallet2::pending_tx > &ptx, std::function< bool(const signed_tx_set &)> accept_func)
 
std::vector< wallet2::pending_txcreate_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)
 
std::vector< wallet2::pending_txcreate_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 bool migrate=false)
 
std::vector< wallet2::pending_txcreate_transactions_single (const crypto::key_image &ki, 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)
 
std::vector< wallet2::pending_txcreate_transactions_from (const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector< size_t > unused_transfers_indices, std::vector< size_t > unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector< uint8_t > &extra, const uint8_t tx_version)
 
bool sanity_check (const std::vector< wallet2::pending_tx > &ptx_vector, std::vector< cryptonote::tx_destination_entry > dsts) const
 
void cold_tx_aux_import (const std::vector< pending_tx > &ptx, const std::vector< std::string > &tx_device_aux)
 
void cold_sign_tx (const std::vector< pending_tx > &ptx_vector, signed_tx_set &exported_txs, std::vector< cryptonote::address_parse_info > &dsts_info, std::vector< std::string > &tx_device_aux)
 
uint64_t cold_key_image_sync (uint64_t &spent, uint64_t &unspent)
 
bool parse_multisig_tx_from_str (std::string multisig_tx_st, multisig_tx_set &exported_txs) const
 
bool load_multisig_tx (cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function< bool(const multisig_tx_set &)> accept_func=NULL)
 
bool load_multisig_tx_from_file (const std::string &filename, multisig_tx_set &exported_txs, std::function< bool(const multisig_tx_set &)> accept_func=NULL)
 
bool sign_multisig_tx_from_file (const std::string &filename, std::vector< crypto::hash > &txids, std::function< bool(const multisig_tx_set &)> accept_func)
 
bool sign_multisig_tx (multisig_tx_set &exported_txs, std::vector< crypto::hash > &txids)
 
bool sign_multisig_tx_to_file (multisig_tx_set &exported_txs, const std::string &filename, std::vector< crypto::hash > &txids)
 
std::vector< pending_txcreate_unmixable_sweep_transactions ()
 
void discard_unmixable_outputs ()
 
bool check_connection (uint32_t *version=NULL, bool *ssl=NULL, uint32_t timeout=200000)
 
void get_transfers (wallet2::transfer_container &incoming_transfers) const
 
void get_payments (const crypto::hash &payment_id, std::list< wallet2::payment_details > &payments, uint64_t min_height=0, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
 
void get_payments (std::list< std::pair< crypto::hash, wallet2::payment_details >> &payments, uint64_t min_height, uint64_t max_height=(uint64_t) -1, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
 
void get_payments_out (std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &confirmed_payments, uint64_t min_height, uint64_t max_height=(uint64_t) -1, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
 
void get_payments_out_migration (std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &confirmed_payments, uint64_t min_height, uint64_t max_height=(uint64_t) -1, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
 
void get_payments_out_sc_migration (std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &confirmed_payments, uint64_t min_height, uint64_t max_height=(uint64_t) -1, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
 
void get_unconfirmed_payments_out (std::list< std::pair< crypto::hash, wallet2::unconfirmed_transfer_details >> &unconfirmed_payments, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
 
void get_unconfirmed_payments (std::list< std::pair< crypto::hash, wallet2::pool_payment_details >> &unconfirmed_payments, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
 
uint64_t get_blockchain_current_height () const
 
bool synced_to_v10 () const
 
bool public_transactions_required () const
 
void rescan_spent ()
 
void rescan_blockchain (bool hard, bool refresh=true, bool keep_key_images=false)
 
bool is_transfer_unlocked (const transfer_details &td) const
 
bool is_transfer_unlocked (uint64_t unlock_time, uint64_t block_height) const
 
uint64_t get_last_block_reward () const
 
uint64_t get_device_last_key_image_sync () const
 
template<class t_archive >
void serialize (t_archive &a, const unsigned int ver)
 
bool always_confirm_transfers () const
 
void always_confirm_transfers (bool always)
 
bool print_ring_members () const
 
void print_ring_members (bool value)
 
bool store_tx_info () const
 
void store_tx_info (bool store)
 
uint32_t default_mixin () const
 
void default_mixin (uint32_t m)
 
uint32_t get_default_priority () const
 
void set_default_priority (uint32_t p)
 
bool auto_refresh () const
 
void auto_refresh (bool r)
 
bool confirm_missing_payment_id () const
 
void confirm_missing_payment_id (bool always)
 
AskPasswordType ask_password () const
 
void ask_password (AskPasswordType ask)
 
void set_min_output_count (uint32_t count)
 
uint32_t get_min_output_count () const
 
void set_min_output_value (uint64_t value)
 
uint64_t get_min_output_value () const
 
void merge_destinations (bool merge)
 
bool merge_destinations () const
 
bool confirm_backlog () const
 
void confirm_backlog (bool always)
 
void set_confirm_backlog_threshold (uint32_t threshold)
 
uint32_t get_confirm_backlog_threshold () const
 
bool confirm_export_overwrite () const
 
void confirm_export_overwrite (bool always)
 
bool auto_low_priority () const
 
void auto_low_priority (bool value)
 
bool segregate_pre_fork_outputs () const
 
void segregate_pre_fork_outputs (bool value)
 
bool key_reuse_mitigation2 () const
 
void key_reuse_mitigation2 (bool value)
 
uint64_t segregation_height () const
 
void segregation_height (uint64_t height)
 
bool ignore_fractional_outputs () const
 
void ignore_fractional_outputs (bool value)
 
bool confirm_non_default_ring_size () const
 
void confirm_non_default_ring_size (bool always)
 
bool track_uses () const
 
void track_uses (bool value)
 
BackgroundMiningSetupType setup_background_mining () const
 
void setup_background_mining (BackgroundMiningSetupType value)
 
const std::string & device_name () const
 
void device_name (const std::string &device_name)
 
const std::string & device_derivation_path () const
 
void device_derivation_path (const std::string &device_derivation_path)
 
bool get_tx_key_cached (const crypto::hash &txid, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys) const
 
void set_tx_key (const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector< crypto::secret_key > &additional_tx_keys)
 
bool get_tx_key (const crypto::hash &txid, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys)
 
void check_tx_key (const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector< crypto::secret_key > &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
 
void check_tx_key_helper (const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
 
void check_tx_key_helper (const cryptonote::transaction &tx, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received) const
 
std::string get_tx_proof (const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message)
 
std::string get_tx_proof (const cryptonote::transaction &tx, const crypto::secret_key &tx_key, const std::vector< crypto::secret_key > &additional_tx_keys, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message) const
 
bool check_tx_proof (const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations)
 
bool check_tx_proof (const cryptonote::transaction &tx, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received) const
 
std::string get_spend_proof (const crypto::hash &txid, const std::string &message)
 
bool check_spend_proof (const crypto::hash &txid, const std::string &message, const std::string &sig_str)
 
std::string get_reserve_proof (const boost::optional< std::pair< uint32_t, uint64_t >> &account_minreserve, const std::string &message)
 Generates a proof that proves the reserve of unspent funds. More...
 
bool check_reserve_proof (const cryptonote::account_public_address &address, const std::string &message, const std::string &sig_str, uint64_t &total, uint64_t &spent)
 Verifies a proof of reserve. More...
 
std::vector< address_book_rowget_address_book () const
 GUI Address book get/store. More...
 
bool add_address_book_row (const cryptonote::account_public_address &address, const crypto::hash &payment_id, const std::string &description, bool is_subaddress)
 
bool delete_address_book_row (std::size_t row_id)
 
uint64_t get_num_rct_outputs ()
 
size_t get_num_transfer_details () const
 
const transfer_detailsget_transfer_details (size_t idx) const
 
void get_hard_fork_info (uint8_t version, uint64_t &earliest_height) const
 
bool use_fork_rules (uint8_t version, int64_t early_blocks=0) const
 
int get_fee_algorithm () const
 
std::string get_wallet_file () const
 
std::string get_keys_file () const
 
std::string get_daemon_address () const
 
const boost::optional< epee::net_utils::http::login > & get_daemon_login () const
 
uint64_t get_daemon_blockchain_height (std::string &err) const
 
uint64_t get_daemon_blockchain_target_height (std::string &err)
 
uint64_t get_approximate_blockchain_height () const
 Calculates the approximate blockchain height from current date/time. More...
 
uint64_t estimate_blockchain_height ()
 
std::vector< size_t > select_available_outputs_from_histogram (uint64_t count, bool atleast, bool unlocked, bool allow_rct)
 
std::vector< size_t > select_available_outputs (const std::function< bool(const transfer_details &td)> &f) const
 
std::vector< size_t > select_available_unmixable_outputs ()
 
std::vector< size_t > select_available_mixable_outputs ()
 
size_t pop_best_value_from (const transfer_container &transfers, std::vector< size_t > &unused_dust_indices, const std::vector< size_t > &selected_transfers, bool smallest=false) const
 
size_t pop_best_value (std::vector< size_t > &unused_dust_indices, const std::vector< size_t > &selected_transfers, bool smallest=false) const
 
void set_tx_note (const crypto::hash &txid, const std::string &note)
 
std::string get_tx_note (const crypto::hash &txid) const
 
void set_tx_device_aux (const crypto::hash &txid, const std::string &aux)
 
std::string get_tx_device_aux (const crypto::hash &txid) const
 
void set_description (const std::string &description)
 
std::string get_description () const
 
const std::pair< std::map< std::string, std::string >, std::vector< std::string > > & get_account_tags ()
 Get the list of registered account tags. More...
 
void set_account_tag (const std::set< uint32_t > &account_indices, const std::string &tag)
 Set a tag to the given accounts. More...
 
void set_account_tag_description (const std::string &tag, const std::string &description)
 Set the label of the given tag. More...
 
std::string sign (const std::string &data) const
 
bool verify (const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const
 
std::string sign_multisig_participant (const std::string &data) const
 sign_multisig_participant signs given message with the multisig public signer key More...
 
bool verify_with_public_key (const std::string &data, const crypto::public_key &public_key, const std::string &signature) const
 verify_with_public_key verifies message was signed with given public key More...
 
std::pair< size_t, std::vector< tools::wallet2::transfer_details > > export_outputs (bool all=false) const
 
std::string export_outputs_to_str (bool all=false) const
 
size_t import_outputs (const std::pair< size_t, std::vector< tools::wallet2::transfer_details >> &outputs)
 
size_t import_outputs_from_str (const std::string &outputs_st)
 
payment_container export_payments () const
 
void import_payments (const payment_container &payments)
 
void import_payments_out (const std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &confirmed_payments)
 
std::tuple< size_t, crypto::hash, std::vector< crypto::hash > > export_blockchain () const
 
void import_blockchain (const std::tuple< size_t, crypto::hash, std::vector< crypto::hash >> &bc)
 
bool export_key_images (const std::string &filename) const
 
std::pair< size_t, std::vector< std::pair< crypto::key_image, crypto::signature > > > export_key_images (bool all=false) const
 
uint64_t import_key_images (const std::vector< std::pair< crypto::key_image, crypto::signature >> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent=true)
 
uint64_t import_key_images (const std::string &filename, uint64_t &spent, uint64_t &unspent)
 
bool import_key_images (std::vector< crypto::key_image > key_images, size_t offset=0, boost::optional< std::unordered_set< size_t >> selected_transfers=boost::none)
 
bool import_key_images (signed_tx_set &signed_tx, size_t offset=0, bool only_selected_transfers=false)
 
crypto::public_key get_tx_pub_key_from_received_outs (const tools::wallet2::transfer_details &td) const
 
void update_pool_state (bool refreshed=false)
 
void remove_obsolete_pool_txs (const std::vector< crypto::hash > &tx_hashes)
 
std::string encrypt (const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated=true) const
 
std::string encrypt (const epee::span< char > &span, const crypto::secret_key &skey, bool authenticated=true) const
 
std::string encrypt (const std::string &plaintext, const crypto::secret_key &skey, bool authenticated=true) const
 
std::string encrypt (const epee::wipeable_string &plaintext, const crypto::secret_key &skey, bool authenticated=true) const
 
std::string encrypt_with_view_secret_key (const std::string &plaintext, bool authenticated=true) const
 
template<typename T = std::string>
T decrypt (const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated=true) const
 
std::string decrypt_with_view_secret_key (const std::string &ciphertext, bool authenticated=true) const
 
std::string make_uri (const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const
 
bool parse_uri (const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector< std::string > &unknown_parameters, std::string &error)
 
uint64_t get_blockchain_height_by_date (uint16_t year, uint8_t month, uint8_t day)
 
bool is_synced () const
 
std::vector< std::pair< uint64_t, uint64_t > > estimate_backlog (const std::vector< std::pair< double, double >> &fee_levels)
 
std::vector< std::pair< uint64_t, uint64_t > > estimate_backlog (uint64_t min_tx_weight, uint64_t max_tx_weight, const std::vector< uint64_t > &fees)
 
uint64_t get_fee_multiplier (uint32_t priority, int fee_algorithm=-1) const
 
uint64_t get_base_fee () const
 
uint64_t get_fee_quantization_mask () const
 
uint64_t get_min_ring_size () const
 
uint64_t get_max_ring_size () const
 
uint64_t adjust_mixin (uint64_t mixin) const
 
uint32_t adjust_priority (uint32_t priority)
 
bool is_unattended () const
 
void light_wallet_get_unspent_outs ()
 
void light_wallet_get_address_txs ()
 
bool light_wallet_get_address_info (tools::COMMAND_RPC_GET_ADDRESS_INFO::response &response)
 
bool light_wallet_login (bool &new_address)
 
bool light_wallet_import_wallet_request (tools::COMMAND_RPC_IMPORT_WALLET_REQUEST::response &response)
 
void light_wallet_get_outs (std::vector< std::vector< get_outs_entry >> &outs, const std::vector< size_t > &selected_transfers, size_t fake_outputs_count)
 
bool light_wallet_parse_rct_str (const std::string &rct_string, const crypto::public_key &tx_pub_key, uint64_t internal_output_index, rct::key &decrypted_mask, rct::key &rct_commit, bool decrypt) const
 
bool light_wallet_key_image_is_ours (const crypto::key_image &key_image, const crypto::public_key &tx_public_key, uint64_t out_index)
 
void set_attribute (const std::string &key, const std::string &value)
 
std::string get_attribute (const std::string &key) const
 
crypto::public_key get_multisig_signer_public_key (const crypto::secret_key &spend_skey) const
 
crypto::public_key get_multisig_signer_public_key () const
 
crypto::public_key get_multisig_signing_public_key (size_t idx) const
 
crypto::public_key get_multisig_signing_public_key (const crypto::secret_key &skey) const
 
template<class t_request , class t_response >
bool invoke_http_json (const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
 
template<class t_request , class t_response >
bool invoke_http_bin (const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
 
template<class t_request , class t_response >
bool invoke_http_json_rpc (const boost::string_ref uri, const std::string &method_name, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET", const std::string &req_id="0")
 
bool set_ring_database (const std::string &filename)
 
const std::string get_ring_database () const
 
bool get_ring (const crypto::key_image &key_image, std::vector< uint64_t > &outs)
 
bool get_rings (const crypto::hash &txid, std::vector< std::pair< crypto::key_image, std::vector< uint64_t >>> &outs)
 
bool set_ring (const crypto::key_image &key_image, const std::vector< uint64_t > &outs, bool relative)
 
bool unset_ring (const std::vector< crypto::key_image > &key_images)
 
bool unset_ring (const crypto::hash &txid)
 
bool find_and_save_rings (bool force=true)
 
bool blackball_output (const std::pair< uint64_t, uint64_t > &output)
 
bool set_blackballed_outputs (const std::vector< std::pair< uint64_t, uint64_t >> &outputs, bool add=false)
 
bool unblackball_output (const std::pair< uint64_t, uint64_t > &output)
 
bool is_output_blackballed (const std::pair< uint64_t, uint64_t > &output) const
 
void freeze (size_t idx)
 
void thaw (size_t idx)
 
bool frozen (size_t idx) const
 
void freeze (const crypto::key_image &ki)
 
void thaw (const crypto::key_image &ki)
 
bool frozen (const crypto::key_image &ki) const
 
bool frozen (const transfer_details &td) const
 
uint64_t get_bytes_sent () const
 
uint64_t get_bytes_received () const
 
void add_checkpoint (uint64_t height, std::string hash)
 
mms::message_storeget_message_store ()
 
const mms::message_storeget_message_store () const
 
mms::multisig_wallet_state get_multisig_wallet_state () const
 
bool lock_keys_file ()
 
bool unlock_keys_file ()
 
bool is_keys_file_locked () const
 
void change_password (const std::string &filename, const epee::wipeable_string &original_password, const epee::wipeable_string &new_password)
 
void set_tx_notify (const std::shared_ptr< tools::Notify > &notify)
 
bool is_tx_spendtime_unlocked (uint64_t unlock_time, uint64_t block_height) const
 
void hash_m_transfer (const transfer_details &transfer, crypto::hash &hash) const
 
uint64_t hash_m_transfers (int64_t transfer_height, crypto::hash &hash) const
 
void finish_rescan_bc_keep_key_images (uint64_t transfer_height, const crypto::hash &hash)
 
void enable_dns (bool enable)
 
void set_offline (bool offline=true)
 

Static Public Member Functions

static const char * tr (const char *str)
 
static bool has_testnet_option (const boost::program_options::variables_map &vm)
 
static bool has_stagenet_option (const boost::program_options::variables_map &vm)
 
static std::string device_name_option (const boost::program_options::variables_map &vm)
 
static std::string device_derivation_path_option (const boost::program_options::variables_map &vm)
 
static void init_options (boost::program_options::options_description &desc_params)
 
static std::pair< std::unique_ptr< wallet2 >, password_containermake_from_json (const boost::program_options::variables_map &vm, bool unattended, const std::string &json_file, const std::function< boost::optional< password_container >(const char *, bool)> &password_prompter)
 Uses stdin and stdout. Returns a wallet2 if no errors. More...
 
static std::pair< std::unique_ptr< wallet2 >, password_containermake_from_file (const boost::program_options::variables_map &vm, bool unattended, const std::string &wallet_file, const std::function< boost::optional< password_container >(const char *, bool)> &password_prompter)
 Uses stdin and stdout. Returns a wallet2 and password for wallet_file if no errors. More...
 
static std::pair< std::unique_ptr< wallet2 >, password_containermake_new (const boost::program_options::variables_map &vm, bool unattended, const std::function< boost::optional< password_container >(const char *, bool)> &password_prompter)
 Uses stdin and stdout. Returns a wallet2 and password for wallet with no file if no errors. More...
 
static std::unique_ptr< wallet2make_dummy (const boost::program_options::variables_map &vm, bool unattended, const std::function< boost::optional< password_container >(const char *, bool)> &password_prompter)
 Just parses variables. More...
 
static bool verify_password (const std::string &keys_file_name, const epee::wipeable_string &password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds)
 verify password for specified wallet keys file. More...
 
static bool query_device (hw::device::device_type &device_type, const std::string &keys_file_name, const epee::wipeable_string &password, uint64_t kdf_rounds=1)
 determine the key storage for the specified wallet file More...
 
static bool verify_multisig_info (const std::string &data, crypto::secret_key &skey, crypto::public_key &pkey)
 
static bool verify_extra_multisig_info (const std::string &data, std::unordered_set< crypto::public_key > &pkeys, crypto::public_key &signer)
 
static void wallet_exists (const std::string &file_path, bool &keys_file_exists, bool &wallet_file_exists)
 Check if wallet keys and bin files exist. More...
 
static std::string get_human_readable_timestamp (uint64_t ts)
 Check if wallet file path is valid format. More...
 
static bool wallet_valid_path_format (const std::string &file_path)
 
static bool parse_long_payment_id (const std::string &payment_id_str, crypto::hash &payment_id)
 
static bool parse_short_payment_id (const std::string &payment_id_str, crypto::hash8 &payment_id)
 
static bool parse_payment_id (const std::string &payment_id_str, crypto::hash &payment_id)
 

Public Attributes

const char *const ATTRIBUTE_DESCRIPTION = "wallet2.description"
 

Static Public Attributes

static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30)
 

Friends

class ::Serialization_portability_wallet_Test
 
class ::wallet_accessor_test
 
class wallet_keys_unlocker
 
class wallet_device_callback
 

Detailed Description

Definition at line 209 of file wallet2.h.

Member Typedef Documentation

◆ get_outs_entry

Definition at line 562 of file wallet2.h.

◆ payment_container

Definition at line 450 of file wallet2.h.

◆ transfer_container

Definition at line 449 of file wallet2.h.

Member Enumeration Documentation

◆ AskPasswordType

Enumerator
AskPasswordNever 
AskPasswordOnAction 
AskPasswordToDecrypt 

Definition at line 225 of file wallet2.h.

◆ BackgroundMiningSetupType

Enumerator
BackgroundMiningMaybe 
BackgroundMiningYes 
BackgroundMiningNo 

Definition at line 231 of file wallet2.h.

◆ RefreshType

Enumerator
RefreshFull 
RefreshOptimizeCoinbase 
RefreshNoCoinbase 
RefreshDefault 

Definition at line 218 of file wallet2.h.

Constructor & Destructor Documentation

◆ wallet2()

tools::wallet2::wallet2 ( cryptonote::network_type  nettype = cryptonote::MAINNET,
uint64_t  kdf_rounds = 1,
bool  unattended = false 
)

Definition at line 1102 of file wallet2.cpp.

1102  :
1103  m_multisig_rescan_info(NULL),
1104  m_multisig_rescan_k(NULL),
1105  m_upper_transaction_weight_limit(0),
1106  m_run(true),
1107  m_callback(0),
1108  m_trusted_daemon(false),
1109  m_nettype(nettype),
1110  m_multisig_rounds_passed(0),
1111  m_always_confirm_transfers(true),
1112  m_print_ring_members(false),
1113  m_store_tx_info(true),
1114  m_default_mixin(0),
1115  m_default_priority(0),
1116  m_refresh_type(RefreshOptimizeCoinbase),
1117  m_auto_refresh(true),
1118  m_first_refresh_done(false),
1119  m_refresh_from_block_height(0),
1120  m_explicit_refresh_from_block_height(true),
1121  m_confirm_missing_payment_id(true),
1122  m_confirm_non_default_ring_size(true),
1123  m_ask_password(AskPasswordOnAction),
1124  m_min_output_count(0),
1125  m_min_output_value(0),
1126  m_merge_destinations(false),
1127  m_confirm_backlog(true),
1128  m_confirm_backlog_threshold(0),
1129  m_confirm_export_overwrite(true),
1130  m_auto_low_priority(true),
1131  m_segregate_pre_fork_outputs(true),
1132  m_key_reuse_mitigation2(true),
1133  m_segregation_height(0),
1134  m_ignore_fractional_outputs(true),
1135  m_track_uses(false),
1136  m_setup_background_mining(BackgroundMiningMaybe),
1137  m_is_initialized(false),
1138  m_kdf_rounds(kdf_rounds),
1139  is_old_file_format(false),
1140  m_watch_only(false),
1141  m_multisig(false),
1142  m_multisig_threshold(0),
1143  m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex),
1144  m_account_public_address{crypto::null_pkey, crypto::null_pkey},
1145  m_subaddress_lookahead_major(SUBADDRESS_LOOKAHEAD_MAJOR),
1146  m_subaddress_lookahead_minor(SUBADDRESS_LOOKAHEAD_MINOR),
1147  m_light_wallet(false),
1148  m_light_wallet_scanned_block_height(0),
1149  m_light_wallet_blockchain_height(0),
1150  m_light_wallet_connected(false),
1151  m_light_wallet_balance(0),
1152  m_light_wallet_unlocked_balance(0),
1153  m_original_keys_available(false),
1154  m_message_store(),
1155  m_key_device_type(hw::device::device_type::SOFTWARE),
1156  m_ring_history_saved(false),
1157  m_ringdb(),
1158  m_last_block_reward(0),
1159  m_encrypt_keys_after_refresh(boost::none),
1160  m_unattended(unattended),
1161  m_devices_registered(false),
1162  m_device_last_key_image_sync(0),
1163  m_use_dns(true),
1164  m_offline(false),
1165  m_account_major_offset(0)
1166 {
1167 }
#define SUBADDRESS_LOOKAHEAD_MINOR
Definition: wallet2.cpp:121
cryptonote::network_type nettype() const
Definition: wallet2.h:824
#define SUBADDRESS_LOOKAHEAD_MAJOR
Definition: wallet2.cpp:120
const crypto::public_key null_pkey
Definition: crypto.cpp:72

◆ ~wallet2()

tools::wallet2::~wallet2 ( )

Definition at line 1169 of file wallet2.cpp.

1170 {
1171 }

Member Function Documentation

◆ account_major_offset() [1/2]

void tools::wallet2::account_major_offset ( uint32_t  offset)
inline

Definition at line 810 of file wallet2.h.

810 {m_account_major_offset = offset;}

◆ account_major_offset() [2/2]

uint32_t tools::wallet2::account_major_offset ( ) const
inline

Definition at line 811 of file wallet2.h.

811 {return m_account_major_offset;}

◆ add_address_book_row()

bool tools::wallet2::add_address_book_row ( const cryptonote::account_public_address address,
const crypto::hash payment_id,
const std::string &  description,
bool  is_subaddress 
)

Definition at line 3451 of file wallet2.cpp.

3452 {
3453  wallet2::address_book_row a;
3454  a.m_address = address;
3455  a.m_payment_id = payment_id;
3456  a.m_description = description;
3457  a.m_is_subaddress = is_subaddress;
3458 
3459  auto old_size = m_address_book.size();
3460  m_address_book.push_back(a);
3461  if(m_address_book.size() == old_size+1)
3462  return true;
3463  return false;
3464 }
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
const char * address
Definition: multisig.cpp:37

◆ add_checkpoint()

void tools::wallet2::add_checkpoint ( uint64_t  height,
std::string  hash 
)

Definition at line 13766 of file wallet2.cpp.

13766  {
13767  m_checkpoints.add_checkpoint(height, hash);
13768 }
bool add_checkpoint(uint64_t height, const std::string &hash_str)
adds a checkpoint to the container
Definition: checkpoints.cpp:76
uint64_t height
Definition: blockchain.cpp:91
POD_CLASS hash
Definition: hash.h:50

◆ add_subaddress()

void tools::wallet2::add_subaddress ( uint32_t  index_major,
const std::string &  label 
)

Definition at line 1470 of file wallet2.cpp.

1471 {
1472  THROW_WALLET_EXCEPTION_IF(index_major >= m_subaddress_labels.size(), error::account_index_outofbound);
1473  uint32_t index_minor = (uint32_t)get_num_subaddresses(index_major);
1474  expand_subaddresses({index_major, index_minor});
1475  m_subaddress_labels[index_major][index_minor] = label;
1476 }
size_t get_num_subaddresses(uint32_t index_major) const
Definition: wallet2.h:802
unsigned int uint32_t
Definition: stdint.h:126
void expand_subaddresses(const cryptonote::subaddress_index &index, const bool udpate_account_tags=true)
Definition: wallet2.cpp:1478
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
Here is the call graph for this function:

◆ add_subaddress_account()

void tools::wallet2::add_subaddress_account ( const std::string &  label,
const bool  update_account_tags = true 
)

Definition at line 1463 of file wallet2.cpp.

1464 {
1466  expand_subaddresses({index_major, 0}, update_account_tags);
1467  m_subaddress_labels[index_major][0] = label;
1468 }
unsigned int uint32_t
Definition: stdint.h:126
void expand_subaddresses(const cryptonote::subaddress_index &index, const bool udpate_account_tags=true)
Definition: wallet2.cpp:1478
size_t get_num_subaddress_accounts() const
Definition: wallet2.h:801
Here is the call graph for this function:
Here is the caller graph for this function:

◆ adjust_mixin()

uint64_t tools::wallet2::adjust_mixin ( uint64_t  mixin) const

Definition at line 7860 of file wallet2.cpp.

7861 {
7862  const uint64_t min_ring_size = get_min_ring_size();
7863  if (mixin + 1 < min_ring_size)
7864  {
7865  MWARNING("Requested ring size " << (mixin + 1) << " too low, using " << min_ring_size);
7866  mixin = min_ring_size-1;
7867  }
7868  const uint64_t max_ring_size = get_max_ring_size();
7869  if (max_ring_size && mixin + 1 > max_ring_size)
7870  {
7871  MWARNING("Requested ring size " << (mixin + 1) << " too high, using " << max_ring_size);
7872  mixin = max_ring_size-1;
7873  }
7874  return mixin;
7875 }
uint64_t get_max_ring_size() const
Definition: wallet2.cpp:7851
unsigned __int64 uint64_t
Definition: stdint.h:136
#define MWARNING(x)
Definition: misc_log_ex.h:74
uint64_t get_min_ring_size() const
Definition: wallet2.cpp:7836

◆ adjust_priority()

uint32_t tools::wallet2::adjust_priority ( uint32_t  priority)

Definition at line 7877 of file wallet2.cpp.

7878 {
7879  // just return 1 for normal priority for aurelius instead of being concerned with backlog and adjusting priority because fees are 0 for everyone
7880  return 1;
7881 
7882  if (priority == 0 && m_default_priority == 0 && auto_low_priority())
7883  {
7884  try
7885  {
7886  // check if there's a backlog in the tx pool
7887  const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
7888  const uint64_t base_fee = get_base_fee();
7889  const uint64_t fee_multiplier = get_fee_multiplier(1);
7890  const double fee_level = fee_multiplier * base_fee * (use_per_byte_fee ? 1 : (12/(double)13 / (double)1024));
7891  const std::vector<std::pair<uint64_t, uint64_t>> blocks = estimate_backlog({std::make_pair(fee_level, fee_level)});
7892  if (blocks.size() != 1)
7893  {
7894  MERROR("Bad estimated backlog array size");
7895  return priority;
7896  }
7897  else if (blocks[0].first > 0)
7898  {
7899  MINFO("We don't use the low priority because there's a backlog in the tx pool.");
7900  return priority;
7901  }
7902 
7903  // get the current full reward zone
7904  uint64_t block_weight_limit = 0;
7905  const auto result = m_node_rpc_proxy.get_block_weight_limit(block_weight_limit);
7906  throw_on_rpc_response_error(result, "get_info");
7907  const uint64_t full_reward_zone = block_weight_limit / 2;
7908 
7909  // get the last N block headers and sum the block sizes
7910  const size_t N = 10;
7911  if (m_blockchain.size() < N)
7912  {
7913  MERROR("The blockchain is too short");
7914  return priority;
7915  }
7918  m_daemon_rpc_mutex.lock();
7919  getbh_req.start_height = m_blockchain.size() - N;
7920  getbh_req.end_height = m_blockchain.size() - 1;
7921  bool r = invoke_http_json_rpc("/json_rpc", "getblockheadersrange", getbh_req, getbh_res, rpc_timeout);
7922  m_daemon_rpc_mutex.unlock();
7923  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getblockheadersrange");
7924  THROW_WALLET_EXCEPTION_IF(getbh_res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getblockheadersrange");
7925  THROW_WALLET_EXCEPTION_IF(getbh_res.status != CORE_RPC_STATUS_OK, error::get_blocks_error, get_rpc_status(getbh_res.status));
7926  if (getbh_res.headers.size() != N)
7927  {
7928  MERROR("Bad blockheaders size");
7929  return priority;
7930  }
7931  size_t block_weight_sum = 0;
7932  for (const cryptonote::block_header_response &i : getbh_res.headers)
7933  {
7934  block_weight_sum += i.block_weight;
7935  }
7936 
7937  // estimate how 'full' the last N blocks are
7938  const size_t P = 100 * block_weight_sum / (N * full_reward_zone);
7939  MINFO((boost::format("The last %d blocks fill roughly %d%% of the full reward zone.") % N % P).str());
7940  if (P > 80)
7941  {
7942  MINFO("We don't use the low priority because recent blocks are quite full.");
7943  return priority;
7944  }
7945  MINFO("We'll use the low priority because probably it's safe to do so.");
7946  return 1;
7947  }
7948  catch (const std::exception &e)
7949  {
7950  MERROR(e.what());
7951  }
7952  }
7953  return priority;
7954 }
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MINFO(x)
Definition: misc_log_ex.h:75
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
std::vector< std::pair< uint64_t, uint64_t > > estimate_backlog(const std::vector< std::pair< double, double >> &fee_levels)
Definition: wallet2.cpp:13489
uint64_t get_base_fee() const
Definition: wallet2.cpp:7785
#define CORE_RPC_STATUS_OK
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
unsigned __int64 uint64_t
Definition: stdint.h:136
boost::optional< std::string > get_block_weight_limit(uint64_t &block_weight_limit) const
size_t size() const
Definition: wallet2.h:181
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm=-1) const
Definition: wallet2.cpp:7732
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
bool invoke_http_json_rpc(const boost::string_ref uri, const std::string &method_name, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET", const std::string &req_id="0")
Definition: wallet2.h:1333
failed_rpc_request< refresh_error, get_blocks_error_message_index > get_blocks_error
#define HF_VERSION_PER_BYTE_FEE
bool auto_low_priority() const
Definition: wallet2.h:1093

◆ always_confirm_transfers() [1/2]

bool tools::wallet2::always_confirm_transfers ( ) const
inline

Definition at line 1065 of file wallet2.h.

1065 { return m_always_confirm_transfers; }

◆ always_confirm_transfers() [2/2]

void tools::wallet2::always_confirm_transfers ( bool  always)
inline

Definition at line 1066 of file wallet2.h.

1066 { m_always_confirm_transfers = always; }

◆ ask_password() [1/2]

AskPasswordType tools::wallet2::ask_password ( ) const
inline

Definition at line 1079 of file wallet2.h.

1079 { return m_ask_password; }
Here is the caller graph for this function:

◆ ask_password() [2/2]

void tools::wallet2::ask_password ( AskPasswordType  ask)
inline

Definition at line 1080 of file wallet2.h.

1080 { m_ask_password = ask; }

◆ auto_low_priority() [1/2]

bool tools::wallet2::auto_low_priority ( ) const
inline

Definition at line 1093 of file wallet2.h.

1093 { return m_auto_low_priority; }

◆ auto_low_priority() [2/2]

void tools::wallet2::auto_low_priority ( bool  value)
inline

Definition at line 1094 of file wallet2.h.

1094 { m_auto_low_priority = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ auto_refresh() [1/2]

bool tools::wallet2::auto_refresh ( ) const
inline

Definition at line 1075 of file wallet2.h.

1075 { return m_auto_refresh; }

◆ auto_refresh() [2/2]

void tools::wallet2::auto_refresh ( bool  r)
inline

Definition at line 1076 of file wallet2.h.

1076 { m_auto_refresh = r; }

◆ balance()

uint64_t tools::wallet2::balance ( uint32_t  subaddr_index_major,
bool  public_blockchain 
) const

Definition at line 6162 of file wallet2.cpp.

6163 {
6164  uint64_t amount = 0;
6165  if(m_light_wallet)
6166  return m_light_wallet_unlocked_balance;
6167  for (const auto& i : balance_per_subaddress(index_major, public_blockchain))
6168  amount += i.second;
6169  return amount;
6170 }
std::map< uint32_t, uint64_t > balance_per_subaddress(uint32_t subaddr_index_major, bool public_blockchain=false) const
Definition: wallet2.cpp:6188
unsigned __int64 uint64_t
Definition: stdint.h:136
Here is the caller graph for this function:

◆ balance_all()

uint64_t tools::wallet2::balance_all ( bool  public_blockchain) const

Definition at line 6292 of file wallet2.cpp.

6293 {
6294  uint64_t r = 0;
6295  for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major)
6296  r += balance(index_major, public_blockchain);
6297  return r;
6298 }
uint64_t balance(uint32_t subaddr_index_major, bool public_blockchain) const
Definition: wallet2.cpp:6162
unsigned int uint32_t
Definition: stdint.h:126
unsigned __int64 uint64_t
Definition: stdint.h:136
size_t get_num_subaddress_accounts() const
Definition: wallet2.h:801

◆ balance_per_subaddress()

std::map< uint32_t, uint64_t > tools::wallet2::balance_per_subaddress ( uint32_t  subaddr_index_major,
bool  public_blockchain = false 
) const

Definition at line 6188 of file wallet2.cpp.

6189 {
6190  std::map<uint32_t, uint64_t> amount_per_subaddr;
6191  for (const auto& td: m_transfers)
6192  {
6193  if((public_blockchain && td.m_tx.version == 1) || (!public_blockchain && td.m_tx.version > 1))
6194  continue;
6195 
6196  if (td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen)
6197  {
6198  auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
6199  if (found == amount_per_subaddr.end())
6200  amount_per_subaddr[td.m_subaddr_index.minor] = td.amount();
6201  else
6202  found->second += td.amount();
6203  }
6204  }
6205  for (const auto& utx: m_unconfirmed_txs) {
6206  if ((public_blockchain && utx.second.m_tx.version == 1) || (!public_blockchain && utx.second.m_tx.version > 1))
6207  continue;
6208 
6209  if (utx.second.m_state != wallet2::unconfirmed_transfer_details::failed) {
6210  //HANDLE LOOPBACK OUTS INCLUDING CHANGE
6211  if(utx.second.m_tx.version > 1){
6212  for (const cryptonote::tx_out &out : utx.second.m_tx.vout) {
6213  if (out.target.type() == typeid(txout_to_key_public)) {
6214  // check whether this out is to one of our subaddresses
6215  auto target = boost::get<cryptonote::txout_to_key_public>(out.target);
6216  auto subaddr_found = m_subaddresses.find(target.address.m_spend_public_key);
6217  // if this out is to us
6218  // and the view key part of the destination matches that of our our subaddress,
6219  // and the major index of this subaddress corresponds to the current account we're getting balance for,
6220  // then add amount to balance
6221  if (subaddr_found != m_subaddresses.end() && get_subaddress(subaddr_found->second).m_view_public_key == target.address.m_view_public_key && subaddr_found->second.major == index_major) {
6222  auto found = amount_per_subaddr.find(subaddr_found->second.minor);
6223  if (found == amount_per_subaddr.end())
6224  amount_per_subaddr[subaddr_found->second.minor] = out.amount;
6225  else
6226  found->second += out.amount;
6227  } else {
6228  continue;
6229  }
6230  }
6231  }
6232  }
6233  // CHANGE HANDLING FOR V1 TX
6234  // (NB LOOPBACK OUTS APART FROM CHANGE AREN'T FACTORED INTO BAL WHILST TX IS UNCONFIRMED
6235  // and there is no need to fix this (monero) issue as we've migrated to a transparent chain)
6236  if (utx.second.m_tx.version == 1 && utx.second.m_subaddr_account == index_major) {
6237  // all changes go to 0-th subaddress (in the current subaddress account)
6238  auto found = amount_per_subaddr.find(0);
6239  if (found == amount_per_subaddr.end())
6240  amount_per_subaddr[0] = utx.second.m_change;
6241  else
6242  found->second += utx.second.m_change;
6243  }
6244  }
6245  }
6246  return amount_per_subaddr;
6247 }
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index &index) const
Definition: wallet2.cpp:1430

◆ blackball_output()

bool tools::wallet2::blackball_output ( const std::pair< uint64_t, uint64_t > &  output)

Definition at line 8175 of file wallet2.cpp.

8176 {
8177  if (!m_ringdb)
8178  return false;
8179  try { return m_ringdb->blackball(output); }
8180  catch (const std::exception &e) { return false; }
8181 }

◆ callback() [1/2]

i_wallet2_callback* tools::wallet2::callback ( ) const
inline

Definition at line 762 of file wallet2.h.

762 { return m_callback; }

◆ callback() [2/2]

void tools::wallet2::callback ( i_wallet2_callback callback)
inline

Definition at line 763 of file wallet2.h.

763 { m_callback = callback; }
i_wallet2_callback * callback() const
Definition: wallet2.h:762
Here is the call graph for this function:
Here is the caller graph for this function:

◆ change_password()

void tools::wallet2::change_password ( const std::string &  filename,
const epee::wipeable_string original_password,
const epee::wipeable_string new_password 
)

Definition at line 4320 of file wallet2.cpp.

4321 {
4322  if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
4323  decrypt_keys(original_password);
4324  setup_keys(new_password);
4325  rewrite(filename, new_password);
4326  if (!filename.empty())
4327  store();
4328 }
void decrypt_keys(const crypto::chacha_key &key)
Definition: wallet2.cpp:4752
void rewrite(const std::string &wallet_name, const epee::wipeable_string &password)
Rewrites to the wallet file for wallet upgrade (doesn&#39;t generate key, assumes it&#39;s already there) ...
Definition: wallet2.cpp:5670

◆ check_connection()

bool tools::wallet2::check_connection ( uint32_t version = NULL,
bool ssl = NULL,
uint32_t  timeout = 200000 
)

Definition at line 5758 of file wallet2.cpp.

5759 {
5760  THROW_WALLET_EXCEPTION_IF(!m_is_initialized, error::wallet_not_initialized);
5761 
5762  if (m_offline)
5763  {
5764  if (version)
5765  *version = 0;
5766  if (ssl)
5767  *ssl = false;
5768  return false;
5769  }
5770 
5771  // TODO: Add light wallet version check.
5772  if(m_light_wallet) {
5773  if (version)
5774  *version = 0;
5775  if (ssl)
5776  *ssl = m_light_wallet_connected; // light wallet is always SSL
5777  return m_light_wallet_connected;
5778  }
5779 
5780  {
5781  boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
5782  if(!m_http_client.is_connected(ssl))
5783  {
5784  m_node_rpc_proxy.invalidate();
5785  if (!m_http_client.connect(std::chrono::milliseconds(timeout)))
5786  return false;
5787  if(!m_http_client.is_connected(ssl))
5788  return false;
5789  }
5790  }
5791 
5792  if (version)
5793  {
5796  bool r = invoke_http_json_rpc("/json_rpc", "get_version", req_t, resp_t);
5797  if(!r) {
5798  *version = 0;
5799  return false;
5800  }
5801  if (resp_t.status != CORE_RPC_STATUS_OK)
5802  *version = 0;
5803  else
5804  *version = resp_t.version;
5805  }
5806 
5807  return true;
5808 }
bool connect(std::chrono::milliseconds timeout)
Definition: http_client.h:333
#define CORE_RPC_STATUS_OK
version
Supported socks variants.
Definition: socks.h:57
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
bool invoke_http_json_rpc(const boost::string_ref uri, const std::string &method_name, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET", const std::string &req_id="0")
Definition: wallet2.h:1333
Here is the call graph for this function:

◆ check_reserve_proof()

bool tools::wallet2::check_reserve_proof ( const cryptonote::account_public_address address,
const std::string &  message,
const std::string &  sig_str,
uint64_t total,
uint64_t spent 
)

Verifies a proof of reserve.

Parameters
addressThe signer's address
messageChallenge message used for signing
sig_strSignature string
total[OUT] the sum of funds included in the signature
spent[OUT] the sum of spent funds included in the signature
Returns
true if the signature verifies correctly

Definition at line 11790 of file wallet2.cpp.

11791 {
11792  uint32_t rpc_version;
11793  THROW_WALLET_EXCEPTION_IF(!check_connection(&rpc_version), error::wallet_internal_error, "Failed to connect to daemon: " + get_daemon_address());
11794  THROW_WALLET_EXCEPTION_IF(rpc_version < MAKE_CORE_RPC_VERSION(1, 0), error::wallet_internal_error, "Daemon RPC version is too old");
11795 
11796  static constexpr char header[] = "ReserveProofV1";
11797  THROW_WALLET_EXCEPTION_IF(!boost::string_ref{sig_str}.starts_with(header), error::wallet_internal_error,
11798  "Signature header check error");
11799 
11800  std::string sig_decoded;
11801  THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(std::strlen(header)), sig_decoded), error::wallet_internal_error,
11802  "Signature decoding error");
11803 
11804  std::istringstream iss(sig_decoded);
11806  std::vector<reserve_proof_entry> proofs;
11807  std::unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys;
11808  ar >> proofs >> subaddr_spendkeys;
11809 
11810  THROW_WALLET_EXCEPTION_IF(subaddr_spendkeys.count(address.m_spend_public_key) == 0, error::wallet_internal_error,
11811  "The given address isn't found in the proof");
11812 
11813  // compute signature prefix hash
11814  std::string prefix_data = message;
11815  prefix_data.append((const char*)&address, sizeof(cryptonote::account_public_address));
11816  for (size_t i = 0; i < proofs.size(); ++i)
11817  {
11818  prefix_data.append((const char*)&proofs[i].key_image, sizeof(crypto::key_image));
11819  }
11820  crypto::hash prefix_hash;
11821  crypto::cn_fast_hash(prefix_data.data(), prefix_data.size(), prefix_hash);
11822 
11823  // fetch txes from daemon
11826  for (size_t i = 0; i < proofs.size(); ++i)
11827  gettx_req.txs_hashes.push_back(epee::string_tools::pod_to_hex(proofs[i].txid));
11828  gettx_req.decode_as_json = false;
11829  gettx_req.prune = true;
11830  m_daemon_rpc_mutex.lock();
11831  bool ok = invoke_http_json("/gettransactions", gettx_req, gettx_res, rpc_timeout);
11832  m_daemon_rpc_mutex.unlock();
11833  THROW_WALLET_EXCEPTION_IF(!ok || gettx_res.txs.size() != proofs.size(),
11834  error::wallet_internal_error, "Failed to get transaction from daemon");
11835 
11836  // check spent status
11839  for (size_t i = 0; i < proofs.size(); ++i)
11840  kispent_req.key_images.push_back(epee::string_tools::pod_to_hex(proofs[i].key_image));
11841  m_daemon_rpc_mutex.lock();
11842  ok = invoke_http_json("/is_key_image_spent", kispent_req, kispent_res, rpc_timeout);
11843  m_daemon_rpc_mutex.unlock();
11844  THROW_WALLET_EXCEPTION_IF(!ok || kispent_res.spent_status.size() != proofs.size(),
11845  error::wallet_internal_error, "Failed to get key image spent status from daemon");
11846 
11847  total = spent = 0;
11848  for (size_t i = 0; i < proofs.size(); ++i)
11849  {
11850  const reserve_proof_entry& proof = proofs[i];
11851  THROW_WALLET_EXCEPTION_IF(gettx_res.txs[i].in_pool, error::wallet_internal_error, "Tx is unconfirmed");
11852 
11854  crypto::hash tx_hash;
11855  ok = get_pruned_tx(gettx_res.txs[i], tx, tx_hash);
11856  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
11857 
11858  THROW_WALLET_EXCEPTION_IF(tx_hash != proof.txid, error::wallet_internal_error, "Failed to get the right transaction from daemon");
11859 
11860  THROW_WALLET_EXCEPTION_IF(proof.index_in_tx >= tx.vout.size(), error::wallet_internal_error, "index_in_tx is out of bound");
11861 
11862  const cryptonote::txout_to_key* const out_key = boost::get<cryptonote::txout_to_key>(std::addressof(tx.vout[proof.index_in_tx].target));
11863  THROW_WALLET_EXCEPTION_IF(!out_key, error::wallet_internal_error, "Output key wasn't found")
11864 
11865  // get tx pub key
11866  const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
11867  THROW_WALLET_EXCEPTION_IF(tx_pub_key == crypto::null_pkey, error::wallet_internal_error, "The tx public key isn't found");
11868  const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
11869 
11870  // check singature for shared secret
11871  ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, proof.shared_secret, proof.shared_secret_sig);
11872  if (!ok && additional_tx_pub_keys.size() == tx.vout.size())
11873  ok = crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[proof.index_in_tx], boost::none, proof.shared_secret, proof.shared_secret_sig);
11874  if (!ok)
11875  return false;
11876 
11877  // check signature for key image
11878  const std::vector<const crypto::public_key*> pubs = { &out_key->key };
11879  ok = crypto::check_ring_signature(prefix_hash, proof.key_image, &pubs[0], 1, &proof.key_image_sig);
11880  if (!ok)
11881  return false;
11882 
11883  // check if the address really received the fund
11884  crypto::key_derivation derivation;
11885  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(proof.shared_secret, rct::rct2sk(rct::I), derivation), error::wallet_internal_error, "Failed to generate key derivation");
11886  crypto::public_key subaddr_spendkey;
11887  crypto::derive_subaddress_public_key(out_key->key, derivation, proof.index_in_tx, subaddr_spendkey);
11888  THROW_WALLET_EXCEPTION_IF(subaddr_spendkeys.count(subaddr_spendkey) == 0, error::wallet_internal_error,
11889  "The address doesn't seem to have received the fund");
11890 
11891  // check amount
11892  uint64_t amount = tx.vout[proof.index_in_tx].amount;
11893  if (amount == 0)
11894  {
11895  // decode rct
11896  crypto::secret_key shared_secret;
11897  crypto::derivation_to_scalar(derivation, proof.index_in_tx, shared_secret);
11898  rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[proof.index_in_tx];
11899  rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tx.rct_signatures.type == rct::RCTTypeBulletproof2);
11900  amount = rct::h2d(ecdh_info.amount);
11901  }
11902  total += amount;
11903  if (kispent_res.spent_status[i])
11904  spent += amount;
11905  }
11906 
11907  // check signatures for all subaddress spend keys
11908  for (const auto &i : subaddr_spendkeys)
11909  {
11910  if (!crypto::check_signature(prefix_hash, i.first, i.second))
11911  return false;
11912  }
11913  return true;
11914 }
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:279
etn_amount h2d(const key &test)
Definition: rctTypes.cpp:161
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
bool decode(const std::string &enc, std::string &data)
Definition: base58.cpp:196
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
bool check_connection(uint32_t *version=NULL, bool *ssl=NULL, uint32_t timeout=200000)
Definition: wallet2.cpp:5758
std::string get_daemon_address() const
Definition: wallet2.cpp:11926
bool check_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const signature *sig)
Definition: crypto.h:333
const char * key
Definition: hmac_keccak.cpp:39
crypto namespace.
Definition: crypto.cpp:58
STL namespace.
uint8_t type
Definition: rctTypes.h:241
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
std::vector< ecdhTuple > ecdhInfo
Definition: rctTypes.h:246
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
#define MAKE_CORE_RPC_VERSION(major, minor)
unsigned int uint32_t
Definition: stdint.h:126
const crypto::public_key null_pkey
Definition: crypto.cpp:72
bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result)
Definition: crypto.h:286
unsigned __int64 uint64_t
Definition: stdint.h:136
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
#define false
Definition: stdbool.h:38
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
std::string message("Message requiring signing")
void ecdhDecode(ecdhTuple &masked, const key &sharedSec, bool v2)
Definition: rctOps.cpp:712
bool check_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11527
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
else if(0==res)
error
Tracks LMDB error codes.
Definition: error.h:44
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:295
Here is the call graph for this function:

◆ check_spend_proof()

bool tools::wallet2::check_spend_proof ( const crypto::hash txid,
const std::string &  message,
const std::string &  sig_str 
)

Definition at line 11163 of file wallet2.cpp.

11164 {
11165  const std::string header = "SpendProofV1";
11166  const size_t header_len = header.size();
11167  THROW_WALLET_EXCEPTION_IF(sig_str.size() < header_len || sig_str.substr(0, header_len) != header, error::wallet_internal_error,
11168  "Signature header check error");
11169 
11170  // fetch tx from daemon
11172  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
11173  req.decode_as_json = false;
11174  req.prune = true;
11176  bool r;
11177  {
11178  const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
11179  r = invoke_http_json("/gettransactions", req, res, rpc_timeout);
11180  }
11181  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gettransactions");
11182  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gettransactions");
11183  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "gettransactions");
11184  THROW_WALLET_EXCEPTION_IF(res.txs.size() != 1, error::wallet_internal_error,
11185  "daemon returned wrong response for gettransactions, wrong txs count = " +
11186  std::to_string(res.txs.size()) + ", expected 1");
11187 
11189  crypto::hash tx_hash;
11190  THROW_WALLET_EXCEPTION_IF(!get_pruned_tx(res.txs[0], tx, tx_hash), error::wallet_internal_error, "failed to get tx from daemon");
11191 
11192  // check signature size
11193  size_t num_sigs = 0;
11194  for(size_t i = 0; i < tx.vin.size(); ++i)
11195  {
11196  const txin_to_key* const in_key = boost::get<txin_to_key>(std::addressof(tx.vin[i]));
11197  if (in_key != nullptr)
11198  num_sigs += in_key->key_offsets.size();
11199  }
11200  std::vector<std::vector<crypto::signature>> signatures = { std::vector<crypto::signature>(1) };
11201  const size_t sig_len = tools::base58::encode(std::string((const char *)&signatures[0][0], sizeof(crypto::signature))).size();
11202  if( sig_str.size() != header_len + num_sigs * sig_len ) {
11203  return false;
11204  }
11205 
11206  // decode base58
11207  signatures.clear();
11208  size_t offset = header_len;
11209  for(size_t i = 0; i < tx.vin.size(); ++i)
11210  {
11211  const txin_to_key* const in_key = boost::get<txin_to_key>(std::addressof(tx.vin[i]));
11212  if (in_key == nullptr)
11213  continue;
11214  signatures.resize(signatures.size() + 1);
11215  signatures.back().resize(in_key->key_offsets.size());
11216  for (size_t j = 0; j < in_key->key_offsets.size(); ++j)
11217  {
11218  std::string sig_decoded;
11219  THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(offset, sig_len), sig_decoded), error::wallet_internal_error, "Signature decoding error");
11220  THROW_WALLET_EXCEPTION_IF(sizeof(crypto::signature) != sig_decoded.size(), error::wallet_internal_error, "Signature decoding error");
11221  memcpy(&signatures.back()[j], sig_decoded.data(), sizeof(crypto::signature));
11222  offset += sig_len;
11223  }
11224  }
11225 
11226  // get signature prefix hash
11227  std::string sig_prefix_data((const char*)&txid, sizeof(crypto::hash));
11228  sig_prefix_data += message;
11229  crypto::hash sig_prefix_hash;
11230  crypto::cn_fast_hash(sig_prefix_data.data(), sig_prefix_data.size(), sig_prefix_hash);
11231 
11232  std::vector<std::vector<crypto::signature>>::const_iterator sig_iter = signatures.cbegin();
11233  for(size_t i = 0; i < tx.vin.size(); ++i)
11234  {
11235  const txin_to_key* const in_key = boost::get<txin_to_key>(std::addressof(tx.vin[i]));
11236  if (in_key == nullptr)
11237  continue;
11238 
11239  // get output pubkeys in the ring
11241  const std::vector<uint64_t> absolute_offsets = cryptonote::relative_output_offsets_to_absolute(in_key->key_offsets);
11242  req.outputs.resize(absolute_offsets.size());
11243  for (size_t j = 0; j < absolute_offsets.size(); ++j)
11244  {
11245  req.outputs[j].amount = in_key->amount;
11246  req.outputs[j].index = absolute_offsets[j];
11247  }
11249  bool r;
11250  {
11251  const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
11252  r = invoke_http_bin("/get_outs.bin", req, res, rpc_timeout);
11253  }
11254  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_outs.bin");
11255  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_outs.bin");
11256  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "get_outs.bin");
11257  THROW_WALLET_EXCEPTION_IF(res.outs.size() != req.outputs.size(), error::wallet_internal_error,
11258  "daemon returned wrong response for get_outs.bin, wrong amounts count = " +
11259  std::to_string(res.outs.size()) + ", expected " + std::to_string(req.outputs.size()));
11260 
11261  // copy pointers
11262  std::vector<const crypto::public_key *> p_output_keys;
11263  for (const COMMAND_RPC_GET_OUTPUTS_BIN::outkey &out : res.outs)
11264  p_output_keys.push_back(&out.key);
11265 
11266  // check this ring
11267  if (!crypto::check_ring_signature(sig_prefix_hash, in_key->k_image, p_output_keys, sig_iter->data()))
11268  return false;
11269  ++sig_iter;
11270  }
11271  THROW_WALLET_EXCEPTION_IF(sig_iter != signatures.cend(), error::wallet_internal_error, "Signature iterator didn't reach the end");
11272  return true;
11273 }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
::std::string string
Definition: gtest-port.h:1097
bool decode(const std::string &enc, std::string &data)
Definition: base58.cpp:196
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
bool check_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const signature *sig)
Definition: crypto.h:333
std::vector< uint64_t > key_offsets
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
std::string encode(const std::string &data)
Definition: base58.cpp:173
#define CORE_RPC_STATUS_OK
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
void cn_fast_hash(const void *data, size_t length, char *hash)
std::string message("Message requiring signing")
bool invoke_http_bin(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1326
POD_CLASS signature
Definition: crypto.h:108
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void * memcpy(void *a, const void *b, size_t c)
crypto::key_image k_image
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
POD_CLASS hash
Definition: hash.h:50
std::string to_string(t_connection_type type)
Here is the call graph for this function:

◆ check_tx_key()

void tools::wallet2::check_tx_key ( const crypto::hash txid,
const crypto::secret_key tx_key,
const std::vector< crypto::secret_key > &  additional_tx_keys,
const cryptonote::account_public_address address,
uint64_t received,
bool in_pool,
uint64_t confirmations 
)

Definition at line 11276 of file wallet2.cpp.

11277 {
11278  crypto::key_derivation derivation;
11279  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, tx_key, derivation), error::wallet_internal_error,
11280  "Failed to generate key derivation from supplied parameters");
11281 
11282  std::vector<crypto::key_derivation> additional_derivations;
11283  additional_derivations.resize(additional_tx_keys.size());
11284  for (size_t i = 0; i < additional_tx_keys.size(); ++i)
11285  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(address.m_view_public_key, additional_tx_keys[i], additional_derivations[i]), error::wallet_internal_error,
11286  "Failed to generate key derivation from supplied parameters");
11287 
11288  check_tx_key_helper(txid, derivation, additional_derivations, address, received, in_pool, confirmations);
11289 }
POD_CLASS key_derivation
Definition: crypto.h:98
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
const char * address
Definition: multisig.cpp:37
void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11323
Here is the call graph for this function:

◆ check_tx_key_helper() [1/2]

void tools::wallet2::check_tx_key_helper ( const crypto::hash txid,
const crypto::key_derivation derivation,
const std::vector< crypto::key_derivation > &  additional_derivations,
const cryptonote::account_public_address address,
uint64_t received,
bool in_pool,
uint64_t confirmations 
)

Definition at line 11323 of file wallet2.cpp.

11324 {
11327  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
11328  req.decode_as_json = false;
11329  req.prune = true;
11330  m_daemon_rpc_mutex.lock();
11331  bool ok = invoke_http_json("/gettransactions", req, res, rpc_timeout);
11332  m_daemon_rpc_mutex.unlock();
11333  THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1),
11334  error::wallet_internal_error, "Failed to get transaction from daemon");
11335 
11337  crypto::hash tx_hash;
11338  if (res.txs.size() == 1)
11339  {
11340  ok = get_pruned_tx(res.txs.front(), tx, tx_hash);
11341  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
11342  }
11343  else
11344  {
11345  cryptonote::blobdata tx_data;
11346  ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data);
11347  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
11349  error::wallet_internal_error, "Failed to validate transaction from daemon");
11350  tx_hash = cryptonote::get_transaction_hash(tx);
11351  }
11352 
11353  THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error,
11354  "Failed to get the right transaction from daemon");
11355  THROW_WALLET_EXCEPTION_IF(!additional_derivations.empty() && additional_derivations.size() != tx.vout.size(), error::wallet_internal_error,
11356  "The size of additional derivations is wrong");
11357 
11358  check_tx_key_helper(tx, derivation, additional_derivations, address, received);
11359 
11360  in_pool = res.txs.front().in_pool;
11361  confirmations = 0;
11362  if (!in_pool)
11363  {
11364  std::string err;
11365  uint64_t bc_height = get_daemon_blockchain_height(err);
11366  if (err.empty())
11367  confirmations = bc_height - res.txs.front().block_height;
11368  }
11369 }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
::std::string string
Definition: gtest-port.h:1097
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
uint64_t get_daemon_blockchain_height(std::string &err) const
Definition: wallet2.cpp:11931
unsigned __int64 uint64_t
Definition: stdint.h:136
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
std::string blobdata
Definition: blobdatatype.h:39
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11323
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
Here is the call graph for this function:

◆ check_tx_key_helper() [2/2]

void tools::wallet2::check_tx_key_helper ( const cryptonote::transaction tx,
const crypto::key_derivation derivation,
const std::vector< crypto::key_derivation > &  additional_derivations,
const cryptonote::account_public_address address,
uint64_t received 
) const

Definition at line 11291 of file wallet2.cpp.

11292 {
11293  received = 0;
11294 
11295  for (size_t n = 0; n < tx.vout.size(); ++n)
11296  {
11297  const cryptonote::txout_to_key* const out_key = boost::get<cryptonote::txout_to_key>(std::addressof(tx.vout[n].target));
11298  if (!out_key)
11299  continue;
11300 
11301  crypto::public_key derived_out_key;
11302  bool r = crypto::derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
11303  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
11304  bool found = out_key->key == derived_out_key;
11305  crypto::key_derivation found_derivation = derivation;
11306  if (!found && !additional_derivations.empty())
11307  {
11308  r = crypto::derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
11309  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
11310  found = out_key->key == derived_out_key;
11311  found_derivation = additional_derivations[n];
11312  }
11313 
11314  if (found)
11315  {
11316  uint64_t amount;
11317  amount = tx.vout[n].amount;
11318  received += amount;
11319  }
11320  }
11321 }
POD_CLASS key_derivation
Definition: crypto.h:98
unsigned __int64 uint64_t
Definition: stdint.h:136
POD_CLASS public_key
Definition: crypto.h:76
crypto::public_key key
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
Definition: crypto.h:275
const char * address
Definition: multisig.cpp:37
Here is the call graph for this function:

◆ check_tx_proof() [1/2]

bool tools::wallet2::check_tx_proof ( const crypto::hash txid,
const cryptonote::account_public_address address,
bool  is_subaddress,
const std::string &  message,
const std::string &  sig_str,
uint64_t received,
bool in_pool,
uint64_t confirmations 
)

Definition at line 11527 of file wallet2.cpp.

11528 {
11529  // fetch tx pubkey from the daemon
11532  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
11533  req.decode_as_json = false;
11534  req.prune = true;
11535  m_daemon_rpc_mutex.lock();
11536  bool ok = invoke_http_json("/gettransactions", req, res, rpc_timeout);
11537  m_daemon_rpc_mutex.unlock();
11538  THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1),
11539  error::wallet_internal_error, "Failed to get transaction from daemon");
11540 
11542  crypto::hash tx_hash;
11543  if (res.txs.size() == 1)
11544  {
11545  ok = get_pruned_tx(res.txs.front(), tx, tx_hash);
11546  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
11547  }
11548  else
11549  {
11550  cryptonote::blobdata tx_data;
11551  ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data);
11552  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
11554  error::wallet_internal_error, "Failed to validate transaction from daemon");
11555  tx_hash = cryptonote::get_transaction_hash(tx);
11556  }
11557 
11558  THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error, "Failed to get the right transaction from daemon");
11559 
11560  if (!check_tx_proof(tx, address, is_subaddress, message, sig_str, received))
11561  return false;
11562 
11563  in_pool = res.txs.front().in_pool;
11564  confirmations = 0;
11565  if (!in_pool)
11566  {
11567  std::string err;
11568  uint64_t bc_height = get_daemon_blockchain_height(err);
11569  if (err.empty())
11570  confirmations = bc_height - res.txs.front().block_height;
11571  }
11572 
11573  return true;
11574 }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
::std::string string
Definition: gtest-port.h:1097
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
uint64_t get_daemon_blockchain_height(std::string &err) const
Definition: wallet2.cpp:11931
unsigned __int64 uint64_t
Definition: stdint.h:136
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
std::string message("Message requiring signing")
bool check_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11527
std::string blobdata
Definition: blobdatatype.h:39
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
Here is the call graph for this function:

◆ check_tx_proof() [2/2]

bool tools::wallet2::check_tx_proof ( const cryptonote::transaction tx,
const cryptonote::account_public_address address,
bool  is_subaddress,
const std::string &  message,
const std::string &  sig_str,
uint64_t received 
) const

Definition at line 11576 of file wallet2.cpp.

11577 {
11578  CHECK_AND_ASSERT_THROW_MES(tx.version == 1, "Tx proofs are for v1 transactions only");
11579  const bool is_out = sig_str.substr(0, 3) == "Out";
11580  const std::string header = is_out ? "OutProofV1" : "InProofV1";
11581  const size_t header_len = header.size();
11582  THROW_WALLET_EXCEPTION_IF(sig_str.size() < header_len || sig_str.substr(0, header_len) != header, error::wallet_internal_error,
11583  "Signature header check error");
11584 
11585  // decode base58
11586  std::vector<crypto::public_key> shared_secret(1);
11587  std::vector<crypto::signature> sig(1);
11588  const size_t pk_len = tools::base58::encode(std::string((const char *)&shared_secret[0], sizeof(crypto::public_key))).size();
11589  const size_t sig_len = tools::base58::encode(std::string((const char *)&sig[0], sizeof(crypto::signature))).size();
11590  const size_t num_sigs = (sig_str.size() - header_len) / (pk_len + sig_len);
11591  THROW_WALLET_EXCEPTION_IF(sig_str.size() != header_len + num_sigs * (pk_len + sig_len), error::wallet_internal_error,
11592  "Wrong signature size");
11593  shared_secret.resize(num_sigs);
11594  sig.resize(num_sigs);
11595  for (size_t i = 0; i < num_sigs; ++i)
11596  {
11597  std::string pk_decoded;
11598  std::string sig_decoded;
11599  const size_t offset = header_len + i * (pk_len + sig_len);
11600  THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(offset, pk_len), pk_decoded), error::wallet_internal_error,
11601  "Signature decoding error");
11602  THROW_WALLET_EXCEPTION_IF(!tools::base58::decode(sig_str.substr(offset + pk_len, sig_len), sig_decoded), error::wallet_internal_error,
11603  "Signature decoding error");
11604  THROW_WALLET_EXCEPTION_IF(sizeof(crypto::public_key) != pk_decoded.size() || sizeof(crypto::signature) != sig_decoded.size(), error::wallet_internal_error,
11605  "Signature decoding error");
11606  memcpy(&shared_secret[i], pk_decoded.data(), sizeof(crypto::public_key));
11607  memcpy(&sig[i], sig_decoded.data(), sizeof(crypto::signature));
11608  }
11609 
11611  THROW_WALLET_EXCEPTION_IF(tx_pub_key == null_pkey, error::wallet_internal_error, "Tx pubkey was not found");
11612 
11613  std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
11614  THROW_WALLET_EXCEPTION_IF(additional_tx_pub_keys.size() + 1 != num_sigs, error::wallet_internal_error, "Signature size mismatch with additional tx pubkeys");
11615 
11617  std::string prefix_data((const char*)&txid, sizeof(crypto::hash));
11618  prefix_data += message;
11619  crypto::hash prefix_hash;
11620  crypto::cn_fast_hash(prefix_data.data(), prefix_data.size(), prefix_hash);
11621 
11622  // check signature
11623  std::vector<int> good_signature(num_sigs, 0);
11624  if (is_out)
11625  {
11626  good_signature[0] = is_subaddress ?
11627  crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], sig[0]) :
11628  crypto::check_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], sig[0]);
11629 
11630  for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
11631  {
11632  good_signature[i + 1] = is_subaddress ?
11633  crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, address.m_spend_public_key, shared_secret[i + 1], sig[i + 1]) :
11634  crypto::check_tx_proof(prefix_hash, additional_tx_pub_keys[i], address.m_view_public_key, boost::none, shared_secret[i + 1], sig[i + 1]);
11635  }
11636  }
11637  else
11638  {
11639  good_signature[0] = is_subaddress ?
11640  crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], sig[0]) :
11641  crypto::check_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], sig[0]);
11642 
11643  for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
11644  {
11645  good_signature[i + 1] = is_subaddress ?
11646  crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], address.m_spend_public_key, shared_secret[i + 1], sig[i + 1]) :
11647  crypto::check_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i], boost::none, shared_secret[i + 1], sig[i + 1]);
11648  }
11649  }
11650 
11651  if (std::any_of(good_signature.begin(), good_signature.end(), [](int i) { return i > 0; }))
11652  {
11653  // obtain key derivation by multiplying scalar 1 to the shared secret
11654  crypto::key_derivation derivation;
11655  if (good_signature[0])
11656  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(shared_secret[0], rct::rct2sk(rct::I), derivation), error::wallet_internal_error, "Failed to generate key derivation");
11657 
11658  std::vector<crypto::key_derivation> additional_derivations(num_sigs - 1);
11659  for (size_t i = 1; i < num_sigs; ++i)
11660  if (good_signature[i])
11661  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(shared_secret[i], rct::rct2sk(rct::I), additional_derivations[i - 1]), error::wallet_internal_error, "Failed to generate key derivation");
11662 
11663  check_tx_key_helper(tx, derivation, additional_derivations, address, received);
11664  return true;
11665  }
11666  return false;
11667 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
bool decode(const std::string &enc, std::string &data)
Definition: base58.cpp:196
crypto namespace.
Definition: crypto.cpp:58
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
std::string encode(const std::string &data)
Definition: base58.cpp:173
const crypto::public_key null_pkey
Definition: crypto.cpp:72
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
std::string message("Message requiring signing")
bool check_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11527
bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional< public_key > &B, const public_key &D, const signature &sig)
Definition: crypto.h:314
POD_CLASS signature
Definition: crypto.h:108
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void * memcpy(void *a, const void *b, size_t c)
crypto::hash get_transaction_hash(const transaction &t)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11323
Here is the call graph for this function:

◆ cold_key_image_sync()

uint64_t tools::wallet2::cold_key_image_sync ( uint64_t spent,
uint64_t unspent 
)

Definition at line 10694 of file wallet2.cpp.

10694  {
10695  auto & hwdev = get_account().get_device();
10696  CHECK_AND_ASSERT_THROW_MES(hwdev.has_ki_cold_sync(), "Device does not support cold ki sync protocol");
10697 
10698  auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev);
10699  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
10700 
10701  std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
10703  setup_shim(&wallet_shim, this);
10704 
10705  dev_cold->ki_sync(&wallet_shim, m_transfers, ski);
10706 
10707  // Call COMMAND_RPC_IS_KEY_IMAGE_SPENT only if daemon is trusted.
10708  uint64_t import_res = import_key_images(ski, 0, spent, unspent, is_trusted_daemon());
10709  m_device_last_key_image_sync = time(NULL);
10710 
10711  return import_res;
10712 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
uint64_t import_key_images(const std::vector< std::pair< crypto::key_image, crypto::signature >> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent=true)
Definition: wallet2.cpp:12333
time_t time
Definition: blockchain.cpp:93
struct hw::wallet_shim wallet_shim
hw::device & get_device() const
Definition: account.h:91
bool is_trusted_daemon() const
Definition: wallet2.h:765
unsigned __int64 uint64_t
Definition: stdint.h:136
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:

◆ cold_sign_tx()

void tools::wallet2::cold_sign_tx ( const std::vector< pending_tx > &  ptx_vector,
signed_tx_set exported_txs,
std::vector< cryptonote::address_parse_info > &  dsts_info,
std::vector< std::string > &  tx_device_aux 
)

Definition at line 10665 of file wallet2.cpp.

10666 {
10667  auto & hwdev = get_account().get_device();
10668  if (!hwdev.has_tx_cold_sign()){
10669  throw std::invalid_argument("Device does not support cold sign protocol");
10670  }
10671 
10672  unsigned_tx_set txs;
10673  for (auto &tx: ptx_vector)
10674  {
10675  txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device()));
10676  }
10677  txs.transfers = std::make_pair(0, m_transfers);
10678 
10679  auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev);
10680  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
10681 
10682  hw::tx_aux_data aux_data;
10684  setup_shim(&wallet_shim, this);
10685  aux_data.tx_recipients = dsts_info;
10686  aux_data.bp_version = use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1;
10687  dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data);
10688  tx_device_aux = aux_data.tx_device_aux;
10689 
10690  MDEBUG("Signed tx data from hw: " << exported_txs.ptx.size() << " transactions");
10691  for (auto &c_ptx: exported_txs.ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(c_ptx.tx));
10692 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
std::vector< tools::wallet2::tx_construction_data > txes
std::vector< std::string > tx_device_aux
Definition: device_cold.hpp:46
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
#define MDEBUG(x)
Definition: misc_log_ex.h:76
struct hw::wallet_shim wallet_shim
hw::device & get_device() const
Definition: account.h:91
#define HF_VERSION_SMALLER_BP
std::string obj_to_json_str(T &obj)
tools::wallet2::transfer_container transfers
boost::optional< int > bp_version
Definition: device_cold.hpp:48
cryptonote::account_base & get_account()
Definition: wallet2.h:734
std::vector< cryptonote::address_parse_info > tx_recipients
Definition: device_cold.hpp:47
Here is the call graph for this function:

◆ cold_tx_aux_import()

void tools::wallet2::cold_tx_aux_import ( const std::vector< pending_tx > &  ptx,
const std::vector< std::string > &  tx_device_aux 
)

Definition at line 10655 of file wallet2.cpp.

10656 {
10657  CHECK_AND_ASSERT_THROW_MES(ptx.size() == tx_device_aux.size(), "TX aux has invalid size");
10658  for (size_t i = 0; i < ptx.size(); ++i){
10659  crypto::hash txid;
10660  txid = get_transaction_hash(ptx[i].tx);
10661  set_tx_device_aux(txid, tx_device_aux[i]);
10662  }
10663 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
void set_tx_device_aux(const crypto::hash &txid, const std::string &aux)
Definition: wallet2.cpp:12000
crypto::hash get_transaction_hash(const transaction &t)
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ commit_tx() [1/2]

void tools::wallet2::commit_tx ( pending_tx ptx_vector)

Definition at line 6887 of file wallet2.cpp.

6888 {
6889  using namespace cryptonote;
6890 
6891  if(m_light_wallet)
6892  {
6895  oreq.address = get_account().get_public_address_str(m_nettype);
6896  oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
6898  m_daemon_rpc_mutex.lock();
6899  bool r = invoke_http_json("/submit_raw_tx", oreq, ores, rpc_timeout, "POST");
6900  m_daemon_rpc_mutex.unlock();
6901  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "submit_raw_tx");
6902  // MyMonero and OpenMonero use different status strings
6903  THROW_WALLET_EXCEPTION_IF(ores.status != "OK" && ores.status != "success" , error::tx_rejected, ptx.tx, get_rpc_status(ores.status), ores.error);
6904  }
6905  else
6906  {
6907  // Normal submit
6909  req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx));
6910  req.do_not_relay = false;
6911  req.do_sanity_checks = true;
6912  COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
6913  m_daemon_rpc_mutex.lock();
6914  bool r = invoke_http_json("/sendrawtransaction", req, daemon_send_resp, rpc_timeout);
6915  m_daemon_rpc_mutex.unlock();
6916  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction");
6917  THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction");
6918  THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status != CORE_RPC_STATUS_OK, error::tx_rejected, ptx.tx, get_rpc_status(daemon_send_resp.status), get_text_reason(daemon_send_resp));
6919  // sanity checks
6920  for (size_t idx: ptx.selected_transfers)
6921  {
6922  THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error,
6923  "Bad output index in selected transfers: " + boost::lexical_cast<std::string>(idx));
6924  }
6925  }
6926  crypto::hash txid;
6927 
6928  txid = get_transaction_hash(ptx.tx);
6929  crypto::hash payment_id = crypto::null_hash;
6930  std::vector<cryptonote::tx_destination_entry> dests;
6931  uint64_t amount_in = 0;
6932  if (store_tx_info())
6933  {
6934  payment_id = get_payment_id(ptx);
6935  dests = ptx.dests;
6936  for(size_t idx: ptx.selected_transfers)
6937  amount_in += m_transfers[idx].amount();
6938  }
6939  add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount, ptx.construction_data.subaddr_account, ptx.construction_data.subaddr_indices);
6940  if (store_tx_info())
6941  {
6942  m_tx_keys.insert(std::make_pair(txid, ptx.tx_key));
6943  m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys));
6944  }
6945 
6946  LOG_PRINT_L2("transaction " << txid << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]");
6947 
6948  for(size_t idx: ptx.selected_transfers)
6949  {
6950  set_spent(idx, 0);
6951  }
6952 
6953  // tx generated, get rid of used k values
6954  for (size_t idx: ptx.selected_transfers)
6955  m_transfers[idx].m_multisig_k.clear();
6956 
6957  //fee includes dust if dust policy specified it.
6958  LOG_PRINT_L1("Transaction successfully sent. <" << txid << ">" << ENDL
6959  << "Commission: " << print_etn(ptx.fee) << " (dust sent to dust addr: " << print_etn((ptx.dust_added_to_fee ? 0 : ptx.dust)) << ")" << ENDL
6960  << "Pre V10 Balance: " << print_etn(balance(ptx.construction_data.subaddr_account, false)) << ENDL
6961  << "Pre V10 Unlocked Balance: " << print_etn(unlocked_balance(ptx.construction_data.subaddr_account, false)) << ENDL
6962  << "Public Chain Balance: " << print_etn(balance(ptx.construction_data.subaddr_account, true)) << ENDL
6963  << "Public Chain Unlocked Balance: " << print_etn(unlocked_balance(ptx.construction_data.subaddr_account, true)) << ENDL
6964  << "Please, wait for confirmation for your balance to be unlocked.");
6965 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
uint64_t unlocked_balance(uint32_t subaddr_index_major, bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
Definition: wallet2.cpp:6172
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
::std::string string
Definition: gtest-port.h:1097
std::string print_etn(uint64_t amount, unsigned int decimal_point)
uint64_t balance(uint32_t subaddr_index_major, bool public_blockchain) const
Definition: wallet2.cpp:6162
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
#define CORE_RPC_STATUS_OK
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
blobdata tx_to_blob(const transaction &tx)
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
unsigned __int64 uint64_t
Definition: stdint.h:136
bool store_tx_info() const
Definition: wallet2.h:1069
#define ENDL
Definition: misc_log_ex.h:149
std::string buff_to_hex_nodelimer(const std::string &src)
Definition: string_tools.h:87
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ commit_tx() [2/2]

void tools::wallet2::commit_tx ( std::vector< pending_tx > &  ptx_vector)

Definition at line 6967 of file wallet2.cpp.

6968 {
6969  for (auto & ptx : ptx_vector)
6970  {
6971  commit_tx(ptx);
6972  }
6973 }
void commit_tx(pending_tx &ptx_vector)
Definition: wallet2.cpp:6887

◆ confirm_backlog() [1/2]

bool tools::wallet2::confirm_backlog ( ) const
inline

Definition at line 1087 of file wallet2.h.

1087 { return m_confirm_backlog; }

◆ confirm_backlog() [2/2]

void tools::wallet2::confirm_backlog ( bool  always)
inline

Definition at line 1088 of file wallet2.h.

1088 { m_confirm_backlog = always; }

◆ confirm_export_overwrite() [1/2]

bool tools::wallet2::confirm_export_overwrite ( ) const
inline

Definition at line 1091 of file wallet2.h.

1091 { return m_confirm_export_overwrite; }

◆ confirm_export_overwrite() [2/2]

void tools::wallet2::confirm_export_overwrite ( bool  always)
inline

Definition at line 1092 of file wallet2.h.

1092 { m_confirm_export_overwrite = always; }

◆ confirm_missing_payment_id() [1/2]

bool tools::wallet2::confirm_missing_payment_id ( ) const
inline

Definition at line 1077 of file wallet2.h.

1077 { return m_confirm_missing_payment_id; }

◆ confirm_missing_payment_id() [2/2]

void tools::wallet2::confirm_missing_payment_id ( bool  always)
inline

Definition at line 1078 of file wallet2.h.

1078 { m_confirm_missing_payment_id = always; }

◆ confirm_non_default_ring_size() [1/2]

bool tools::wallet2::confirm_non_default_ring_size ( ) const
inline

Definition at line 1103 of file wallet2.h.

1103 { return m_confirm_non_default_ring_size; }

◆ confirm_non_default_ring_size() [2/2]

void tools::wallet2::confirm_non_default_ring_size ( bool  always)
inline

Definition at line 1104 of file wallet2.h.

1104 { m_confirm_non_default_ring_size = always; }

◆ create_transactions_2()

std::vector< wallet2::pending_tx > tools::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 
)

Definition at line 9725 of file wallet2.cpp.

9726 {
9727  //ensure device is let in NONE mode in any case
9728  hw::device &hwdev = m_account.get_device();
9729  boost::unique_lock<hw::device> hwdev_lock (hwdev);
9730  hw::reset_mode rst(hwdev);
9731 
9732  //destinations in the full etn-address format
9733  auto original_dsts = dsts;
9734 
9735  if(m_light_wallet) {
9736  // Populate m_transfers
9738  }
9739 
9740  uint8_t tx_version = this->public_transactions_required() ? 3 : 1;
9741  //vector of pairs of <subaddr minor index : vector<transfer indexes for that subaddr index inside m_transfers>>
9742  std::vector<std::pair<uint32_t, std::vector<size_t>>> unused_transfers_indices_per_subaddr;
9743  std::vector<std::pair<uint32_t, std::vector<size_t>>> unused_dust_indices_per_subaddr;
9744  uint64_t needed_etn;
9745  uint64_t accumulated_fee, accumulated_outputs, accumulated_change;
9746  struct TX {
9747  std::vector<size_t> selected_transfers;
9748  std::vector<cryptonote::tx_destination_entry> dsts;
9750  pending_tx ptx;
9751  size_t weight;
9752  uint64_t needed_fee;
9753  std::vector<std::vector<tools::wallet2::get_outs_entry>> outs;
9754 
9755  TX() : weight(0), needed_fee(0) {}
9756 
9757  void add(const cryptonote::tx_destination_entry &de, uint64_t amount, unsigned int original_output_index, bool merge_destinations) {
9758  if (merge_destinations)
9759  {
9760  std::vector<cryptonote::tx_destination_entry>::iterator i;
9761  i = std::find_if(dsts.begin(), dsts.end(), [&](const cryptonote::tx_destination_entry &d) { return !memcmp (&d.addr, &de.addr, sizeof(de.addr)); });
9762  if (i == dsts.end())
9763  {
9764  dsts.push_back(de);
9765  i = dsts.end() - 1;
9766  i->amount = 0;
9767  }
9768  i->amount += amount;
9769  }
9770  else
9771  {
9772  THROW_WALLET_EXCEPTION_IF(original_output_index > dsts.size(), error::wallet_internal_error,
9773  std::string("original_output_index too large: ") + std::to_string(original_output_index) + " > " + std::to_string(dsts.size()));
9774  if (original_output_index == dsts.size())
9775  {
9776  dsts.push_back(de);
9777  dsts.back().amount = 0;
9778  }
9779  THROW_WALLET_EXCEPTION_IF(memcmp(&dsts[original_output_index].addr, &de.addr, sizeof(de.addr)), error::wallet_internal_error, "Mismatched destination address");
9780  dsts[original_output_index].amount += amount;
9781  }
9782  }
9783  };
9784  std::vector<TX> txes;
9785  bool adding_fee; // true if new outputs go towards fee, rather than destinations
9786 
9787  uint64_t needed_fee, available_for_fee = 0;
9788  uint64_t upper_transaction_weight_limit;
9789  uint64_t extra_bytes = extra.size();
9790  switch(hwdev.get_type()){
9791 
9792  // Normal Software Limit
9793  case 0 : upper_transaction_weight_limit = get_upper_transaction_weight_limit(); break;
9794 
9795  // Ledger NanoS: ~3.3kB of RAM for app variables. Give a bit of buffer (300) for other variables on device
9796  // and subtract the size of the extra.
9797  // because in the Ledger app this still lives on the stack at the same time the entire prefix does.
9798  // This is a rough rule of thumb estimate... The logic can be updated at a later stage.
9799  // Right now we just need to make we don't fail to build any tx (and split the tx to avoid this happening)
9800  case 1 : upper_transaction_weight_limit = 3000 - extra_bytes; break;
9801 
9802  //Trezor limit set at the same as Ledger for the time being.
9803  case 2 : upper_transaction_weight_limit = 3000 - extra_bytes; break;
9804  //Future hw devices
9805  }
9806  const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
9807  const bool use_rct = use_fork_rules(HF_VERSION_ENABLE_RCT, 0);
9808  const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
9809  const rct::RCTConfig rct_config {
9811  bulletproof ? (use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1) : 0
9812  };
9813 
9814  const uint64_t base_fee = get_base_fee();
9815  const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
9816  const uint64_t fee_quantization_mask = get_fee_quantization_mask();
9817 
9818  // throw if attempting a transaction with no destinations
9819  THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
9820 
9821  // calculate total amount being sent to all destinations
9822  // throw if total amount overflows uint64_t
9823  needed_etn = 0;
9824  for(auto& dt: dsts)
9825  {
9826  THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
9827  needed_etn += dt.amount;
9828  LOG_PRINT_L2("transfer: adding " << print_etn(dt.amount) << ", for a total of " << print_etn (needed_etn));
9829  THROW_WALLET_EXCEPTION_IF(needed_etn < dt.amount, error::tx_sum_overflow, dsts, 0, m_nettype);
9830  }
9831 
9832  // throw if attempting a transaction with no etn
9833  THROW_WALLET_EXCEPTION_IF(needed_etn == 0, error::zero_destination);
9834 
9835  std::map<uint32_t, std::pair<uint64_t, uint64_t>> unlocked_balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account, tx_version >= 3);
9836  std::map<uint32_t, uint64_t> balance_per_subaddr = balance_per_subaddress(subaddr_account, tx_version >= 3);
9837 
9838  if (subaddr_indices.empty()) // "index=<N1>[,<N2>,...]" wasn't specified -> use all the indices with non-zero unlocked balance
9839  {
9840  for (const auto& i : balance_per_subaddr)
9841  subaddr_indices.insert(i.first);
9842  }
9843 
9844  // early out if we know we can't make it anyway
9845  // we could also check for being within FEE_PER_KB, but if the fee calculation
9846  // ever changes, this might be missed, so let this go through
9847  uint64_t min_fee = (fee_multiplier * base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof));
9848  //Whilst we're still dealing with fee/kb:
9849  if (!use_per_byte_fee){
9850  min_fee /= 1000;
9851  if(min_fee == 0){min_fee += 10;}
9852  }
9853  uint64_t balance_subtotal = 0;
9854  uint64_t unlocked_balance_subtotal = 0;
9855  for (uint32_t index_minor : subaddr_indices)
9856  {
9857  balance_subtotal += balance_per_subaddr[index_minor];
9858  unlocked_balance_subtotal += unlocked_balance_per_subaddr[index_minor].first;
9859  }
9860  THROW_WALLET_EXCEPTION_IF(needed_etn + min_fee > balance_subtotal, error::not_enough_etn,
9861  balance_subtotal, needed_etn, 0);
9862  // first check overall balance is enough, then unlocked one, so we throw distinct exceptions
9863  THROW_WALLET_EXCEPTION_IF(needed_etn + min_fee > unlocked_balance_subtotal, error::not_enough_unlocked_etn,
9864  unlocked_balance_subtotal, needed_etn, 0);
9865 
9866  for (uint32_t i : subaddr_indices)
9867  LOG_PRINT_L2("Candidate subaddress index for spending: " << i);
9868 
9869  // determine threshold for fractional amount
9870  const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof);
9871  const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof);
9872  THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
9873  const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
9874  const uint64_t fractional_threshold = (fee_multiplier * base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
9875 
9876  // gather all dust and non-dust outputs belonging to specified subaddresses
9877  size_t num_nondust_outputs = 0;
9878  size_t num_dust_outputs = 0;
9879  for (size_t i = 0; i < m_transfers.size(); ++i)
9880  {
9881  const transfer_details& td = m_transfers[i];
9882  if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
9883  {
9884  MDEBUG("Ignoring output " << i << " of amount " << print_etn(td.amount()) << " which is below threshold " << print_etn(fractional_threshold));
9885  continue;
9886  }
9887  if (!td.m_spent && !td.m_frozen && (!td.m_key_image_partial || td.m_tx.version > 1) && (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)
9888  {
9889  if((tx_version < 3 && td.m_tx.version > 1) || (tx_version >= 3 && td.m_tx.version == 1))
9890  continue;
9891 
9892  const uint32_t index_minor = td.m_subaddr_index.minor;
9893  auto find_predicate = [&index_minor](const std::pair<uint32_t, std::vector<size_t>>& x) { return x.first == index_minor; };
9894  if ((td.is_rct()) || is_valid_decomposed_amount(td.amount()))
9895  {
9896  auto found = std::find_if(unused_transfers_indices_per_subaddr.begin(), unused_transfers_indices_per_subaddr.end(), find_predicate);
9897  if (found == unused_transfers_indices_per_subaddr.end())
9898  {
9899  unused_transfers_indices_per_subaddr.push_back({index_minor, {i}});
9900  }
9901  else
9902  {
9903  found->second.push_back(i);
9904  }
9905  ++num_nondust_outputs;
9906  }
9907  else
9908  {
9909  auto found = std::find_if(unused_dust_indices_per_subaddr.begin(), unused_dust_indices_per_subaddr.end(), find_predicate);
9910  if (found == unused_dust_indices_per_subaddr.end())
9911  {
9912  unused_dust_indices_per_subaddr.push_back({index_minor, {i}});
9913  }
9914  else
9915  {
9916  found->second.push_back(i);
9917  }
9918  ++num_dust_outputs;
9919  }
9920  }
9921  }
9922 
9923  // sort output indices
9924  {
9925  auto sort_predicate = [&unlocked_balance_per_subaddr] (const std::pair<uint32_t, std::vector<size_t>>& x, const std::pair<uint32_t, std::vector<size_t>>& y)
9926  {
9927  return unlocked_balance_per_subaddr[x.first].first > unlocked_balance_per_subaddr[y.first].first;
9928  };
9929  std::sort(unused_transfers_indices_per_subaddr.begin(), unused_transfers_indices_per_subaddr.end(), sort_predicate);
9930  std::sort(unused_dust_indices_per_subaddr.begin(), unused_dust_indices_per_subaddr.end(), sort_predicate);
9931  }
9932 
9933  LOG_PRINT_L2("Starting with " << num_nondust_outputs << " non-dust outputs and " << num_dust_outputs << " dust outputs");
9934 
9935  if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
9936  return std::vector<wallet2::pending_tx>();
9937 
9938  // if empty, put dummy entry so that the front can be referenced later in the loop
9939  if (unused_dust_indices_per_subaddr.empty())
9940  unused_dust_indices_per_subaddr.push_back({});
9941  if (unused_transfers_indices_per_subaddr.empty())
9942  unused_transfers_indices_per_subaddr.push_back({});
9943 
9944  // start with an empty tx
9945  txes.push_back(TX());
9946  accumulated_fee = 0;
9947  accumulated_outputs = 0;
9948  accumulated_change = 0;
9949  adding_fee = false;
9950  needed_fee = 0;
9951  std::vector<std::vector<tools::wallet2::get_outs_entry>> outs;
9952 
9953  // for rct, since we don't see the amounts, we will try to make all transactions
9954  // look the same, with 1 or 2 inputs, and 2 outputs. One input is preferable, as
9955  // this prevents linking to another by provenance analysis, but two is ok if we
9956  // try to pick outputs not from the same block. We will get two outputs, one for
9957  // the destination, and one for change.
9958  LOG_PRINT_L2("checking preferred");
9959  std::vector<size_t> preferred_inputs;
9960  uint64_t rct_outs_needed = 2 * (fake_outs_count + 1);
9961  rct_outs_needed += 100; // some fudge factor since we don't know how many are locked
9962  if (use_rct)
9963  {
9964  // this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
9965  // will get us a known fee.
9966  uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, base_fee, fee_multiplier, fee_quantization_mask);
9967  preferred_inputs = pick_preferred_rct_inputs(needed_etn + estimated_fee, subaddr_account, subaddr_indices);
9968  if (!preferred_inputs.empty())
9969  {
9970  string s;
9971  for (auto i: preferred_inputs) s += boost::lexical_cast<std::string>(i) + " (" + print_etn(m_transfers[i].amount()) + ") ";
9972  LOG_PRINT_L1("Found preferred rct inputs for rct tx: " << s);
9973 
9974  // bring the list of available outputs stored by the same subaddress index to the front of the list
9975  uint32_t index_minor = m_transfers[preferred_inputs[0]].m_subaddr_index.minor;
9976  for (size_t i = 1; i < unused_transfers_indices_per_subaddr.size(); ++i)
9977  {
9978  if (unused_transfers_indices_per_subaddr[i].first == index_minor)
9979  {
9980  std::swap(unused_transfers_indices_per_subaddr[0], unused_transfers_indices_per_subaddr[i]);
9981  break;
9982  }
9983  }
9984  for (size_t i = 1; i < unused_dust_indices_per_subaddr.size(); ++i)
9985  {
9986  if (unused_dust_indices_per_subaddr[i].first == index_minor)
9987  {
9988  std::swap(unused_dust_indices_per_subaddr[0], unused_dust_indices_per_subaddr[i]);
9989  break;
9990  }
9991  }
9992  }
9993  }
9994  LOG_PRINT_L2("done checking preferred");
9995 
9996  // while:
9997  // - we have something to send
9998  // - or we need to gather more fee
9999  // - or we have just one input in that tx, which is rct (to try and make all/most rct txes 2/2)
10000  unsigned int original_output_index = 0;
10001  std::vector<size_t>* unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
10002  std::vector<size_t>* unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
10003 
10005  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)) {
10006  TX &tx = txes.back();
10007 
10008  LOG_PRINT_L2("Start of loop with " << unused_transfers_indices->size() << " " << unused_dust_indices->size() << ", tx.dsts.size() " << tx.dsts.size());
10009  LOG_PRINT_L2("unused_transfers_indices: " << strjoin(*unused_transfers_indices, " "));
10010  LOG_PRINT_L2("unused_dust_indices: " << strjoin(*unused_dust_indices, " "));
10011  LOG_PRINT_L2("dsts size " << dsts.size() << ", first " << (dsts.empty() ? "-" : cryptonote::print_etn(dsts[0].amount)));
10012  LOG_PRINT_L2("adding_fee " << adding_fee << ", use_rct " << use_rct);
10013 
10014  // if we need to spend etn and don't have any left, we fail
10015  if (unused_dust_indices->empty() && unused_transfers_indices->empty()) {
10016  LOG_PRINT_L2("No more outputs to choose from");
10017  THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account, tx_version >= 3), needed_etn, accumulated_fee + needed_fee);
10018  }
10019 
10020  // get a random unspent output and use it to pay part (or all) of the current destination (and maybe next one, etc)
10021  // This could be more clever, but maybe at the cost of making probabilistic inferences easier
10022  size_t idx;
10023  if (!preferred_inputs.empty()) {
10024  idx = pop_back(preferred_inputs);
10025  pop_if_present(*unused_transfers_indices, idx);
10026  pop_if_present(*unused_dust_indices, idx);
10027  } else if ((dsts.empty() || dsts[0].amount == 0) && !adding_fee) {
10028  // the "make rct txes 2/2" case - we pick a small value output to "clean up" the wallet too
10029  std::vector<size_t> indices = get_only_rct(*unused_dust_indices, *unused_transfers_indices);
10030  idx = pop_best_value(indices, tx.selected_transfers, true);
10031 
10032  // we might not want to add it if it's a large output and we don't have many left
10033  uint64_t min_output_value = m_min_output_value;
10034  uint32_t min_output_count = m_min_output_count;
10035  if (min_output_value == 0 && min_output_count == 0)
10036  {
10037  min_output_value = DEFAULT_MIN_OUTPUT_VALUE;
10038  min_output_count = DEFAULT_MIN_OUTPUT_COUNT;
10039  }
10040  if (m_transfers[idx].amount() >= min_output_value) {
10041  if (get_count_above(m_transfers, *unused_transfers_indices, min_output_value) < min_output_count) {
10042  LOG_PRINT_L2("Second output was not strictly needed, and we're running out of outputs above " << print_etn(min_output_value) << ", not adding");
10043  break;
10044  }
10045  }
10046 
10047  // since we're trying to add a second output which is not strictly needed,
10048  // we only add it if it's unrelated enough to the first one
10049  float relatedness = get_output_relatedness(m_transfers[idx], m_transfers[tx.selected_transfers.front()]);
10050  if (relatedness > SECOND_OUTPUT_RELATEDNESS_THRESHOLD)
10051  {
10052  LOG_PRINT_L2("Second output was not strictly needed, and relatedness " << relatedness << ", not adding");
10053  break;
10054  }
10055  pop_if_present(*unused_transfers_indices, idx);
10056  pop_if_present(*unused_dust_indices, idx);
10057  } else
10058  idx = pop_best_value(unused_transfers_indices->empty() ? *unused_dust_indices : *unused_transfers_indices, tx.selected_transfers);
10059 
10060  const transfer_details &td = m_transfers[idx];
10061  LOG_PRINT_L2("Picking output " << idx << ", amount " << print_etn(td.amount()) << ", ki " << td.m_key_image);
10062 
10063  // add this output to the list to spend
10064  tx.selected_transfers.push_back(idx);
10065  uint64_t available_amount = td.amount();
10066  accumulated_outputs += available_amount;
10067 
10068  // clear any fake outs we'd already gathered, since we'll need a new set
10069  outs.clear();
10070 
10071  if (adding_fee)
10072  {
10073  LOG_PRINT_L2("We need more fee, adding it to fee");
10074  available_for_fee += available_amount;
10075  }
10076  else
10077  {
10078  while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof) < TX_WEIGHT_TARGET(upper_transaction_weight_limit))
10079  {
10080  // we can fully pay that destination
10081  LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
10082  " for " << print_etn(dsts[0].amount));
10083  tx.add(dsts[0], dsts[0].amount, original_output_index, m_merge_destinations);
10084  available_amount -= dsts[0].amount;
10085  dsts[0].amount = 0;
10086  pop_index(dsts, 0);
10087  ++original_output_index;
10088  }
10089 
10090  if (available_amount > 0 && !dsts.empty() && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) {
10091  // we can partially fill that destination
10092  LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
10093  " for " << print_etn(available_amount) << "/" << print_etn(dsts[0].amount));
10094  tx.add(dsts[0], available_amount, original_output_index, m_merge_destinations);
10095  dsts[0].amount -= available_amount;
10096  available_amount = 0;
10097  }
10098  }
10099 
10100  // here, check if we need to sent tx and start a new one
10101  LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
10102  << upper_transaction_weight_limit);
10103  bool try_tx = false;
10104  // if we have preferred picks, but haven't yet used all of them, continue
10105  if (preferred_inputs.empty())
10106  {
10107  if (adding_fee)
10108  {
10109  /* might not actually be enough if adding this output bumps size to next kB, but we need to try */
10110  try_tx = available_for_fee >= needed_fee;
10111  }
10112  else
10113  {
10114  const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof);
10115  try_tx = dsts.empty() || (estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit));
10116  THROW_WALLET_EXCEPTION_IF(try_tx && tx.dsts.empty(), error::tx_too_big, estimated_rct_tx_weight, upper_transaction_weight_limit);
10117  }
10118  }
10119 
10120  if (try_tx) {
10121  cryptonote::transaction test_tx;
10122  test_tx.version = tx_version;
10123  pending_tx test_ptx;
10124 
10125  needed_fee = estimate_fee(use_per_byte_fee, use_rct ,tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, base_fee, fee_multiplier, fee_quantization_mask);
10126 
10127  uint64_t inputs = 0, outputs = needed_fee;
10128  for (size_t idx: tx.selected_transfers) inputs += m_transfers[idx].amount();
10129  for (const auto &o: tx.dsts) outputs += o.amount;
10130 
10131  if (inputs < outputs)
10132  {
10133  LOG_PRINT_L2("We don't have enough for the basic fee, switching to adding_fee");
10134  adding_fee = true;
10135  goto skip_tx;
10136  }
10137 
10138  LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " <<
10139  tx.selected_transfers.size() << " inputs");
10140 
10141  transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
10142  detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
10143  auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
10144  needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
10145  available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0);
10146  LOG_PRINT_L2("Made a " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_etn(available_for_fee) << " available for fee (" <<
10147  print_etn(needed_fee) << " needed)");
10148 
10149  if (needed_fee > available_for_fee && !dsts.empty() && dsts[0].amount > 0)
10150  {
10151  // we don't have enough for the fee, but we've only partially paid the current address,
10152  // so we can take the fee from the paid amount, since we'll have to make another tx anyway
10153  std::vector<cryptonote::tx_destination_entry>::iterator i;
10154  i = std::find_if(tx.dsts.begin(), tx.dsts.end(),
10155  [&](const cryptonote::tx_destination_entry &d) { return !memcmp (&d.addr, &dsts[0].addr, sizeof(dsts[0].addr)); });
10156  THROW_WALLET_EXCEPTION_IF(i == tx.dsts.end(), error::wallet_internal_error, "paid address not found in outputs");
10157  if (i->amount > needed_fee)
10158  {
10159  uint64_t new_paid_amount = i->amount /*+ test_ptx.fee*/ - needed_fee;
10160  LOG_PRINT_L2("Adjusting amount paid to " << get_account_address_as_str(m_nettype, i->is_subaddress, i->addr) << " from " <<
10161  print_etn(i->amount) << " to " << print_etn(new_paid_amount) << " to accommodate " <<
10162  print_etn(needed_fee) << " fee");
10163  dsts[0].amount += i->amount - new_paid_amount;
10164  i->amount = new_paid_amount;
10165  test_ptx.fee = needed_fee;
10166  available_for_fee = needed_fee;
10167  }
10168  }
10169 
10170  if (needed_fee > available_for_fee)
10171  {
10172  LOG_PRINT_L2("We could not make a tx, switching to fee accumulation");
10173 
10174  adding_fee = true;
10175  }
10176  else
10177  {
10178  LOG_PRINT_L2("We made a tx, adjusting fee and saving it, we need " << print_etn(needed_fee) << " and we have " << print_etn(test_ptx.fee));
10179  while (needed_fee > test_ptx.fee) {
10180  transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
10181  detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
10182  txBlob = t_serializable_object_to_blob(test_ptx.tx);
10183  needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
10184  LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_etn(test_ptx.fee) <<
10185  " fee and " << print_etn(test_ptx.change_dts.amount) << " change");
10186  }
10187 
10188  LOG_PRINT_L2("Made a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_etn(test_ptx.fee) <<
10189  " fee and " << print_etn(test_ptx.change_dts.amount) << " change");
10190 
10191  tx.tx = test_tx;
10192  tx.ptx = test_ptx;
10193  tx.weight = get_transaction_weight(test_tx, txBlob.size());
10194  tx.outs = outs;
10195  tx.needed_fee = test_ptx.fee;
10196  accumulated_fee += test_ptx.fee;
10197  accumulated_change += test_ptx.change_dts.amount;
10198  adding_fee = false;
10199  if (!dsts.empty())
10200  {
10201  LOG_PRINT_L2("We have more to pay, starting another tx");
10202  txes.push_back(TX());
10203  original_output_index = 0;
10204  }
10205  }
10206  }
10207 
10208 skip_tx:
10209  // if unused_*_indices is empty while unused_*_indices_per_subaddr has multiple elements, and if we still have something to pay,
10210  // pop front of unused_*_indices_per_subaddr and have unused_*_indices point to the front of unused_*_indices_per_subaddr
10211  if ((!dsts.empty() && dsts[0].amount > 0) || adding_fee)
10212  {
10213  if (unused_transfers_indices->empty() && unused_transfers_indices_per_subaddr.size() > 1)
10214  {
10215  unused_transfers_indices_per_subaddr.erase(unused_transfers_indices_per_subaddr.begin());
10216  unused_transfers_indices = &unused_transfers_indices_per_subaddr[0].second;
10217  }
10218  if (unused_dust_indices->empty() && unused_dust_indices_per_subaddr.size() > 1)
10219  {
10220  unused_dust_indices_per_subaddr.erase(unused_dust_indices_per_subaddr.begin());
10221  unused_dust_indices = &unused_dust_indices_per_subaddr[0].second;
10222  }
10223  }
10224  }
10225 
10226  if (adding_fee)
10227  {
10228  LOG_PRINT_L1("We ran out of outputs while trying to gather final fee");
10229  THROW_WALLET_EXCEPTION_IF(1, error::tx_not_possible, unlocked_balance(subaddr_account, tx_version >= 3), needed_etn, accumulated_fee + needed_fee);
10230  }
10231 
10232  LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_etn(accumulated_fee) <<
10233  " total fee, " << print_etn(accumulated_change) << " total change");
10234 
10236  for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
10237  {
10238  TX &tx = *i;
10239  cryptonote::transaction test_tx;
10240  test_tx.version = tx_version;
10241  pending_tx test_ptx;
10242  transfer_selected(tx.dsts,
10243  tx.selected_transfers,
10244  fake_outs_count,
10245  tx.outs,
10246  unlock_time,
10247  tx.needed_fee,
10248  extra,
10250  tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD),
10251  test_tx,
10252  test_ptx);
10253 
10254  auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
10255  tx.tx = test_tx;
10256  tx.ptx = test_ptx;
10257  tx.weight = get_transaction_weight(test_tx, txBlob.size());
10258  }
10259 
10260  std::vector<wallet2::pending_tx> ptx_vector;
10261  for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
10262  {
10263  TX &tx = *i;
10264  uint64_t tx_etn = 0;
10265  for (size_t idx: tx.selected_transfers)
10266  tx_etn += m_transfers[idx].amount();
10267  LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() <<
10268  " " << get_transaction_hash(tx.ptx.tx) << ": " << get_weight_string(tx.weight) << ", sending " << print_etn(tx_etn) << " in " << tx.selected_transfers.size() <<
10269  " outputs to " << tx.dsts.size() << " destination(s), including " <<
10270  print_etn(tx.ptx.fee) << " fee, " << print_etn(tx.ptx.change_dts.amount) << " change");
10271  ptx_vector.push_back(tx.ptx);
10272  }
10273 
10274  THROW_WALLET_EXCEPTION_IF(!sanity_check(ptx_vector, original_dsts), error::wallet_internal_error, "Created transaction(s) failed sanity check");
10275 
10276  // if we made it this far, we're OK to actually send the transactions
10277  return ptx_vector;
10278 }
virtual device_type get_type() const =0
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
uint64_t unlocked_balance(uint32_t subaddr_index_major, bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
Definition: wallet2.cpp:6172
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
#define DEFAULT_MIN_OUTPUT_VALUE
Definition: wallet2.cpp:138
int get_fee_algorithm() const
Definition: wallet2.cpp:7824
::std::string string
Definition: gtest-port.h:1097
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool is_transfer_unlocked(const transfer_details &td) const
Definition: wallet2.cpp:6565
virtual bool set_mode(device_mode mode)
Definition: device.hpp:130
unsigned char uint8_t
Definition: stdint.h:124
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
uint64_t get_base_fee() const
Definition: wallet2.cpp:7785
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
#define MDEBUG(x)
Definition: misc_log_ex.h:76
std::map< uint32_t, uint64_t > balance_per_subaddress(uint32_t subaddr_index_major, bool public_blockchain=false) const
Definition: wallet2.cpp:6188
return true
#define DEFAULT_MIN_OUTPUT_COUNT
Definition: wallet2.cpp:137
#define SECOND_OUTPUT_RELATEDNESS_THRESHOLD
Definition: wallet2.cpp:118
bool is_valid_decomposed_amount(uint64_t amount)
unsigned int uint32_t
Definition: stdint.h:126
hw::device & get_device() const
Definition: account.h:91
#define HF_VERSION_SMALLER_BP
unsigned __int64 uint64_t
Definition: stdint.h:136
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
bool public_transactions_required() const
Definition: wallet2.h:900
#define HF_VERSION_ENABLE_RCT
void light_wallet_get_unspent_outs()
Definition: wallet2.cpp:9284
size_t pop_best_value(std::vector< size_t > &unused_dust_indices, const std::vector< size_t > &selected_transfers, bool smallest=false) const
Definition: wallet2.cpp:6740
account_public_address addr
uint64_t const DEFAULT_DUST_THRESHOLD
void digit_split_strategy(const std::vector< cryptonote::tx_destination_entry > &dsts, const cryptonote::tx_destination_entry &change_dst, uint64_t dust_threshold, std::vector< cryptonote::tx_destination_entry > &splitted_dsts, std::vector< cryptonote::tx_destination_entry > &dust_dsts)
Definition: wallet2.h:2098
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm=-1) const
Definition: wallet2.cpp:7732
bool merge_destinations() const
Definition: wallet2.h:1086
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
std::string to_string(t_connection_type type)
bool sanity_check(const std::vector< wallet2::pending_tx > &ptx_vector, std::vector< cryptonote::tx_destination_entry > dsts) const
Definition: wallet2.cpp:10280
std::map< uint32_t, std::pair< uint64_t, uint64_t > > unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool public_blockchain=false) const
Definition: wallet2.cpp:6249
#define HF_VERSION_PER_BYTE_FEE
uint64_t get_fee_quantization_mask() const
Definition: wallet2.cpp:7807
void transfer_selected(const std::vector< cryptonote::tx_destination_entry > &dsts, const std::vector< size_t > &selected_transfers, size_t fake_outputs_count, std::vector< std::vector< tools::wallet2::get_outs_entry >> &outs, uint64_t unlock_time, uint64_t fee, const std::vector< uint8_t > &extra, T destination_split_strategy, const tx_dust_policy &dust_policy, cryptonote::transaction &tx, pending_tx &ptx)
Definition: wallet2.cpp:8952
#define TX_WEIGHT_TARGET(bytes)
Definition: wallet2.cpp:100
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_transactions_all()

std::vector< wallet2::pending_tx > tools::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 bool  migrate = false 
)

Definition at line 10359 of file wallet2.cpp.

10360 {
10361  std::vector<size_t> unused_transfers_indices;
10362  std::vector<size_t> unused_dust_indices;
10363  const bool use_rct = use_fork_rules(4, 0);
10364  uint8_t tx_version = public_transactions_required() ? (migrate ? 2 : 3) : 1; //public migration **NOT** SC migration. SC migration tx are just vanilla v3 tx.
10365  THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account, tx_version >=3) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet");
10366  std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr;
10367 
10368  // gather all dust ***and*** non-dust outputs of specified subaddress (if any) and below specified threshold (if any)
10369  bool fund_found = false;
10370  for (size_t i = 0; i < m_transfers.size(); ++i)
10371  {
10372  const transfer_details& td = m_transfers[i];
10373 
10374  if((tx_version < 3 && td.m_tx.version > 1) || (tx_version >= 3 && td.m_tx.version == 1))
10375  continue;
10376 
10377  if (!td.m_spent && !td.m_frozen && (!td.m_key_image_partial || tx_version >= 3) && (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))
10378  {
10379  fund_found = true;
10380  if (below == 0 || td.amount() < below)
10381  {
10382  if ((td.is_rct()) || is_valid_decomposed_amount(td.amount()))
10383  unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].first.push_back(i);
10384  else
10385  unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].second.push_back(i);
10386  }
10387  }
10388  }
10389  THROW_WALLET_EXCEPTION_IF(!fund_found, error::wallet_internal_error, "No unlocked balance in the specified subaddress(es)");
10390  THROW_WALLET_EXCEPTION_IF(unused_transfer_dust_indices_per_subaddr.empty(), error::wallet_internal_error, "The smallest amount found is not below the specified threshold");
10391 
10392  if (subaddr_indices.empty())
10393  {
10394  // in case subaddress index wasn't specified, choose non-empty subaddress randomly (with index=0 being chosen last)
10395  if (unused_transfer_dust_indices_per_subaddr.count(0) == 1 && unused_transfer_dust_indices_per_subaddr.size() > 1)
10396  unused_transfer_dust_indices_per_subaddr.erase(0);
10397  auto i = unused_transfer_dust_indices_per_subaddr.begin();
10398  std::advance(i, crypto::rand_idx(unused_transfer_dust_indices_per_subaddr.size()));
10399  unused_transfers_indices = i->second.first;
10400  unused_dust_indices = i->second.second;
10401  LOG_PRINT_L2("Spending from subaddress index " << i->first);
10402  }
10403  else
10404  {
10405  for (const auto& p : unused_transfer_dust_indices_per_subaddr)
10406  {
10407  unused_transfers_indices.insert(unused_transfers_indices.end(), p.second.first.begin(), p.second.first.end());
10408  unused_dust_indices.insert(unused_dust_indices.end(), p.second.second.begin(), p.second.second.end());
10409  LOG_PRINT_L2("Spending from subaddress index " << p.first);
10410  }
10411  }
10412 
10413  return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra, tx_version);
10414 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
uint64_t unlocked_balance(uint32_t subaddr_index_major, bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
Definition: wallet2.cpp:6172
bool is_transfer_unlocked(const transfer_details &td) const
Definition: wallet2.cpp:6565
unsigned char uint8_t
Definition: stdint.h:124
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition: crypto.h:244
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
return true
bool is_valid_decomposed_amount(uint64_t amount)
bool public_transactions_required() const
Definition: wallet2.h:900
std::vector< wallet2::pending_tx > create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector< size_t > unused_transfers_indices, std::vector< size_t > unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector< uint8_t > &extra, const uint8_t tx_version)
Definition: wallet2.cpp:10439
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
const char * address
Definition: multisig.cpp:37
Here is the call graph for this function:

◆ create_transactions_from()

std::vector< wallet2::pending_tx > tools::wallet2::create_transactions_from ( const cryptonote::account_public_address address,
bool  is_subaddress,
const size_t  outputs,
std::vector< size_t >  unused_transfers_indices,
std::vector< size_t >  unused_dust_indices,
const size_t  fake_outs_count,
const uint64_t  unlock_time,
uint32_t  priority,
const std::vector< uint8_t > &  extra,
const uint8_t  tx_version 
)

Definition at line 10439 of file wallet2.cpp.

10440 {
10441  //ensure device is let in NONE mode in any case
10442  hw::device &hwdev = m_account.get_device();
10443  boost::unique_lock<hw::device> hwdev_lock (hwdev);
10444  hw::reset_mode rst(hwdev);
10445 
10446  uint64_t accumulated_fee, accumulated_outputs, accumulated_change;
10447  struct TX {
10448  std::vector<size_t> selected_transfers;
10449  std::vector<cryptonote::tx_destination_entry> dsts;
10451  pending_tx ptx;
10452  size_t weight;
10453  uint64_t needed_fee;
10454  std::vector<std::vector<get_outs_entry>> outs;
10455 
10456  TX() : weight(0), needed_fee(0) {}
10457  };
10458  std::vector<TX> txes;
10459  uint64_t needed_fee, available_for_fee = 0;
10460  uint64_t upper_transaction_weight_limit = get_upper_transaction_weight_limit(); //max size of a tx - usually ~ half the block size
10461  std::vector<std::vector<get_outs_entry>> outs;
10462 
10463  const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE);
10464  const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0);
10465  const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
10466  const rct::RCTConfig rct_config {
10468  bulletproof ? (use_fork_rules(HF_VERSION_SMALLER_BP, -10) ? 2 : 1) : 0,
10469  };
10470  const uint64_t base_fee = get_base_fee();
10471  const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
10472  const uint64_t fee_quantization_mask = get_fee_quantization_mask();
10473 
10474  LOG_PRINT_L2("Starting with " << unused_transfers_indices.size() << " non-dust outputs and " << unused_dust_indices.size() << " dust outputs");
10475 
10476  if (unused_dust_indices.empty() && unused_transfers_indices.empty())
10477  return std::vector<wallet2::pending_tx>();
10478 
10479  // start with an empty tx
10480  txes.push_back(TX());
10481  accumulated_fee = 0;
10482  accumulated_outputs = 0;
10483  accumulated_change = 0;
10484  needed_fee = 0;
10485 
10486  // while we have something to send
10488  while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) {
10489  TX &tx = txes.back();
10490 
10491  // get a random unspent output and use it to pay next chunk. We try to alternate
10492  // dust and non dust to ensure we never get with only dust, from which we might
10493  // get a tx that can't pay for itself
10494  uint64_t fee_dust_threshold;
10496  {
10497  const uint64_t estimated_tx_weight_with_one_extra_output = estimate_tx_weight(use_rct, tx.selected_transfers.size() + 1, fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof);
10498  fee_dust_threshold = calculate_fee_from_weight(base_fee, estimated_tx_weight_with_one_extra_output, fee_multiplier, fee_quantization_mask);
10499  }
10500  else
10501  {
10502  fee_dust_threshold = base_fee * fee_multiplier * (upper_transaction_weight_limit + 1023) / 1024;
10503  }
10504 
10505  size_t idx =
10506  unused_transfers_indices.empty()
10507  ? pop_best_value(unused_dust_indices, tx.selected_transfers)
10508  : unused_dust_indices.empty()
10509  ? pop_best_value(unused_transfers_indices, tx.selected_transfers)
10510  : ((tx.selected_transfers.size() & 1) || accumulated_outputs > fee_dust_threshold)
10511  ? pop_best_value(unused_dust_indices, tx.selected_transfers)
10512  : pop_best_value(unused_transfers_indices, tx.selected_transfers);
10513 
10514  const transfer_details &td = m_transfers[idx];
10515  LOG_PRINT_L2("Picking output " << idx << ", amount " << print_etn(td.amount()));
10516 
10517  // add this output to the list to spend
10518  tx.selected_transfers.push_back(idx);
10519  uint64_t available_amount = td.amount();
10520  accumulated_outputs += available_amount;
10521 
10522  // clear any fake outs we'd already gathered, since we'll need a new set
10523  outs.clear();
10524 
10525  // here, check if we need to sent tx and start a new one
10526  LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
10527  << upper_transaction_weight_limit);
10528  const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 2, extra.size(), bulletproof);
10529  bool try_tx = (unused_dust_indices.empty() && unused_transfers_indices.empty()) || ( estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit));
10530 
10531  if (try_tx) {
10532  cryptonote::transaction test_tx;
10533  test_tx.version = tx_version;
10534  pending_tx test_ptx;
10535 
10536  needed_fee = tx_version == 2 ? 0 : estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, base_fee, fee_multiplier, fee_quantization_mask);
10537 
10538  // add N - 1 outputs for correct initial fee estimation
10539  for (size_t i = 0; i < ((outputs > 1) ? outputs - 1 : outputs); ++i)
10540  tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress));
10541 
10542  LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " <<
10543  tx.selected_transfers.size() << " outputs");
10544 
10545  transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
10546  detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
10547 
10548  auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
10549  needed_fee = tx_version == 2 ? 0 : calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
10550  available_for_fee = test_ptx.fee + test_ptx.change_dts.amount;
10551  for (auto &dt: test_ptx.dests)
10552  available_for_fee += dt.amount;
10553  LOG_PRINT_L2("Made a " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_etn(available_for_fee) << " available for fee (" <<
10554  print_etn(needed_fee) << " needed)");
10555 
10556  // add last output, missed for fee estimation
10557  if (outputs > 1)
10558  tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress));
10559 
10560  THROW_WALLET_EXCEPTION_IF(needed_fee > available_for_fee, error::wallet_internal_error, "Transaction cannot pay for itself");
10561 
10562  do {
10563  LOG_PRINT_L2("We made a tx, adjusting fee and saving it");
10564  // distribute total transferred amount between outputs
10565  uint64_t amount_transferred = available_for_fee - needed_fee; //shouuld be zero for migration transactions
10566  uint64_t dt_amount = amount_transferred / outputs;
10567  // residue is distributed as one atomic unit per output until it reaches zero
10568  uint64_t residue = amount_transferred % outputs;
10569  for (auto &dt: tx.dsts)
10570  {
10571  uint64_t dt_residue = 0;
10572  if (residue > 0)
10573  {
10574  dt_residue = 1;
10575  residue -= 1;
10576  }
10577  dt.amount = dt_amount + dt_residue;
10578  }
10579  transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
10580  detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
10581  txBlob = t_serializable_object_to_blob(test_ptx.tx);
10582  needed_fee = tx_version == 2 ? 0 : calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
10583  LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_etn(test_ptx.fee) <<
10584  " fee and " << print_etn(test_ptx.change_dts.amount) << " change");
10585  } while (needed_fee > test_ptx.fee);
10586 
10587  LOG_PRINT_L2("Made a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_etn(test_ptx.fee) <<
10588  " fee and " << print_etn(test_ptx.change_dts.amount) << " change");
10589 
10590  tx.tx = test_tx;
10591  tx.ptx = test_ptx;
10592  tx.weight = get_transaction_weight(test_tx, txBlob.size());
10593  tx.outs = outs;
10594  tx.needed_fee = test_ptx.fee;
10595  accumulated_fee += test_ptx.fee;
10596  accumulated_change += test_ptx.change_dts.amount;
10597  if (!unused_transfers_indices.empty() || !unused_dust_indices.empty())
10598  {
10599  LOG_PRINT_L2("We have more to pay, starting another tx");
10600  txes.push_back(TX());
10601  }
10602  }
10603  }
10604 
10605  LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_etn(accumulated_fee) <<
10606  " total fee, " << print_etn(accumulated_change) << " total change");
10607 
10609  for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
10610  {
10611  TX &tx = *i;
10612  cryptonote::transaction test_tx;
10613  test_tx.version = tx_version;
10614  pending_tx test_ptx;
10615  transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra,
10616  detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
10617 
10618  auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
10619  tx.tx = test_tx;
10620  tx.ptx = test_ptx;
10621  tx.weight = get_transaction_weight(test_tx, txBlob.size());
10622  }
10623 
10624  std::vector<wallet2::pending_tx> ptx_vector;
10625  for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i)
10626  {
10627  TX &tx = *i;
10628  uint64_t tx_etn = 0;
10629  for (size_t idx: tx.selected_transfers)
10630  tx_etn += m_transfers[idx].amount();
10631  LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() <<
10632  " " << get_transaction_hash(tx.ptx.tx) << ": " << get_weight_string(tx.weight) << ", sending " << print_etn(tx_etn) << " in " << tx.selected_transfers.size() <<
10633  " outputs to " << tx.dsts.size() << " destination(s), including " <<
10634  print_etn(tx.ptx.fee) << " fee, " << print_etn(tx.ptx.change_dts.amount) << " change");
10635  ptx_vector.push_back(tx.ptx);
10636  }
10637 
10638  uint64_t a = 0;
10639  for (const TX &tx: txes)
10640  {
10641  for (size_t idx: tx.selected_transfers)
10642  {
10643  a += m_transfers[idx].amount();
10644  }
10645  a -= tx.ptx.fee;
10646  }
10647  std::vector<cryptonote::tx_destination_entry> synthetic_dsts(1, cryptonote::tx_destination_entry("", a, address, is_subaddress));
10648  THROW_WALLET_EXCEPTION_IF(!sanity_check(ptx_vector, synthetic_dsts), error::wallet_internal_error, "Created transaction(s) failed sanity check");
10649 
10650  // if we made it this far, we're OK to actually send the transactions
10651  return ptx_vector;
10652 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
int get_fee_algorithm() const
Definition: wallet2.cpp:7824
std::string print_etn(uint64_t amount, unsigned int decimal_point)
virtual bool set_mode(device_mode mode)
Definition: device.hpp:130
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
uint64_t get_base_fee() const
Definition: wallet2.cpp:7785
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
hw::device & get_device() const
Definition: account.h:91
#define HF_VERSION_SMALLER_BP
unsigned __int64 uint64_t
Definition: stdint.h:136
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
size_t pop_best_value(std::vector< size_t > &unused_dust_indices, const std::vector< size_t > &selected_transfers, bool smallest=false) const
Definition: wallet2.cpp:6740
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
uint64_t const DEFAULT_DUST_THRESHOLD
void digit_split_strategy(const std::vector< cryptonote::tx_destination_entry > &dsts, const cryptonote::tx_destination_entry &change_dst, uint64_t dust_threshold, std::vector< cryptonote::tx_destination_entry > &splitted_dsts, std::vector< cryptonote::tx_destination_entry > &dust_dsts)
Definition: wallet2.h:2098
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm=-1) const
Definition: wallet2.cpp:7732
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
const char * address
Definition: multisig.cpp:37
bool sanity_check(const std::vector< wallet2::pending_tx > &ptx_vector, std::vector< cryptonote::tx_destination_entry > dsts) const
Definition: wallet2.cpp:10280
#define HF_VERSION_PER_BYTE_FEE
uint64_t get_fee_quantization_mask() const
Definition: wallet2.cpp:7807
void transfer_selected(const std::vector< cryptonote::tx_destination_entry > &dsts, const std::vector< size_t > &selected_transfers, size_t fake_outputs_count, std::vector< std::vector< tools::wallet2::get_outs_entry >> &outs, uint64_t unlock_time, uint64_t fee, const std::vector< uint8_t > &extra, T destination_split_strategy, const tx_dust_policy &dust_policy, cryptonote::transaction &tx, pending_tx &ptx)
Definition: wallet2.cpp:8952
#define TX_WEIGHT_TARGET(bytes)
Definition: wallet2.cpp:100
Here is the call graph for this function:

◆ create_transactions_single()

std::vector< wallet2::pending_tx > tools::wallet2::create_transactions_single ( const crypto::key_image ki,
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 
)

Definition at line 10416 of file wallet2.cpp.

10417 {
10418  std::vector<size_t> unused_transfers_indices;
10419  std::vector<size_t> unused_dust_indices;
10420  uint8_t tx_version = 1; //todo: 4.0.0.0 leave it as this for now until we update it for sending by chainstate index
10421  const bool use_rct = use_fork_rules(4, 0);
10422  // find output with the given key image (
10423  for (size_t i = 0; i < m_transfers.size(); ++i)
10424  {
10425  const transfer_details& td = m_transfers[i];
10426 
10427  if (td.m_key_image_known && td.m_tx.version == 1 && td.m_key_image == ki && !td.m_spent && !td.m_frozen && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td))
10428  {
10429  if (td.is_rct() || is_valid_decomposed_amount(td.amount()))
10430  unused_transfers_indices.push_back(i);
10431  else
10432  unused_dust_indices.push_back(i);
10433  break;
10434  }
10435  }
10436  return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra, tx_version);
10437 }
bool is_transfer_unlocked(const transfer_details &td) const
Definition: wallet2.cpp:6565
unsigned char uint8_t
Definition: stdint.h:124
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
bool is_valid_decomposed_amount(uint64_t amount)
std::vector< wallet2::pending_tx > create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector< size_t > unused_transfers_indices, std::vector< size_t > unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector< uint8_t > &extra, const uint8_t tx_version)
Definition: wallet2.cpp:10439
const char * address
Definition: multisig.cpp:37
Here is the call graph for this function:

◆ create_unmixable_sweep_transactions()

std::vector< wallet2::pending_tx > tools::wallet2::create_unmixable_sweep_transactions ( )

Definition at line 10870 of file wallet2.cpp.

10871 {
10872  // From hard fork 1, we don't consider small amounts to be dust anymore
10873  const bool hf1_rules = use_fork_rules(2, 10); // first hard fork has version 2
10874  tx_dust_policy dust_policy(hf1_rules ? 0 : ::config::DEFAULT_DUST_THRESHOLD);
10875 
10876  uint8_t tx_version = this->public_transactions_required() ? 3 : 1;
10877  const uint64_t base_fee = get_base_fee();
10878 
10879  // may throw
10880  std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs();
10881  size_t num_dust_outputs = unmixable_outputs.size();
10882 
10883  if (num_dust_outputs == 0)
10884  {
10885  return std::vector<wallet2::pending_tx>();
10886  }
10887 
10888  // split in "dust" and "non dust" to make it easier to select outputs
10889  std::vector<size_t> unmixable_transfer_outputs, unmixable_dust_outputs;
10890  for (auto n: unmixable_outputs)
10891  {
10892  if (m_transfers[n].amount() < base_fee)
10893  unmixable_dust_outputs.push_back(n);
10894  else
10895  unmixable_transfer_outputs.push_back(n);
10896  }
10897 
10898  return create_transactions_from(m_account_public_address, false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector<uint8_t>(), tx_version);
10899 }
std::vector< size_t > select_available_unmixable_outputs()
Definition: wallet2.cpp:10858
unsigned char uint8_t
Definition: stdint.h:124
uint64_t get_base_fee() const
Definition: wallet2.cpp:7785
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
unsigned __int64 uint64_t
Definition: stdint.h:136
bool public_transactions_required() const
Definition: wallet2.h:900
std::vector< wallet2::pending_tx > create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector< size_t > unused_transfers_indices, std::vector< size_t > unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector< uint8_t > &extra, const uint8_t tx_version)
Definition: wallet2.cpp:10439
uint64_t const DEFAULT_DUST_THRESHOLD

◆ decrypt()

template<typename T >
template epee::wipeable_string tools::wallet2::decrypt ( const std::string &  ciphertext,
const crypto::secret_key skey,
bool  authenticated = true 
) const

Definition at line 13223 of file wallet2.cpp.

13224 {
13225  const size_t prefix_size = sizeof(chacha_iv) + (authenticated ? sizeof(crypto::signature) : 0);
13226  THROW_WALLET_EXCEPTION_IF(ciphertext.size() < prefix_size,
13227  error::wallet_internal_error, "Unexpected ciphertext size");
13228 
13229  crypto::chacha_key key;
13230  crypto::generate_chacha_key(&skey, sizeof(skey), key, m_kdf_rounds);
13231  const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
13232  if (authenticated)
13233  {
13235  crypto::cn_fast_hash(ciphertext.data(), ciphertext.size() - sizeof(signature), hash);
13236  crypto::public_key pkey;
13238  const crypto::signature &signature = *(const crypto::signature*)&ciphertext[ciphertext.size() - sizeof(crypto::signature)];
13240  error::wallet_internal_error, "Failed to authenticate ciphertext");
13241  }
13242  std::unique_ptr<char[]> buffer{new char[ciphertext.size() - prefix_size]};
13243  auto wiper = epee::misc_utils::create_scope_leave_handler([&]() { memwipe(buffer.get(), ciphertext.size() - prefix_size); });
13244  crypto::chacha20(ciphertext.data() + sizeof(iv), ciphertext.size() - prefix_size, key, iv, buffer.get());
13245  return T(buffer.get(), ciphertext.size() - prefix_size);
13246 }
const uint32_t T[512]
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
const char * key
Definition: hmac_keccak.cpp:39
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
POD_CLASS hash
Definition: hash.h:50
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
void * memwipe(void *src, size_t n)
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:295

◆ decrypt_keys() [1/2]

void tools::wallet2::decrypt_keys ( const crypto::chacha_key &  key)

Definition at line 4752 of file wallet2.cpp.

4753 {
4754  m_account.encrypt_viewkey(key);
4755  m_account.decrypt_keys(key);
4756 }
const char * key
Definition: hmac_keccak.cpp:39
void decrypt_keys(const crypto::chacha_key &key)
Definition: account.h:105
void encrypt_viewkey(const crypto::chacha_key &key)
Definition: account.h:106
Here is the caller graph for this function:

◆ decrypt_keys() [2/2]

void tools::wallet2::decrypt_keys ( const epee::wipeable_string password)

Definition at line 4765 of file wallet2.cpp.

4766 {
4767  crypto::chacha_key key;
4768  crypto::generate_chacha_key(password.data(), password.size(), key, m_kdf_rounds);
4769  decrypt_keys(key);
4770 }
size_t size() const noexcept
void decrypt_keys(const crypto::chacha_key &key)
Definition: wallet2.cpp:4752
const char * key
Definition: hmac_keccak.cpp:39
const char * data() const noexcept

◆ decrypt_with_view_secret_key()

std::string tools::wallet2::decrypt_with_view_secret_key ( const std::string &  ciphertext,
bool  authenticated = true 
) const

Definition at line 13250 of file wallet2.cpp.

13251 {
13252  return decrypt(ciphertext, get_account().get_keys().m_view_secret_key, authenticated);
13253 }
T decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated=true) const
Definition: wallet2.cpp:13223
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:

◆ default_mixin() [1/2]

uint32_t tools::wallet2::default_mixin ( ) const
inline

Definition at line 1071 of file wallet2.h.

1071 { return m_default_mixin; }

◆ default_mixin() [2/2]

void tools::wallet2::default_mixin ( uint32_t  m)
inline

Definition at line 1072 of file wallet2.h.

1072 { m_default_mixin = m; }

◆ deinit()

bool tools::wallet2::deinit ( )

Definition at line 4031 of file wallet2.cpp.

4032 {
4033  m_is_initialized=false;
4034  unlock_keys_file();
4035  m_account.deinit();
4036  return true;
4037 }
bool unlock_keys_file()
Definition: wallet2.cpp:8225

◆ delete_address_book_row()

bool tools::wallet2::delete_address_book_row ( std::size_t  row_id)

Definition at line 3466 of file wallet2.cpp.

3466  {
3467  if(m_address_book.size() <= row_id)
3468  return false;
3469 
3470  m_address_book.erase(m_address_book.begin()+row_id);
3471 
3472  return true;
3473 }

◆ device_derivation_path() [1/2]

const std::string& tools::wallet2::device_derivation_path ( ) const
inline

Definition at line 1111 of file wallet2.h.

1111 { return m_device_derivation_path; }

◆ device_derivation_path() [2/2]

void tools::wallet2::device_derivation_path ( const std::string &  device_derivation_path)
inline

Definition at line 1112 of file wallet2.h.

1112 { m_device_derivation_path = device_derivation_path; }
const std::string & device_derivation_path() const
Definition: wallet2.h:1111
Here is the call graph for this function:
Here is the caller graph for this function:

◆ device_derivation_path_option()

std::string tools::wallet2::device_derivation_path_option ( const boost::program_options::variables_map &  vm)
static

Definition at line 1188 of file wallet2.cpp.

1189 {
1190  return command_line::get_arg(vm, options().hw_device_derivation_path);
1191 }
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:271
Here is the call graph for this function:

◆ device_name() [1/2]

const std::string& tools::wallet2::device_name ( ) const
inline

Definition at line 1109 of file wallet2.h.

1109 { return m_device_name; }

◆ device_name() [2/2]

void tools::wallet2::device_name ( const std::string &  device_name)
inline

Definition at line 1110 of file wallet2.h.

1110 { m_device_name = device_name; }
const std::string & device_name() const
Definition: wallet2.h:1109
Here is the call graph for this function:
Here is the caller graph for this function:

◆ device_name_option()

std::string tools::wallet2::device_name_option ( const boost::program_options::variables_map &  vm)
static

Definition at line 1183 of file wallet2.cpp.

1184 {
1185  return command_line::get_arg(vm, options().hw_device);
1186 }
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:271
Here is the call graph for this function:

◆ discard_unmixable_outputs()

void tools::wallet2::discard_unmixable_outputs ( )

Definition at line 10901 of file wallet2.cpp.

10902 {
10903  // may throw
10904  std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs();
10905  for (size_t idx : unmixable_outputs)
10906  {
10907  freeze(idx);
10908  }
10909 }
std::vector< size_t > select_available_unmixable_outputs()
Definition: wallet2.cpp:10858
void freeze(size_t idx)
Definition: wallet2.cpp:1584

◆ dump_tx_to_str()

std::string tools::wallet2::dump_tx_to_str ( const std::vector< pending_tx > &  ptx_vector) const

Definition at line 6984 of file wallet2.cpp.

6985 {
6986  LOG_PRINT_L0("saving " << ptx_vector.size() << " transactions");
6987  unsigned_tx_set txs;
6988  for (auto &tx: ptx_vector)
6989  {
6990  // Short payment id is encrypted with tx_key.
6991  // Since sign_tx() generates new tx_keys and encrypts the payment id, we need to save the decrypted payment ID
6992  // Save tx construction_data to unsigned_tx_set
6993  txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device()));
6994  }
6995 
6996  txs.transfers = export_outputs();
6997  // save as binary
6998  std::ostringstream oss;
7000  try
7001  {
7002  ar << txs;
7003  }
7004  catch (...)
7005  {
7006  return std::string();
7007  }
7008  LOG_PRINT_L2("Saving unsigned tx data: " << oss.str());
7009  std::string ciphertext = encrypt_with_view_secret_key(oss.str());
7010 
7011  return std::string(UNSIGNED_TX_PREFIX) + ciphertext;
7012 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
std::vector< tools::wallet2::tx_construction_data > txes
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
hw::device & get_device() const
Definition: account.h:91
std::pair< size_t, std::vector< tools::wallet2::transfer_details > > export_outputs(bool all=false) const
Definition: wallet2.cpp:12723
#define UNSIGNED_TX_PREFIX
Definition: wallet2.cpp:107
std::string encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated=true) const
Definition: wallet2.cpp:13217

◆ enable_dns()

void tools::wallet2::enable_dns ( bool  enable)
inline

Definition at line 1383 of file wallet2.h.

1383 { m_use_dns = enable; }

◆ encrypt() [1/4]

std::string tools::wallet2::encrypt ( const char *  plaintext,
size_t  len,
const crypto::secret_key skey,
bool  authenticated = true 
) const

Definition at line 13181 of file wallet2.cpp.

13182 {
13183  crypto::chacha_key key;
13184  crypto::generate_chacha_key(&skey, sizeof(skey), key, m_kdf_rounds);
13185  std::string ciphertext;
13186  crypto::chacha_iv iv = crypto::rand<crypto::chacha_iv>();
13187  ciphertext.resize(len + sizeof(iv) + (authenticated ? sizeof(crypto::signature) : 0));
13188  crypto::chacha20(plaintext, len, key, iv, &ciphertext[sizeof(iv)]);
13189  memcpy(&ciphertext[0], &iv, sizeof(iv));
13190  if (authenticated)
13191  {
13193  crypto::cn_fast_hash(ciphertext.data(), ciphertext.size() - sizeof(signature), hash);
13194  crypto::public_key pkey;
13196  crypto::signature &signature = *(crypto::signature*)&ciphertext[ciphertext.size() - sizeof(crypto::signature)];
13198  }
13199  return ciphertext;
13200 }
::std::string string
Definition: gtest-port.h:1097
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:292
const char * key
Definition: hmac_keccak.cpp:39
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
void * memcpy(void *a, const void *b, size_t c)
POD_CLASS hash
Definition: hash.h:50
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
Here is the caller graph for this function:

◆ encrypt() [2/4]

std::string tools::wallet2::encrypt ( const epee::span< char > &  span,
const crypto::secret_key skey,
bool  authenticated = true 
) const

Definition at line 13202 of file wallet2.cpp.

13203 {
13204  return encrypt(plaintext.data(), plaintext.size(), skey, authenticated);
13205 }
std::string encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated=true) const
Definition: wallet2.cpp:13181

◆ encrypt() [3/4]

std::string tools::wallet2::encrypt ( const std::string &  plaintext,
const crypto::secret_key skey,
bool  authenticated = true 
) const

Definition at line 13207 of file wallet2.cpp.

13208 {
13209  return encrypt(plaintext.data(), plaintext.size(), skey, authenticated);
13210 }
std::string encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated=true) const
Definition: wallet2.cpp:13181

◆ encrypt() [4/4]

std::string tools::wallet2::encrypt ( const epee::wipeable_string plaintext,
const crypto::secret_key skey,
bool  authenticated = true 
) const

Definition at line 13212 of file wallet2.cpp.

13213 {
13214  return encrypt(plaintext.data(), plaintext.size(), skey, authenticated);
13215 }
size_t size() const noexcept
const char * data() const noexcept
std::string encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated=true) const
Definition: wallet2.cpp:13181

◆ encrypt_keys() [1/2]

void tools::wallet2::encrypt_keys ( const crypto::chacha_key &  key)

Definition at line 4746 of file wallet2.cpp.

4747 {
4748  m_account.encrypt_keys(key);
4749  m_account.decrypt_viewkey(key);
4750 }
const char * key
Definition: hmac_keccak.cpp:39
void encrypt_keys(const crypto::chacha_key &key)
Definition: account.h:104
void decrypt_viewkey(const crypto::chacha_key &key)
Definition: account.h:107
Here is the caller graph for this function:

◆ encrypt_keys() [2/2]

void tools::wallet2::encrypt_keys ( const epee::wipeable_string password)

Definition at line 4758 of file wallet2.cpp.

4759 {
4760  crypto::chacha_key key;
4761  crypto::generate_chacha_key(password.data(), password.size(), key, m_kdf_rounds);
4762  encrypt_keys(key);
4763 }
size_t size() const noexcept
const char * key
Definition: hmac_keccak.cpp:39
void encrypt_keys(const crypto::chacha_key &key)
Definition: wallet2.cpp:4746
const char * data() const noexcept

◆ encrypt_with_view_secret_key()

std::string tools::wallet2::encrypt_with_view_secret_key ( const std::string &  plaintext,
bool  authenticated = true 
) const

Definition at line 13217 of file wallet2.cpp.

13218 {
13219  return encrypt(plaintext, get_account().get_keys().m_view_secret_key, authenticated);
13220 }
cryptonote::account_base & get_account()
Definition: wallet2.h:734
std::string encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated=true) const
Definition: wallet2.cpp:13181

◆ estimate_backlog() [1/2]

std::vector< std::pair< uint64_t, uint64_t > > tools::wallet2::estimate_backlog ( const std::vector< std::pair< double, double >> &  fee_levels)

Definition at line 13489 of file wallet2.cpp.

13490 {
13491  for (const auto &fee_level: fee_levels)
13492  {
13493  THROW_WALLET_EXCEPTION_IF(fee_level.first == 0.0, error::wallet_internal_error, "Invalid 0 fee");
13494  THROW_WALLET_EXCEPTION_IF(fee_level.second == 0.0, error::wallet_internal_error, "Invalid 0 fee");
13495  }
13496 
13497  // get txpool backlog
13500  m_daemon_rpc_mutex.lock();
13501  bool r = invoke_http_json_rpc("/json_rpc", "get_txpool_backlog", req, res, rpc_timeout);
13502  m_daemon_rpc_mutex.unlock();
13503  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "Failed to connect to daemon");
13504  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_txpool_backlog");
13505  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
13506 
13507  uint64_t block_weight_limit = 0;
13508  const auto result = m_node_rpc_proxy.get_block_weight_limit(block_weight_limit);
13509  throw_on_rpc_response_error(result, "get_info");
13510  uint64_t full_reward_zone = block_weight_limit / 2;
13511  THROW_WALLET_EXCEPTION_IF(full_reward_zone == 0, error::wallet_internal_error, "Invalid block weight limit from daemon");
13512 
13513  std::vector<std::pair<uint64_t, uint64_t>> blocks;
13514  for (const auto &fee_level: fee_levels)
13515  {
13516  const double our_fee_byte_min = fee_level.first;
13517  const double our_fee_byte_max = fee_level.second;
13518  uint64_t priority_weight_min = 0, priority_weight_max = 0;
13519  for (const auto &i: res.backlog)
13520  {
13521  if (i.weight == 0)
13522  {
13523  MWARNING("Got 0 weight tx from txpool, ignored");
13524  continue;
13525  }
13526  double this_fee_byte = i.fee / (double)i.weight;
13527  if (this_fee_byte >= our_fee_byte_min)
13528  priority_weight_min += i.weight;
13529  if (this_fee_byte >= our_fee_byte_max)
13530  priority_weight_max += i.weight;
13531  }
13532 
13533  uint64_t nblocks_min = priority_weight_min / full_reward_zone;
13534  uint64_t nblocks_max = priority_weight_max / full_reward_zone;
13535  MDEBUG("estimate_backlog: priority_weight " << priority_weight_min << " - " << priority_weight_max << " for "
13536  << our_fee_byte_min << " - " << our_fee_byte_max << " piconero byte fee, "
13537  << nblocks_min << " - " << nblocks_max << " blocks at block weight " << full_reward_zone);
13538  blocks.push_back(std::make_pair(nblocks_min, nblocks_max));
13539  }
13540  return blocks;
13541 }
const char * res
Definition: hmac_keccak.cpp:41
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
#define CORE_RPC_STATUS_OK
#define MDEBUG(x)
Definition: misc_log_ex.h:76
unsigned __int64 uint64_t
Definition: stdint.h:136
boost::optional< std::string > get_block_weight_limit(uint64_t &block_weight_limit) const
#define MWARNING(x)
Definition: misc_log_ex.h:74
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
bool invoke_http_json_rpc(const boost::string_ref uri, const std::string &method_name, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET", const std::string &req_id="0")
Definition: wallet2.h:1333
else if(0==res)
Here is the call graph for this function:

◆ estimate_backlog() [2/2]

std::vector< std::pair< uint64_t, uint64_t > > tools::wallet2::estimate_backlog ( uint64_t  min_tx_weight,
uint64_t  max_tx_weight,
const std::vector< uint64_t > &  fees 
)

Definition at line 13543 of file wallet2.cpp.

13544 {
13545  THROW_WALLET_EXCEPTION_IF(min_tx_weight == 0, error::wallet_internal_error, "Invalid 0 fee");
13546  THROW_WALLET_EXCEPTION_IF(max_tx_weight == 0, error::wallet_internal_error, "Invalid 0 fee");
13547  for (uint64_t fee: fees)
13548  {
13549  THROW_WALLET_EXCEPTION_IF(fee == 0, error::wallet_internal_error, "Invalid 0 fee");
13550  }
13551  std::vector<std::pair<double, double>> fee_levels;
13552  for (uint64_t fee: fees)
13553  {
13554  double our_fee_byte_min = fee / (double)min_tx_weight, our_fee_byte_max = fee / (double)max_tx_weight;
13555  fee_levels.emplace_back(our_fee_byte_min, our_fee_byte_max);
13556  }
13557  return estimate_backlog(fee_levels);
13558 }
std::vector< std::pair< uint64_t, uint64_t > > estimate_backlog(const std::vector< std::pair< double, double >> &fee_levels)
Definition: wallet2.cpp:13489
unsigned __int64 uint64_t
Definition: stdint.h:136
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)

◆ estimate_blockchain_height()

uint64_t tools::wallet2::estimate_blockchain_height ( )

Definition at line 4990 of file wallet2.cpp.

4991  {
4992  // -1 month for fluctuations in block time and machine date/time setup.
4993  // avg seconds per block
4994  const int seconds_per_block = DIFFICULTY_TARGET_V6;
4995  // ~num blocks per month
4996  const uint64_t blocks_per_month = 60*60*24*30/seconds_per_block;
4997 
4998  // try asking the daemon first
4999  std::string err;
5000  uint64_t height = 0;
5001 
5002  // we get the max of approximated height and local height.
5003  // approximated height is the least of daemon target height
5004  // (the max of what the other daemons are claiming is their
5005  // height) and the theoretical height based on the local
5006  // clock. This will be wrong only if both the local clock
5007  // is bad *and* a peer daemon claims a highest height than
5008  // the real chain.
5009  // local height is the height the local daemon is currently
5010  // synced to, it will be lower than the real chain height if
5011  // the daemon is currently syncing.
5012  // If we use the approximate height we subtract one month as
5013  // a safety margin.
5015  uint64_t target_height = get_daemon_blockchain_target_height(err);
5016  if (err.empty()) {
5017  if (target_height < height)
5018  height = target_height;
5019  } else {
5020  // if we couldn't talk to the daemon, check safety margin.
5021  if (height > blocks_per_month)
5022  height -= blocks_per_month;
5023  else
5024  height = 0;
5025  }
5026  uint64_t local_height = get_daemon_blockchain_height(err);
5027  if (err.empty() && local_height > height)
5028  height = local_height;
5029  return height;
5030  }
uint64_t get_approximate_blockchain_height() const
Calculates the approximate blockchain height from current date/time.
Definition: wallet2.cpp:11965
::std::string string
Definition: gtest-port.h:1097
uint64_t height
Definition: blockchain.cpp:91
#define DIFFICULTY_TARGET_V6
uint64_t get_daemon_blockchain_height(std::string &err) const
Definition: wallet2.cpp:11931
unsigned __int64 uint64_t
Definition: stdint.h:136
uint64_t get_daemon_blockchain_target_height(std::string &err)
Definition: wallet2.cpp:11949

◆ exchange_multisig_keys() [1/2]

std::string tools::wallet2::exchange_multisig_keys ( const epee::wipeable_string password,
const std::vector< std::string > &  info 
)

Definition at line 5280 of file wallet2.cpp.

5282 {
5284  error::wallet_internal_error, "Empty multisig info");
5285 
5286  if (info[0].substr(0, MULTISIG_EXTRA_INFO_MAGIC.size()) != MULTISIG_EXTRA_INFO_MAGIC)
5287  {
5289  error::wallet_internal_error, "Unsupported info string");
5290  }
5291 
5292  std::vector<crypto::public_key> signers;
5293  std::unordered_set<crypto::public_key> pkeys;
5294 
5295  THROW_WALLET_EXCEPTION_IF(!unpack_extra_multisig_info(info, signers, pkeys),
5296  error::wallet_internal_error, "Bad extra multisig info");
5297 
5298  return exchange_multisig_keys(password, pkeys, signers);
5299 }
std::string exchange_multisig_keys(const epee::wipeable_string &password, const std::vector< std::string > &info)
Definition: wallet2.cpp:5280
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)

◆ exchange_multisig_keys() [2/2]

std::string tools::wallet2::exchange_multisig_keys ( const epee::wipeable_string password,
std::unordered_set< crypto::public_key pkeys,
std::vector< crypto::public_key signers 
)

Any but first round of keys exchange.

Definition at line 5301 of file wallet2.cpp.

5304 {
5305  CHECK_AND_ASSERT_THROW_MES(!derivations.empty(), "empty pkeys");
5306  CHECK_AND_ASSERT_THROW_MES(!signers.empty(), "empty signers");
5307 
5308  bool ready = false;
5309  CHECK_AND_ASSERT_THROW_MES(multisig(&ready), "The wallet is not multisig");
5310  CHECK_AND_ASSERT_THROW_MES(!ready, "Multisig wallet creation process has already been finished");
5311 
5312  // keys are decrypted
5314  if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
5315  {
5316  crypto::chacha_key chacha_key;
5317  crypto::generate_chacha_key(password.data(), password.size(), chacha_key, m_kdf_rounds);
5318  m_account.encrypt_viewkey(chacha_key);
5319  m_account.decrypt_keys(chacha_key);
5320  keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this, chacha_key]() { m_account.encrypt_keys(chacha_key); m_account.decrypt_viewkey(chacha_key); });
5321  }
5322 
5323  if (m_multisig_rounds_passed == multisig_rounds_required(m_multisig_signers.size(), m_multisig_threshold) - 1)
5324  {
5325  // the last round is passed and we have to calculate spend public key
5326  // add ours if not included
5328 
5329  if (std::find(signers.begin(), signers.end(), local_signer) == signers.end())
5330  {
5331  signers.push_back(local_signer);
5332  for (const auto &msk: get_account().get_multisig_keys())
5333  {
5334  derivations.insert(rct::rct2pk(rct::scalarmultBase(rct::sk2rct(msk))));
5335  }
5336  }
5337 
5338  CHECK_AND_ASSERT_THROW_MES(signers.size() == m_multisig_signers.size(), "Bad signers size");
5339 
5340  // Summing all of unique public multisig keys to calculate common public spend key
5341  crypto::public_key spend_public_key = cryptonote::generate_multisig_M_N_spend_public_key(std::vector<crypto::public_key>(derivations.begin(), derivations.end()));
5342  m_account_public_address.m_spend_public_key = spend_public_key;
5343  m_account.finalize_multisig(spend_public_key);
5344 
5345  m_multisig_signers = signers;
5346  std::sort(m_multisig_signers.begin(), m_multisig_signers.end(), [](const crypto::public_key &e0, const crypto::public_key &e1){ return memcmp(&e0, &e1, sizeof(e0)); });
5347 
5348  ++m_multisig_rounds_passed;
5349  m_multisig_derivations.clear();
5350 
5351  // keys are encrypted again
5352  keys_reencryptor = epee::misc_utils::auto_scope_leave_caller();
5353 
5354  if (!m_wallet_file.empty())
5355  {
5356  bool r = store_keys(m_keys_file, password, false);
5358 
5359  if (boost::filesystem::exists(m_wallet_file + ".address.txt"))
5360  {
5361  r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
5362  if(!r) MERROR("String with address text not saved");
5363  }
5364  }
5365 
5366  m_subaddresses.clear();
5367  m_subaddress_labels.clear();
5368  add_subaddress_account(tr("Primary account"));
5369 
5370  if (!m_wallet_file.empty())
5371  store();
5372 
5373  return {};
5374  }
5375 
5376  // Below are either middle or secret spend key establishment rounds
5377 
5378  for (const auto& key: m_multisig_derivations)
5379  derivations.erase(key);
5380 
5381  // Deriving multisig keys (set of Mi = b * Bi) according to DH from other participants' multisig keys.
5382  auto new_derivations = cryptonote::generate_multisig_derivations(get_account().get_keys(), std::vector<crypto::public_key>(derivations.begin(), derivations.end()));
5383 
5384  std::string extra_multisig_info;
5385  if (m_multisig_rounds_passed == multisig_rounds_required(m_multisig_signers.size(), m_multisig_threshold) - 2) // next round is last
5386  {
5387  // Next round is last therefore we are performing secret spend establishment round as described above.
5388  MINFO("Creating spend key...");
5389 
5390  // Calculating our secret multisig keys by hashing our public multisig keys.
5391  auto multisig_keys = cryptonote::calculate_multisig_keys(std::vector<crypto::public_key>(new_derivations.begin(), new_derivations.end()));
5392  // And summing it to get personal secret spend key
5394 
5395  m_account.make_multisig(m_account.get_keys().m_view_secret_key, spend_skey, rct::rct2pk(rct::identity()), multisig_keys);
5396 
5397  // Packing public multisig keys to exchange with others and calculate common public spend key in the last round
5398  extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, secret_keys_to_public_keys(multisig_keys), spend_skey);
5399  }
5400  else
5401  {
5402  // This is just middle round
5403  MINFO("Preparing keys for next exchange round...");
5404  extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, new_derivations, m_account.get_keys().m_spend_secret_key);
5405  m_multisig_derivations = new_derivations;
5406  }
5407 
5408  ++m_multisig_rounds_passed;
5409 
5410  create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt"));
5411  return extra_multisig_info;
5412 }
#define MERROR(x)
Definition: misc_log_ex.h:73
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
size_t size() const noexcept
#define MINFO(x)
Definition: misc_log_ex.h:75
::std::string string
Definition: gtest-port.h:1097
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector< crypto::secret_key > &multisig_keys)
Definition: account.cpp:250
std::vector< crypto::public_key > generate_multisig_derivations(const account_keys &keys, const std::vector< crypto::public_key > &derivations)
generate_multisig_derivations performs common DH key derivation. Each middle round in M/N scheme is D...
Definition: multisig.cpp:87
const char * key
Definition: hmac_keccak.cpp:39
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
void add_subaddress_account(const std::string &label, const bool update_account_tags=true)
Definition: wallet2.cpp:1463
void encrypt_keys(const crypto::chacha_key &key)
Definition: account.h:104
const account_keys & get_keys() const
Definition: account.cpp:264
crypto::public_key generate_multisig_M_N_spend_public_key(const std::vector< crypto::public_key > &pkeys)
generate_multisig_M_N_spend_public_key calculates multisig wallet&#39;s spend public key by summing all o...
Definition: multisig.cpp:132
uint32_t multisig_rounds_required(uint32_t participants, uint32_t threshold)
Definition: multisig.cpp:181
std::vector< crypto::secret_key > calculate_multisig_keys(const std::vector< crypto::public_key > &derivations)
calculate_multisig_keys. Calculates secret multisig keys from others&#39; participants ones as follows: m...
Definition: multisig.cpp:111
file_error_base< file_save_error_message_index > file_save_error
void decrypt_keys(const crypto::chacha_key &key)
Definition: account.h:105
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
Definition: file_io_utils.h:73
POD_CLASS public_key
Definition: crypto.h:76
crypto::secret_key m_view_secret_key
Definition: account.h:45
void scalarmultBase(key &aG, const key &a)
Definition: rctOps.cpp:350
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
key identity()
Definition: rctOps.h:73
static const char * tr(const char *str)
Definition: wallet2.cpp:994
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::secret_key m_spend_secret_key
Definition: account.h:44
cryptonote::account_base & get_account()
Definition: wallet2.h:734
void finalize_multisig(const crypto::public_key &spend_public_key)
Definition: account.cpp:259
const char * data() const noexcept
void encrypt_viewkey(const crypto::chacha_key &key)
Definition: account.h:106
void decrypt_viewkey(const crypto::chacha_key &key)
Definition: account.h:107
crypto::secret_key calculate_multisig_signer_key(const std::vector< crypto::secret_key > &multisig_keys)
Definition: multisig.cpp:100
bool multisig(bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
Definition: wallet2.cpp:5634

◆ expand_subaddresses()

void tools::wallet2::expand_subaddresses ( const cryptonote::subaddress_index index,
const bool  udpate_account_tags = true 
)

Definition at line 1478 of file wallet2.cpp.

1479 {
1480  hw::device &hwdev = m_account.get_device();
1481  if (m_subaddress_labels.size() <= index.major)
1482  {
1483  // add new accounts
1485  const uint32_t major_end = get_subaddress_clamped_sum(index.major, m_subaddress_lookahead_major);
1486  for (index2.major = m_subaddress_labels.size(); index2.major < major_end; ++index2.major)
1487  {
1488  const uint32_t end = get_subaddress_clamped_sum((index2.major == index.major ? index.minor : 0), m_subaddress_lookahead_minor);
1489  const std::vector<crypto::public_key> pkeys = hwdev.get_subaddress_spend_public_keys(m_account.get_keys(), index2.major + (index2.major != 0 ? m_account_major_offset : 0), 0, end);
1490  for (index2.minor = 0; index2.minor < end; ++index2.minor)
1491  {
1492  const crypto::public_key &D = pkeys[index2.minor];
1493  m_subaddresses[D] = index2;
1494  }
1495  }
1496  m_subaddress_labels.resize(index.major + 1, {"Untitled account"});
1497  m_subaddress_labels[index.major].resize(index.minor + 1);
1498 
1499  if(update_account_tags)
1500  get_account_tags();
1501  }
1502  else if (m_subaddress_labels[index.major].size() <= index.minor)
1503  {
1504  // add new subaddresses
1505  const uint32_t end = get_subaddress_clamped_sum(index.minor, m_subaddress_lookahead_minor);
1506  const uint32_t begin = m_subaddress_labels[index.major].size();
1507  cryptonote::subaddress_index index2 = {index.major, begin};
1508  const std::vector<crypto::public_key> pkeys = hwdev.get_subaddress_spend_public_keys(m_account.get_keys(), index2.major + (index2.major != 0 ? m_account_major_offset : 0), index2.minor, end);
1509  for (; index2.minor < end; ++index2.minor)
1510  {
1511  const crypto::public_key &D = pkeys[index2.minor - begin];
1512  m_subaddresses[D] = index2;
1513  }
1514  m_subaddress_labels[index.major].resize(index.minor + 1);
1515  }
1516 }
const account_keys & get_keys() const
Definition: account.cpp:264
unsigned int uint32_t
Definition: stdint.h:126
hw::device & get_device() const
Definition: account.h:91
POD_CLASS public_key
Definition: crypto.h:76
virtual std::vector< crypto::public_key > get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end)=0
const std::pair< std::map< std::string, std::string >, std::vector< std::string > > & get_account_tags()
Get the list of registered account tags.
Definition: wallet2.cpp:12036
Here is the call graph for this function:
Here is the caller graph for this function:

◆ explicit_refresh_from_block_height() [1/2]

void tools::wallet2::explicit_refresh_from_block_height ( bool  expl)
inline

Definition at line 745 of file wallet2.h.

745 {m_explicit_refresh_from_block_height = expl;}

◆ explicit_refresh_from_block_height() [2/2]

bool tools::wallet2::explicit_refresh_from_block_height ( ) const
inline

Definition at line 746 of file wallet2.h.

746 {return m_explicit_refresh_from_block_height;}

◆ export_blockchain()

std::tuple< size_t, crypto::hash, std::vector< crypto::hash > > tools::wallet2::export_blockchain ( ) const

Definition at line 12691 of file wallet2.cpp.

12692 {
12693  std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> bc;
12694  std::get<0>(bc) = m_blockchain.offset();
12695  std::get<1>(bc) = m_blockchain.empty() ? crypto::null_hash: m_blockchain.genesis();
12696  for (size_t n = m_blockchain.offset(); n < m_blockchain.size(); ++n)
12697  {
12698  std::get<2>(bc).push_back(m_blockchain[n]);
12699  }
12700  return bc;
12701 }
const crypto::hash & genesis() const
Definition: wallet2.h:183
bool empty() const
Definition: wallet2.h:190
size_t size() const
Definition: wallet2.h:181
size_t offset() const
Definition: wallet2.h:182

◆ export_key_images() [1/2]

bool tools::wallet2::export_key_images ( const std::string &  filename) const

Definition at line 12191 of file wallet2.cpp.

12192 {
12194  std::pair<size_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images();
12197  const uint32_t offset = ski.first;
12198 
12199  std::string data;
12200  data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key));
12201  data.resize(4);
12202  data[0] = offset & 0xff;
12203  data[1] = (offset >> 8) & 0xff;
12204  data[2] = (offset >> 16) & 0xff;
12205  data[3] = (offset >> 24) & 0xff;
12206  data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
12207  data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
12208  for (const auto &i: ski.second)
12209  {
12210  data += std::string((const char *)&i.first, sizeof(crypto::key_image));
12211  data += std::string((const char *)&i.second, sizeof(crypto::signature));
12212  }
12213 
12214  // encrypt data, keep magic plaintext
12215  PERF_TIMER(export_key_images_encrypt);
12216  std::string ciphertext = encrypt_with_view_secret_key(data);
12217  return epee::file_io_utils::save_string_to_file(filename, magic + ciphertext);
12218 }
#define KEY_IMAGE_EXPORT_FILE_MAGIC
Definition: wallet2.cpp:123
#define PERF_TIMER(name)
Definition: perf_timer.h:82
::std::string string
Definition: gtest-port.h:1097
const account_keys & get_keys() const
Definition: account.cpp:264
bool export_key_images(const std::string &filename) const
Definition: wallet2.cpp:12191
unsigned int uint32_t
Definition: stdint.h:126
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
Definition: file_io_utils.h:73
POD_CLASS public_key
Definition: crypto.h:76
account_public_address m_account_address
Definition: account.h:43
POD_CLASS signature
Definition: crypto.h:108
POD_CLASS key_image
Definition: crypto.h:102
cryptonote::account_base & get_account()
Definition: wallet2.h:734
std::string encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated=true) const
Definition: wallet2.cpp:13217
Here is the call graph for this function:

◆ export_key_images() [2/2]

std::pair< size_t, std::vector< std::pair< crypto::key_image, crypto::signature > > > tools::wallet2::export_key_images ( bool  all = false) const

Definition at line 12221 of file wallet2.cpp.

12222 {
12223  PERF_TIMER(export_key_images_raw);
12224  std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
12225 
12226  size_t offset = 0;
12227  if (!all)
12228  {
12229  while (offset < m_transfers.size() && !m_transfers[offset].m_key_image_request)
12230  ++offset;
12231  }
12232 
12233  ski.reserve(m_transfers.size() - offset);
12234  for (size_t n = offset; n < m_transfers.size(); ++n)
12235  {
12236  const transfer_details &td = m_transfers[n];
12237 
12238  // get ephemeral public key
12239  const cryptonote::tx_out &out = td.m_tx.vout[td.m_internal_output_index];
12240  THROW_WALLET_EXCEPTION_IF(out.target.type() != typeid(txout_to_key), error::wallet_internal_error,
12241  "Output is not txout_to_key");
12242  const cryptonote::txout_to_key &o = boost::get<const cryptonote::txout_to_key>(out.target);
12243  const crypto::public_key pkey = o.key;
12244 
12245  // get tx pub key
12246  std::vector<tx_extra_field> tx_extra_fields;
12247  if(!parse_tx_extra(td.m_tx.extra, tx_extra_fields))
12248  {
12249  // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key
12250  }
12251 
12253  const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
12254 
12255  // generate ephemeral secret key
12256  crypto::key_image ki;
12257  cryptonote::keypair in_ephemeral;
12258  bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, pkey, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, ki, m_account.get_device(), m_account_major_offset);
12259  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
12260 
12261  THROW_WALLET_EXCEPTION_IF(td.m_key_image_known && !td.m_key_image_partial && ki != td.m_key_image,
12262  error::wallet_internal_error, "key_image generated not matched with cached key image");
12263  THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != pkey,
12264  error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key");
12265 
12266  // sign the key image with the output secret key
12268  std::vector<const crypto::public_key*> key_ptrs;
12269  key_ptrs.push_back(&pkey);
12270 
12271  crypto::generate_ring_signature((const crypto::hash&)td.m_key_image, td.m_key_image, key_ptrs, in_ephemeral.sec, 0, &signature);
12272 
12273  ski.push_back(std::make_pair(td.m_key_image, signature));
12274  }
12275  return std::make_pair(offset, ski);
12276 }
crypto::public_key pub
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const
Definition: wallet2.cpp:12143
crypto::secret_key sec
#define PERF_TIMER(name)
Definition: perf_timer.h:82
const account_keys & get_keys() const
Definition: account.cpp:264
hw::device & get_device() const
Definition: account.h:91
bool generate_key_image_helper(const account_keys &ack, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
void generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const secret_key &sec, std::size_t sec_index, signature *sig)
Definition: crypto.h:327
POD_CLASS public_key
Definition: crypto.h:76
POD_CLASS signature
Definition: crypto.h:108
crypto::public_key key
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
POD_CLASS hash
Definition: hash.h:50
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
Here is the call graph for this function:

◆ export_multisig()

cryptonote::blobdata tools::wallet2::export_multisig ( )

Export multisig info This will generate and remember new k values

Definition at line 12994 of file wallet2.cpp.

12995 {
12996  std::vector<tools::wallet2::multisig_info> info;
12997 
12999 
13000  info.resize(m_transfers.size());
13001  for (size_t n = 0; n < m_transfers.size(); ++n)
13002  {
13003  transfer_details &td = m_transfers[n];
13004  crypto::key_image ki;
13005  td.m_multisig_k.clear();
13006  info[n].m_LR.clear();
13007  info[n].m_partial_key_images.clear();
13008 
13009  for (size_t m = 0; m < get_account().get_multisig_keys().size(); ++m)
13010  {
13011  // we want to export the partial key image, not the full one, so we can't use td.m_key_image
13012  bool r = generate_multisig_key_image(get_account().get_keys(), m, td.get_public_key(), ki);
13013  CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate key image");
13014  info[n].m_partial_key_images.push_back(ki);
13015  }
13016 
13017  // Wallet tries to create as many transactions as many signers combinations. We calculate the maximum number here as follows:
13018  // if we have 2/4 wallet with signers: A, B, C, D and A is a transaction creator it will need to pick up 1 signer from 3 wallets left.
13019  // That means counting combinations for excluding 2-of-3 wallets (k = total signers count - threshold, n = total signers count - 1).
13020  size_t nlr = tools::combinations_count(m_multisig_signers.size() - m_multisig_threshold, m_multisig_signers.size() - 1);
13021  for (size_t m = 0; m < nlr; ++m)
13022  {
13023  td.m_multisig_k.push_back(rct::skGen());
13024  const rct::multisig_kLRki kLRki = get_multisig_kLRki(n, td.m_multisig_k.back());
13025  info[n].m_LR.push_back({kLRki.L, kLRki.R});
13026  }
13027 
13028  info[n].m_signer = signer;
13029  }
13030 
13031  std::stringstream oss;
13033  ar << info;
13034 
13036  std::string header;
13037  header += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
13038  header += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
13039  header += std::string((const char *)&signer, sizeof(crypto::public_key));
13040  std::string ciphertext = encrypt_with_view_secret_key(header + oss.str());
13041 
13042  return MULTISIG_EXPORT_FILE_MAGIC + ciphertext;
13043 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
::std::string string
Definition: gtest-port.h:1097
uint64_t combinations_count(uint32_t k, uint32_t n)
Definition: combinator.cpp:35
#define MULTISIG_EXPORT_FILE_MAGIC
Definition: wallet2.cpp:125
const account_keys & get_keys() const
Definition: account.cpp:264
bool generate_multisig_key_image(const account_keys &keys, size_t multisig_key_index, const crypto::public_key &out_key, crypto::key_image &ki)
Definition: multisig.cpp:142
POD_CLASS public_key
Definition: crypto.h:76
void skGen(key &sk)
Definition: rctOps.cpp:253
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
account_public_address m_account_address
Definition: account.h:43
POD_CLASS key_image
Definition: crypto.h:102
cryptonote::account_base & get_account()
Definition: wallet2.h:734
const std::vector< crypto::secret_key > & get_multisig_keys() const
Definition: account.h:102
std::string encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated=true) const
Definition: wallet2.cpp:13217
Here is the call graph for this function:

◆ export_outputs()

std::pair< size_t, std::vector< tools::wallet2::transfer_details > > tools::wallet2::export_outputs ( bool  all = false) const

Definition at line 12723 of file wallet2.cpp.

12724 {
12726  std::vector<tools::wallet2::transfer_details> outs;
12727 
12728  size_t offset = 0;
12729  if (!all)
12730  while (offset < m_transfers.size() && (m_transfers[offset].m_key_image_known && !m_transfers[offset].m_key_image_request))
12731  ++offset;
12732 
12733  outs.reserve(m_transfers.size() - offset);
12734  for (size_t n = offset; n < m_transfers.size(); ++n)
12735  {
12736  const transfer_details &td = m_transfers[n];
12737 
12738  outs.push_back(td);
12739  }
12740 
12741  return std::make_pair(offset, outs);
12742 }
#define PERF_TIMER(name)
Definition: perf_timer.h:82
std::pair< size_t, std::vector< tools::wallet2::transfer_details > > export_outputs(bool all=false) const
Definition: wallet2.cpp:12723

◆ export_outputs_to_str()

std::string tools::wallet2::export_outputs_to_str ( bool  all = false) const

Definition at line 12744 of file wallet2.cpp.

12745 {
12747 
12748  std::stringstream oss;
12750  const auto& outputs = export_outputs(all);
12751  ar << outputs;
12752 
12755  std::string header;
12756  header += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
12757  header += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
12758  PERF_TIMER(export_outputs_encryption);
12759  std::string ciphertext = encrypt_with_view_secret_key(header + oss.str());
12760  return magic + ciphertext;
12761 }
#define PERF_TIMER(name)
Definition: perf_timer.h:82
::std::string string
Definition: gtest-port.h:1097
#define OUTPUT_EXPORT_FILE_MAGIC
Definition: wallet2.cpp:140
const account_keys & get_keys() const
Definition: account.cpp:264
std::string export_outputs_to_str(bool all=false) const
Definition: wallet2.cpp:12744
POD_CLASS public_key
Definition: crypto.h:76
account_public_address m_account_address
Definition: account.h:43
std::pair< size_t, std::vector< tools::wallet2::transfer_details > > export_outputs(bool all=false) const
Definition: wallet2.cpp:12723
cryptonote::account_base & get_account()
Definition: wallet2.h:734
std::string encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated=true) const
Definition: wallet2.cpp:13217

◆ export_payments()

wallet2::payment_container tools::wallet2::export_payments ( ) const

Definition at line 12665 of file wallet2.cpp.

12666 {
12667  payment_container payments;
12668  for (auto const &p : m_payments)
12669  {
12670  payments.emplace(p);
12671  }
12672  return payments;
12673 }
std::unordered_multimap< crypto::hash, payment_details > payment_container
Definition: wallet2.h:450

◆ finalize_multisig() [1/2]

bool tools::wallet2::finalize_multisig ( const epee::wipeable_string password,
const std::vector< std::string > &  info 
)

Finalizes creation of a multisig wallet.

Definition at line 5516 of file wallet2.cpp.

5517 {
5518  std::unordered_set<crypto::public_key> public_keys;
5519  std::vector<crypto::public_key> signers;
5520  if (!unpack_extra_multisig_info(info, signers, public_keys))
5521  {
5522  MERROR("Bad multisig info");
5523  return false;
5524  }
5525 
5526  return finalize_multisig(password, public_keys, signers);
5527 }
#define MERROR(x)
Definition: misc_log_ex.h:73
bool finalize_multisig(const epee::wipeable_string &password, const std::vector< std::string > &info)
Finalizes creation of a multisig wallet.
Definition: wallet2.cpp:5516
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91

◆ finalize_multisig() [2/2]

bool tools::wallet2::finalize_multisig ( const epee::wipeable_string password,
const std::unordered_set< crypto::public_key > &  pkeys,
std::vector< crypto::public_key signers 
)

Finalizes creation of a multisig wallet.

Definition at line 5476 of file wallet2.cpp.

5477 {
5478  bool ready;
5479  uint32_t threshold, total;
5480  if (!multisig(&ready, &threshold, &total))
5481  {
5482  MERROR("This is not a multisig wallet");
5483  return false;
5484  }
5485  if (ready)
5486  {
5487  MERROR("This multisig wallet is already finalized");
5488  return false;
5489  }
5490  if (threshold + 1 != total)
5491  {
5492  MERROR("finalize_multisig should only be used for N-1/N wallets, use exchange_multisig_keys instead");
5493  return false;
5494  }
5495  exchange_multisig_keys(password, pkeys, signers);
5496  return true;
5497 }
#define MERROR(x)
Definition: misc_log_ex.h:73
std::string exchange_multisig_keys(const epee::wipeable_string &password, const std::vector< std::string > &info)
Definition: wallet2.cpp:5280
unsigned int uint32_t
Definition: stdint.h:126
bool multisig(bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
Definition: wallet2.cpp:5634
uint8_t threshold
Definition: blockchain.cpp:92

◆ find_and_save_rings()

bool tools::wallet2::find_and_save_rings ( bool  force = true)

Definition at line 8109 of file wallet2.cpp.

8110 {
8111  if (!force && m_ring_history_saved)
8112  return true;
8113  if (!m_ringdb)
8114  return false;
8115 
8118 
8119  MDEBUG("Finding and saving rings...");
8120 
8121  // get payments we made
8122  std::vector<crypto::hash> txs_hashes;
8123  std::list<std::pair<crypto::hash,wallet2::confirmed_transfer_details>> payments;
8124  get_payments_out(payments, 0, std::numeric_limits<uint64_t>::max(), boost::none, std::set<uint32_t>());
8125  for (const std::pair<crypto::hash,wallet2::confirmed_transfer_details> &entry: payments)
8126  {
8127  const crypto::hash &txid = entry.first;
8128  txs_hashes.push_back(txid);
8129  }
8130 
8131  MDEBUG("Found " << std::to_string(txs_hashes.size()) << " transactions");
8132 
8133  // get those transactions from the daemon
8134  auto it = txs_hashes.begin();
8135  static const size_t SLICE_SIZE = 200;
8136  for (size_t slice = 0; slice < txs_hashes.size(); slice += SLICE_SIZE)
8137  {
8138  req.decode_as_json = false;
8139  req.prune = true;
8140  req.txs_hashes.clear();
8141  size_t ntxes = slice + SLICE_SIZE > txs_hashes.size() ? txs_hashes.size() - slice : SLICE_SIZE;
8142  for (size_t s = slice; s < slice + ntxes; ++s)
8143  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txs_hashes[s]));
8144  bool r;
8145  {
8146  const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
8147  r = invoke_http_json("/gettransactions", req, res, rpc_timeout);
8148  }
8149  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gettransactions");
8150  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gettransactions");
8151  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "gettransactions");
8152  THROW_WALLET_EXCEPTION_IF(res.txs.size() != req.txs_hashes.size(), error::wallet_internal_error,
8153  "daemon returned wrong response for gettransactions, wrong txs count = " +
8154  std::to_string(res.txs.size()) + ", expected " + std::to_string(req.txs_hashes.size()));
8155 
8156  MDEBUG("Scanning " << res.txs.size() << " transactions");
8157  THROW_WALLET_EXCEPTION_IF(slice + res.txs.size() > txs_hashes.size(), error::wallet_internal_error, "Unexpected tx array size");
8158  for (size_t i = 0; i < res.txs.size(); ++i, ++it)
8159  {
8160  const auto &tx_info = res.txs[i];
8162  crypto::hash tx_hash;
8163  THROW_WALLET_EXCEPTION_IF(!get_pruned_tx(tx_info, tx, tx_hash), error::wallet_internal_error,
8164  "Failed to get transaction from daemon");
8165  THROW_WALLET_EXCEPTION_IF(!(tx_hash == *it), error::wallet_internal_error, "Wrong txid received");
8166  THROW_WALLET_EXCEPTION_IF(!add_rings(get_ringdb_key(), tx), error::wallet_internal_error, "Failed to save ring");
8167  }
8168  }
8169 
8170  MINFO("Found and saved rings for " << txs_hashes.size() << " transactions");
8171  m_ring_history_saved = true;
8172  return true;
8173 }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
#define MINFO(x)
Definition: misc_log_ex.h:75
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
void get_payments_out(std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &confirmed_payments, uint64_t min_height, uint64_t max_height=(uint64_t) -1, const boost::optional< uint32_t > &subaddr_account=boost::none, const std::set< uint32_t > &subaddr_indices={}) const
Definition: wallet2.cpp:6346
#define CORE_RPC_STATUS_OK
#define MDEBUG(x)
Definition: misc_log_ex.h:76
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
POD_CLASS hash
Definition: hash.h:50
std::string to_string(t_connection_type type)
Here is the call graph for this function:

◆ finish_rescan_bc_keep_key_images()

void tools::wallet2::finish_rescan_bc_keep_key_images ( uint64_t  transfer_height,
const crypto::hash hash 
)

Definition at line 13734 of file wallet2.cpp.

13735 {
13736  // Compute hash of m_transfers, if differs there had to be BC reorg.
13737  crypto::hash new_transfers_hash{};
13738  hash_m_transfers((int64_t) transfer_height, new_transfers_hash);
13739 
13740  if (new_transfers_hash != hash)
13741  {
13742  // Soft-Reset to avoid inconsistency in case of BC reorg.
13743  clear_soft(false); // keep_key_images works only with soft reset.
13744  THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, "Transfers changed during rescan, soft or hard rescan is needed");
13745  }
13746 
13747  // Restore key images in m_transfers from m_key_images
13748  for(auto it = m_key_images.begin(); it != m_key_images.end(); it++)
13749  {
13750  THROW_WALLET_EXCEPTION_IF(it->second >= m_transfers.size(), error::wallet_internal_error, "Key images cache contains illegal transfer offset");
13751  m_transfers[it->second].m_key_image = it->first;
13752  m_transfers[it->second].m_key_image_known = true;
13753  }
13754 }
uint64_t hash_m_transfers(int64_t transfer_height, crypto::hash &hash) const
Definition: wallet2.cpp:13710
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
signed __int64 int64_t
Definition: stdint.h:135
POD_CLASS hash
Definition: hash.h:50

◆ freeze() [1/2]

void tools::wallet2::freeze ( size_t  idx)

Definition at line 1584 of file wallet2.cpp.

1585 {
1586  CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index");
1587  transfer_details &td = m_transfers[idx];
1588  td.m_frozen = true;
1589 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
Here is the caller graph for this function:

◆ freeze() [2/2]

void tools::wallet2::freeze ( const crypto::key_image ki)

Definition at line 1605 of file wallet2.cpp.

1606 {
1608 }
const transfer_details & get_transfer_details(size_t idx) const
Definition: wallet2.cpp:10852
void freeze(size_t idx)
Definition: wallet2.cpp:1584
Here is the call graph for this function:

◆ frozen() [1/3]

bool tools::wallet2::frozen ( size_t  idx) const

Definition at line 1598 of file wallet2.cpp.

1599 {
1600  CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index");
1601  const transfer_details &td = m_transfers[idx];
1602  return td.m_frozen;
1603 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
Here is the caller graph for this function:

◆ frozen() [2/3]

bool tools::wallet2::frozen ( const crypto::key_image ki) const

Definition at line 1615 of file wallet2.cpp.

1616 {
1617  return frozen(get_transfer_details(ki));
1618 }
bool frozen(size_t idx) const
Definition: wallet2.cpp:1598
const transfer_details & get_transfer_details(size_t idx) const
Definition: wallet2.cpp:10852
Here is the call graph for this function:

◆ frozen() [3/3]

bool tools::wallet2::frozen ( const transfer_details td) const

Definition at line 1631 of file wallet2.cpp.

1632 {
1633  return td.m_frozen;
1634 }

◆ generate() [1/4]

void tools::wallet2::generate ( const std::string &  wallet_,
const epee::wipeable_string password,
const epee::wipeable_string multisig_data,
bool  create_address_file = false 
)

Generates a wallet or restores one.

Parameters
wallet_Name of wallet file
passwordPassword of wallet file
multisig_dataThe multisig restore info and keys
create_address_fileWhether to create an address file

Definition at line 4869 of file wallet2.cpp.

4871 {
4872  clear();
4873  prepare_file_names(wallet_);
4874 
4875  if (!wallet_.empty())
4876  {
4877  boost::system::error_code ignored_ec;
4878  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
4879  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
4880  }
4881 
4882  m_account.generate(rct::rct2sk(rct::zero()), true, false);
4883 
4884  THROW_WALLET_EXCEPTION_IF(multisig_data.size() < 32, error::invalid_multisig_seed);
4885  size_t offset = 0;
4886  uint32_t threshold = *(uint32_t*)(multisig_data.data() + offset);
4887  offset += sizeof(uint32_t);
4888  uint32_t total = *(uint32_t*)(multisig_data.data() + offset);
4889  offset += sizeof(uint32_t);
4890  THROW_WALLET_EXCEPTION_IF(threshold < 2, error::invalid_multisig_seed);
4891  THROW_WALLET_EXCEPTION_IF(total != threshold && total != threshold + 1, error::invalid_multisig_seed);
4892  const size_t n_multisig_keys = total == threshold ? 1 : threshold;
4893  THROW_WALLET_EXCEPTION_IF(multisig_data.size() != 8 + 32 * (4 + n_multisig_keys + total), error::invalid_multisig_seed);
4894 
4895  std::vector<crypto::secret_key> multisig_keys;
4896  std::vector<crypto::public_key> multisig_signers;
4897  crypto::secret_key spend_secret_key = *(crypto::secret_key*)(multisig_data.data() + offset);
4898  offset += sizeof(crypto::secret_key);
4899  crypto::public_key spend_public_key = *(crypto::public_key*)(multisig_data.data() + offset);
4900  offset += sizeof(crypto::public_key);
4901  crypto::secret_key view_secret_key = *(crypto::secret_key*)(multisig_data.data() + offset);
4902  offset += sizeof(crypto::secret_key);
4903  crypto::public_key view_public_key = *(crypto::public_key*)(multisig_data.data() + offset);
4904  offset += sizeof(crypto::public_key);
4905  for (size_t n = 0; n < n_multisig_keys; ++n)
4906  {
4907  multisig_keys.push_back(*(crypto::secret_key*)(multisig_data.data() + offset));
4908  offset += sizeof(crypto::secret_key);
4909  }
4910  for (size_t n = 0; n < total; ++n)
4911  {
4912  multisig_signers.push_back(*(crypto::public_key*)(multisig_data.data() + offset));
4913  offset += sizeof(crypto::public_key);
4914  }
4915 
4916  crypto::public_key calculated_view_public_key;
4917  THROW_WALLET_EXCEPTION_IF(!crypto::secret_key_to_public_key(view_secret_key, calculated_view_public_key), error::invalid_multisig_seed);
4918  THROW_WALLET_EXCEPTION_IF(view_public_key != calculated_view_public_key, error::invalid_multisig_seed);
4919  crypto::public_key local_signer;
4920  THROW_WALLET_EXCEPTION_IF(!crypto::secret_key_to_public_key(spend_secret_key, local_signer), error::invalid_multisig_seed);
4921  THROW_WALLET_EXCEPTION_IF(std::find(multisig_signers.begin(), multisig_signers.end(), local_signer) == multisig_signers.end(), error::invalid_multisig_seed);
4922  rct::key skey = rct::zero();
4923  for (const auto &msk: multisig_keys)
4924  sc_add(skey.bytes, skey.bytes, rct::sk2rct(msk).bytes);
4925  THROW_WALLET_EXCEPTION_IF(!(rct::rct2sk(skey) == spend_secret_key), error::invalid_multisig_seed);
4926  memwipe(&skey, sizeof(rct::key));
4927 
4928  m_account.make_multisig(view_secret_key, spend_secret_key, spend_public_key, multisig_keys);
4929  m_account.finalize_multisig(spend_public_key);
4930 
4931  // Not possible to restore a multisig wallet that is able to activate the MMS
4932  // (because the original keys are not (yet) part of the restore info), so
4933  // keep m_original_keys_available to false
4934  init_type(hw::device::device_type::SOFTWARE);
4935  m_multisig = true;
4936  m_multisig_threshold = threshold;
4937  m_multisig_signers = multisig_signers;
4938  setup_keys(password);
4939 
4940  create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
4941  setup_new_blockchain();
4942 
4943  if (!wallet_.empty())
4944  store();
4945 }
size_t size() const noexcept
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector< crypto::secret_key > &multisig_keys)
Definition: account.cpp:250
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
crypto::secret_key generate(const crypto::secret_key &recovery_key=crypto::secret_key(), bool recover=false, bool two_random=false)
Definition: account.cpp:158
unsigned int uint32_t
Definition: stdint.h:126
POD_CLASS public_key
Definition: crypto.h:76
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void finalize_multisig(const crypto::public_key &spend_public_key)
Definition: account.cpp:259
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
void * memwipe(void *src, size_t n)
const char * data() const noexcept
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
key zero()
Definition: rctOps.h:70
file_error_base< file_exists_message_index > file_exists
uint8_t threshold
Definition: blockchain.cpp:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate() [2/4]

crypto::secret_key tools::wallet2::generate ( const std::string &  wallet_,
const epee::wipeable_string password,
const crypto::secret_key recovery_param = crypto::secret_key(),
bool  recover = false,
bool  two_random = false,
bool  create_address_file = false 
)

Generates a wallet or restores one.

Parameters
wallet_Name of wallet file
passwordPassword of wallet file
recovery_paramIf it is a restore, the recovery key
recoverWhether it is a restore
two_randomWhether it is a non-deterministic wallet
create_address_fileWhether to create an address file
Returns
The secret key of the generated wallet

Definition at line 4957 of file wallet2.cpp.

4959 {
4960  clear();
4961  prepare_file_names(wallet_);
4962 
4963  if (!wallet_.empty())
4964  {
4965  boost::system::error_code ignored_ec;
4966  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
4967  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
4968  }
4969 
4970  crypto::secret_key retval = m_account.generate(recovery_param, recover, two_random);
4971 
4972  init_type(hw::device::device_type::SOFTWARE);
4973  setup_keys(password);
4974 
4975  // calculate a starting refresh height
4976  if(m_refresh_from_block_height == 0 && !recover){
4977  m_refresh_from_block_height = estimate_blockchain_height();
4978  }
4979 
4980  create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
4981 
4982  setup_new_blockchain();
4983 
4984  if (!wallet_.empty())
4985  store();
4986 
4987  return retval;
4988 }
crypto::secret_key generate(const crypto::secret_key &recovery_key=crypto::secret_key(), bool recover=false, bool two_random=false)
Definition: account.cpp:158
uint64_t estimate_blockchain_height()
Definition: wallet2.cpp:4990
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
file_error_base< file_exists_message_index > file_exists

◆ generate() [3/4]

void tools::wallet2::generate ( const std::string &  wallet_,
const epee::wipeable_string password,
const cryptonote::account_public_address account_public_address,
const crypto::secret_key spendkey,
const crypto::secret_key viewkey,
bool  create_address_file = false 
)

Creates a wallet from a public address and a spend/view secret key pair.

Parameters
wallet_Name of wallet file
passwordPassword of wallet file
account_public_addressThe account's public address
spendkeyspend secret key
viewkeyview secret key
create_address_fileWhether to create an address file

Definition at line 5077 of file wallet2.cpp.

5080 {
5081  clear();
5082  prepare_file_names(wallet_);
5083 
5084  if (!wallet_.empty())
5085  {
5086  boost::system::error_code ignored_ec;
5087  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
5088  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
5089  }
5090 
5091  m_account.create_from_keys(account_public_address, spendkey, viewkey);
5092  init_type(hw::device::device_type::SOFTWARE);
5093  m_account_public_address = account_public_address;
5094  setup_keys(password);
5095 
5096  create_keys_file(wallet_, false, password, create_address_file);
5097 
5098  setup_new_blockchain();
5099 
5100  if (!wallet_.empty())
5101  store();
5102 }
void create_from_keys(const cryptonote::account_public_address &address, const crypto::secret_key &spendkey, const crypto::secret_key &viewkey)
Definition: account.cpp:189
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
const char * spendkey
Definition: multisig.cpp:38
file_error_base< file_exists_message_index > file_exists

◆ generate() [4/4]

void tools::wallet2::generate ( const std::string &  wallet_,
const epee::wipeable_string password,
const cryptonote::account_public_address account_public_address,
const crypto::secret_key viewkey = crypto::secret_key(),
bool  create_address_file = false 
)

Creates a watch only wallet from a public address and a view secret key.

Parameters
wallet_Name of wallet file
passwordPassword of wallet file
account_public_addressThe account's public address
viewkeyview secret key
create_address_fileWhether to create an address file

Definition at line 5040 of file wallet2.cpp.

5043 {
5044  clear();
5045  prepare_file_names(wallet_);
5046 
5047  if (!wallet_.empty())
5048  {
5049  boost::system::error_code ignored_ec;
5050  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
5051  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
5052  }
5053 
5054  m_account.create_from_viewkey(account_public_address, viewkey);
5055  init_type(hw::device::device_type::SOFTWARE);
5056  m_watch_only = true;
5057  m_account_public_address = account_public_address;
5058  setup_keys(password);
5059 
5060  create_keys_file(wallet_, true, password, m_nettype != MAINNET || create_address_file);
5061 
5062  setup_new_blockchain();
5063 
5064  if (!wallet_.empty())
5065  store();
5066 }
void create_from_viewkey(const cryptonote::account_public_address &address, const crypto::secret_key &viewkey)
Definition: account.cpp:243
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
file_error_base< file_exists_message_index > file_exists

◆ get_account() [1/2]

cryptonote::account_base& tools::wallet2::get_account ( )
inline

Definition at line 734 of file wallet2.h.

734 {return m_account;}
Here is the caller graph for this function:

◆ get_account() [2/2]

const cryptonote::account_base& tools::wallet2::get_account ( ) const
inline

Definition at line 735 of file wallet2.h.

735 {return m_account;}

◆ get_account_tags()

const std::pair< std::map< std::string, std::string >, std::vector< std::string > > & tools::wallet2::get_account_tags ( )

Get the list of registered account tags.

Returns
first.Key=(tag's name), first.Value=(tag's label), second[i]=(i-th account's tag)

Definition at line 12036 of file wallet2.cpp.

12037 {
12038  // ensure consistency
12039  if (m_account_tags.second.size() != get_num_subaddress_accounts())
12040  m_account_tags.second.resize(get_num_subaddress_accounts(), "");
12041  for (const std::string& tag : m_account_tags.second)
12042  {
12043  if (!tag.empty() && m_account_tags.first.count(tag) == 0)
12044  m_account_tags.first.insert({tag, ""});
12045  }
12046  for (auto i = m_account_tags.first.begin(); i != m_account_tags.first.end(); )
12047  {
12048  if (std::find(m_account_tags.second.begin(), m_account_tags.second.end(), i->first) == m_account_tags.second.end())
12049  i = m_account_tags.first.erase(i);
12050  else
12051  ++i;
12052  }
12053  return m_account_tags;
12054 }
::std::string string
Definition: gtest-port.h:1097
size_t get_num_subaddress_accounts() const
Definition: wallet2.h:801
Here is the caller graph for this function:

◆ get_address()

cryptonote::account_public_address tools::wallet2::get_address ( ) const
inline

Definition at line 793 of file wallet2.h.

793 { return get_subaddress({0,0}); }
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index &index) const
Definition: wallet2.cpp:1430
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_address_as_str()

std::string tools::wallet2::get_address_as_str ( ) const
inline

Definition at line 798 of file wallet2.h.

798 { return get_subaddress_as_str({0, 0}); }
std::string get_subaddress_as_str(const cryptonote::subaddress_index &index) const
Definition: wallet2.cpp:1452
Here is the call graph for this function:

◆ get_address_book()

std::vector<address_book_row> tools::wallet2::get_address_book ( ) const
inline

GUI Address book get/store.

Definition at line 1150 of file wallet2.h.

1150 { return m_address_book; }

◆ get_approximate_blockchain_height()

uint64_t tools::wallet2::get_approximate_blockchain_height ( ) const

Calculates the approximate blockchain height from current date/time.

Definition at line 11965 of file wallet2.cpp.

11966 {
11967  // time of v2 fork
11968  const time_t fork_time = m_nettype == TESTNET ? 1341378000 : m_nettype == STAGENET ? 1521000000 : 1538815057;
11969  // v2 fork block
11970  const uint64_t fork_block = m_nettype == TESTNET ? 190060 : m_nettype == STAGENET ? 32000 : 307500;
11971  // avg seconds per block
11972  const int seconds_per_block = DIFFICULTY_TARGET_V6;
11973  // Calculated blockchain height
11974  uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block;
11975  // testnet got some huge rollbacks, so the estimation is way off
11976  static const uint64_t approximate_testnet_rolled_back_blocks = 303967;
11977  if (m_nettype == TESTNET && approx_blockchain_height > approximate_testnet_rolled_back_blocks)
11978  approx_blockchain_height -= approximate_testnet_rolled_back_blocks;
11979  // estiamte blocks from v6
11980  if(m_nettype == MAINNET) {
11981  approx_blockchain_height += 82000;
11982  }
11983  LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height);
11984  return approx_blockchain_height;
11985 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
time_t time
Definition: blockchain.cpp:93
#define DIFFICULTY_TARGET_V6
unsigned __int64 uint64_t
Definition: stdint.h:136

◆ get_attribute()

std::string tools::wallet2::get_attribute ( const std::string &  key) const

Definition at line 12018 of file wallet2.cpp.

12019 {
12020  std::unordered_map<std::string, std::string>::const_iterator i = m_attributes.find(key);
12021  if (i == m_attributes.end())
12022  return std::string();
12023  return i->second;
12024 }
::std::string string
Definition: gtest-port.h:1097
const char * key
Definition: hmac_keccak.cpp:39

◆ get_base_fee()

uint64_t tools::wallet2::get_base_fee ( ) const

Definition at line 7785 of file wallet2.cpp.

7786 {
7787  if(m_light_wallet)
7788  {
7790  return m_light_wallet_per_kb_fee / 1024;
7791  else
7792  return m_light_wallet_per_kb_fee;
7793  }
7794  bool use_dyn_fee = use_fork_rules(HF_VERSION_DYNAMIC_FEE, -720 * 1);
7795  if (!use_dyn_fee){
7797  return FEE_PER_KB_V11;
7798  } else{
7799  return FEE_PER_KB_V6;
7800  }
7801  }
7802 
7803 
7804  return get_dynamic_base_fee_estimate(); //this never gets hit for any version before 100
7805 }
#define FEE_PER_KB_V11
#define HF_VERSION_ZERO_FEE
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
#define FEE_PER_KB_V6
#define HF_VERSION_DYNAMIC_FEE
#define HF_VERSION_PER_BYTE_FEE

◆ get_blockchain_current_height()

uint64_t tools::wallet2::get_blockchain_current_height ( ) const
inline

Definition at line 898 of file wallet2.h.

898 { return m_light_wallet_blockchain_height ? m_light_wallet_blockchain_height : m_blockchain.size(); }
size_t size() const
Definition: wallet2.h:181
Here is the caller graph for this function:

◆ get_blockchain_height_by_date()

uint64_t tools::wallet2::get_blockchain_height_by_date ( uint16_t  year,
uint8_t  month,
uint8_t  day 
)

Definition at line 13393 of file wallet2.cpp.

13394 {
13395  uint32_t version;
13396  if (!check_connection(&version))
13397  {
13398  throw std::runtime_error("failed to connect to daemon: " + get_daemon_address());
13399  }
13400  if (version < MAKE_CORE_RPC_VERSION(1, 6))
13401  {
13402  throw std::runtime_error("this function requires RPC version 1.6 or higher");
13403  }
13404  std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 };
13405  date.tm_year = year - 1900;
13406  date.tm_mon = month - 1;
13407  date.tm_mday = day;
13408  if (date.tm_mon < 0 || 11 < date.tm_mon || date.tm_mday < 1 || 31 < date.tm_mday)
13409  {
13410  throw std::runtime_error("month or day out of range");
13411  }
13412  uint64_t timestamp_target = std::mktime(&date);
13413  std::string err;
13414  uint64_t height_min = 0;
13415  uint64_t height_max = get_daemon_blockchain_height(err) - 1;
13416  if (!err.empty())
13417  {
13418  throw std::runtime_error("failed to get blockchain height");
13419  }
13420  while (true)
13421  {
13424  uint64_t height_mid = (height_min + height_max) / 2;
13425  req.heights =
13426  {
13427  height_min,
13428  height_mid,
13429  height_max
13430  };
13431  bool r = invoke_http_bin("/getblocks_by_height.bin", req, res, rpc_timeout);
13432  if (!r || res.status != CORE_RPC_STATUS_OK)
13433  {
13434  std::ostringstream oss;
13435  oss << "failed to get blocks by heights: ";
13436  for (auto height : req.heights)
13437  oss << height << ' ';
13438  oss << endl << "reason: ";
13439  if (!r)
13440  oss << "possibly lost connection to daemon";
13441  else if (res.status == CORE_RPC_STATUS_BUSY)
13442  oss << "daemon is busy";
13443  else
13444  oss << get_rpc_status(res.status);
13445  throw std::runtime_error(oss.str());
13446  }
13447  cryptonote::block blk_min, blk_mid, blk_max;
13448  if (res.blocks.size() < 3) throw std::runtime_error("Not enough blocks returned from daemon");
13449  if (!parse_and_validate_block_from_blob(res.blocks[0].block, blk_min)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_min));
13450  if (!parse_and_validate_block_from_blob(res.blocks[1].block, blk_mid)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_mid));
13451  if (!parse_and_validate_block_from_blob(res.blocks[2].block, blk_max)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_max));
13452  uint64_t timestamp_min = blk_min.timestamp;
13453  uint64_t timestamp_mid = blk_mid.timestamp;
13454  uint64_t timestamp_max = blk_max.timestamp;
13455  if (!(timestamp_min <= timestamp_mid && timestamp_mid <= timestamp_max))
13456  {
13457  // the timestamps are not in the chronological order.
13458  // assuming they're sufficiently close to each other, simply return the smallest height
13459  return std::min({height_min, height_mid, height_max});
13460  }
13461  if (timestamp_target > timestamp_max)
13462  {
13463  throw std::runtime_error("specified date is in the future");
13464  }
13465  if (timestamp_target <= timestamp_min + 2 * 24 * 60 * 60) // two days of "buffer" period
13466  {
13467  return height_min;
13468  }
13469  if (timestamp_target <= timestamp_mid)
13470  height_max = height_mid;
13471  else
13472  height_min = height_mid;
13473  if (height_max - height_min <= 2 * 24 * 30) // don't divide the height range finer than two days
13474  {
13475  return height_min;
13476  }
13477  }
13478 }
const char * res
Definition: hmac_keccak.cpp:41
::std::string string
Definition: gtest-port.h:1097
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
bool check_connection(uint32_t *version=NULL, bool *ssl=NULL, uint32_t timeout=200000)
Definition: wallet2.cpp:5758
uint64_t height
Definition: blockchain.cpp:91
#define CORE_RPC_STATUS_BUSY
std::string get_daemon_address() const
Definition: wallet2.cpp:11926
#define CORE_RPC_STATUS_OK
#define MAKE_CORE_RPC_VERSION(major, minor)
unsigned int uint32_t
Definition: stdint.h:126
uint64_t get_daemon_blockchain_height(std::string &err) const
Definition: wallet2.cpp:11931
unsigned __int64 uint64_t
Definition: stdint.h:136
version
Supported socks variants.
Definition: socks.h:57
bool invoke_http_bin(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1326
std::string to_string(t_connection_type type)
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
Here is the call graph for this function:

◆ get_bytes_received()

uint64_t tools::wallet2::get_bytes_received ( ) const

Definition at line 13761 of file wallet2.cpp.

13762 {
13763  return m_http_client.get_bytes_received();
13764 }

◆ get_bytes_sent()

uint64_t tools::wallet2::get_bytes_sent ( ) const

Definition at line 13756 of file wallet2.cpp.

13757 {
13758  return m_http_client.get_bytes_sent();
13759 }

◆ get_confirm_backlog_threshold()

uint32_t tools::wallet2::get_confirm_backlog_threshold ( ) const
inline

Definition at line 1090 of file wallet2.h.

1090 { return m_confirm_backlog_threshold; };

◆ get_daemon_address()

std::string tools::wallet2::get_daemon_address ( ) const

Definition at line 11926 of file wallet2.cpp.

11927 {
11928  return m_daemon_address;
11929 }
Here is the caller graph for this function:

◆ get_daemon_blockchain_height()

uint64_t tools::wallet2::get_daemon_blockchain_height ( std::string &  err) const

Definition at line 11931 of file wallet2.cpp.

11932 {
11933  uint64_t height;
11934 
11935  boost::optional<std::string> result = m_node_rpc_proxy.get_height(height);
11936  if (result)
11937  {
11938  if (m_trusted_daemon)
11939  err = *result;
11940  else
11941  err = "daemon error";
11942  return 0;
11943  }
11944 
11945  err = "";
11946  return height;
11947 }
uint64_t height
Definition: blockchain.cpp:91
unsigned __int64 uint64_t
Definition: stdint.h:136
boost::optional< std::string > get_height(uint64_t &height) const

◆ get_daemon_blockchain_target_height()

uint64_t tools::wallet2::get_daemon_blockchain_target_height ( std::string &  err)

Definition at line 11949 of file wallet2.cpp.

11950 {
11951  err = "";
11952  uint64_t target_height = 0;
11953  const auto result = m_node_rpc_proxy.get_target_height(target_height);
11954  if (result && *result != CORE_RPC_STATUS_OK)
11955  {
11956  if (m_trusted_daemon)
11957  err = *result;
11958  else
11959  err = "daemon error";
11960  return 0;
11961  }
11962  return target_height;
11963 }
#define CORE_RPC_STATUS_OK
unsigned __int64 uint64_t
Definition: stdint.h:136
boost::optional< std::string > get_target_height(uint64_t &height) const

◆ get_daemon_login()

const boost::optional<epee::net_utils::http::login>& tools::wallet2::get_daemon_login ( ) const
inline

Definition at line 1165 of file wallet2.h.

1165 { return m_daemon_login; }
Here is the caller graph for this function:

◆ get_default_priority()

uint32_t tools::wallet2::get_default_priority ( ) const
inline

Definition at line 1073 of file wallet2.h.

1073 { return m_default_priority; }

◆ get_description()

std::string tools::wallet2::get_description ( ) const

Definition at line 12031 of file wallet2.cpp.

12032 {
12034 }
const char *const ATTRIBUTE_DESCRIPTION
Definition: wallet2.h:1309
std::string get_attribute(const std::string &key) const
Definition: wallet2.cpp:12018

◆ get_device_last_key_image_sync()

uint64_t tools::wallet2::get_device_last_key_image_sync ( ) const
inline

Definition at line 907 of file wallet2.h.

907 { return m_device_last_key_image_sync; }

◆ get_device_type()

hw::device::device_type tools::wallet2::get_device_type ( ) const
inline

Definition at line 831 of file wallet2.h.

831 { return m_key_device_type; }
Here is the caller graph for this function:

◆ get_fee_algorithm()

int tools::wallet2::get_fee_algorithm ( ) const

Definition at line 7824 of file wallet2.cpp.

7825 {
7826  // changes at v3, v5, v8
7827  if (use_fork_rules(6, 0))
7828  return 3;
7829  if (use_fork_rules(5, 0))
7830  return 2;
7831  if (use_fork_rules(3, -720 * 14))
7832  return 1;
7833  return 0;
7834 }
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720

◆ get_fee_multiplier()

uint64_t tools::wallet2::get_fee_multiplier ( uint32_t  priority,
int  fee_algorithm = -1 
) const

Definition at line 7732 of file wallet2.cpp.

7733 {
7734  static const struct
7735  {
7736  size_t count;
7737  uint64_t multipliers[4];
7738  }
7739  multipliers[] =
7740  {
7741  { 3, {1, 2, 3} },
7742  { 3, {1, 20, 166} },
7743  { 4, {1, 4, 20, 166} },
7744  { 4, {1, 2, 4, 8} },
7745  };
7746 
7747  if (fee_algorithm == -1)
7748  fee_algorithm = get_fee_algorithm();
7749 
7750  // 0 -> default (here, x1 till fee algorithm 2, x4 from it)
7751  if (priority == 0)
7752  priority = m_default_priority;
7753  if (priority == 0)
7754  {
7755  if (fee_algorithm == 2)
7756  priority = 2;
7757  else
7758  priority = 1;
7759  }
7760 
7761  THROW_WALLET_EXCEPTION_IF(fee_algorithm < 0 || fee_algorithm > 4, error::invalid_priority);
7762 
7763  // 1 to 3/4 are allowed as priorities
7764  const uint32_t max_priority = multipliers[fee_algorithm].count;
7765  if (priority >= 1 && priority <= max_priority)
7766  {
7767  return multipliers[fee_algorithm].multipliers[priority-1];
7768  }
7769 
7770  THROW_WALLET_EXCEPTION_IF (false, error::invalid_priority);
7771  return 1;
7772 }
int get_fee_algorithm() const
Definition: wallet2.cpp:7824
mdb_size_t count(MDB_cursor *cur)
unsigned int uint32_t
Definition: stdint.h:126
unsigned __int64 uint64_t
Definition: stdint.h:136
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
Here is the call graph for this function:

◆ get_fee_quantization_mask()

uint64_t tools::wallet2::get_fee_quantization_mask ( ) const

Definition at line 7807 of file wallet2.cpp.

7808 {
7809  if(m_light_wallet)
7810  {
7811  return 1; // TODO
7812  }
7813  bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
7814  if (!use_per_byte_fee)
7815  return 1;
7816 
7817  uint64_t fee_quantization_mask;
7818  boost::optional<std::string> result = m_node_rpc_proxy.get_fee_quantization_mask(fee_quantization_mask);
7819  if (result)
7820  return 1;
7821  return fee_quantization_mask;
7822 }
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
unsigned __int64 uint64_t
Definition: stdint.h:136
boost::optional< std::string > get_fee_quantization_mask(uint64_t &fee_quantization_mask) const
#define HF_VERSION_PER_BYTE_FEE

◆ get_hard_fork_info()

void tools::wallet2::get_hard_fork_info ( uint8_t  version,
uint64_t earliest_height 
) const

Definition at line 10714 of file wallet2.cpp.

10715 {
10716  boost::optional<std::string> result = m_node_rpc_proxy.get_earliest_height(version, earliest_height);
10717  throw_on_rpc_response_error(result, "get_hard_fork_info");
10718 }
boost::optional< std::string > get_earliest_height(uint8_t version, uint64_t &earliest_height) const
version
Supported socks variants.
Definition: socks.h:57

◆ get_human_readable_timestamp()

static std::string tools::wallet2::get_human_readable_timestamp ( uint64_t  ts)
inlinestatic

Check if wallet file path is valid format.

Parameters
file_pathWallet file path
Returns
Whether path is valid format

Definition at line 1039 of file wallet2.h.

1040  {
1041  char buffer[64];
1042  if (ts < 1234567890)
1043  return "<unknown>";
1044  time_t tt = ts;
1045  struct tm tm;
1046  #ifdef WIN32
1047  gmtime_s(&tm, &tt);
1048  #else
1049  gmtime_r(&tt, &tm);
1050  #endif
1051  uint64_t now = time(NULL);
1052  uint64_t diff = ts > now ? ts - now : now - ts;
1053  if (diff > 24*3600)
1054  strftime(buffer, sizeof(buffer), "%Y-%m-%d", &tm);
1055  else
1056  strftime(buffer, sizeof(buffer), "%I:%M:%S %p", &tm);
1057  return std::string(buffer);
1058 }
::std::string string
Definition: gtest-port.h:1097
time_t time
Definition: blockchain.cpp:93
unsigned __int64 uint64_t
Definition: stdint.h:136

◆ get_integrated_address_as_str()

std::string tools::wallet2::get_integrated_address_as_str ( const crypto::hash8 payment_id) const

Definition at line 1458 of file wallet2.cpp.

1459 {
1460  return cryptonote::get_account_integrated_address_as_str(m_nettype, get_address(), payment_id);
1461 }
std::string get_account_integrated_address_as_str(network_type nettype, account_public_address const &adr, crypto::hash8 const &payment_id)
cryptonote::account_public_address get_address() const
Definition: wallet2.h:793
Here is the call graph for this function:

◆ get_keys_file()

std::string tools::wallet2::get_keys_file ( ) const

Definition at line 11921 of file wallet2.cpp.

11922 {
11923  return m_keys_file;
11924 }

◆ get_last_block_reward()

uint64_t tools::wallet2::get_last_block_reward ( ) const
inline

Definition at line 906 of file wallet2.h.

906 { return m_last_block_reward; }

◆ get_light_wallet_blockchain_height()

uint64_t tools::wallet2::get_light_wallet_blockchain_height ( ) const
inline

Definition at line 780 of file wallet2.h.

780 { return m_light_wallet_blockchain_height; }

◆ get_light_wallet_scanned_block_height()

uint64_t tools::wallet2::get_light_wallet_scanned_block_height ( ) const
inline

Definition at line 779 of file wallet2.h.

779 { return m_light_wallet_scanned_block_height; }

◆ get_max_ring_size()

uint64_t tools::wallet2::get_max_ring_size ( ) const

Definition at line 7851 of file wallet2.cpp.

7852 {
7854  return 11;
7856  return 1;
7857  return 0;
7858 }
#define HF_VERSION_MAX_RING_11
#define HF_VERSION_ENFORCE_0_DECOY_TXS
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720

◆ get_message_store() [1/2]

mms::message_store& tools::wallet2::get_message_store ( )
inline

Definition at line 1367 of file wallet2.h.

1367 { return m_message_store; };

◆ get_message_store() [2/2]

const mms::message_store& tools::wallet2::get_message_store ( ) const
inline

Definition at line 1368 of file wallet2.h.

1368 { return m_message_store; };

◆ get_min_output_count()

uint32_t tools::wallet2::get_min_output_count ( ) const
inline

Definition at line 1082 of file wallet2.h.

1082 { return m_min_output_count; }

◆ get_min_output_value()

uint64_t tools::wallet2::get_min_output_value ( ) const
inline

Definition at line 1084 of file wallet2.h.

1084 { return m_min_output_value; }

◆ get_min_ring_size()

uint64_t tools::wallet2::get_min_ring_size ( ) const

Definition at line 7836 of file wallet2.cpp.

7837 {
7839  return 11;
7841  return 7;
7843  return 5;
7845  return 1;
7847  return 3;
7848  return 0;
7849 }
#define HF_VERSION_MIN_MIXIN_2
#define HF_VERSION_ENFORCE_0_DECOY_TXS
#define HF_VERSION_MIN_MIXIN_4
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
#define HF_VERSION_MIN_MIXIN_6
#define HF_VERSION_MIN_MIXIN_10

◆ get_multisig_info()

std::string tools::wallet2::get_multisig_info ( ) const

Get a packaged multisig information string

Definition at line 5529 of file wallet2.cpp.

5530 {
5531  // It's a signed package of private view key and public spend key
5532  const crypto::secret_key skey = cryptonote::get_multisig_blinded_secret_key(get_account().get_keys().m_view_secret_key);
5533  const crypto::public_key pkey = get_multisig_signer_public_key(get_account().get_keys().m_spend_secret_key);
5535 
5536  std::string data;
5537  data += std::string((const char *)&skey, sizeof(crypto::secret_key));
5538  data += std::string((const char *)&pkey, sizeof(crypto::public_key));
5539 
5540  data.resize(data.size() + sizeof(crypto::signature));
5541  crypto::cn_fast_hash(data.data(), data.size() - sizeof(signature), hash);
5542  crypto::signature &signature = *(crypto::signature*)&data[data.size() - sizeof(crypto::signature)];
5543  crypto::generate_signature(hash, pkey, get_multisig_blinded_secret_key(get_account().get_keys().m_spend_secret_key), signature);
5544 
5545  return std::string("MultisigV1") + tools::base58::encode(data);
5546 }
::std::string string
Definition: gtest-port.h:1097
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:292
std::string encode(const std::string &data)
Definition: base58.cpp:173
crypto::secret_key get_multisig_blinded_secret_key(const crypto::secret_key &key)
Definition: multisig.cpp:47
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
POD_CLASS signature
Definition: crypto.h:108
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ get_multisig_seed()

bool tools::wallet2::get_multisig_seed ( epee::wipeable_string seed,
const epee::wipeable_string passphrase = std::string(),
bool  raw = true 
) const

Definition at line 1327 of file wallet2.cpp.

1328 {
1329  bool ready;
1330  uint32_t threshold, total;
1331  if (!multisig(&ready, &threshold, &total))
1332  {
1333  std::cout << "This is not a multisig wallet" << std::endl;
1334  return false;
1335  }
1336  if (!ready)
1337  {
1338  std::cout << "This multisig wallet is not yet finalized" << std::endl;
1339  return false;
1340  }
1341  if (!raw && seed_language.empty())
1342  {
1343  std::cout << "seed_language not set" << std::endl;
1344  return false;
1345  }
1346 
1347  crypto::secret_key skey;
1348  crypto::public_key pkey;
1349  const account_keys &keys = get_account().get_keys();
1350  epee::wipeable_string data;
1351  data.append((const char*)&threshold, sizeof(uint32_t));
1352  data.append((const char*)&total, sizeof(uint32_t));
1353  skey = keys.m_spend_secret_key;
1354  data.append((const char*)&skey, sizeof(skey));
1356  data.append((const char*)&pkey, sizeof(pkey));
1357  skey = keys.m_view_secret_key;
1358  data.append((const char*)&skey, sizeof(skey));
1360  data.append((const char*)&pkey, sizeof(pkey));
1361  for (const auto &skey: keys.m_multisig_keys)
1362  data.append((const char*)&skey, sizeof(skey));
1363  for (const auto &signer: m_multisig_signers)
1364  data.append((const char*)&signer, sizeof(signer));
1365 
1366  if (!passphrase.empty())
1367  {
1369  crypto::cn_slow_hash(passphrase.data(), passphrase.size(), (crypto::hash&)key);
1370  sc_reduce32((unsigned char*)key.data);
1371  data = encrypt(data, key, true);
1372  }
1373 
1374  if (raw)
1375  {
1376  seed = epee::to_hex::wipeable_string({(const unsigned char*)data.data(), data.size()});
1377  }
1378  else
1379  {
1380  if (!crypto::ElectrumWords::bytes_to_words(data.data(), data.size(), seed, seed_language))
1381  {
1382  std::cout << "Failed to encode seed";
1383  return false;
1384  }
1385  }
1386 
1387  return true;
1388 }
size_t size() const noexcept
const char * key
Definition: hmac_keccak.cpp:39
void append(const char *ptr, size_t len)
static epee::wipeable_string wipeable_string(const span< const std::uint8_t > src)
Definition: hex.cpp:69
const account_keys & get_keys() const
Definition: account.cpp:264
bool bytes_to_words(const char *src, size_t len, epee::wipeable_string &words, const std::string &language_name)
Converts bytes (secret key) to seed words.
unsigned int uint32_t
Definition: stdint.h:126
void sc_reduce32(unsigned char *)
bool empty() const noexcept
POD_CLASS public_key
Definition: crypto.h:76
crypto::secret_key m_view_secret_key
Definition: account.h:45
account_public_address m_account_address
Definition: account.h:43
crypto::secret_key m_spend_secret_key
Definition: account.h:44
std::vector< crypto::secret_key > m_multisig_keys
Definition: account.h:46
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height)
const char * data() const noexcept
std::string encrypt(const char *plaintext, size_t len, const crypto::secret_key &skey, bool authenticated=true) const
Definition: wallet2.cpp:13181
bool multisig(bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
Definition: wallet2.cpp:5634
uint8_t threshold
Definition: blockchain.cpp:92
Here is the call graph for this function:

◆ get_multisig_signer_public_key() [1/2]

crypto::public_key tools::wallet2::get_multisig_signer_public_key ( const crypto::secret_key spend_skey) const

Definition at line 12891 of file wallet2.cpp.

12892 {
12893  crypto::public_key pkey;
12895  return pkey;
12896 }
crypto::secret_key get_multisig_blinded_secret_key(const crypto::secret_key &key)
Definition: multisig.cpp:47
POD_CLASS public_key
Definition: crypto.h:76
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
Here is the call graph for this function:

◆ get_multisig_signer_public_key() [2/2]

crypto::public_key tools::wallet2::get_multisig_signer_public_key ( ) const

Definition at line 12898 of file wallet2.cpp.

12899 {
12900  CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
12901  crypto::public_key signer;
12902  CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(get_account().get_keys().m_spend_secret_key, signer), "Failed to generate signer public key");
12903  return signer;
12904 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
POD_CLASS public_key
Definition: crypto.h:76
cryptonote::account_base & get_account()
Definition: wallet2.h:734
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
Here is the call graph for this function:

◆ get_multisig_signing_public_key() [1/2]

crypto::public_key tools::wallet2::get_multisig_signing_public_key ( size_t  idx) const

Definition at line 12914 of file wallet2.cpp.

12915 {
12916  CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
12917  CHECK_AND_ASSERT_THROW_MES(idx < get_account().get_multisig_keys().size(), "Multisig signing key index out of range");
12918  return get_multisig_signing_public_key(get_account().get_multisig_keys()[idx]);
12919 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
crypto::public_key get_multisig_signing_public_key(size_t idx) const
Definition: wallet2.cpp:12914
cryptonote::account_base & get_account()
Definition: wallet2.h:734

◆ get_multisig_signing_public_key() [2/2]

crypto::public_key tools::wallet2::get_multisig_signing_public_key ( const crypto::secret_key skey) const

Definition at line 12906 of file wallet2.cpp.

12907 {
12908  CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
12909  crypto::public_key pkey;
12910  CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(msk, pkey), "Failed to derive public key");
12911  return pkey;
12912 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
POD_CLASS public_key
Definition: crypto.h:76
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
Here is the call graph for this function:

◆ get_multisig_wallet_state()

mms::multisig_wallet_state tools::wallet2::get_multisig_wallet_state ( ) const

Definition at line 13615 of file wallet2.cpp.

13616 {
13618  state.nettype = m_nettype;
13619  state.multisig = multisig(&state.multisig_is_ready);
13620  state.has_multisig_partial_key_images = has_multisig_partial_key_images();
13621  state.multisig_rounds_passed = m_multisig_rounds_passed;
13622  state.num_transfer_details = m_transfers.size();
13623  if (state.multisig)
13624  {
13625  THROW_WALLET_EXCEPTION_IF(!m_original_keys_available, error::wallet_internal_error, "MMS use not possible because own original Electroneum address not available");
13626  state.address = m_original_address;
13627  state.view_secret_key = m_original_view_secret_key;
13628  }
13629  else
13630  {
13631  state.address = m_account.get_keys().m_account_address;
13632  state.view_secret_key = m_account.get_keys().m_view_secret_key;
13633  }
13634  state.mms_file=m_mms_file;
13635  return state;
13636 }
const account_keys & get_keys() const
Definition: account.cpp:264
bool has_multisig_partial_key_images() const
Definition: wallet2.cpp:5647
crypto::secret_key m_view_secret_key
Definition: account.h:45
account_public_address m_account_address
Definition: account.h:43
Definition: blake256.h:37
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
bool multisig(bool *ready=NULL, uint32_t *threshold=NULL, uint32_t *total=NULL) const
Definition: wallet2.cpp:5634

◆ get_num_rct_outputs()

uint64_t tools::wallet2::get_num_rct_outputs ( )

Definition at line 10831 of file wallet2.cpp.

10832 {
10835  m_daemon_rpc_mutex.lock();
10836  req_t.amounts.push_back(0);
10837  req_t.min_count = 0;
10838  req_t.max_count = 0;
10839  req_t.unlocked = true;
10840  req_t.recent_cutoff = 0;
10841  bool r = invoke_http_json_rpc("/json_rpc", "get_output_histogram", req_t, resp_t, rpc_timeout);
10842  m_daemon_rpc_mutex.unlock();
10843  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_num_rct_outputs");
10844  THROW_WALLET_EXCEPTION_IF(resp_t.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
10845  THROW_WALLET_EXCEPTION_IF(resp_t.status != CORE_RPC_STATUS_OK, error::get_histogram_error, resp_t.status);
10846  THROW_WALLET_EXCEPTION_IF(resp_t.histogram.size() != 1, error::get_histogram_error, "Expected exactly one response");
10847  THROW_WALLET_EXCEPTION_IF(resp_t.histogram[0].amount != 0, error::get_histogram_error, "Expected 0 amount");
10848 
10849  return resp_t.histogram[0].total_instances;
10850 }
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
#define CORE_RPC_STATUS_OK
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
bool invoke_http_json_rpc(const boost::string_ref uri, const std::string &method_name, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET", const std::string &req_id="0")
Definition: wallet2.h:1333
Here is the call graph for this function:

◆ get_num_subaddress_accounts()

size_t tools::wallet2::get_num_subaddress_accounts ( ) const
inline

Definition at line 801 of file wallet2.h.

801 { return m_subaddress_labels.size(); } // number of accounts in wallet
Here is the caller graph for this function:

◆ get_num_subaddresses()

size_t tools::wallet2::get_num_subaddresses ( uint32_t  index_major) const
inline

Definition at line 802 of file wallet2.h.

802 { return index_major < m_subaddress_labels.size() ? m_subaddress_labels[index_major].size() : 0; } // number of subaddresses in a particular account
Here is the caller graph for this function:

◆ get_num_transfer_details()

size_t tools::wallet2::get_num_transfer_details ( ) const
inline

Definition at line 1155 of file wallet2.h.

1155 { return m_transfers.size(); }
Here is the caller graph for this function:

◆ get_payments() [1/2]

void tools::wallet2::get_payments ( const crypto::hash payment_id,
std::list< wallet2::payment_details > &  payments,
uint64_t  min_height = 0,
const boost::optional< uint32_t > &  subaddr_account = boost::none,
const std::set< uint32_t > &  subaddr_indices = {} 
) const

Definition at line 6320 of file wallet2.cpp.

6321 {
6322  auto range = m_payments.equal_range(payment_id);
6323  std::for_each(range.first, range.second, [&payments, &min_height, &subaddr_account, &subaddr_indices](const payment_container::value_type& x) {
6324  if (min_height < x.second.m_block_height &&
6325  (!subaddr_account || *subaddr_account == x.second.m_subaddr_index.major) &&
6326  (subaddr_indices.empty() || subaddr_indices.count(x.second.m_subaddr_index.minor) == 1))
6327  {
6328  payments.push_back(x.second);
6329  }
6330  });
6331 }

◆ get_payments() [2/2]

void tools::wallet2::get_payments ( std::list< std::pair< crypto::hash, wallet2::payment_details >> &  payments,
uint64_t  min_height,
uint64_t  max_height = (uint64_t)-1,
const boost::optional< uint32_t > &  subaddr_account = boost::none,
const std::set< uint32_t > &  subaddr_indices = {} 
) const

Definition at line 6333 of file wallet2.cpp.

6334 {
6335  auto range = std::make_pair(m_payments.begin(), m_payments.end());
6336  std::for_each(range.first, range.second, [&payments, &min_height, &max_height, &subaddr_account, &subaddr_indices](const payment_container::value_type& x) {
6337  if (min_height < x.second.m_block_height && max_height >= x.second.m_block_height &&
6338  (!subaddr_account || *subaddr_account == x.second.m_subaddr_index.major) &&
6339  (subaddr_indices.empty() || subaddr_indices.count(x.second.m_subaddr_index.minor) == 1))
6340  {
6341  payments.push_back(x);
6342  }
6343  });
6344 }

◆ get_payments_out()

void tools::wallet2::get_payments_out ( std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &  confirmed_payments,
uint64_t  min_height,
uint64_t  max_height = (uint64_t)-1,
const boost::optional< uint32_t > &  subaddr_account = boost::none,
const std::set< uint32_t > &  subaddr_indices = {} 
) const

Definition at line 6346 of file wallet2.cpp.

6348 {
6349  for (auto i = m_confirmed_txs.begin(); i != m_confirmed_txs.end(); ++i) {
6350  if (i->second.m_block_height <= min_height || i->second.m_block_height > max_height)
6351  continue;
6352  if (subaddr_account && *subaddr_account != i->second.m_subaddr_account)
6353  continue;
6354  if (!subaddr_indices.empty() && std::count_if(i->second.m_subaddr_indices.begin(), i->second.m_subaddr_indices.end(), [&subaddr_indices](uint32_t index) { return subaddr_indices.count(index) == 1; }) == 0)
6355  continue;
6356  if (i->second.m_is_migration) //avoid as processed by separate function
6357  continue;
6358  if(i->second.m_is_sc_migration) //avoid as processed by separate function
6359  continue;
6360  confirmed_payments.push_back(*i);
6361  }
6362 }//----------------------------------------------------------------------------------------------------
unsigned int uint32_t
Definition: stdint.h:126

◆ get_payments_out_migration()

void tools::wallet2::get_payments_out_migration ( std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &  confirmed_payments,
uint64_t  min_height,
uint64_t  max_height = (uint64_t)-1,
const boost::optional< uint32_t > &  subaddr_account = boost::none,
const std::set< uint32_t > &  subaddr_indices = {} 
) const

Definition at line 6363 of file wallet2.cpp.

6365 {
6366  for (auto i = m_confirmed_txs.begin(); i != m_confirmed_txs.end(); ++i) {
6367  if (i->second.m_block_height <= min_height || i->second.m_block_height > max_height)
6368  continue;
6369  if (subaddr_account && *subaddr_account != i->second.m_subaddr_account)
6370  continue;
6371  if (!subaddr_indices.empty() && std::count_if(i->second.m_subaddr_indices.begin(), i->second.m_subaddr_indices.end(), [&subaddr_indices](uint32_t index) { return subaddr_indices.count(index) == 1; }) == 0)
6372  continue;
6373  if (!i->second.m_is_migration)
6374  continue;
6375 
6376  confirmed_payments.push_back(*i);
6377  }
6378 }
unsigned int uint32_t
Definition: stdint.h:126

◆ get_payments_out_sc_migration()

void tools::wallet2::get_payments_out_sc_migration ( std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &  confirmed_payments,
uint64_t  min_height,
uint64_t  max_height = (uint64_t)-1,
const boost::optional< uint32_t > &  subaddr_account = boost::none,
const std::set< uint32_t > &  subaddr_indices = {} 
) const

Definition at line 6380 of file wallet2.cpp.

6381  {
6382 
6383  for (auto i = m_confirmed_txs.begin(); i != m_confirmed_txs.end(); ++i) {
6384  if (i->second.m_block_height <= min_height || i->second.m_block_height > max_height)
6385  continue;
6386  if (subaddr_account && *subaddr_account != i->second.m_subaddr_account)
6387  continue;
6388  if (!subaddr_indices.empty() && std::count_if(i->second.m_subaddr_indices.begin(), i->second.m_subaddr_indices.end(), [&subaddr_indices](uint32_t index) { return subaddr_indices.count(index) == 1; }) == 0)
6389  continue;
6390  if (!i->second.m_is_sc_migration)
6391  continue;
6392  confirmed_payments.push_back(*i);
6393  }
6394 }
unsigned int uint32_t
Definition: stdint.h:126

◆ get_refresh_from_block_height()

uint64_t tools::wallet2::get_refresh_from_block_height ( ) const
inline

Definition at line 743 of file wallet2.h.

743 {return m_refresh_from_block_height;}

◆ get_refresh_type()

RefreshType tools::wallet2::get_refresh_type ( ) const
inline

Definition at line 822 of file wallet2.h.

822 { return m_refresh_type; }

◆ get_reserve_proof()

std::string tools::wallet2::get_reserve_proof ( const boost::optional< std::pair< uint32_t, uint64_t >> &  account_minreserve,
const std::string &  message 
)

Generates a proof that proves the reserve of unspent funds.

Parameters
account_minreserveWhen specified, collect outputs only belonging to the given account and prove the smallest reserve above the given amount When unspecified, proves for all unspent outputs across all accounts
messageArbitrary challenge message to be signed together
Returns
Signature string

Definition at line 11669 of file wallet2.cpp.

11670 {
11671  THROW_WALLET_EXCEPTION_IF(m_watch_only || m_multisig, error::wallet_internal_error, "Reserve proof can only be generated by a full wallet");
11672  THROW_WALLET_EXCEPTION_IF(balance_all(false) == 0, error::wallet_internal_error, "Zero balance");
11673  THROW_WALLET_EXCEPTION_IF(account_minreserve && balance(account_minreserve->first, false) < account_minreserve->second, error::wallet_internal_error,
11674  "Not enough balance in this account for the requested minimum reserve amount");
11675 
11676  // determine which outputs to include in the proof
11677  std::vector<size_t> selected_transfers;
11678  for (size_t i = 0; i < m_transfers.size(); ++i)
11679  {
11680  const transfer_details &td = m_transfers[i];
11681  if (!td.m_spent && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
11682  selected_transfers.push_back(i);
11683  }
11684 
11685  if (account_minreserve)
11686  {
11687  THROW_WALLET_EXCEPTION_IF(account_minreserve->second == 0, error::wallet_internal_error, "Proved amount must be greater than 0");
11688  // minimize the number of outputs included in the proof, by only picking the N largest outputs that can cover the requested min reserve amount
11689  std::sort(selected_transfers.begin(), selected_transfers.end(), [&](const size_t a, const size_t b)
11690  { return m_transfers[a].amount() > m_transfers[b].amount(); });
11691  while (selected_transfers.size() >= 2 && m_transfers[selected_transfers[1]].amount() >= account_minreserve->second)
11692  selected_transfers.erase(selected_transfers.begin());
11693  size_t sz = 0;
11694  uint64_t total = 0;
11695  while (total < account_minreserve->second)
11696  {
11697  total += m_transfers[selected_transfers[sz]].amount();
11698  ++sz;
11699  }
11700  selected_transfers.resize(sz);
11701  }
11702 
11703  // compute signature prefix hash
11704  std::string prefix_data = message;
11705  prefix_data.append((const char*)&m_account.get_keys().m_account_address, sizeof(cryptonote::account_public_address));
11706  for (size_t i = 0; i < selected_transfers.size(); ++i)
11707  {
11708  prefix_data.append((const char*)&m_transfers[selected_transfers[i]].m_key_image, sizeof(crypto::key_image));
11709  }
11710  crypto::hash prefix_hash;
11711  crypto::cn_fast_hash(prefix_data.data(), prefix_data.size(), prefix_hash);
11712 
11713  // generate proof entries
11714  std::vector<reserve_proof_entry> proofs(selected_transfers.size());
11715  std::unordered_set<cryptonote::subaddress_index> subaddr_indices = { {0,0} };
11716  for (size_t i = 0; i < selected_transfers.size(); ++i)
11717  {
11718  transfer_details &td = m_transfers[selected_transfers[i]];
11719  reserve_proof_entry& proof = proofs[i];
11720  proof.txid = td.m_txid;
11721  proof.index_in_tx = td.m_internal_output_index;
11722  proof.key_image = td.m_key_image;
11723  cryptonote::subaddress_index index2 = {td.m_subaddr_index.major + (td.m_subaddr_index.major != 0 ? m_account_major_offset : 0), td.m_subaddr_index.minor};
11724  td.m_subaddr_index = index2;
11725  subaddr_indices.insert(td.m_subaddr_index);
11726 
11727  // get tx pub key
11728  const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index);
11729  THROW_WALLET_EXCEPTION_IF(tx_pub_key == crypto::null_pkey, error::wallet_internal_error, "The tx public key isn't found");
11730  const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
11731 
11732  // determine which tx pub key was used for deriving the output key
11733  const crypto::public_key *tx_pub_key_used = &tx_pub_key;
11734  for (int i = 0; i < 2; ++i)
11735  {
11736  proof.shared_secret = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(*tx_pub_key_used), rct::sk2rct(m_account.get_keys().m_view_secret_key)));
11737  crypto::key_derivation derivation;
11738  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(proof.shared_secret, rct::rct2sk(rct::I), derivation),
11739  error::wallet_internal_error, "Failed to generate key derivation");
11740  crypto::public_key subaddress_spendkey;
11741  THROW_WALLET_EXCEPTION_IF(!derive_subaddress_public_key(td.get_public_key(), derivation, proof.index_in_tx, subaddress_spendkey),
11742  error::wallet_internal_error, "Failed to derive subaddress public key");
11743  if (m_subaddresses.count(subaddress_spendkey) == 1)
11744  break;
11745  THROW_WALLET_EXCEPTION_IF(additional_tx_pub_keys.empty(), error::wallet_internal_error,
11746  "Normal tx pub key doesn't derive the expected output, while the additional tx pub keys are empty");
11747  THROW_WALLET_EXCEPTION_IF(i == 1, error::wallet_internal_error,
11748  "Neither normal tx pub key nor additional tx pub key derive the expected output key");
11749  tx_pub_key_used = &additional_tx_pub_keys[proof.index_in_tx];
11750  }
11751 
11752  // generate signature for shared secret
11753  crypto::generate_tx_proof(prefix_hash, m_account.get_keys().m_account_address.m_view_public_key, *tx_pub_key_used, boost::none, proof.shared_secret, m_account.get_keys().m_view_secret_key, proof.shared_secret_sig);
11754 
11755  // derive ephemeral secret key
11756  crypto::key_image ki;
11757  cryptonote::keypair ephemeral;
11758  const bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, td.get_public_key(), tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, ephemeral, ki, m_account.get_device(), m_account_major_offset);
11759  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
11760  THROW_WALLET_EXCEPTION_IF(ephemeral.pub != td.get_public_key(), error::wallet_internal_error, "Derived public key doesn't agree with the stored one");
11761 
11762  // generate signature for key image
11763  const std::vector<const crypto::public_key*> pubs = { &ephemeral.pub };
11764  crypto::generate_ring_signature(prefix_hash, td.m_key_image, &pubs[0], 1, ephemeral.sec, 0, &proof.key_image_sig);
11765  }
11766 
11767  // collect all subaddress spend keys that received those outputs and generate their signatures
11768  std::unordered_map<crypto::public_key, crypto::signature> subaddr_spendkeys;
11769  for (const cryptonote::subaddress_index &index : subaddr_indices)
11770  {
11771  crypto::secret_key subaddr_spend_skey = m_account.get_keys().m_spend_secret_key;
11772  if (!index.is_zero())
11773  {
11775  crypto::secret_key tmp = subaddr_spend_skey;
11776  sc_add((unsigned char*)&subaddr_spend_skey, (unsigned char*)&m, (unsigned char*)&tmp);
11777  }
11778  crypto::public_key subaddr_spend_pkey;
11779  secret_key_to_public_key(subaddr_spend_skey, subaddr_spend_pkey);
11780  crypto::generate_signature(prefix_hash, subaddr_spend_pkey, subaddr_spend_skey, subaddr_spendkeys[subaddr_spend_pkey]);
11781  }
11782 
11783  // serialize & encode
11784  std::ostringstream oss;
11786  ar << proofs << subaddr_spendkeys;
11787  return "ReserveProofV1" + tools::base58::encode(oss.str());
11788 }
uint64_t balance_all(bool public_blockchain) const
Definition: wallet2.cpp:6292
crypto::public_key pub
crypto::secret_key sec
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
void scalarmultKey(key &aP, const key &P, const key &a)
Definition: rctOps.cpp:368
uint64_t balance(uint32_t subaddr_index_major, bool public_blockchain) const
Definition: wallet2.cpp:6162
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:292
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
std::string encode(const std::string &data)
Definition: base58.cpp:173
const account_keys & get_keys() const
Definition: account.cpp:264
void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional< public_key > &B, const public_key &D, const secret_key &r, signature &sig)
Definition: crypto.h:311
const crypto::public_key null_pkey
Definition: crypto.cpp:72
hw::device & get_device() const
Definition: account.h:91
bool generate_key_image_helper(const account_keys &ack, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result)
Definition: crypto.h:286
void generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const secret_key &sec, std::size_t sec_index, signature *sig)
Definition: crypto.h:327
unsigned __int64 uint64_t
Definition: stdint.h:136
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
std::string message("Message requiring signing")
crypto::secret_key m_view_secret_key
Definition: account.h:45
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
account_public_address m_account_address
Definition: account.h:43
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::secret_key m_spend_secret_key
Definition: account.h:44
virtual crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index)=0
POD_CLASS hash
Definition: hash.h:50
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
Here is the call graph for this function:

◆ get_ring()

bool tools::wallet2::get_ring ( const crypto::key_image key_image,
std::vector< uint64_t > &  outs 
)

Definition at line 8057 of file wallet2.cpp.

8058 {
8059  try { return get_ring(get_ringdb_key(), key_image, outs); }
8060  catch (const std::exception &e) { return false; }
8061 }
POD_CLASS key_image
Definition: crypto.h:102
bool get_ring(const crypto::key_image &key_image, std::vector< uint64_t > &outs)
Definition: wallet2.cpp:8057

◆ get_ring_database()

const std::string tools::wallet2::get_ring_database ( ) const
inline

Definition at line 1341 of file wallet2.h.

1341 { return m_ring_database; }

◆ get_rings()

bool tools::wallet2::get_rings ( const crypto::hash txid,
std::vector< std::pair< crypto::key_image, std::vector< uint64_t >>> &  outs 
)

Definition at line 8034 of file wallet2.cpp.

8035 {
8036  for (auto i: m_confirmed_txs)
8037  {
8038  if (txid == i.first)
8039  {
8040  for (const auto &x: i.second.m_rings)
8041  outs.push_back({x.first, cryptonote::relative_output_offsets_to_absolute(x.second)});
8042  return true;
8043  }
8044  }
8045  for (auto i: m_unconfirmed_txs)
8046  {
8047  if (txid == i.first)
8048  {
8049  for (const auto &x: i.second.m_rings)
8050  outs.push_back({x.first, cryptonote::relative_output_offsets_to_absolute(x.second)});
8051  return true;
8052  }
8053  }
8054  return false;
8055 }
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
Here is the call graph for this function:

◆ get_seed()

bool tools::wallet2::get_seed ( epee::wipeable_string electrum_words,
const epee::wipeable_string passphrase = epee::wipeable_string() 
) const

Definition at line 1301 of file wallet2.cpp.

1302 {
1303  bool keys_deterministic = is_deterministic();
1304  if (!keys_deterministic)
1305  {
1306  std::cout << "This is not a deterministic wallet" << std::endl;
1307  return false;
1308  }
1309  if (seed_language.empty())
1310  {
1311  std::cout << "seed_language not set" << std::endl;
1312  return false;
1313  }
1314 
1316  if (!passphrase.empty())
1317  key = cryptonote::encrypt_key(key, passphrase);
1318  if (!crypto::ElectrumWords::bytes_to_words(key, electrum_words, seed_language))
1319  {
1320  std::cout << "Failed to create seed from key for language: " << seed_language << std::endl;
1321  return false;
1322  }
1323 
1324  return true;
1325 }
const char * key
Definition: hmac_keccak.cpp:39
crypto::secret_key encrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase)
const account_keys & get_keys() const
Definition: account.cpp:264
bool bytes_to_words(const char *src, size_t len, epee::wipeable_string &words, const std::string &language_name)
Converts bytes (secret key) to seed words.
bool empty() const noexcept
bool is_deterministic() const
Checks if deterministic wallet.
Definition: wallet2.cpp:1293
crypto::secret_key m_spend_secret_key
Definition: account.h:44
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:

◆ get_seed_language()

const std::string & tools::wallet2::get_seed_language ( ) const

Gets the seed language.

Definition at line 1417 of file wallet2.cpp.

1418 {
1419  return seed_language;
1420 }

◆ get_spend_proof()

std::string tools::wallet2::get_spend_proof ( const crypto::hash txid,
const std::string &  message 
)

Definition at line 11047 of file wallet2.cpp.

11048 {
11049  THROW_WALLET_EXCEPTION_IF(m_watch_only, error::wallet_internal_error,
11050  "get_spend_proof requires spend secret key and is not available for a watch-only wallet");
11051 
11052  // fetch tx from daemon
11054  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
11055  req.decode_as_json = false;
11056  req.prune = true;
11058  bool r;
11059  {
11060  const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
11061  r = invoke_http_json("/gettransactions", req, res, rpc_timeout);
11062  }
11063  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gettransactions");
11064  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gettransactions");
11065  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "gettransactions");
11066  THROW_WALLET_EXCEPTION_IF(res.txs.size() != 1, error::wallet_internal_error,
11067  "daemon returned wrong response for gettransactions, wrong txs count = " +
11068  std::to_string(res.txs.size()) + ", expected 1");
11069 
11071  crypto::hash tx_hash;
11072  THROW_WALLET_EXCEPTION_IF(!get_pruned_tx(res.txs[0], tx, tx_hash), error::wallet_internal_error, "Failed to get tx from daemon");
11073 
11074  std::vector<std::vector<crypto::signature>> signatures;
11075 
11076  // get signature prefix hash
11077  std::string sig_prefix_data((const char*)&txid, sizeof(crypto::hash));
11078  sig_prefix_data += message;
11079  crypto::hash sig_prefix_hash;
11080  crypto::cn_fast_hash(sig_prefix_data.data(), sig_prefix_data.size(), sig_prefix_hash);
11081 
11082  for(size_t i = 0; i < tx.vin.size(); ++i)
11083  {
11084  const txin_to_key* const in_key = boost::get<txin_to_key>(std::addressof(tx.vin[i]));
11085  if (in_key == nullptr)
11086  continue;
11087 
11088  // check if the key image belongs to us
11089  const auto found = m_key_images.find(in_key->k_image);
11090  if(found == m_key_images.end())
11091  {
11092  THROW_WALLET_EXCEPTION_IF(i > 0, error::wallet_internal_error, "subset of key images belong to us, very weird!");
11093  THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, "This tx wasn't generated by this wallet!");
11094  }
11095 
11096  // derive the real output keypair
11097  const transfer_details& in_td = m_transfers[found->second];
11098  const txout_to_key* const in_tx_out_pkey = boost::get<txout_to_key>(std::addressof(in_td.m_tx.vout[in_td.m_internal_output_index].target));
11099  THROW_WALLET_EXCEPTION_IF(in_tx_out_pkey == nullptr, error::wallet_internal_error, "Output is not txout_to_key");
11100  const crypto::public_key in_tx_pub_key = get_tx_pub_key_from_extra(in_td.m_tx, in_td.m_pk_index);
11101  const std::vector<crypto::public_key> in_additionakl_tx_pub_keys = get_additional_tx_pub_keys_from_extra(in_td.m_tx);
11102  keypair in_ephemeral;
11103  crypto::key_image in_img;
11104  THROW_WALLET_EXCEPTION_IF(!generate_key_image_helper(m_account.get_keys(), m_subaddresses, in_tx_out_pkey->key, in_tx_pub_key, in_additionakl_tx_pub_keys, in_td.m_internal_output_index, in_ephemeral, in_img, m_account.get_device(), m_account_major_offset),
11105  error::wallet_internal_error, "failed to generate key image");
11106  THROW_WALLET_EXCEPTION_IF(in_key->k_image != in_img, error::wallet_internal_error, "key image mismatch");
11107 
11108  // get output pubkeys in the ring
11109  const std::vector<uint64_t> absolute_offsets = cryptonote::relative_output_offsets_to_absolute(in_key->key_offsets);
11110  const size_t ring_size = in_key->key_offsets.size();
11111  THROW_WALLET_EXCEPTION_IF(absolute_offsets.size() != ring_size, error::wallet_internal_error, "absolute offsets size is wrong");
11113  req.outputs.resize(ring_size);
11114  for (size_t j = 0; j < ring_size; ++j)
11115  {
11116  req.outputs[j].amount = in_key->amount;
11117  req.outputs[j].index = absolute_offsets[j];
11118  }
11120  bool r;
11121  {
11122  const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
11123  r = invoke_http_bin("/get_outs.bin", req, res, rpc_timeout);
11124  }
11125  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_outs.bin");
11126  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_outs.bin");
11127  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "get_outs.bin");
11128  THROW_WALLET_EXCEPTION_IF(res.outs.size() != ring_size, error::wallet_internal_error,
11129  "daemon returned wrong response for get_outs.bin, wrong amounts count = " +
11130  std::to_string(res.outs.size()) + ", expected " + std::to_string(ring_size));
11131 
11132  // copy pubkey pointers
11133  std::vector<const crypto::public_key *> p_output_keys;
11134  for (const COMMAND_RPC_GET_OUTPUTS_BIN::outkey &out : res.outs)
11135  p_output_keys.push_back(&out.key);
11136 
11137  // figure out real output index and secret key
11138  size_t sec_index = -1;
11139  for (size_t j = 0; j < ring_size; ++j)
11140  {
11141  if (res.outs[j].key == in_ephemeral.pub)
11142  {
11143  sec_index = j;
11144  break;
11145  }
11146  }
11147  THROW_WALLET_EXCEPTION_IF(sec_index >= ring_size, error::wallet_internal_error, "secret index not found");
11148 
11149  // generate ring sig for this input
11150  signatures.push_back(std::vector<crypto::signature>());
11151  std::vector<crypto::signature>& sigs = signatures.back();
11152  sigs.resize(in_key->key_offsets.size());
11153  crypto::generate_ring_signature(sig_prefix_hash, in_key->k_image, p_output_keys, in_ephemeral.sec, sec_index, sigs.data());
11154  }
11155 
11156  std::string sig_str = "SpendProofV1";
11157  for (const std::vector<crypto::signature>& ring_sig : signatures)
11158  for (const crypto::signature& sig : ring_sig)
11159  sig_str += tools::base58::encode(std::string((const char *)&sig, sizeof(crypto::signature)));
11160  return sig_str;
11161 }
const char * res
Definition: hmac_keccak.cpp:41
crypto::public_key pub
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
crypto::secret_key sec
::std::string string
Definition: gtest-port.h:1097
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
std::vector< uint64_t > key_offsets
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
std::string encode(const std::string &data)
Definition: base58.cpp:173
#define CORE_RPC_STATUS_OK
const account_keys & get_keys() const
Definition: account.cpp:264
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
hw::device & get_device() const
Definition: account.h:91
bool generate_key_image_helper(const account_keys &ack, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
void generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const secret_key &sec, std::size_t sec_index, signature *sig)
Definition: crypto.h:327
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
std::string message("Message requiring signing")
bool invoke_http_bin(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1326
POD_CLASS signature
Definition: crypto.h:108
crypto::public_key key
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::key_image k_image
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
POD_CLASS hash
Definition: hash.h:50
std::string to_string(t_connection_type type)
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
Here is the call graph for this function:

◆ get_subaddress()

cryptonote::account_public_address tools::wallet2::get_subaddress ( const cryptonote::subaddress_index index) const

Definition at line 1430 of file wallet2.cpp.

1431 {
1432  hw::device &hwdev = m_account.get_device();
1433  cryptonote::subaddress_index index2 = {index.major + (index.major != 0 ? m_account_major_offset : 0), index.minor};
1434  return hwdev.get_subaddress(m_account.get_keys(), index2);
1435 }
const account_keys & get_keys() const
Definition: account.cpp:264
hw::device & get_device() const
Definition: account.h:91
virtual cryptonote::account_public_address get_subaddress(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index)=0
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_subaddress_as_str()

std::string tools::wallet2::get_subaddress_as_str ( const cryptonote::subaddress_index index) const

Definition at line 1452 of file wallet2.cpp.

1453 {
1455  return cryptonote::get_account_address_as_str(m_nettype, !index.is_zero(), address);
1456 }
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index &index) const
Definition: wallet2.cpp:1430
const char * address
Definition: multisig.cpp:37
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_subaddress_index()

boost::optional< cryptonote::subaddress_index > tools::wallet2::get_subaddress_index ( const cryptonote::account_public_address address) const

Definition at line 1437 of file wallet2.cpp.

1438 {
1439  auto index = m_subaddresses.find(address.m_spend_public_key);
1440  if (index == m_subaddresses.end())
1441  return boost::none;
1442  return index->second;
1443 }
const char * address
Definition: multisig.cpp:37

◆ get_subaddress_label()

std::string tools::wallet2::get_subaddress_label ( const cryptonote::subaddress_index index) const

Definition at line 1518 of file wallet2.cpp.

1519 {
1520  if (index.major >= m_subaddress_labels.size() || index.minor >= m_subaddress_labels[index.major].size())
1521  {
1522  MERROR("Subaddress label doesn't exist");
1523  return "";
1524  }
1525  return m_subaddress_labels[index.major][index.minor];
1526 }
#define MERROR(x)
Definition: misc_log_ex.h:73

◆ get_subaddress_lookahead()

std::pair<size_t, size_t> tools::wallet2::get_subaddress_lookahead ( ) const
inline

Definition at line 808 of file wallet2.h.

808 { return {m_subaddress_lookahead_major, m_subaddress_lookahead_minor}; }

◆ get_subaddress_spend_public_key()

crypto::public_key tools::wallet2::get_subaddress_spend_public_key ( const cryptonote::subaddress_index index) const

Definition at line 1445 of file wallet2.cpp.

1446 {
1447  hw::device &hwdev = m_account.get_device();
1448  cryptonote::subaddress_index index2 = {index.major + (index.major != 0 ? m_account_major_offset : 0), index.minor};
1449  return hwdev.get_subaddress_spend_public_key(m_account.get_keys(), index2);
1450 }
const account_keys & get_keys() const
Definition: account.cpp:264
hw::device & get_device() const
Definition: account.h:91
virtual crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index)=0
Here is the call graph for this function:

◆ get_subaddress_spend_public_keys()

std::vector<crypto::public_key> tools::wallet2::get_subaddress_spend_public_keys ( uint32_t  account,
uint32_t  begin,
uint32_t  end 
) const

◆ get_transfer_details()

const wallet2::transfer_details & tools::wallet2::get_transfer_details ( size_t  idx) const

Definition at line 10852 of file wallet2.cpp.

10853 {
10854  THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error, "Bad transfer index");
10855  return m_transfers[idx];
10856 }
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
Here is the caller graph for this function:

◆ get_transfers()

void tools::wallet2::get_transfers ( wallet2::transfer_container incoming_transfers) const

Definition at line 6315 of file wallet2.cpp.

6316 {
6317  incoming_transfers = m_transfers;
6318 }
Here is the caller graph for this function:

◆ get_tx_device_aux()

std::string tools::wallet2::get_tx_device_aux ( const crypto::hash txid) const

Definition at line 12005 of file wallet2.cpp.

12006 {
12007  std::unordered_map<crypto::hash, std::string>::const_iterator i = m_tx_device.find(txid);
12008  if (i == m_tx_device.end())
12009  return std::string();
12010  return i->second;
12011 }
::std::string string
Definition: gtest-port.h:1097

◆ get_tx_key()

bool tools::wallet2::get_tx_key ( const crypto::hash txid,
crypto::secret_key tx_key,
std::vector< crypto::secret_key > &  additional_tx_keys 
)

Definition at line 10924 of file wallet2.cpp.

10925 {
10926  bool r = get_tx_key_cached(txid, tx_key, additional_tx_keys);
10927  if (r)
10928  {
10929  return true;
10930  }
10931 
10932  auto & hwdev = get_account().get_device();
10933 
10934  // So far only Cold protocol devices are supported.
10935  if (hwdev.device_protocol() != hw::device::PROTOCOL_COLD)
10936  {
10937  return false;
10938  }
10939 
10940  const auto tx_data_it = m_tx_device.find(txid);
10941  if (tx_data_it == m_tx_device.end())
10942  {
10943  MDEBUG("Aux data not found for txid: " << txid);
10944  return false;
10945  }
10946 
10947  auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev);
10948  CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface");
10949  if (!dev_cold->is_get_tx_key_supported())
10950  {
10951  MDEBUG("get_tx_key not supported by the device");
10952  return false;
10953  }
10954 
10955  hw::device_cold::tx_key_data_t tx_key_data;
10956  dev_cold->load_tx_key_data(tx_key_data, tx_data_it->second);
10957 
10958  // Load missing tx prefix hash
10959  if (tx_key_data.tx_prefix_hash.empty())
10960  {
10963  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
10964  req.decode_as_json = false;
10965  req.prune = true;
10966  m_daemon_rpc_mutex.lock();
10967  bool ok = invoke_http_json("/gettransactions", req, res, rpc_timeout);
10968  m_daemon_rpc_mutex.unlock();
10969  THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1),
10970  error::wallet_internal_error, "Failed to get transaction from daemon");
10971 
10973  crypto::hash tx_hash{};
10974  cryptonote::blobdata tx_data;
10975  crypto::hash tx_prefix_hash{};
10976  ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data);
10977  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
10978  THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(tx_data, tx, tx_hash, tx_prefix_hash),
10979  error::wallet_internal_error, "Failed to validate transaction from daemon");
10980  THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error,
10981  "Failed to get the right transaction from daemon");
10982 
10983  tx_key_data.tx_prefix_hash = std::string(tx_prefix_hash.data, 32);
10984  }
10985 
10986  std::vector<crypto::secret_key> tx_keys;
10987  dev_cold->get_tx_key(tx_keys, tx_key_data, m_account.get_keys().m_view_secret_key);
10988  if (tx_keys.empty())
10989  {
10990  return false;
10991  }
10992 
10993  tx_key = tx_keys[0];
10994  tx_keys.erase(tx_keys.begin());
10995  additional_tx_keys = tx_keys;
10996 
10997  return true;
10998 }
const char * res
Definition: hmac_keccak.cpp:41
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
::std::string string
Definition: gtest-port.h:1097
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys) const
Definition: wallet2.cpp:10911
#define MDEBUG(x)
Definition: misc_log_ex.h:76
const account_keys & get_keys() const
Definition: account.cpp:264
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
hw::device & get_device() const
Definition: account.h:91
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
crypto::secret_key m_view_secret_key
Definition: account.h:45
std::string blobdata
Definition: blobdatatype.h:39
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
Here is the call graph for this function:

◆ get_tx_key_cached()

bool tools::wallet2::get_tx_key_cached ( const crypto::hash txid,
crypto::secret_key tx_key,
std::vector< crypto::secret_key > &  additional_tx_keys 
) const

Definition at line 10911 of file wallet2.cpp.

10912 {
10913  additional_tx_keys.clear();
10914  const std::unordered_map<crypto::hash, crypto::secret_key>::const_iterator i = m_tx_keys.find(txid);
10915  if (i == m_tx_keys.end())
10916  return false;
10917  tx_key = i->second;
10918  const auto j = m_additional_tx_keys.find(txid);
10919  if (j != m_additional_tx_keys.end())
10920  additional_tx_keys = j->second;
10921  return true;
10922 }

◆ get_tx_note()

std::string tools::wallet2::get_tx_note ( const crypto::hash txid) const

Definition at line 11992 of file wallet2.cpp.

11993 {
11994  std::unordered_map<crypto::hash, std::string>::const_iterator i = m_tx_notes.find(txid);
11995  if (i == m_tx_notes.end())
11996  return std::string();
11997  return i->second;
11998 }
::std::string string
Definition: gtest-port.h:1097

◆ get_tx_proof() [1/2]

std::string tools::wallet2::get_tx_proof ( const crypto::hash txid,
const cryptonote::account_public_address address,
bool  is_subaddress,
const std::string &  message 
)

Definition at line 11371 of file wallet2.cpp.

11372 {
11373  // fetch tx pubkey from the daemon
11376  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
11377  req.decode_as_json = false;
11378  req.prune = true;
11379  m_daemon_rpc_mutex.lock();
11380  bool ok = invoke_http_json("/gettransactions", req, res, rpc_timeout);
11381  m_daemon_rpc_mutex.unlock();
11382  THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1),
11383  error::wallet_internal_error, "Failed to get transaction from daemon");
11384 
11386  crypto::hash tx_hash;
11387  if (res.txs.size() == 1)
11388  {
11389  ok = get_pruned_tx(res.txs.front(), tx, tx_hash);
11390  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
11391  }
11392  else
11393  {
11394  cryptonote::blobdata tx_data;
11395  ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data);
11396  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to parse transaction from daemon");
11398  error::wallet_internal_error, "Failed to validate transaction from daemon");
11399  tx_hash = cryptonote::get_transaction_hash(tx);
11400  }
11401 
11402  CHECK_AND_ASSERT_THROW_MES(tx.version == 1, "Tx proofs are for v1 transactions only");
11403  THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error, "Failed to get the right transaction from daemon");
11404 
11405  // determine if the address is found in the subaddress hash table (i.e. whether the proof is outbound or inbound)
11407  std::vector<crypto::secret_key> additional_tx_keys;
11408  const bool is_out = m_subaddresses.count(address.m_spend_public_key) == 0;
11409  if (is_out)
11410  {
11411  THROW_WALLET_EXCEPTION_IF(!get_tx_key(txid, tx_key, additional_tx_keys), error::wallet_internal_error, "Tx secret key wasn't found in the wallet file.");
11412  }
11413 
11414  return get_tx_proof(tx, tx_key, additional_tx_keys, address, is_subaddress, message);
11415 }
const char * res
Definition: hmac_keccak.cpp:41
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
const crypto::secret_key null_skey
Definition: crypto.cpp:73
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys)
Definition: wallet2.cpp:10924
std::string message("Message requiring signing")
std::string blobdata
Definition: blobdatatype.h:39
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
std::string get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message)
Definition: wallet2.cpp:11371
Here is the call graph for this function:

◆ get_tx_proof() [2/2]

std::string tools::wallet2::get_tx_proof ( const cryptonote::transaction tx,
const crypto::secret_key tx_key,
const std::vector< crypto::secret_key > &  additional_tx_keys,
const cryptonote::account_public_address address,
bool  is_subaddress,
const std::string &  message 
) const

Definition at line 11417 of file wallet2.cpp.

11418 {
11419  hw::device &hwdev = m_account.get_device();
11420  rct::key aP;
11421  // determine if the address is found in the subaddress hash table (i.e. whether the proof is outbound or inbound)
11422  const bool is_out = m_subaddresses.count(address.m_spend_public_key) == 0;
11423 
11425  std::string prefix_data((const char*)&txid, sizeof(crypto::hash));
11426  prefix_data += message;
11427  crypto::hash prefix_hash;
11428  crypto::cn_fast_hash(prefix_data.data(), prefix_data.size(), prefix_hash);
11429 
11430  std::vector<crypto::public_key> shared_secret;
11431  std::vector<crypto::signature> sig;
11432  std::string sig_str;
11433  if (is_out)
11434  {
11435  const size_t num_sigs = 1 + additional_tx_keys.size();
11436  shared_secret.resize(num_sigs);
11437  sig.resize(num_sigs);
11438 
11439  hwdev.scalarmultKey(aP, rct::pk2rct(address.m_view_public_key), rct::sk2rct(tx_key));
11440  shared_secret[0] = rct::rct2pk(aP);
11441  crypto::public_key tx_pub_key;
11442  if (is_subaddress)
11443  {
11444  hwdev.scalarmultKey(aP, rct::pk2rct(address.m_spend_public_key), rct::sk2rct(tx_key));
11445  tx_pub_key = rct2pk(aP);
11446  hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[0], tx_key, sig[0]);
11447  }
11448  else
11449  {
11450  hwdev.secret_key_to_public_key(tx_key, tx_pub_key);
11451  hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[0], tx_key, sig[0]);
11452  }
11453  for (size_t i = 1; i < num_sigs; ++i)
11454  {
11455  hwdev.scalarmultKey(aP, rct::pk2rct(address.m_view_public_key), rct::sk2rct(additional_tx_keys[i - 1]));
11456  shared_secret[i] = rct::rct2pk(aP);
11457  if (is_subaddress)
11458  {
11459  hwdev.scalarmultKey(aP, rct::pk2rct(address.m_spend_public_key), rct::sk2rct(additional_tx_keys[i - 1]));
11460  tx_pub_key = rct2pk(aP);
11461  hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, address.m_spend_public_key, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
11462  }
11463  else
11464  {
11465  hwdev.secret_key_to_public_key(additional_tx_keys[i - 1], tx_pub_key);
11466  hwdev.generate_tx_proof(prefix_hash, tx_pub_key, address.m_view_public_key, boost::none, shared_secret[i], additional_tx_keys[i - 1], sig[i]);
11467  }
11468  }
11469  sig_str = std::string("OutProofV1");
11470  }
11471  else
11472  {
11474  THROW_WALLET_EXCEPTION_IF(tx_pub_key == null_pkey, error::wallet_internal_error, "Tx pubkey was not found");
11475 
11476  std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
11477  const size_t num_sigs = 1 + additional_tx_pub_keys.size();
11478  shared_secret.resize(num_sigs);
11479  sig.resize(num_sigs);
11480 
11481  const crypto::secret_key& a = m_account.get_keys().m_view_secret_key;
11482  hwdev.scalarmultKey(aP, rct::pk2rct(tx_pub_key), rct::sk2rct(a));
11483  shared_secret[0] = rct2pk(aP);
11484  if (is_subaddress)
11485  {
11486  hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, address.m_spend_public_key, shared_secret[0], a, sig[0]);
11487  }
11488  else
11489  {
11490  hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, tx_pub_key, boost::none, shared_secret[0], a, sig[0]);
11491  }
11492  for (size_t i = 1; i < num_sigs; ++i)
11493  {
11494  hwdev.scalarmultKey(aP,rct::pk2rct(additional_tx_pub_keys[i - 1]), rct::sk2rct(a));
11495  shared_secret[i] = rct2pk(aP);
11496  if (is_subaddress)
11497  {
11498  hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], address.m_spend_public_key, shared_secret[i], a, sig[i]);
11499  }
11500  else
11501  {
11502  hwdev.generate_tx_proof(prefix_hash, address.m_view_public_key, additional_tx_pub_keys[i - 1], boost::none, shared_secret[i], a, sig[i]);
11503  }
11504  }
11505  sig_str = std::string("InProofV1");
11506  }
11507  const size_t num_sigs = shared_secret.size();
11508 
11509  // check if this address actually received any funds
11510  crypto::key_derivation derivation;
11511  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(shared_secret[0], rct::rct2sk(rct::I), derivation), error::wallet_internal_error, "Failed to generate key derivation");
11512  std::vector<crypto::key_derivation> additional_derivations(num_sigs - 1);
11513  for (size_t i = 1; i < num_sigs; ++i)
11514  THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(shared_secret[i], rct::rct2sk(rct::I), additional_derivations[i - 1]), error::wallet_internal_error, "Failed to generate key derivation");
11515  uint64_t received;
11516  check_tx_key_helper(tx, derivation, additional_derivations, address, received);
11517  THROW_WALLET_EXCEPTION_IF(!received, error::wallet_internal_error, tr("No funds received in this tx."));
11518 
11519  // concatenate all signature strings
11520  for (size_t i = 0; i < num_sigs; ++i)
11521  sig_str +=
11522  tools::base58::encode(std::string((const char *)&shared_secret[i], sizeof(crypto::public_key))) +
11523  tools::base58::encode(std::string((const char *)&sig[i], sizeof(crypto::signature)));
11524  return sig_str;
11525 }
virtual bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub)=0
virtual bool scalarmultKey(rct::key &aP, const rct::key &P, const rct::key &a)=0
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
std::string encode(const std::string &data)
Definition: base58.cpp:173
const account_keys & get_keys() const
Definition: account.cpp:264
const crypto::public_key null_pkey
Definition: crypto.cpp:72
hw::device & get_device() const
Definition: account.h:91
unsigned __int64 uint64_t
Definition: stdint.h:136
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
std::string message("Message requiring signing")
crypto::secret_key m_view_secret_key
Definition: account.h:45
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
POD_CLASS signature
Definition: crypto.h:108
static const char * tr(const char *str)
Definition: wallet2.cpp:994
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
virtual void generate_tx_proof(const crypto::hash &prefix_hash, const crypto::public_key &R, const crypto::public_key &A, const boost::optional< crypto::public_key > &B, const crypto::public_key &D, const crypto::secret_key &r, crypto::signature &sig)=0
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11323
Here is the call graph for this function:

◆ get_tx_pub_key_from_received_outs()

crypto::public_key tools::wallet2::get_tx_pub_key_from_received_outs ( const tools::wallet2::transfer_details td) const

Definition at line 12143 of file wallet2.cpp.

12144 {
12145  std::vector<tx_extra_field> tx_extra_fields;
12146  if(!parse_tx_extra(td.m_tx.extra, tx_extra_fields))
12147  {
12148  // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key
12149  }
12150 
12151  // Due to a previous bug, there might be more than one tx pubkey in extra, one being
12152  // the result of a previously discarded signature.
12153  // For speed, since scanning for outputs is a slow process, we check whether extra
12154  // contains more than one pubkey. If not, the first one is returned. If yes, they're
12155  // checked for whether they yield at least one output
12156  tx_extra_pub_key pub_key_field;
12157  THROW_WALLET_EXCEPTION_IF(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 0), error::wallet_internal_error,
12158  "Public key wasn't found in the transaction extra");
12159  const crypto::public_key tx_pub_key = pub_key_field.pub_key;
12160  bool two_found = find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 1);
12161  if (!two_found) {
12162  // easy case, just one found
12163  return tx_pub_key;
12164  }
12165 
12166  // more than one, loop and search
12167  const cryptonote::account_keys& keys = m_account.get_keys();
12168  size_t pk_index = 0;
12169  hw::device &hwdev = m_account.get_device();
12170 
12171  while (find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) {
12172  const crypto::public_key tx_pub_key = pub_key_field.pub_key;
12173  crypto::key_derivation derivation;
12174  bool r = hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
12175  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
12176 
12177  for (size_t i = 0; i < td.m_tx.vout.size(); ++i)
12178  {
12179  tx_scan_info_t tx_scan_info;
12180  check_acc_out_precomp(td.m_tx.vout[i], derivation, {}, i, tx_scan_info);
12181  if (!tx_scan_info.error && tx_scan_info.received)
12182  return tx_pub_key;
12183  }
12184  }
12185 
12186  // we found no key yielding an output, but it might be in the additional
12187  // tx pub keys only, which we do not need to check, so return the first one
12188  return tx_pub_key;
12189 }
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
crypto::public_key pub_key
Definition: tx_extra.h:101
POD_CLASS key_derivation
Definition: crypto.h:98
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation)=0
std::vector< uint8_t > extra
const account_keys & get_keys() const
Definition: account.cpp:264
hw::device & get_device() const
Definition: account.h:91
cryptonote::transaction_prefix m_tx
Definition: wallet2.h:304
POD_CLASS public_key
Definition: crypto.h:76
crypto::secret_key m_view_secret_key
Definition: account.h:45
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)

◆ get_unconfirmed_payments()

void tools::wallet2::get_unconfirmed_payments ( std::list< std::pair< crypto::hash, wallet2::pool_payment_details >> &  unconfirmed_payments,
const boost::optional< uint32_t > &  subaddr_account = boost::none,
const std::set< uint32_t > &  subaddr_indices = {} 
) const

Definition at line 6408 of file wallet2.cpp.

6409 {
6410  for (auto i = m_unconfirmed_payments.begin(); i != m_unconfirmed_payments.end(); ++i) {
6411  if ((!subaddr_account || *subaddr_account == i->second.m_pd.m_subaddr_index.major) &&
6412  (subaddr_indices.empty() || subaddr_indices.count(i->second.m_pd.m_subaddr_index.minor) == 1))
6413  unconfirmed_payments.push_back(*i);
6414  }
6415 }

◆ get_unconfirmed_payments_out()

void tools::wallet2::get_unconfirmed_payments_out ( std::list< std::pair< crypto::hash, wallet2::unconfirmed_transfer_details >> &  unconfirmed_payments,
const boost::optional< uint32_t > &  subaddr_account = boost::none,
const std::set< uint32_t > &  subaddr_indices = {} 
) const

Definition at line 6396 of file wallet2.cpp.

6397 {
6398  for (auto i = m_unconfirmed_txs.begin(); i != m_unconfirmed_txs.end(); ++i) {
6399  if (subaddr_account && *subaddr_account != i->second.m_subaddr_account)
6400  continue;
6401  if (!subaddr_indices.empty() && std::count_if(i->second.m_subaddr_indices.begin(), i->second.m_subaddr_indices.end(), [&subaddr_indices](uint32_t index) { return subaddr_indices.count(index) == 1; }) == 0)
6402  continue;
6403  unconfirmed_payments.push_back(*i);
6404  }
6405 }
unsigned int uint32_t
Definition: stdint.h:126

◆ get_wallet_file()

std::string tools::wallet2::get_wallet_file ( ) const

Definition at line 11916 of file wallet2.cpp.

11917 {
11918  return m_wallet_file;
11919 }

◆ has_multisig_partial_key_images()

bool tools::wallet2::has_multisig_partial_key_images ( ) const

Definition at line 5647 of file wallet2.cpp.

5648 {
5649  if (!m_multisig)
5650  return false;
5651  for (const auto &td: m_transfers)
5652  if (td.m_key_image_partial && td.m_tx.version == 1)
5653  return true;
5654  return false;
5655 }

◆ has_stagenet_option()

bool tools::wallet2::has_stagenet_option ( const boost::program_options::variables_map &  vm)
static

Definition at line 1178 of file wallet2.cpp.

1179 {
1180  return command_line::get_arg(vm, options().stagenet);
1181 }
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:271
Here is the call graph for this function:
Here is the caller graph for this function:

◆ has_testnet_option()

bool tools::wallet2::has_testnet_option ( const boost::program_options::variables_map &  vm)
static

Definition at line 1173 of file wallet2.cpp.

1174 {
1175  return command_line::get_arg(vm, options().testnet);
1176 }
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
Definition: command_line.h:271
Here is the call graph for this function:
Here is the caller graph for this function:

◆ has_unknown_key_images()

bool tools::wallet2::has_unknown_key_images ( ) const

Definition at line 5657 of file wallet2.cpp.

5658 {
5659  for (const auto &td: m_transfers)
5660  if (!td.m_key_image_known && td.m_tx.version == 1)
5661  return true;
5662  return false;
5663 }

◆ hash_m_transfer()

void tools::wallet2::hash_m_transfer ( const transfer_details transfer,
crypto::hash hash 
) const

Definition at line 13699 of file wallet2.cpp.

13700 {
13701  KECCAK_CTX state;
13702  keccak_init(&state);
13703  keccak_update(&state, (const uint8_t *) transfer.m_txid.data, sizeof(transfer.m_txid.data));
13704  keccak_update(&state, (const uint8_t *) transfer.m_internal_output_index, sizeof(transfer.m_internal_output_index));
13705  keccak_update(&state, (const uint8_t *) transfer.m_global_output_index, sizeof(transfer.m_global_output_index));
13706  keccak_update(&state, (const uint8_t *) transfer.m_amount, sizeof(transfer.m_amount));
13707  keccak_finish(&state, (uint8_t *) hash.data);
13708 }
void keccak_finish(KECCAK_CTX *ctx, uint8_t *md)
unsigned char uint8_t
Definition: stdint.h:124
void keccak_init(KECCAK_CTX *ctx)
Definition: blake256.h:37
void keccak_update(KECCAK_CTX *ctx, const uint8_t *in, size_t inlen)
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ hash_m_transfers()

uint64_t tools::wallet2::hash_m_transfers ( int64_t  transfer_height,
crypto::hash hash 
) const

Definition at line 13710 of file wallet2.cpp.

13711 {
13712  CHECK_AND_ASSERT_THROW_MES(transfer_height > (int64_t)m_transfers.size(), "Hash height is greater than number of transfers");
13713 
13714  KECCAK_CTX state;
13715  crypto::hash tmp_hash{};
13716  uint64_t current_height = 0;
13717 
13718  keccak_init(&state);
13719  for(const transfer_details & transfer : m_transfers){
13720  if (transfer_height >= 0 && current_height >= (uint64_t)transfer_height){
13721  break;
13722  }
13723 
13724  hash_m_transfer(transfer, tmp_hash);
13725  keccak_update(&state, (const uint8_t *) transfer.m_block_height, sizeof(transfer.m_block_height));
13726  keccak_update(&state, (const uint8_t *) tmp_hash.data, sizeof(tmp_hash.data));
13727  current_height += 1;
13728  }
13729 
13730  keccak_finish(&state, (uint8_t *) hash.data);
13731  return current_height;
13732 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
void keccak_finish(KECCAK_CTX *ctx, uint8_t *md)
unsigned char uint8_t
Definition: stdint.h:124
unsigned __int64 uint64_t
Definition: stdint.h:136
void keccak_init(KECCAK_CTX *ctx)
Definition: blake256.h:37
signed __int64 int64_t
Definition: stdint.h:135
void keccak_update(KECCAK_CTX *ctx, const uint8_t *in, size_t inlen)
void hash_m_transfer(const transfer_details &transfer, crypto::hash &hash) const
Definition: wallet2.cpp:13699
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ ignore_fractional_outputs() [1/2]

bool tools::wallet2::ignore_fractional_outputs ( ) const
inline

Definition at line 1101 of file wallet2.h.

1101 { return m_ignore_fractional_outputs; }

◆ ignore_fractional_outputs() [2/2]

void tools::wallet2::ignore_fractional_outputs ( bool  value)
inline

Definition at line 1102 of file wallet2.h.

1102 { m_ignore_fractional_outputs = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ import_blockchain()

void tools::wallet2::import_blockchain ( const std::tuple< size_t, crypto::hash, std::vector< crypto::hash >> &  bc)

Definition at line 12703 of file wallet2.cpp.

12704 {
12705  m_blockchain.clear();
12706  if (std::get<0>(bc))
12707  {
12708  for (size_t n = std::get<0>(bc); n > 0; --n)
12709  m_blockchain.push_back(std::get<1>(bc));
12710  m_blockchain.trim(std::get<0>(bc));
12711  }
12712  for (auto const &b : std::get<2>(bc))
12713  {
12714  m_blockchain.push_back(b);
12715  }
12716  cryptonote::block genesis;
12717  generate_genesis(genesis);
12718  crypto::hash genesis_hash = get_block_hash(genesis);
12719  check_genesis(genesis_hash);
12720  m_last_block_reward = cryptonote::get_outs_etn_amount(genesis.miner_tx);
12721 }
void trim(size_t height)
Definition: wallet2.h:191
uint64_t get_outs_etn_amount(const transaction &tx)
void clear()
Definition: wallet2.h:189
crypto::hash get_block_hash(uint64_t height)
POD_CLASS hash
Definition: hash.h:50
void push_back(const crypto::hash &hash)
Definition: wallet2.h:184
Here is the caller graph for this function:

◆ import_key_images() [1/4]

uint64_t tools::wallet2::import_key_images ( const std::vector< std::pair< crypto::key_image, crypto::signature >> &  signed_key_images,
size_t  offset,
uint64_t spent,
uint64_t unspent,
bool  check_spent = true 
)

Definition at line 12333 of file wallet2.cpp.

12334 {
12335  PERF_TIMER(import_key_images_lots);
12337  COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
12338 
12339  THROW_WALLET_EXCEPTION_IF(offset > m_transfers.size(), error::wallet_internal_error, "Offset larger than known outputs");
12340  THROW_WALLET_EXCEPTION_IF(signed_key_images.size() > m_transfers.size() - offset, error::wallet_internal_error,
12341  "The blockchain is out of date compared to the signed key images");
12342 
12343  if (signed_key_images.empty() && offset == 0)
12344  {
12345  spent = 0;
12346  unspent = 0;
12347  return 0;
12348  }
12349 
12350  req.key_images.reserve(signed_key_images.size());
12351 
12352  PERF_TIMER_START(import_key_images_A);
12353  for (size_t n = 0; n < signed_key_images.size(); ++n)
12354  {
12355  const transfer_details &td = m_transfers[n + offset];
12356  const crypto::key_image &key_image = signed_key_images[n].first;
12357  const crypto::signature &signature = signed_key_images[n].second;
12358 
12359  // get ephemeral public key
12360  const cryptonote::tx_out &out = td.m_tx.vout[td.m_internal_output_index];
12361  THROW_WALLET_EXCEPTION_IF(out.target.type() != typeid(txout_to_key), error::wallet_internal_error,
12362  "Non txout_to_key output found");
12363  const cryptonote::txout_to_key &o = boost::get<cryptonote::txout_to_key>(out.target);
12364  const crypto::public_key pkey = o.key;
12365 
12366  if (!td.m_key_image_known || !(key_image == td.m_key_image))
12367  {
12368  std::vector<const crypto::public_key*> pkeys;
12369  pkeys.push_back(&pkey);
12371  error::wallet_internal_error, "Key image out of validity domain: input " + boost::lexical_cast<std::string>(n + offset) + "/"
12372  + boost::lexical_cast<std::string>(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image));
12373 
12375  error::signature_check_failed, boost::lexical_cast<std::string>(n + offset) + "/"
12376  + boost::lexical_cast<std::string>(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image)
12377  + ", signature " + epee::string_tools::pod_to_hex(signature) + ", pubkey " + epee::string_tools::pod_to_hex(*pkeys[0]));
12378  }
12379  req.key_images.push_back(epee::string_tools::pod_to_hex(key_image));
12380  }
12381  PERF_TIMER_STOP(import_key_images_A);
12382 
12383  PERF_TIMER_START(import_key_images_B);
12384  for (size_t n = 0; n < signed_key_images.size(); ++n)
12385  {
12386  m_transfers[n + offset].m_key_image = signed_key_images[n].first;
12387  m_key_images[m_transfers[n + offset].m_key_image] = n + offset;
12388  m_transfers[n + offset].m_key_image_known = true;
12389  m_transfers[n + offset].m_key_image_request = false;
12390  m_transfers[n + offset].m_key_image_partial = false;
12391  }
12392  PERF_TIMER_STOP(import_key_images_B);
12393 
12394  if(check_spent)
12395  {
12396  PERF_TIMER(import_key_images_RPC);
12397  m_daemon_rpc_mutex.lock();
12398  bool r = invoke_http_json("/is_key_image_spent", req, daemon_resp, rpc_timeout);
12399  m_daemon_rpc_mutex.unlock();
12400  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
12401  THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
12402  THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::is_key_image_spent_error, daemon_resp.status);
12403  THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != signed_key_images.size(), error::wallet_internal_error,
12404  "daemon returned wrong response for is_key_image_spent, wrong amounts count = " +
12405  std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(signed_key_images.size()));
12406  for (size_t n = 0; n < daemon_resp.spent_status.size(); ++n)
12407  {
12408  transfer_details &td = m_transfers[n + offset];
12409  td.m_spent = daemon_resp.spent_status[n] != SPENT_STATUS::UNSPENT;
12410  }
12411  }
12412  spent = 0;
12413  unspent = 0;
12414  std::unordered_set<crypto::hash> spent_txids; // For each spent key image, search for a tx in m_transfers that uses it as input.
12415  std::vector<size_t> swept_transfers; // If such a spending tx wasn't found in m_transfers, this means the spending tx
12416  // was created by sweep_all, so we can't know the spent height and other detailed info.
12417  std::unordered_map<crypto::key_image, crypto::hash> spent_key_images;
12418 
12419  PERF_TIMER_START(import_key_images_C);
12420  for (const transfer_details &td: m_transfers)
12421  {
12422  for (const cryptonote::txin_v& in : td.m_tx.vin)
12423  {
12424  if (in.type() == typeid(cryptonote::txin_to_key))
12425  spent_key_images.insert(std::make_pair(boost::get<cryptonote::txin_to_key>(in).k_image, td.m_txid));
12426  }
12427  }
12428  PERF_TIMER_STOP(import_key_images_C);
12429 
12430  // accumulate outputs before the updated data
12431  for(size_t i = 0; i < offset; ++i)
12432  {
12433  const transfer_details &td = m_transfers[i];
12434  if (td.m_frozen)
12435  continue;
12436  uint64_t amount = td.amount();
12437  if (td.m_spent)
12438  spent += amount;
12439  else
12440  unspent += amount;
12441  }
12442 
12443  PERF_TIMER_START(import_key_images_D);
12444  for(size_t i = 0; i < signed_key_images.size(); ++i)
12445  {
12446  const transfer_details &td = m_transfers[i + offset];
12447  if (td.m_frozen)
12448  continue;
12449  uint64_t amount = td.amount();
12450  if (td.m_spent)
12451  spent += amount;
12452  else
12453  unspent += amount;
12454  LOG_PRINT_L2("Transfer " << i << ": " << print_etn(amount) << " (" << td.m_global_output_index << "): "
12455  << (td.m_spent ? "spent" : "unspent") << " (key image " << req.key_images[i] << ")");
12456 
12457  if (i < daemon_resp.spent_status.size() && daemon_resp.spent_status[i] == SPENT_STATUS::SPENT_IN_BLOCKCHAIN)
12458  {
12459  const std::unordered_map<crypto::key_image, crypto::hash>::const_iterator skii = spent_key_images.find(td.m_key_image);
12460  if (skii == spent_key_images.end())
12461  swept_transfers.push_back(i);
12462  else
12463  spent_txids.insert(skii->second);
12464  }
12465  }
12466  PERF_TIMER_STOP(import_key_images_D);
12467 
12468  MDEBUG("Total: " << print_etn(spent) << " spent, " << print_etn(unspent) << " unspent");
12469 
12470  if (check_spent)
12471  {
12472  // query outgoing txes
12475  gettxs_req.decode_as_json = false;
12476  gettxs_req.prune = true;
12477  gettxs_req.txs_hashes.reserve(spent_txids.size());
12478  for (const crypto::hash& spent_txid : spent_txids)
12479  gettxs_req.txs_hashes.push_back(epee::string_tools::pod_to_hex(spent_txid));
12480 
12481 
12482  PERF_TIMER_START(import_key_images_E);
12483  m_daemon_rpc_mutex.lock();
12484  bool r = invoke_http_json("/gettransactions", gettxs_req, gettxs_res, rpc_timeout);
12485  m_daemon_rpc_mutex.unlock();
12486  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gettransactions");
12487  THROW_WALLET_EXCEPTION_IF(gettxs_res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gettransactions");
12488  THROW_WALLET_EXCEPTION_IF(gettxs_res.txs.size() != spent_txids.size(), error::wallet_internal_error,
12489  "daemon returned wrong response for gettransactions, wrong count = " + std::to_string(gettxs_res.txs.size()) + ", expected " + std::to_string(spent_txids.size()));
12490  PERF_TIMER_STOP(import_key_images_E);
12491 
12492  // process each outgoing tx
12493  PERF_TIMER_START(import_key_images_F);
12494  auto spent_txid = spent_txids.begin();
12495  hw::device &hwdev = m_account.get_device();
12496  auto it = spent_txids.begin();
12497  for (const COMMAND_RPC_GET_TRANSACTIONS::entry& e : gettxs_res.txs)
12498  {
12499  THROW_WALLET_EXCEPTION_IF(e.in_pool, error::wallet_internal_error, "spent tx isn't supposed to be in txpool");
12500 
12501  cryptonote::transaction spent_tx;
12502  crypto::hash spnet_txid_parsed;
12503  THROW_WALLET_EXCEPTION_IF(!get_pruned_tx(e, spent_tx, spnet_txid_parsed), error::wallet_internal_error, "Failed to get tx from daemon");
12504  THROW_WALLET_EXCEPTION_IF(!(spnet_txid_parsed == *it), error::wallet_internal_error, "parsed txid mismatch");
12505  ++it;
12506 
12507  // get received (change) amount
12508  uint64_t tx_etn_got_in_outs = 0;
12509  const cryptonote::account_keys& keys = m_account.get_keys();
12510  const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(spent_tx);
12511  crypto::key_derivation derivation;
12512  bool r = hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
12513  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
12514  const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(spent_tx);
12515  std::vector<crypto::key_derivation> additional_derivations;
12516  for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
12517  {
12518  additional_derivations.push_back({});
12519  r = hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
12520  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
12521  }
12522  size_t output_index = 0;
12523  bool miner_tx = cryptonote::is_coinbase(spent_tx);
12524  for (const cryptonote::tx_out& out : spent_tx.vout)
12525  {
12526  tx_scan_info_t tx_scan_info;
12527  check_acc_out_precomp(out, derivation, additional_derivations, output_index, tx_scan_info);
12528  THROW_WALLET_EXCEPTION_IF(tx_scan_info.error, error::wallet_internal_error, "check_acc_out_precomp failed");
12529  if (tx_scan_info.received)
12530  {
12531  if (tx_scan_info.etn_transfered == 0 && !miner_tx)
12532  {
12533  rct::key mask;
12534  tx_scan_info.etn_transfered = tools::decodeRct(spent_tx.rct_signatures, tx_scan_info.received->derivation, output_index, mask, hwdev);
12535  }
12536  THROW_WALLET_EXCEPTION_IF(tx_etn_got_in_outs >= std::numeric_limits<uint64_t>::max() - tx_scan_info.etn_transfered,
12537  error::wallet_internal_error, "Overflow in received amounts");
12538  tx_etn_got_in_outs += tx_scan_info.etn_transfered;
12539  }
12540  ++output_index;
12541  }
12542 
12543  // get spent amount
12544  uint64_t tx_etn_spent_in_ins = 0;
12545  uint32_t subaddr_account = (uint32_t)-1;
12546  std::set<uint32_t> subaddr_indices;
12547  for (const cryptonote::txin_v& in : spent_tx.vin)
12548  {
12549  if (in.type() != typeid(cryptonote::txin_to_key))
12550  continue;
12551  auto it = m_key_images.find(boost::get<cryptonote::txin_to_key>(in).k_image);
12552  if (it != m_key_images.end())
12553  {
12554  THROW_WALLET_EXCEPTION_IF(it->second >= m_transfers.size(), error::wallet_internal_error, std::string("Key images cache contains illegal transfer offset: ") + std::to_string(it->second) + std::string(" m_transfers.size() = ") + std::to_string(m_transfers.size()));
12555  const transfer_details& td = m_transfers[it->second];
12556  uint64_t amount = boost::get<cryptonote::txin_to_key>(in).amount;
12557  if (amount > 0)
12558  {
12559  THROW_WALLET_EXCEPTION_IF(amount != td.amount(), error::wallet_internal_error,
12560  std::string("Inconsistent amount in tx input: got ") + print_etn(amount) +
12561  std::string(", expected ") + print_etn(td.amount()));
12562  }
12563  amount = td.amount();
12564  tx_etn_spent_in_ins += amount;
12565 
12566  LOG_PRINT_L0("Spent ETN: " << print_etn(amount) << ", with tx: " << *spent_txid);
12567  set_spent(it->second, e.block_height);
12568  if (m_callback)
12569  m_callback->on_etn_spent(e.block_height, *spent_txid, spent_tx, amount, spent_tx, td.m_subaddr_index);
12570  if (subaddr_account != (uint32_t)-1 && subaddr_account != td.m_subaddr_index.major)
12571  LOG_PRINT_L0("WARNING: This tx spends outputs received by different subaddress accounts, which isn't supposed to happen");
12572  subaddr_account = td.m_subaddr_index.major;
12573  subaddr_indices.insert(td.m_subaddr_index.minor);
12574  }
12575  }
12576 
12577  // create outgoing payment
12578  process_outgoing(*spent_txid, spent_tx, e.block_height, e.block_timestamp, tx_etn_spent_in_ins, tx_etn_got_in_outs, subaddr_account, subaddr_indices);
12579 
12580  // erase corresponding incoming payment
12581  for (auto j = m_payments.begin(); j != m_payments.end(); ++j)
12582  {
12583  if (j->second.m_tx_hash == *spent_txid)
12584  {
12585  m_payments.erase(j);
12586  break;
12587  }
12588  }
12589 
12590  ++spent_txid;
12591  }
12592  PERF_TIMER_STOP(import_key_images_F);
12593 
12594  PERF_TIMER_START(import_key_images_G);
12595  for (size_t n : swept_transfers)
12596  {
12597  const transfer_details& td = m_transfers[n];
12598  confirmed_transfer_details pd;
12599  pd.m_change = (uint64_t)-1; // change is unknown
12600  pd.m_amount_in = pd.m_amount_out = td.amount(); // fee is unknown
12601  pd.m_block_height = 0; // spent block height is unknown
12602  pd.m_is_migration = td.m_tx.version == 2;
12603  if(td.m_tx.version == 3){
12604  cryptonote::account_public_address dest_address = boost::get<cryptonote::txout_to_key_public>(td.m_tx.vout[0].target).address;
12605  bool is_portal_address;
12606  if(m_nettype == MAINNET){
12607  is_portal_address = epee::string_tools::pod_to_hex(dest_address.m_spend_public_key) == "8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137" && epee::string_tools::pod_to_hex(dest_address.m_view_public_key) == "2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375";
12608  }else{
12609  is_portal_address = epee::string_tools::pod_to_hex(dest_address.m_spend_public_key) == "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3" && epee::string_tools::pod_to_hex(dest_address.m_view_public_key) == "5866666666666666666666666666666666666666666666666666666666666666";
12610  }
12611  pd.m_is_sc_migration = is_portal_address;
12612  }
12613  const crypto::hash &spent_txid = crypto::null_hash; // spent txid is unknown
12614  m_confirmed_txs.insert(std::make_pair(spent_txid, pd));
12615  }
12616  PERF_TIMER_STOP(import_key_images_G);
12617  }
12618 
12619  // this can be 0 if we do not know the height
12620  return m_transfers[signed_key_images.size() + offset - 1].m_block_height;
12621 }
bool is_coinbase(const transaction &tx)
key curveOrder()
Definition: rctOps.h:76
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
#define PERF_TIMER(name)
Definition: perf_timer.h:82
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
std::string print_etn(uint64_t amount, unsigned int decimal_point)
void scalarmultKey(key &aP, const key &P, const key &a)
Definition: rctOps.cpp:368
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
bool check_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const signature *sig)
Definition: crypto.h:333
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
#define PERF_TIMER_START(name)
Definition: perf_timer.h:85
virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation)=0
#define CORE_RPC_STATUS_OK
#define MDEBUG(x)
Definition: misc_log_ex.h:76
const account_keys & get_keys() const
Definition: account.cpp:264
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
unsigned int uint32_t
Definition: stdint.h:126
hw::device & get_device() const
Definition: account.h:91
unsigned __int64 uint64_t
Definition: stdint.h:136
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
POD_CLASS public_key
Definition: crypto.h:76
crypto::secret_key m_view_secret_key
Definition: account.h:45
POD_CLASS signature
Definition: crypto.h:108
key identity()
Definition: rctOps.h:73
crypto::public_key key
POD_CLASS key_image
Definition: crypto.h:102
#define PERF_TIMER_STOP(name)
Definition: perf_timer.h:86
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
std::string to_string(t_connection_type type)
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
virtual void on_etn_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)
Definition: wallet2.h:130
Here is the call graph for this function:
Here is the caller graph for this function:

◆ import_key_images() [2/4]

uint64_t tools::wallet2::import_key_images ( const std::string &  filename,
uint64_t spent,
uint64_t unspent 
)

Definition at line 12278 of file wallet2.cpp.

12279 {
12280  PERF_TIMER(import_key_images_fsu);
12281  std::string data;
12282  bool r = epee::file_io_utils::load_file_to_string(filename, data);
12283 
12284  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename);
12285 
12286  const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
12287  if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
12288  {
12289  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic in ") + filename);
12290  }
12291 
12292  try
12293  {
12294  PERF_TIMER(import_key_images_decrypt);
12295  data = decrypt_with_view_secret_key(std::string(data, magiclen));
12296  }
12297  catch (const std::exception &e)
12298  {
12299  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what());
12300  }
12301 
12302  const size_t headerlen = 4 + 2 * sizeof(crypto::public_key);
12303  THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ") + filename);
12304  const uint32_t offset = (uint8_t)data[0] | (((uint8_t)data[1]) << 8) | (((uint8_t)data[2]) << 16) | (((uint8_t)data[3]) << 24);
12305  const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[4];
12306  const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[4 + sizeof(crypto::public_key)];
12308  if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key)
12309  {
12310  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " are for a different account");
12311  }
12312  THROW_WALLET_EXCEPTION_IF(offset > m_transfers.size(), error::wallet_internal_error, "Offset larger than known outputs");
12313 
12314  const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
12315  THROW_WALLET_EXCEPTION_IF((data.size() - headerlen) % record_size,
12316  error::wallet_internal_error, std::string("Bad data size from file ") + filename);
12317  size_t nki = (data.size() - headerlen) / record_size;
12318 
12319  std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
12320  ski.reserve(nki);
12321  for (size_t n = 0; n < nki; ++n)
12322  {
12323  crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(&data[headerlen + n * record_size]);
12324  crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data[headerlen + n * record_size + sizeof(crypto::key_image)]);
12325 
12326  ski.push_back(std::make_pair(key_image, signature));
12327  }
12328 
12329  return import_key_images(ski, offset, spent, unspent);
12330 }
#define KEY_IMAGE_EXPORT_FILE_MAGIC
Definition: wallet2.cpp:123
#define PERF_TIMER(name)
Definition: perf_timer.h:82
::std::string string
Definition: gtest-port.h:1097
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
unsigned char uint8_t
Definition: stdint.h:124
uint64_t import_key_images(const std::vector< std::pair< crypto::key_image, crypto::signature >> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent=true)
Definition: wallet2.cpp:12333
const account_keys & get_keys() const
Definition: account.cpp:264
unsigned int uint32_t
Definition: stdint.h:126
std::string decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated=true) const
Definition: wallet2.cpp:13250
POD_CLASS public_key
Definition: crypto.h:76
account_public_address m_account_address
Definition: account.h:43
POD_CLASS signature
Definition: crypto.h:108
POD_CLASS key_image
Definition: crypto.h:102
static const char * tr(const char *str)
Definition: wallet2.cpp:994
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
#define THROW_WALLET_EXCEPTION(err_type,...)
Here is the call graph for this function:

◆ import_key_images() [3/4]

bool tools::wallet2::import_key_images ( std::vector< crypto::key_image key_images,
size_t  offset = 0,
boost::optional< std::unordered_set< size_t >>  selected_transfers = boost::none 
)

◆ import_key_images() [4/4]

bool tools::wallet2::import_key_images ( signed_tx_set signed_tx,
size_t  offset = 0,
bool  only_selected_transfers = false 
)

Definition at line 12650 of file wallet2.cpp.

12651 {
12652  std::unordered_set<size_t> selected_transfers;
12653  if (only_selected_transfers)
12654  {
12655  for (const pending_tx & ptx : signed_tx.ptx)
12656  {
12657  for (const size_t s: ptx.selected_transfers)
12658  selected_transfers.insert(s);
12659  }
12660  }
12661 
12662  return import_key_images(signed_tx.key_images, offset, only_selected_transfers ? boost::make_optional(selected_transfers) : boost::none);
12663 }
uint64_t import_key_images(const std::vector< std::pair< crypto::key_image, crypto::signature >> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent=true)
Definition: wallet2.cpp:12333

◆ import_multisig()

size_t tools::wallet2::import_multisig ( std::vector< cryptonote::blobdata info)

Import a set of multisig info from multisig partners

Returns
the number of inputs which were imported

Definition at line 13067 of file wallet2.cpp.

13068 {
13069  CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
13070 
13071  std::vector<std::vector<tools::wallet2::multisig_info>> info;
13072  std::unordered_set<crypto::public_key> seen;
13073  for (cryptonote::blobdata &data: blobs)
13074  {
13075  const size_t magiclen = strlen(MULTISIG_EXPORT_FILE_MAGIC);
13076  THROW_WALLET_EXCEPTION_IF(data.size() < magiclen || memcmp(data.data(), MULTISIG_EXPORT_FILE_MAGIC, magiclen),
13077  error::wallet_internal_error, "Bad multisig info file magic in ");
13078 
13079  data = decrypt_with_view_secret_key(std::string(data, magiclen));
13080 
13081  const size_t headerlen = 3 * sizeof(crypto::public_key);
13082  THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, "Bad data size");
13083 
13084  const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[0];
13085  const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[sizeof(crypto::public_key)];
13086  const crypto::public_key &signer = *(const crypto::public_key*)&data[2*sizeof(crypto::public_key)];
13088  THROW_WALLET_EXCEPTION_IF(public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key,
13089  error::wallet_internal_error, "Multisig info is for a different account");
13090  if (get_multisig_signer_public_key() == signer)
13091  {
13092  MINFO("Multisig info from this wallet ignored");
13093  continue;
13094  }
13095  if (seen.find(signer) != seen.end())
13096  {
13097  MINFO("Duplicate multisig info ignored");
13098  continue;
13099  }
13100  seen.insert(signer);
13101 
13102  std::string body(data, headerlen);
13103  std::istringstream iss(body);
13104  std::vector<tools::wallet2::multisig_info> i;
13106  ar >> i;
13107  MINFO(boost::format("%u outputs found") % boost::lexical_cast<std::string>(i.size()));
13108  info.push_back(std::move(i));
13109  }
13110 
13111  CHECK_AND_ASSERT_THROW_MES(info.size() + 1 <= m_multisig_signers.size() && info.size() + 1 >= m_multisig_threshold, "Wrong number of multisig sources");
13112 
13113  std::vector<std::vector<rct::key>> k;
13114  k.reserve(m_transfers.size());
13115  for (const auto &td: m_transfers)
13116  k.push_back(td.m_multisig_k);
13117 
13118  // how many outputs we're going to update
13119  size_t n_outputs = m_transfers.size();
13120  for (const auto &pi: info)
13121  if (pi.size() < n_outputs)
13122  n_outputs = pi.size();
13123 
13124  if (n_outputs == 0)
13125  return 0;
13126 
13127  // check signers are consistent
13128  for (const auto &pi: info)
13129  {
13130  CHECK_AND_ASSERT_THROW_MES(std::find(m_multisig_signers.begin(), m_multisig_signers.end(), pi[0].m_signer) != m_multisig_signers.end(),
13131  "Signer is not a member of this multisig wallet");
13132  for (size_t n = 1; n < n_outputs; ++n)
13133  CHECK_AND_ASSERT_THROW_MES(pi[n].m_signer == pi[0].m_signer, "Mismatched signers in imported multisig info");
13134  }
13135 
13136  // trim data we don't have info for from all participants
13137  for (auto &pi: info)
13138  pi.resize(n_outputs);
13139 
13140  // sort by signer
13141  if (!info.empty() && !info.front().empty())
13142  {
13143  std::sort(info.begin(), info.end(), [](const std::vector<tools::wallet2::multisig_info> &i0, const std::vector<tools::wallet2::multisig_info> &i1){ return memcmp(&i0[0].m_signer, &i1[0].m_signer, sizeof(i0[0].m_signer)); });
13144  }
13145 
13146  // first pass to determine where to detach the blockchain
13147  for (size_t n = 0; n < n_outputs; ++n)
13148  {
13149  const transfer_details &td = m_transfers[n];
13150  if (!td.m_key_image_partial)
13151  continue;
13152  MINFO("Multisig info importing from block height " << td.m_block_height);
13153  detach_blockchain(td.m_block_height);
13154  break;
13155  }
13156 
13157  for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n)
13158  {
13159  update_multisig_rescan_info(k, info, n);
13160  }
13161 
13162  m_multisig_rescan_k = &k;
13163  m_multisig_rescan_info = &info;
13164  try
13165  {
13166 
13167  refresh(false);
13168  }
13169  catch (...)
13170  {
13171  m_multisig_rescan_info = NULL;
13172  m_multisig_rescan_k = NULL;
13173  throw;
13174  }
13175  m_multisig_rescan_info = NULL;
13176  m_multisig_rescan_k = NULL;
13177 
13178  return n_outputs;
13179 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
#define MINFO(x)
Definition: misc_log_ex.h:75
::std::string string
Definition: gtest-port.h:1097
#define MULTISIG_EXPORT_FILE_MAGIC
Definition: wallet2.cpp:125
const account_keys & get_keys() const
Definition: account.cpp:264
std::string decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated=true) const
Definition: wallet2.cpp:13250
POD_CLASS public_key
Definition: crypto.h:76
std::string blobdata
Definition: blobdatatype.h:39
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
account_public_address m_account_address
Definition: account.h:43
const T & move(const T &t)
Definition: gtest-port.h:1317
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
void refresh(bool trusted_daemon)
Definition: wallet2.cpp:3060
Here is the call graph for this function:

◆ import_outputs()

size_t tools::wallet2::import_outputs ( const std::pair< size_t, std::vector< tools::wallet2::transfer_details >> &  outputs)

Definition at line 12763 of file wallet2.cpp.

12764 {
12766 
12767  THROW_WALLET_EXCEPTION_IF(outputs.first > m_transfers.size(), error::wallet_internal_error,
12768  "Imported outputs omit more outputs that we know of");
12769 
12770  const size_t offset = outputs.first;
12771  const size_t original_size = m_transfers.size();
12772  m_transfers.resize(offset + outputs.second.size());
12773  for (size_t i = 0; i < offset; ++i)
12774  m_transfers[i].m_key_image_request = false;
12775  for (size_t i = 0; i < outputs.second.size(); ++i)
12776  {
12777  transfer_details td = outputs.second[i];
12778 
12779  // skip those we've already imported, or which have different data
12780  if (i + offset < original_size)
12781  {
12782  // compare the data used to create the key image below
12783  const transfer_details &org_td = m_transfers[i + offset];
12784  if (!org_td.m_key_image_known)
12785  goto process;
12786 #define CMPF(f) if (!(td.f == org_td.f)) goto process
12787  CMPF(m_txid);
12788  CMPF(m_key_image);
12789  CMPF(m_internal_output_index);
12790 #undef CMPF
12791  if (!(get_transaction_prefix_hash(td.m_tx) == get_transaction_prefix_hash(org_td.m_tx)))
12792  goto process;
12793 
12794  // copy anyway, since the comparison does not include ancillary fields which may have changed
12795  m_transfers[i + offset] = std::move(td);
12796  continue;
12797  }
12798 
12799 process:
12800 
12801  // the hot wallet wouldn't have known about key images (except if we already exported them)
12802  cryptonote::keypair in_ephemeral;
12803 
12804  THROW_WALLET_EXCEPTION_IF(td.m_tx.vout.empty(), error::wallet_internal_error, "tx with no outputs at index " + boost::lexical_cast<std::string>(i + offset));
12806  const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
12807 
12808  THROW_WALLET_EXCEPTION_IF(td.m_tx.vout[td.m_internal_output_index].target.type() != typeid(cryptonote::txout_to_key),
12809  error::wallet_internal_error, "Unsupported output type");
12810  const crypto::public_key& out_key = boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key;
12811  bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device(), m_account_major_offset);
12812  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
12813  expand_subaddresses(td.m_subaddr_index);
12814  td.m_key_image_known = true;
12815  td.m_key_image_request = true;
12816  td.m_key_image_partial = false;
12817  THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != out_key,
12818  error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + boost::lexical_cast<std::string>(i + offset));
12819 
12820  m_key_images[td.m_key_image] = i + offset;
12821  m_pub_keys[td.get_public_key()] = i + offset;
12822  m_transfers[i + offset] = std::move(td);
12823  }
12824 
12825  return m_transfers.size();
12826 }
crypto::public_key pub
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const
Definition: wallet2.cpp:12143
#define PERF_TIMER(name)
Definition: perf_timer.h:82
::std::string string
Definition: gtest-port.h:1097
const char * key
Definition: hmac_keccak.cpp:39
const account_keys & get_keys() const
Definition: account.cpp:264
hw::device & get_device() const
Definition: account.h:91
bool generate_key_image_helper(const account_keys &ack, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
POD_CLASS public_key
Definition: crypto.h:76
void expand_subaddresses(const cryptonote::subaddress_index &index, const bool udpate_account_tags=true)
Definition: wallet2.cpp:1478
#define CMPF(f)
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
const T & move(const T &t)
Definition: gtest-port.h:1317
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
size_t import_outputs(const std::pair< size_t, std::vector< tools::wallet2::transfer_details >> &outputs)
Definition: wallet2.cpp:12763
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ import_outputs_from_str()

size_t tools::wallet2::import_outputs_from_str ( const std::string &  outputs_st)

Definition at line 12828 of file wallet2.cpp.

12829 {
12831  std::string data = outputs_st;
12832  const size_t magiclen = strlen(OUTPUT_EXPORT_FILE_MAGIC);
12833  if (data.size() < magiclen || memcmp(data.data(), OUTPUT_EXPORT_FILE_MAGIC, magiclen))
12834  {
12835  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad magic from outputs"));
12836  }
12837 
12838  try
12839  {
12840  PERF_TIMER(import_outputs_decrypt);
12841  data = decrypt_with_view_secret_key(std::string(data, magiclen));
12842  }
12843  catch (const std::exception &e)
12844  {
12845  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt outputs: ") + e.what());
12846  }
12847 
12848  const size_t headerlen = 2 * sizeof(crypto::public_key);
12849  if (data.size() < headerlen)
12850  {
12851  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad data size for outputs"));
12852  }
12853  const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[0];
12854  const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[sizeof(crypto::public_key)];
12856  if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key)
12857  {
12858  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Outputs from are for a different account"));
12859  }
12860 
12861  size_t imported_outputs = 0;
12862  try
12863  {
12864  std::string body(data, headerlen);
12865  std::stringstream iss;
12866  iss << body;
12867  std::pair<size_t, std::vector<tools::wallet2::transfer_details>> outputs;
12868  try
12869  {
12871  ar >> outputs;
12872  }
12873  catch (...)
12874  {
12875  iss.str("");
12876  iss << body;
12877  boost::archive::binary_iarchive ar(iss);
12878  ar >> outputs;
12879  }
12880 
12881  imported_outputs = import_outputs(outputs);
12882  }
12883  catch (const std::exception &e)
12884  {
12885  THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to import outputs") + e.what());
12886  }
12887 
12888  return imported_outputs;
12889 }
#define PERF_TIMER(name)
Definition: perf_timer.h:82
::std::string string
Definition: gtest-port.h:1097
size_t import_outputs_from_str(const std::string &outputs_st)
Definition: wallet2.cpp:12828
#define OUTPUT_EXPORT_FILE_MAGIC
Definition: wallet2.cpp:140
const account_keys & get_keys() const
Definition: account.cpp:264
std::string decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated=true) const
Definition: wallet2.cpp:13250
POD_CLASS public_key
Definition: crypto.h:76
account_public_address m_account_address
Definition: account.h:43
size_t import_outputs(const std::pair< size_t, std::vector< tools::wallet2::transfer_details >> &outputs)
Definition: wallet2.cpp:12763
cryptonote::account_base & get_account()
Definition: wallet2.h:734
#define THROW_WALLET_EXCEPTION(err_type,...)

◆ import_payments()

void tools::wallet2::import_payments ( const payment_container payments)

Definition at line 12674 of file wallet2.cpp.

12675 {
12676  m_payments.clear();
12677  for (auto const &p : payments)
12678  {
12679  m_payments.emplace(p);
12680  }
12681 }
Here is the caller graph for this function:

◆ import_payments_out()

void tools::wallet2::import_payments_out ( const std::list< std::pair< crypto::hash, wallet2::confirmed_transfer_details >> &  confirmed_payments)

Definition at line 12682 of file wallet2.cpp.

12683 {
12684  m_confirmed_txs.clear();
12685  for (auto const &p : confirmed_payments)
12686  {
12687  m_confirmed_txs.emplace(p);
12688  }
12689 }
Here is the caller graph for this function:

◆ init()

bool tools::wallet2::init ( std::string  daemon_address = "http://localhost:8080",
boost::optional< epee::net_utils::http::login daemon_login = boost::none,
boost::asio::ip::tcp::endpoint  proxy = {},
uint64_t  upper_transaction_weight_limit = 0,
bool  trusted_daemon = true,
epee::net_utils::ssl_options_t  ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect,
std::string  blockchain_db_path = "" 
)

Definition at line 1282 of file wallet2.cpp.

1283 {
1284  m_checkpoints.init_default_checkpoints(m_nettype);
1285  m_is_initialized = true;
1286  m_upper_transaction_weight_limit = upper_transaction_weight_limit;
1287 
1288  if (proxy != boost::asio::ip::tcp::endpoint{})
1289  m_http_client.set_connector(net::socks::connector{std::move(proxy)});
1290  return set_daemon(daemon_address, daemon_login, trusted_daemon, std::move(ssl_options));
1291 }
bool init_default_checkpoints(network_type nettype)
loads the default main chain checkpoints
Primarily for use with epee::net_utils::http_client.
Definition: socks_connect.h:41
bool set_daemon(std::string daemon_address="http://localhost:8080", boost::optional< epee::net_utils::http::login > daemon_login=boost::none, bool trusted_daemon=true, epee::net_utils::ssl_options_t ssl_options=epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
Definition: wallet2.cpp:1268
const T & move(const T &t)
Definition: gtest-port.h:1317
string daemon_address
Definition: transfers.cpp:42
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_options()

void tools::wallet2::init_options ( boost::program_options::options_description &  desc_params)
static

Definition at line 1193 of file wallet2.cpp.

1194 {
1195  const options opts{};
1196  command_line::add_arg(desc_params, opts.daemon_address);
1197  command_line::add_arg(desc_params, opts.daemon_host);
1198  command_line::add_arg(desc_params, opts.proxy);
1199  command_line::add_arg(desc_params, opts.trusted_daemon);
1200  command_line::add_arg(desc_params, opts.untrusted_daemon);
1201  command_line::add_arg(desc_params, opts.password);
1202  command_line::add_arg(desc_params, opts.password_file);
1203  command_line::add_arg(desc_params, opts.daemon_port);
1204  command_line::add_arg(desc_params, opts.daemon_login);
1205  command_line::add_arg(desc_params, opts.daemon_ssl);
1206  command_line::add_arg(desc_params, opts.daemon_ssl_private_key);
1207  command_line::add_arg(desc_params, opts.daemon_ssl_certificate);
1208  command_line::add_arg(desc_params, opts.daemon_ssl_ca_certificates);
1209  command_line::add_arg(desc_params, opts.daemon_ssl_allowed_fingerprints);
1210  command_line::add_arg(desc_params, opts.daemon_ssl_allow_any_cert);
1211  command_line::add_arg(desc_params, opts.daemon_ssl_allow_chained);
1212  command_line::add_arg(desc_params, opts.testnet);
1213  command_line::add_arg(desc_params, opts.stagenet);
1214  command_line::add_arg(desc_params, opts.shared_ringdb_dir);
1215  command_line::add_arg(desc_params, opts.kdf_rounds);
1216  mms::message_store::init_options(desc_params);
1217  command_line::add_arg(desc_params, opts.hw_device);
1218  command_line::add_arg(desc_params, opts.hw_device_derivation_path);
1219  command_line::add_arg(desc_params, opts.tx_notify);
1220  command_line::add_arg(desc_params, opts.no_dns);
1221  command_line::add_arg(desc_params, opts.offline);
1222  command_line::add_arg(desc_params, opts.data_dir);
1223  command_line::add_arg(desc_params, opts.fallback_to_pow_checkpoint_height);
1224  command_line::add_arg(desc_params, opts.fallback_to_pow_checkpoint_hash);
1225 }
static void init_options(boost::program_options::options_description &desc_params)
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
Definition: command_line.h:188
Here is the call graph for this function:
Here is the caller graph for this function:

◆ invoke_http_bin()

template<class t_request , class t_response >
bool tools::wallet2::invoke_http_bin ( const boost::string_ref  uri,
const t_request &  req,
t_response &  res,
std::chrono::milliseconds  timeout = std::chrono::seconds(15),
const boost::string_ref  http_method = "GET" 
)
inline

Definition at line 1326 of file wallet2.h.

1327  {
1328  if (m_offline) return false;
1329  boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
1330  return epee::net_utils::invoke_http_bin(uri, req, res, m_http_client, timeout, http_method);
1331  }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_bin(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref method="GET")
Here is the call graph for this function:

◆ invoke_http_json()

template<class t_request , class t_response >
bool tools::wallet2::invoke_http_json ( const boost::string_ref  uri,
const t_request &  req,
t_response &  res,
std::chrono::milliseconds  timeout = std::chrono::seconds(15),
const boost::string_ref  http_method = "GET" 
)
inline

Definition at line 1319 of file wallet2.h.

1320  {
1321  if (m_offline) return false;
1322  boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
1323  return epee::net_utils::invoke_http_json(uri, req, res, m_http_client, timeout, http_method);
1324  }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_json(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref method="GET")
Here is the call graph for this function:

◆ invoke_http_json_rpc()

template<class t_request , class t_response >
bool tools::wallet2::invoke_http_json_rpc ( const boost::string_ref  uri,
const std::string &  method_name,
const t_request &  req,
t_response &  res,
std::chrono::milliseconds  timeout = std::chrono::seconds(15),
const boost::string_ref  http_method = "GET",
const std::string &  req_id = "0" 
)
inline

Definition at line 1333 of file wallet2.h.

1334  {
1335  if (m_offline) return false;
1336  boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
1337  return epee::net_utils::invoke_http_json_rpc(uri, method_name, req, res, m_http_client, timeout, http_method, req_id);
1338  }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET", const std::string &req_id="0")
Here is the call graph for this function:

◆ is_deprecated()

bool tools::wallet2::is_deprecated ( ) const

Tells if the wallet file is deprecated.

Definition at line 1546 of file wallet2.cpp.

1547 {
1548  return is_old_file_format;
1549 }

◆ is_deterministic()

bool tools::wallet2::is_deterministic ( ) const

Checks if deterministic wallet.

Definition at line 1293 of file wallet2.cpp.

1294 {
1295  crypto::secret_key second;
1296  keccak((uint8_t *)&get_account().get_keys().m_spend_secret_key, sizeof(crypto::secret_key), (uint8_t *)&second, sizeof(crypto::secret_key));
1297  sc_reduce32((uint8_t *)&second);
1298  return memcmp(second.data,get_account().get_keys().m_view_secret_key.data, sizeof(crypto::secret_key)) == 0;
1299 }
unsigned char uint8_t
Definition: stdint.h:124
void sc_reduce32(unsigned char *)
void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_keys_file_locked()

bool tools::wallet2::is_keys_file_locked ( ) const

Definition at line 8236 of file wallet2.cpp.

8237 {
8238  return m_keys_file_locker->locked();
8239 }

◆ is_output_blackballed()

bool tools::wallet2::is_output_blackballed ( const std::pair< uint64_t, uint64_t > &  output) const

Definition at line 8206 of file wallet2.cpp.

8207 {
8208  if (!m_ringdb)
8209  return false;
8210  try { return m_ringdb->blackballed(output); }
8211  catch (const std::exception &e) { return false; }
8212 }

◆ is_synced()

bool tools::wallet2::is_synced ( ) const

Definition at line 13480 of file wallet2.cpp.

13481 {
13482  uint64_t height;
13483  boost::optional<std::string> result = m_node_rpc_proxy.get_target_height(height);
13484  if (result && *result != CORE_RPC_STATUS_OK)
13485  return false;
13487 }
uint64_t height
Definition: blockchain.cpp:91
#define CORE_RPC_STATUS_OK
unsigned __int64 uint64_t
Definition: stdint.h:136
boost::optional< std::string > get_target_height(uint64_t &height) const
uint64_t get_blockchain_current_height() const
Definition: wallet2.h:898

◆ is_transfer_unlocked() [1/2]

bool tools::wallet2::is_transfer_unlocked ( const transfer_details td) const

Definition at line 6565 of file wallet2.cpp.

6566 {
6567  return is_transfer_unlocked(td.m_tx.unlock_time, td.m_block_height);
6568 }
bool is_transfer_unlocked(const transfer_details &td) const
Definition: wallet2.cpp:6565

◆ is_transfer_unlocked() [2/2]

bool tools::wallet2::is_transfer_unlocked ( uint64_t  unlock_time,
uint64_t  block_height 
) const

Definition at line 6570 of file wallet2.cpp.

6571 {
6572  if(!is_tx_spendtime_unlocked(unlock_time, block_height))
6573  return false;
6574 
6575  uint64_t v8height = m_nettype == TESTNET ? 446674 : 589169;
6576  uint16_t UNLOCK_WINDOW = block_height > v8height ? ETN_DEFAULT_TX_SPENDABLE_AGE_V8 : CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE;
6577 
6578  if(block_height + UNLOCK_WINDOW > get_blockchain_current_height())
6579  return false;
6580 
6581  return true;
6582 }
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
unsigned short uint16_t
Definition: stdint.h:125
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height) const
Definition: wallet2.cpp:6584
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
uint64_t get_blockchain_current_height() const
Definition: wallet2.h:898

◆ is_trusted_daemon()

bool tools::wallet2::is_trusted_daemon ( ) const
inline

Definition at line 765 of file wallet2.h.

765 { return m_trusted_daemon; }
Here is the caller graph for this function:

◆ is_tx_spendtime_unlocked()

bool tools::wallet2::is_tx_spendtime_unlocked ( uint64_t  unlock_time,
uint64_t  block_height 
) const

Definition at line 6584 of file wallet2.cpp.

6585 {
6586  if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
6587  {
6588  //interpret as block index
6590  return true;
6591  else
6592  return false;
6593  }else
6594  {
6595  //interpret as time
6596  uint64_t current_time = static_cast<uint64_t>(time(NULL));
6597  // XXX: this needs to be fast, so we'd need to get the starting heights
6598  // from the daemon to be correct once voting kicks in
6599  uint64_t v6height = m_nettype == TESTNET ? 190059 : 307499;
6601  if(current_time + leeway >= unlock_time)
6602  return true;
6603  else
6604  return false;
6605  }
6606  return false;
6607 }
#define CRYPTONOTE_MAX_BLOCK_NUMBER
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V6
time_t time
Definition: blockchain.cpp:93
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
unsigned __int64 uint64_t
Definition: stdint.h:136
uint64_t get_blockchain_current_height() const
Definition: wallet2.h:898
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS

◆ is_unattended()

bool tools::wallet2::is_unattended ( ) const
inline

Definition at line 1274 of file wallet2.h.

1274 { return m_unattended; }
Here is the caller graph for this function:

◆ key_on_device()

bool tools::wallet2::key_on_device ( ) const
inline

Definition at line 830 of file wallet2.h.

830 { return get_device_type() != hw::device::device_type::SOFTWARE; }
hw::device::device_type get_device_type() const
Definition: wallet2.h:831
Here is the call graph for this function:

◆ key_reuse_mitigation2() [1/2]

bool tools::wallet2::key_reuse_mitigation2 ( ) const
inline

Definition at line 1097 of file wallet2.h.

1097 { return m_key_reuse_mitigation2; }

◆ key_reuse_mitigation2() [2/2]

void tools::wallet2::key_reuse_mitigation2 ( bool  value)
inline

Definition at line 1098 of file wallet2.h.

1098 { m_key_reuse_mitigation2 = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ light_wallet()

bool tools::wallet2::light_wallet ( ) const
inline

Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned.

Definition at line 777 of file wallet2.h.

777 { return m_light_wallet; }
Here is the caller graph for this function:

◆ light_wallet_get_address_info()

bool tools::wallet2::light_wallet_get_address_info ( tools::COMMAND_RPC_GET_ADDRESS_INFO::response response)

Definition at line 9438 of file wallet2.cpp.

9439 {
9440  MTRACE(__FUNCTION__);
9441 
9443 
9444  request.address = get_account().get_public_address_str(m_nettype);
9445  request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
9446  m_daemon_rpc_mutex.lock();
9447  bool r = invoke_http_json("/get_address_info", request, response, rpc_timeout, "POST");
9448  m_daemon_rpc_mutex.unlock();
9449  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_address_info");
9450  // TODO: Validate result
9451  return true;
9452 }
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
#define MTRACE(x)
Definition: misc_log_ex.h:77
epee::misc_utils::struct_init< response_t > response
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:

◆ light_wallet_get_address_txs()

void tools::wallet2::light_wallet_get_address_txs ( )

Definition at line 9454 of file wallet2.cpp.

9455 {
9456  MDEBUG("Refreshing light wallet");
9457 
9460 
9461  ireq.address = get_account().get_public_address_str(m_nettype);
9462  ireq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
9463  m_daemon_rpc_mutex.lock();
9464  bool r = invoke_http_json("/get_address_txs", ireq, ires, rpc_timeout, "POST");
9465  m_daemon_rpc_mutex.unlock();
9466  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_address_txs");
9467  //OpenMonero sends status=success, Mymonero doesn't.
9468  THROW_WALLET_EXCEPTION_IF((!ires.status.empty() && ires.status != "success"), error::no_connection_to_daemon, "get_address_txs");
9469 
9470 
9471  // Abort if no transactions
9472  if(ires.transactions.empty())
9473  return;
9474 
9475  // Create searchable vectors
9476  std::vector<crypto::hash> payments_txs;
9477  for(const auto &p: m_payments)
9478  payments_txs.push_back(p.second.m_tx_hash);
9479  std::vector<crypto::hash> unconfirmed_payments_txs;
9480  for(const auto &up: m_unconfirmed_payments)
9481  unconfirmed_payments_txs.push_back(up.second.m_pd.m_tx_hash);
9482 
9483  // for balance calculation
9484  uint64_t wallet_total_sent = 0;
9485  // txs in pool
9486  std::vector<crypto::hash> pool_txs;
9487 
9488  for (const auto &t: ires.transactions) {
9489  const uint64_t total_received = t.total_received;
9490  uint64_t total_sent = t.total_sent;
9491 
9492  // Check key images - subtract fake outputs from total_sent
9493  for(const auto &so: t.spent_outputs)
9494  {
9495  crypto::public_key tx_public_key;
9497  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, so.tx_pub_key), error::wallet_internal_error, "Invalid tx_pub_key field");
9498  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, so.key_image), error::wallet_internal_error, "Invalid key_image field");
9499  string_tools::hex_to_pod(so.tx_pub_key, tx_public_key);
9500  string_tools::hex_to_pod(so.key_image, key_image);
9501 
9502  if(!light_wallet_key_image_is_ours(key_image, tx_public_key, so.out_index)) {
9503  THROW_WALLET_EXCEPTION_IF(so.amount > t.total_sent, error::wallet_internal_error, "Lightwallet: total sent is negative!");
9504  total_sent -= so.amount;
9505  }
9506  }
9507 
9508  // Do not add tx if empty.
9509  if(total_sent == 0 && total_received == 0)
9510  continue;
9511 
9512  crypto::hash payment_id = null_hash;
9513  crypto::hash tx_hash;
9514 
9515  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, t.payment_id), error::wallet_internal_error, "Invalid payment_id field");
9516  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, t.hash), error::wallet_internal_error, "Invalid hash field");
9517  string_tools::hex_to_pod(t.payment_id, payment_id);
9518  string_tools::hex_to_pod(t.hash, tx_hash);
9519 
9520  // lightwallet specific info
9521  bool incoming = (total_received > total_sent);
9522  address_tx address_tx;
9523  address_tx.m_tx_hash = tx_hash;
9524  address_tx.m_incoming = incoming;
9525  address_tx.m_amount = incoming ? total_received - total_sent : total_sent - total_received;
9526  address_tx.m_fee = 0; // TODO
9527  address_tx.m_block_height = t.height;
9528  address_tx.m_unlock_time = t.unlock_time;
9529  address_tx.m_timestamp = t.timestamp;
9530  address_tx.m_coinbase = t.coinbase;
9531  address_tx.m_mempool = t.mempool;
9532  m_light_wallet_address_txs.emplace(tx_hash,address_tx);
9533 
9534  // populate data needed for history (m_payments, m_unconfirmed_payments, m_confirmed_txs)
9535  // INCOMING transfers
9536  if(total_received > total_sent) {
9537  payment_details payment;
9538  payment.m_tx_hash = tx_hash;
9539  payment.m_amount = total_received - total_sent;
9540  payment.m_fee = 0; // TODO
9541  payment.m_block_height = t.height;
9542  payment.m_unlock_time = t.unlock_time;
9543  payment.m_timestamp = t.timestamp;
9544  payment.m_coinbase = t.coinbase;
9545 
9546  if (t.mempool) {
9547  if (std::find(unconfirmed_payments_txs.begin(), unconfirmed_payments_txs.end(), tx_hash) == unconfirmed_payments_txs.end()) {
9548  pool_txs.push_back(tx_hash);
9549  // assume false as we don't get that info from the light wallet server
9550  crypto::hash payment_id;
9551  THROW_WALLET_EXCEPTION_IF(!epee::string_tools::hex_to_pod(t.payment_id, payment_id),
9552  error::wallet_internal_error, "Failed to parse payment id");
9553  emplace_or_replace(m_unconfirmed_payments, payment_id, pool_payment_details{payment, false, false});
9554  if (0 != m_callback) {
9555  m_callback->on_lw_unconfirmed_etn_received(t.height, payment.m_tx_hash, payment.m_amount);
9556  }
9557  }
9558  } else {
9559  if (std::find(payments_txs.begin(), payments_txs.end(), tx_hash) == payments_txs.end()) {
9560  m_payments.emplace(tx_hash, payment);
9561  if (0 != m_callback) {
9562  m_callback->on_lw_etn_received(t.height, payment.m_tx_hash, payment.m_amount);
9563  }
9564  }
9565  }
9566  // Outgoing transfers
9567  } else {
9568  uint64_t amount_sent = total_sent - total_received;
9569  cryptonote::transaction dummy_tx; // not used by light wallet
9570  // increase wallet total sent
9571  wallet_total_sent += total_sent;
9572  if (t.mempool)
9573  {
9574  // Handled by add_unconfirmed_tx in commit_tx
9575  // If sent from another wallet instance we need to add it
9576  if(m_unconfirmed_txs.find(tx_hash) == m_unconfirmed_txs.end())
9577  {
9578  unconfirmed_transfer_details utd;
9579  utd.m_amount_in = amount_sent;
9580  utd.m_amount_out = amount_sent;
9581  utd.m_change = 0;
9582  utd.m_payment_id = payment_id;
9583  utd.m_timestamp = t.timestamp;
9585  m_unconfirmed_txs.emplace(tx_hash,utd);
9586  }
9587  }
9588  else
9589  {
9590  // Only add if new
9591  auto confirmed_tx = m_confirmed_txs.find(tx_hash);
9592  if(confirmed_tx == m_confirmed_txs.end()) {
9593  // tx is added to m_unconfirmed_txs - move to confirmed
9594  if(m_unconfirmed_txs.find(tx_hash) != m_unconfirmed_txs.end())
9595  {
9596  process_unconfirmed(tx_hash, dummy_tx, t.height);
9597  }
9598  // Tx sent by another wallet instance
9599  else
9600  {
9601  confirmed_transfer_details ctd;
9602  ctd.m_amount_in = amount_sent;
9603  ctd.m_amount_out = amount_sent;
9604  ctd.m_change = 0;
9605  ctd.m_payment_id = payment_id;
9606  ctd.m_block_height = t.height;
9607  ctd.m_timestamp = t.timestamp;
9608  m_confirmed_txs.emplace(tx_hash,ctd);
9609  }
9610  if (0 != m_callback)
9611  {
9612  m_callback->on_lw_etn_spent(t.height, tx_hash, amount_sent);
9613  }
9614  }
9615  // If not new - check the amount and update if necessary.
9616  // when sending a tx to same wallet the receiving amount has to be credited
9617  else
9618  {
9619  if(confirmed_tx->second.m_amount_in != amount_sent || confirmed_tx->second.m_amount_out != amount_sent)
9620  {
9621  MDEBUG("Adjusting amount sent/received for tx: <" + t.hash + ">. Is tx sent to own wallet? " << print_etn(amount_sent) << " != " << print_etn(confirmed_tx->second.m_amount_in));
9622  confirmed_tx->second.m_amount_in = amount_sent;
9623  confirmed_tx->second.m_amount_out = amount_sent;
9624  confirmed_tx->second.m_change = 0;
9625  }
9626  }
9627  }
9628  }
9629  }
9630  // TODO: purge old unconfirmed_txs
9631  remove_obsolete_pool_txs(pool_txs);
9632 
9633  // Calculate wallet balance
9634  m_light_wallet_balance = ires.total_received-wallet_total_sent;
9635  // MyMonero doesn't send unlocked balance
9636  if(ires.total_received_unlocked > 0)
9637  m_light_wallet_unlocked_balance = ires.total_received_unlocked-wallet_total_sent;
9638  else
9639  m_light_wallet_unlocked_balance = m_light_wallet_balance;
9640 }
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
std::string print_etn(uint64_t amount, unsigned int decimal_point)
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
virtual void on_lw_unconfirmed_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition: wallet2.h:136
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
#define MDEBUG(x)
Definition: misc_log_ex.h:76
bool validate_hex(uint64_t length, const std::string &str)
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
virtual void on_lw_etn_spent(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition: wallet2.h:137
unsigned __int64 uint64_t
Definition: stdint.h:136
void remove_obsolete_pool_txs(const std::vector< crypto::hash > &tx_hashes)
Definition: wallet2.cpp:3136
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
virtual void on_lw_etn_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
Definition: wallet2.h:135
POD_CLASS public_key
Definition: crypto.h:76
bool light_wallet_key_image_is_ours(const crypto::key_image &key_image, const crypto::public_key &tx_public_key, uint64_t out_index)
Definition: wallet2.cpp:9667
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ light_wallet_get_outs()

void tools::wallet2::light_wallet_get_outs ( std::vector< std::vector< get_outs_entry >> &  outs,
const std::vector< size_t > &  selected_transfers,
size_t  fake_outputs_count 
)

Definition at line 8268 of file wallet2.cpp.

8268  {
8269 
8270  MDEBUG("LIGHTWALLET - Getting random outs");
8271 
8274 
8275  size_t light_wallet_requested_outputs_count = (size_t)((fake_outputs_count + 1) * 1.5 + 1);
8276 
8277  // Amounts to ask for
8278  // MyMonero api handle amounts and fees as strings
8279  for(size_t idx: selected_transfers) {
8280  const uint64_t ask_amount = m_transfers[idx].is_rct() ? 0 : m_transfers[idx].amount();
8281  std::ostringstream amount_ss;
8282  amount_ss << ask_amount;
8283  oreq.amounts.push_back(amount_ss.str());
8284  }
8285 
8286  oreq.count = light_wallet_requested_outputs_count;
8287  m_daemon_rpc_mutex.lock();
8288  bool r = invoke_http_json("/get_random_outs", oreq, ores, rpc_timeout, "POST");
8289  m_daemon_rpc_mutex.unlock();
8290  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_random_outs");
8291  THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs received from light wallet node. Error: " + ores.Error);
8292 
8293  // Check if we got enough outputs for each amount
8294  for(auto& out: ores.amount_outs) {
8295  const uint64_t out_amount = boost::lexical_cast<uint64_t>(out.amount);
8296  THROW_WALLET_EXCEPTION_IF(out.outputs.size() < light_wallet_requested_outputs_count , error::wallet_internal_error, "Not enough outputs for amount: " + boost::lexical_cast<std::string>(out.amount));
8297  MDEBUG(out.outputs.size() << " outputs for amount "+ boost::lexical_cast<std::string>(out.amount) + " received from light wallet node");
8298  }
8299 
8300  MDEBUG("selected transfers size: " << selected_transfers.size());
8301 
8302  for(size_t idx: selected_transfers)
8303  {
8304  // Create new index
8305  outs.push_back(std::vector<get_outs_entry>());
8306  outs.back().reserve(fake_outputs_count + 1);
8307 
8308  // add real output first
8309  const transfer_details &td = m_transfers[idx];
8310  const uint64_t amount = td.is_rct() ? 0 : td.amount();
8311  outs.back().push_back(std::make_tuple(td.m_global_output_index, td.get_public_key(), rct::commit(td.amount(), td.m_mask)));
8312  MDEBUG("added real output " << string_tools::pod_to_hex(td.get_public_key()));
8313 
8314  // Even if the lightwallet server returns random outputs, we pick them randomly.
8315  std::vector<size_t> order;
8316  order.resize(light_wallet_requested_outputs_count);
8317  for (size_t n = 0; n < order.size(); ++n)
8318  order[n] = n;
8319  std::shuffle(order.begin(), order.end(), std::default_random_engine(crypto::rand<unsigned>()));
8320 
8321 
8322  LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs with amounts " << print_etn(td.is_rct() ? 0 : td.amount()));
8323  MDEBUG("OUTS SIZE: " << outs.back().size());
8324  for (size_t o = 0; o < light_wallet_requested_outputs_count && outs.back().size() < fake_outputs_count + 1; ++o)
8325  {
8326  // Random pick
8327  size_t i = order[o];
8328 
8329  // Find which random output key to use
8330  bool found_amount = false;
8331  size_t amount_key;
8332  for(amount_key = 0; amount_key < ores.amount_outs.size(); ++amount_key)
8333  {
8334  if(boost::lexical_cast<uint64_t>(ores.amount_outs[amount_key].amount) == amount) {
8335  found_amount = true;
8336  break;
8337  }
8338  }
8339  THROW_WALLET_EXCEPTION_IF(!found_amount , error::wallet_internal_error, "Outputs for amount " + boost::lexical_cast<std::string>(ores.amount_outs[amount_key].amount) + " not found" );
8340 
8341  LOG_PRINT_L2("Index " << i << "/" << light_wallet_requested_outputs_count << ": idx " << ores.amount_outs[amount_key].outputs[i].global_index << " (real " << td.m_global_output_index << "), unlocked " << "(always in light)" << ", key " << ores.amount_outs[0].outputs[i].public_key);
8342 
8343  // Convert light wallet string data to proper data structures
8344  crypto::public_key tx_public_key;
8345  rct::key mask = AUTO_VAL_INIT(mask); // decrypted mask - not used here
8346  rct::key rct_commit = AUTO_VAL_INIT(rct_commit);
8347  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, ores.amount_outs[amount_key].outputs[i].public_key), error::wallet_internal_error, "Invalid public_key");
8348  string_tools::hex_to_pod(ores.amount_outs[amount_key].outputs[i].public_key, tx_public_key);
8349  const uint64_t global_index = ores.amount_outs[amount_key].outputs[i].global_index;
8350  if(!light_wallet_parse_rct_str(ores.amount_outs[amount_key].outputs[i].rct, tx_public_key, 0, mask, rct_commit, false))
8351  rct_commit = rct::zeroCommit(td.amount());
8352 
8353  if (tx_add_fake_output(outs, global_index, tx_public_key, rct_commit, td.m_global_output_index, true)) {
8354  MDEBUG("added fake output " << ores.amount_outs[amount_key].outputs[i].public_key);
8355  MDEBUG("index " << global_index);
8356  }
8357  }
8358 
8359  THROW_WALLET_EXCEPTION_IF(outs.back().size() < fake_outputs_count + 1 , error::wallet_internal_error, "Not enough fake outputs found" );
8360 
8361  // Real output is the first. Shuffle outputs
8362  MTRACE(outs.back().size() << " outputs added. Sorting outputs by index:");
8363  std::sort(outs.back().begin(), outs.back().end(), [](const get_outs_entry &a, const get_outs_entry &b) { return std::get<0>(a) < std::get<0>(b); });
8364 
8365  // Print output order
8366  for(auto added_out: outs.back())
8367  MTRACE(std::get<0>(added_out));
8368 
8369  }
8370 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
#define MTRACE(x)
Definition: misc_log_ex.h:77
::std::string string
Definition: gtest-port.h:1097
std::string print_etn(uint64_t amount, unsigned int decimal_point)
key commit(etn_amount amount, const key &mask)
Definition: rctOps.cpp:336
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
tuple make_tuple()
Definition: gtest-tuple.h:675
#define MDEBUG(x)
Definition: misc_log_ex.h:76
bool validate_hex(uint64_t length, const std::string &str)
bool light_wallet_parse_rct_str(const std::string &rct_string, const crypto::public_key &tx_pub_key, uint64_t internal_output_index, rct::key &decrypted_mask, rct::key &rct_commit, bool decrypt) const
Definition: wallet2.cpp:9642
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
unsigned __int64 uint64_t
Definition: stdint.h:136
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
POD_CLASS public_key
Definition: crypto.h:76
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
std::tuple< uint64_t, crypto::public_key, rct::key > get_outs_entry
Definition: chaingen.h:352
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
key zeroCommit(etn_amount amount)
Definition: rctOps.cpp:322
Here is the call graph for this function:

◆ light_wallet_get_unspent_outs()

void tools::wallet2::light_wallet_get_unspent_outs ( )

Definition at line 9284 of file wallet2.cpp.

9285 {
9286  MDEBUG("Getting unspent outs");
9287 
9290 
9291  oreq.amount = "0";
9292  oreq.address = get_account().get_public_address_str(m_nettype);
9293  oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
9294  // openMonero specific
9295  oreq.dust_threshold = boost::lexical_cast<std::string>(::config::DEFAULT_DUST_THRESHOLD);
9296  // below are required by openMonero api - but are not used.
9297  oreq.mixin = 0;
9298  oreq.use_dust = true;
9299 
9300 
9301  m_daemon_rpc_mutex.lock();
9302  bool r = invoke_http_json("/get_unspent_outs", oreq, ores, rpc_timeout, "POST");
9303  m_daemon_rpc_mutex.unlock();
9304  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_unspent_outs");
9305  THROW_WALLET_EXCEPTION_IF(ores.status == "error", error::wallet_internal_error, ores.reason);
9306 
9307  m_light_wallet_per_kb_fee = ores.per_kb_fee;
9308 
9309  std::unordered_map<crypto::hash,bool> transfers_txs;
9310  for(const auto &t: m_transfers)
9311  transfers_txs.emplace(t.m_txid,t.m_spent);
9312 
9313  MDEBUG("FOUND " << ores.outputs.size() <<" outputs");
9314 
9315  // return if no outputs found
9316  if(ores.outputs.empty())
9317  return;
9318 
9319  // Clear old outputs
9320  m_transfers.clear();
9321 
9322  for (const auto &o: ores.outputs) {
9323  bool spent = false;
9324  bool add_transfer = true;
9325  crypto::key_image unspent_key_image;
9326  crypto::public_key tx_public_key = AUTO_VAL_INIT(tx_public_key);
9327  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, o.tx_pub_key), error::wallet_internal_error, "Invalid tx_pub_key field");
9328  string_tools::hex_to_pod(o.tx_pub_key, tx_public_key);
9329 
9330  for (const std::string &ski: o.spend_key_images) {
9331  spent = false;
9332 
9333  // Check if key image is ours
9334  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, ski), error::wallet_internal_error, "Invalid key image");
9335  string_tools::hex_to_pod(ski, unspent_key_image);
9336  if(light_wallet_key_image_is_ours(unspent_key_image, tx_public_key, o.index)){
9337  MTRACE("Output " << o.public_key << " is spent. Key image: " << ski);
9338  spent = true;
9339  break;
9340  } {
9341  MTRACE("Unspent output found. " << o.public_key);
9342  }
9343  }
9344 
9345  // Check if tx already exists in m_transfers.
9346  crypto::hash txid;
9347  crypto::public_key tx_pub_key;
9349  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, o.tx_hash), error::wallet_internal_error, "Invalid tx_hash field");
9350  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, o.public_key), error::wallet_internal_error, "Invalid public_key field");
9351  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, o.tx_pub_key), error::wallet_internal_error, "Invalid tx_pub_key field");
9352  string_tools::hex_to_pod(o.tx_hash, txid);
9353  string_tools::hex_to_pod(o.public_key, public_key);
9354  string_tools::hex_to_pod(o.tx_pub_key, tx_pub_key);
9355 
9356  for(auto &t: m_transfers){
9357  if(t.get_public_key() == public_key) {
9358  t.m_spent = spent;
9359  add_transfer = false;
9360  break;
9361  }
9362  }
9363 
9364  if(!add_transfer)
9365  continue;
9366 
9367  m_transfers.push_back(boost::value_initialized<transfer_details>());
9368  transfer_details& td = m_transfers.back();
9369 
9370  td.m_block_height = o.height;
9371  td.m_global_output_index = o.global_index;
9372  td.m_txid = txid;
9373 
9374  // Add to extra
9375  add_tx_pub_key_to_extra(td.m_tx, tx_pub_key);
9376 
9377  td.m_key_image = unspent_key_image;
9378  td.m_key_image_known = !m_watch_only && !m_multisig;
9379  td.m_key_image_request = false;
9380  td.m_key_image_partial = m_multisig;
9381  td.m_amount = o.amount;
9382  td.m_pk_index = 0;
9383  td.m_internal_output_index = o.index;
9384  td.m_spent = spent;
9385  td.m_frozen = false;
9386 
9387  tx_out txout;
9388  txout.target = txout_to_key(public_key);
9389  txout.amount = td.m_amount;
9390 
9391  td.m_tx.vout.resize(td.m_internal_output_index + 1);
9392  td.m_tx.vout[td.m_internal_output_index] = txout;
9393 
9394  // Add unlock time and coinbase bool got from get_address_txs api call
9395  std::unordered_map<crypto::hash,address_tx>::const_iterator found = m_light_wallet_address_txs.find(txid);
9396  THROW_WALLET_EXCEPTION_IF(found == m_light_wallet_address_txs.end(), error::wallet_internal_error, "Lightwallet: tx not found in m_light_wallet_address_txs");
9397  bool miner_tx = found->second.m_coinbase;
9398  td.m_tx.unlock_time = found->second.m_unlock_time;
9399 
9400  if (!o.rct.empty())
9401  {
9402  // Coinbase tx's
9403  if(miner_tx)
9404  {
9405  td.m_mask = rct::identity();
9406  }
9407  else
9408  {
9409  // rct txs
9410  // decrypt rct mask, calculate commit hash and compare against blockchain commit hash
9411  rct::key rct_commit;
9412  light_wallet_parse_rct_str(o.rct, tx_pub_key, td.m_internal_output_index, td.m_mask, rct_commit, true);
9413  bool valid_commit = (rct_commit == rct::commit(td.amount(), td.m_mask));
9414  if(!valid_commit)
9415  {
9416  MDEBUG("output index: " << o.global_index);
9417  MDEBUG("mask: " + string_tools::pod_to_hex(td.m_mask));
9418  MDEBUG("calculated commit: " + string_tools::pod_to_hex(rct::commit(td.amount(), td.m_mask)));
9419  MDEBUG("expected commit: " + string_tools::pod_to_hex(rct_commit));
9420  MDEBUG("amount: " << td.amount());
9421  }
9422  THROW_WALLET_EXCEPTION_IF(!valid_commit, error::wallet_internal_error, "Lightwallet: rct commit hash mismatch!");
9423  }
9424  td.m_rct = true;
9425  }
9426  else
9427  {
9428  td.m_mask = rct::identity();
9429  td.m_rct = false;
9430  }
9431  if(!spent)
9432  set_unspent(m_transfers.size()-1);
9433  m_key_images[td.m_key_image] = m_transfers.size()-1;
9434  m_pub_keys[td.get_public_key()] = m_transfers.size()-1;
9435  }
9436 }
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
#define MTRACE(x)
Definition: misc_log_ex.h:77
::std::string string
Definition: gtest-port.h:1097
key commit(etn_amount amount, const key &mask)
Definition: rctOps.cpp:336
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
#define MDEBUG(x)
Definition: misc_log_ex.h:76
bool validate_hex(uint64_t length, const std::string &str)
bool light_wallet_parse_rct_str(const std::string &rct_string, const crypto::public_key &tx_pub_key, uint64_t internal_output_index, rct::key &decrypted_mask, rct::key &rct_commit, bool decrypt) const
Definition: wallet2.cpp:9642
bool add_tx_pub_key_to_extra(transaction &tx, const crypto::public_key &tx_pub_key)
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
POD_CLASS public_key
Definition: crypto.h:76
uint64_t const DEFAULT_DUST_THRESHOLD
key identity()
Definition: rctOps.h:73
bool light_wallet_key_image_is_ours(const crypto::key_image &key_image, const crypto::public_key &tx_public_key, uint64_t out_index)
Definition: wallet2.cpp:9667
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
txout_target_v target
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ light_wallet_import_wallet_request()

bool tools::wallet2::light_wallet_import_wallet_request ( tools::COMMAND_RPC_IMPORT_WALLET_REQUEST::response response)

Definition at line 9269 of file wallet2.cpp.

9270 {
9271  MDEBUG("Light wallet import wallet request");
9273  oreq.address = get_account().get_public_address_str(m_nettype);
9274  oreq.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
9275  m_daemon_rpc_mutex.lock();
9276  bool r = invoke_http_json("/import_wallet_request", oreq, response, rpc_timeout, "POST");
9277  m_daemon_rpc_mutex.unlock();
9278  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "import_wallet_request");
9279 
9280 
9281  return true;
9282 }
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
epee::misc_utils::struct_init< response_t > response
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
#define MDEBUG(x)
Definition: misc_log_ex.h:76
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:

◆ light_wallet_key_image_is_ours()

bool tools::wallet2::light_wallet_key_image_is_ours ( const crypto::key_image key_image,
const crypto::public_key tx_public_key,
uint64_t  out_index 
)

Definition at line 9667 of file wallet2.cpp.

9668 {
9669  // Lookup key image from cache
9670  std::map<uint64_t, crypto::key_image> index_keyimage_map;
9671  std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> >::const_iterator found_pub_key = m_key_image_cache.find(tx_public_key);
9672  if(found_pub_key != m_key_image_cache.end()) {
9673  // pub key found. key image for index cached?
9674  index_keyimage_map = found_pub_key->second;
9675  std::map<uint64_t,crypto::key_image>::const_iterator index_found = index_keyimage_map.find(out_index);
9676  if(index_found != index_keyimage_map.end())
9677  return key_image == index_found->second;
9678  }
9679 
9680  // Not in cache - calculate key image
9681  crypto::key_image calculated_key_image;
9682  cryptonote::keypair in_ephemeral;
9683 
9684  // Subaddresses aren't supported in mymonero/openmonero yet. Roll out the original scheme:
9685  // compute D = a*R
9686  // compute P = Hs(D || i)*G + B
9687  // compute x = Hs(D || i) + b (and check if P==x*G)
9688  // compute I = x*Hp(P)
9689  const account_keys& ack = get_account().get_keys();
9690  crypto::key_derivation derivation;
9691  bool r = crypto::generate_key_derivation(tx_public_key, ack.m_view_secret_key, derivation);
9692  CHECK_AND_ASSERT_MES(r, false, "failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
9693 
9694  r = crypto::derive_public_key(derivation, out_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub);
9695  CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key (" << derivation << ", " << out_index << ", " << ack.m_account_address.m_spend_public_key << ")");
9696 
9697  crypto::derive_secret_key(derivation, out_index, ack.m_spend_secret_key, in_ephemeral.sec);
9698  crypto::public_key out_pkey_test;
9699  r = crypto::secret_key_to_public_key(in_ephemeral.sec, out_pkey_test);
9700  CHECK_AND_ASSERT_MES(r, false, "failed to secret_key_to_public_key(" << in_ephemeral.sec << ")");
9701  CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_pkey_test, false, "derived secret key doesn't match derived public key");
9702 
9703  crypto::generate_key_image(in_ephemeral.pub, in_ephemeral.sec, calculated_key_image);
9704 
9705  index_keyimage_map.emplace(out_index, calculated_key_image);
9706  m_key_image_cache.emplace(tx_public_key, index_keyimage_map);
9707  return key_image == calculated_key_image;
9708 }
crypto::public_key pub
void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key)
Definition: crypto.h:282
crypto::secret_key sec
POD_CLASS key_derivation
Definition: crypto.h:98
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
const account_keys & get_keys() const
Definition: account.cpp:264
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image)
Definition: crypto.h:324
POD_CLASS public_key
Definition: crypto.h:76
crypto::secret_key m_view_secret_key
Definition: account.h:45
account_public_address m_account_address
Definition: account.h:43
POD_CLASS key_image
Definition: crypto.h:102
crypto::secret_key m_spend_secret_key
Definition: account.h:44
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
Definition: crypto.h:275
cryptonote::account_base & get_account()
Definition: wallet2.h:734
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
Here is the call graph for this function:

◆ light_wallet_login()

bool tools::wallet2::light_wallet_login ( bool new_address)

Definition at line 9240 of file wallet2.cpp.

9241 {
9242  MDEBUG("Light wallet login request");
9243  m_light_wallet_connected = false;
9246  request.address = get_account().get_public_address_str(m_nettype);
9247  request.view_key = string_tools::pod_to_hex(get_account().get_keys().m_view_secret_key);
9248  // Always create account if it doesn't exist.
9249  request.create_account = true;
9250  m_daemon_rpc_mutex.lock();
9251  bool connected = invoke_http_json("/login", request, response, rpc_timeout, "POST");
9252  m_daemon_rpc_mutex.unlock();
9253  // MyMonero doesn't send any status message. OpenMonero does.
9254  m_light_wallet_connected = connected && (response.status.empty() || response.status == "success");
9255  new_address = response.new_address;
9256  MDEBUG("Status: " << response.status);
9257  MDEBUG("Reason: " << response.reason);
9258  MDEBUG("New wallet: " << response.new_address);
9259  if(m_light_wallet_connected)
9260  {
9261  // Clear old data on successful login.
9262  // m_transfers.clear();
9263  // m_payments.clear();
9264  // m_unconfirmed_payments.clear();
9265  }
9266  return m_light_wallet_connected;
9267 }
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
epee::misc_utils::struct_init< response_t > response
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
#define MDEBUG(x)
Definition: misc_log_ex.h:76
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:

◆ light_wallet_parse_rct_str()

bool tools::wallet2::light_wallet_parse_rct_str ( const std::string &  rct_string,
const crypto::public_key tx_pub_key,
uint64_t  internal_output_index,
rct::key decrypted_mask,
rct::key rct_commit,
bool  decrypt 
) const

Definition at line 9642 of file wallet2.cpp.

9643 {
9644  // rct string is empty if output is non RCT
9645  if (rct_string.empty())
9646  return false;
9647  // rct_string is a string with length 64+64+64 (<rct commit> + <encrypted mask> + <rct amount>)
9648  rct::key encrypted_mask;
9649  std::string rct_commit_str = rct_string.substr(0,64);
9650  std::string encrypted_mask_str = rct_string.substr(64,64);
9651  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, rct_commit_str), error::wallet_internal_error, "Invalid rct commit hash: " + rct_commit_str);
9652  THROW_WALLET_EXCEPTION_IF(string_tools::validate_hex(64, encrypted_mask_str), error::wallet_internal_error, "Invalid rct mask: " + encrypted_mask_str);
9653  string_tools::hex_to_pod(rct_commit_str, rct_commit);
9654  string_tools::hex_to_pod(encrypted_mask_str, encrypted_mask);
9655  if (decrypt) {
9656  // Decrypt the mask
9657  crypto::key_derivation derivation;
9658  bool r = generate_key_derivation(tx_pub_key, get_account().get_keys().m_view_secret_key, derivation);
9659  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
9660  crypto::secret_key scalar;
9661  crypto::derivation_to_scalar(derivation, internal_output_index, scalar);
9662  sc_sub(decrypted_mask.bytes,encrypted_mask.bytes,rct::hash_to_scalar(rct::sk2rct(scalar)).bytes);
9663  }
9664  return true;
9665 }
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:279
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *)
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
bool validate_hex(uint64_t length, const std::string &str)
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
void hash_to_scalar(key &hash, const void *data, const std::size_t l)
Definition: rctOps.cpp:536
unsigned char bytes[32]
Definition: rctTypes.h:86
T decrypt(const std::string &ciphertext, const crypto::secret_key &skey, bool authenticated=true) const
Definition: wallet2.cpp:13223
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
Here is the call graph for this function:

◆ load()

void tools::wallet2::load ( const std::string &  wallet,
const epee::wipeable_string password 
)

Definition at line 5833 of file wallet2.cpp.

5834 {
5835  clear();
5836  prepare_file_names(wallet_);
5837 
5838  boost::system::error_code e;
5839  bool exists = boost::filesystem::exists(m_keys_file, e);
5840  THROW_WALLET_EXCEPTION_IF(e || !exists, error::file_not_found, m_keys_file);
5841  lock_keys_file();
5842  THROW_WALLET_EXCEPTION_IF(!is_keys_file_locked(), error::wallet_internal_error, "internal error: \"" + m_keys_file + "\" is opened by another wallet program");
5843 
5844  // this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded).
5845  unlock_keys_file();
5846  if (!load_keys(m_keys_file, password))
5847  {
5849  }
5850  LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_nettype));
5851  lock_keys_file();
5852 
5853  wallet_keys_unlocker unlocker(*this, m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only, password);
5854 
5855  //keys loaded ok!
5856  //try to load wallet file. but even if we failed, it is not big problem
5857  if(!boost::filesystem::exists(m_wallet_file, e) || e)
5858  {
5859  LOG_PRINT_L0("file not found: " << m_wallet_file << ", starting with empty blockchain");
5860  m_account_public_address = m_account.get_keys().m_account_address;
5861  }
5862  else
5863  {
5864  wallet2::cache_file_data cache_file_data;
5865  std::string buf;
5866  bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf, std::numeric_limits<size_t>::max());
5868 
5869  // try to read it as an encrypted cache
5870  try
5871  {
5872  LOG_PRINT_L1("Trying to decrypt cache data");
5873 
5874  r = ::serialization::parse_binary(buf, cache_file_data);
5875  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + m_wallet_file + '\"');
5876  std::string cache_data;
5877  cache_data.resize(cache_file_data.cache_data.size());
5878  crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]);
5879 
5880  try {
5881  std::stringstream iss;
5882  iss << cache_data;
5884  ar >> *this;
5885  }
5886  catch(...)
5887  {
5888  // try with previous scheme: direct from keys
5889  crypto::chacha_key key;
5890  generate_chacha_key_from_secret_keys(key);
5891  crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cache_data[0]);
5892  try {
5893  std::stringstream iss;
5894  iss << cache_data;
5896  ar >> *this;
5897  }
5898  catch (...)
5899  {
5900  crypto::chacha8(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cache_data[0]);
5901  try
5902  {
5903  std::stringstream iss;
5904  iss << cache_data;
5906  ar >> *this;
5907  }
5908  catch (...)
5909  {
5910  LOG_PRINT_L0("Failed to open portable binary, trying unportable");
5911  boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
5912  std::stringstream iss;
5913  iss.str("");
5914  iss << cache_data;
5915  boost::archive::binary_iarchive ar(iss);
5916  ar >> *this;
5917  }
5918  }
5919  }
5920  }
5921  catch (...)
5922  {
5923  LOG_PRINT_L1("Failed to load encrypted cache, trying unencrypted");
5924  try {
5925  std::stringstream iss;
5926  iss << buf;
5928  ar >> *this;
5929  }
5930  catch (...)
5931  {
5932  LOG_PRINT_L0("Failed to open portable binary, trying unportable");
5933  boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
5934  std::stringstream iss;
5935  iss.str("");
5936  iss << buf;
5937  boost::archive::binary_iarchive ar(iss);
5938  ar >> *this;
5939  }
5940  }
5942  m_account_public_address.m_spend_public_key != m_account.get_keys().m_account_address.m_spend_public_key ||
5943  m_account_public_address.m_view_public_key != m_account.get_keys().m_account_address.m_view_public_key,
5944  error::wallet_files_doesnt_correspond, m_keys_file, m_wallet_file);
5945  }
5946 
5947  cryptonote::block genesis;
5948  generate_genesis(genesis);
5949  crypto::hash genesis_hash = get_block_hash(genesis);
5950 
5951  if (m_blockchain.empty())
5952  {
5953  m_blockchain.push_back(genesis_hash);
5954  m_last_block_reward = cryptonote::get_outs_etn_amount(genesis.miner_tx);
5955  }
5956  else
5957  {
5958  check_genesis(genesis_hash);
5959  }
5960 
5961  trim_hashchain();
5962 
5963  if (get_num_subaddress_accounts() == 0)
5964  add_subaddress_account(tr("Primary account"));
5965 
5966  try
5967  {
5968  find_and_save_rings(false);
5969  }
5970  catch (const std::exception &e)
5971  {
5972  MERROR("Failed to save rings, will try again next time");
5973  }
5974 
5975  try
5976  {
5977  m_message_store.read_from_file(get_multisig_wallet_state(), m_mms_file);
5978  }
5979  catch (const std::exception &e)
5980  {
5981  MERROR("Failed to initialize MMS, it will be unusable");
5982  }
5983 }
#define MERROR(x)
Definition: misc_log_ex.h:73
mms::multisig_wallet_state get_multisig_wallet_state() const
Definition: wallet2.cpp:13615
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
::std::string string
Definition: gtest-port.h:1097
uint64_t get_outs_etn_amount(const transaction &tx)
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
const char * key
Definition: hmac_keccak.cpp:39
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
bool parse_binary(const std::string &blob, T &v)
Definition: binary_utils.h:41
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
void add_subaddress_account(const std::string &label, const bool update_account_tags=true)
Definition: wallet2.cpp:1463
void chacha8(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
const account_keys & get_keys() const
Definition: account.cpp:264
friend class wallet_keys_unlocker
Definition: wallet2.h:213
file_error_base< file_not_found_message_index > file_not_found
bool unlock_keys_file()
Definition: wallet2.cpp:8225
void read_from_file(const multisig_wallet_state &state, const std::string &filename)
file_error_base< file_read_error_message_index > file_read_error
bool empty() const
Definition: wallet2.h:190
const char * buf
Definition: slow_memmem.cpp:74
bool is_keys_file_locked() const
Definition: wallet2.cpp:8236
account_public_address m_account_address
Definition: account.h:43
size_t get_num_subaddress_accounts() const
Definition: wallet2.h:801
static const char * tr(const char *str)
Definition: wallet2.cpp:994
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_block_hash(uint64_t height)
POD_CLASS hash
Definition: hash.h:50
bool find_and_save_rings(bool force=true)
Definition: wallet2.cpp:8109
void push_back(const crypto::hash &hash)
Definition: wallet2.h:184
bool lock_keys_file()
Definition: wallet2.cpp:8214
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_multisig_tx()

bool tools::wallet2::load_multisig_tx ( cryptonote::blobdata  blob,
multisig_tx_set exported_txs,
std::function< bool(const multisig_tx_set &)>  accept_func = NULL 
)

Definition at line 7549 of file wallet2.cpp.

7550 {
7551  if(!parse_multisig_tx_from_str(s, exported_txs))
7552  {
7553  LOG_PRINT_L0("Failed to parse multisig transaction from string");
7554  return false;
7555  }
7556 
7557  LOG_PRINT_L1("Loaded multisig tx unsigned data from binary: " << exported_txs.m_ptx.size() << " transactions");
7558  for (auto &ptx: exported_txs.m_ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(ptx.tx));
7559 
7560  if (accept_func && !accept_func(exported_txs))
7561  {
7562  LOG_PRINT_L1("Transactions rejected by callback");
7563  return false;
7564  }
7565 
7566  const bool is_signed = exported_txs.m_signers.size() >= m_multisig_threshold;
7567  if (is_signed)
7568  {
7569  for (const auto &ptx: exported_txs.m_ptx)
7570  {
7571  const crypto::hash txid = get_transaction_hash(ptx.tx);
7572  if (store_tx_info())
7573  {
7574  m_tx_keys.insert(std::make_pair(txid, ptx.tx_key));
7575  m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys));
7576  }
7577  }
7578  }
7579 
7580  return true;
7581 }
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
std::string obj_to_json_str(T &obj)
bool store_tx_info() const
Definition: wallet2.h:1069
crypto::hash get_transaction_hash(const transaction &t)
POD_CLASS hash
Definition: hash.h:50
bool parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx_set &exported_txs) const
Definition: wallet2.cpp:7505
Here is the call graph for this function:

◆ load_multisig_tx_from_file()

bool tools::wallet2::load_multisig_tx_from_file ( const std::string &  filename,
multisig_tx_set exported_txs,
std::function< bool(const multisig_tx_set &)>  accept_func = NULL 
)

Definition at line 7583 of file wallet2.cpp.

7584 {
7585  std::string s;
7586  boost::system::error_code errcode;
7587 
7588  if (!boost::filesystem::exists(filename, errcode))
7589  {
7590  LOG_PRINT_L0("File " << filename << " does not exist: " << errcode);
7591  return false;
7592  }
7593  if (!epee::file_io_utils::load_file_to_string(filename.c_str(), s))
7594  {
7595  LOG_PRINT_L0("Failed to load from " << filename);
7596  return false;
7597  }
7598 
7599  if (!load_multisig_tx(s, exported_txs, accept_func))
7600  {
7601  LOG_PRINT_L0("Failed to parse multisig tx data from " << filename);
7602  return false;
7603  }
7604  return true;
7605 }
::std::string string
Definition: gtest-port.h:1097
bool load_multisig_tx(cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function< bool(const multisig_tx_set &)> accept_func=NULL)
Definition: wallet2.cpp:7549
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
Here is the call graph for this function:

◆ load_tx()

bool tools::wallet2::load_tx ( const std::string &  signed_filename,
std::vector< tools::wallet2::pending_tx > &  ptx,
std::function< bool(const signed_tx_set &)>  accept_func = NULL 
)

Definition at line 7321 of file wallet2.cpp.

7322 {
7323  std::string s;
7324  boost::system::error_code errcode;
7325  signed_tx_set signed_txs;
7326 
7327  if (!boost::filesystem::exists(signed_filename, errcode))
7328  {
7329  LOG_PRINT_L0("File " << signed_filename << " does not exist: " << errcode);
7330  return false;
7331  }
7332 
7333  if (!epee::file_io_utils::load_file_to_string(signed_filename.c_str(), s))
7334  {
7335  LOG_PRINT_L0("Failed to load from " << signed_filename);
7336  return false;
7337  }
7338 
7339  return parse_tx_from_str(s, ptx, accept_func);
7340 }
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector< tools::wallet2::pending_tx > &ptx, std::function< bool(const signed_tx_set &)> accept_func)
Definition: wallet2.cpp:7342
Here is the call graph for this function:

◆ load_unsigned_tx()

bool tools::wallet2::load_unsigned_tx ( const std::string &  unsigned_filename,
unsigned_tx_set exported_txs 
) const

Definition at line 7014 of file wallet2.cpp.

7015 {
7016  std::string s;
7017  boost::system::error_code errcode;
7018 
7019  if (!boost::filesystem::exists(unsigned_filename, errcode))
7020  {
7021  LOG_PRINT_L0("File " << unsigned_filename << " does not exist: " << errcode);
7022  return false;
7023  }
7024  if (!epee::file_io_utils::load_file_to_string(unsigned_filename.c_str(), s))
7025  {
7026  LOG_PRINT_L0("Failed to load from " << unsigned_filename);
7027  return false;
7028  }
7029 
7030  return parse_unsigned_tx_from_str(s, exported_txs);
7031 }
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const
Definition: wallet2.cpp:7033
Here is the call graph for this function:

◆ lock_keys_file()

bool tools::wallet2::lock_keys_file ( )

Definition at line 8214 of file wallet2.cpp.

8215 {
8216  if (m_keys_file_locker)
8217  {
8218  MDEBUG(m_keys_file << " is already locked.");
8219  return false;
8220  }
8221  m_keys_file_locker.reset(new tools::file_locker(m_keys_file));
8222  return true;
8223 }
#define MDEBUG(x)
Definition: misc_log_ex.h:76

◆ make_dummy()

std::unique_ptr< wallet2 > tools::wallet2::make_dummy ( const boost::program_options::variables_map &  vm,
bool  unattended,
const std::function< boost::optional< password_container >(const char *, bool)> &  password_prompter 
)
static

Just parses variables.

Definition at line 1261 of file wallet2.cpp.

1262 {
1263  const options opts{};
1264  return make_basic(vm, unattended, opts, password_prompter);
1265 }

◆ make_from_file()

std::pair< std::unique_ptr< wallet2 >, password_container > tools::wallet2::make_from_file ( const boost::program_options::variables_map &  vm,
bool  unattended,
const std::string &  wallet_file,
const std::function< boost::optional< password_container >(const char *, bool)> &  password_prompter 
)
static

Uses stdin and stdout. Returns a wallet2 and password for wallet_file if no errors.

Definition at line 1233 of file wallet2.cpp.

1235 {
1236  const options opts{};
1237  auto pwd = get_password(vm, opts, password_prompter, false);
1238  if (!pwd)
1239  {
1240  return {nullptr, password_container{}};
1241  }
1242  auto wallet = make_basic(vm, unattended, opts, password_prompter);
1243  if (wallet && !wallet_file.empty())
1244  {
1245  wallet->load(wallet_file, pwd->password());
1246  }
1247  return {std::move(wallet), std::move(*pwd)};
1248 }
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_from_json()

std::pair< std::unique_ptr< wallet2 >, tools::password_container > tools::wallet2::make_from_json ( const boost::program_options::variables_map &  vm,
bool  unattended,
const std::string &  json_file,
const std::function< boost::optional< password_container >(const char *, bool)> &  password_prompter 
)
static

Uses stdin and stdout. Returns a wallet2 if no errors.

Definition at line 1227 of file wallet2.cpp.

1228 {
1229  const options opts{};
1230  return generate_from_json(json_file, vm, unattended, opts, password_prompter);
1231 }
Here is the caller graph for this function:

◆ make_multisig() [1/2]

std::string tools::wallet2::make_multisig ( const epee::wipeable_string password,
const std::vector< std::string > &  info,
uint32_t  threshold 
)

Creates a multisig wallet.

Returns
empty if done, non empty if we need to send another string to other participants

Definition at line 5466 of file wallet2.cpp.

5469 {
5470  std::vector<crypto::secret_key> secret_keys(info.size());
5471  std::vector<crypto::public_key> public_keys(info.size());
5472  unpack_multisig_info(info, public_keys, secret_keys);
5473  return make_multisig(password, secret_keys, public_keys, threshold);
5474 }
std::string make_multisig(const epee::wipeable_string &password, const std::vector< std::string > &info, uint32_t threshold)
Creates a multisig wallet.
Definition: wallet2.cpp:5466
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
uint8_t threshold
Definition: blockchain.cpp:92

◆ make_multisig() [2/2]

std::string tools::wallet2::make_multisig ( const epee::wipeable_string password,
const std::vector< crypto::secret_key > &  view_keys,
const std::vector< crypto::public_key > &  spend_keys,
uint32_t  threshold 
)

Creates a multisig wallet.

Returns
empty if done, non empty if we need to send another string to other participants

Definition at line 5145 of file wallet2.cpp.

5149 {
5150  CHECK_AND_ASSERT_THROW_MES(!view_keys.empty(), "empty view keys");
5151  CHECK_AND_ASSERT_THROW_MES(view_keys.size() == spend_keys.size(), "Mismatched view/spend key sizes");
5152  CHECK_AND_ASSERT_THROW_MES(threshold > 1 && threshold <= spend_keys.size() + 1, "Invalid threshold");
5153 
5154  std::string extra_multisig_info;
5155  std::vector<crypto::secret_key> multisig_keys;
5156  rct::key spend_pkey = rct::identity();
5157  rct::key spend_skey;
5158  std::vector<crypto::public_key> multisig_signers;
5159 
5160  // decrypt keys
5162  if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
5163  {
5164  crypto::chacha_key chacha_key;
5165  crypto::generate_chacha_key(password.data(), password.size(), chacha_key, m_kdf_rounds);
5166  m_account.encrypt_viewkey(chacha_key);
5167  m_account.decrypt_keys(chacha_key);
5168  keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this, chacha_key]() { m_account.encrypt_keys(chacha_key); m_account.decrypt_viewkey(chacha_key); });
5169  }
5170 
5171  // In common multisig scheme there are 4 types of key exchange rounds:
5172  // 1. First round is exchange of view secret keys and public spend keys.
5173  // 2. Middle round is exchange of derivations: Ki = b * Mj, where b - spend secret key,
5174  // M - public multisig key (in first round it equals to public spend key), K - new public multisig key.
5175  // 3. Secret spend establishment round sets your secret multisig keys as follows: kl = H(Ml), where M - is *your* public multisig key,
5176  // k - secret multisig key used to sign transactions. k and M are sets of keys, of course.
5177  // And secret spend key as the sum of all participant's secret multisig keys
5178  // 4. Last round establishes multisig wallet's public spend key. Participants exchange their public multisig keys
5179  // and calculate common spend public key as sum of all unique participants' public multisig keys.
5180  // Note that N/N scheme has only first round. N-1/N has 2 rounds: first and last. Common M/N has all 4 rounds.
5181 
5182  // IMPORTANT: wallet's public spend key is not equal to secret_spend_key * G!
5183  // Wallet's public spend key is the sum of unique public multisig keys of all participants.
5184  // secret_spend_key * G = public signer key
5185 
5186  if (threshold == spend_keys.size() + 1)
5187  {
5188  // In N / N case we only need to do one round and calculate secret multisig keys and new secret spend key
5189  MINFO("Creating spend key...");
5190 
5191  // Calculates all multisig keys and spend key
5192  cryptonote::generate_multisig_N_N(get_account().get_keys(), spend_keys, multisig_keys, spend_skey, spend_pkey);
5193 
5194  // Our signer key is b * G, where b is secret spend key.
5195  multisig_signers = spend_keys;
5196  multisig_signers.push_back(get_multisig_signer_public_key(get_account().get_keys().m_spend_secret_key));
5197  }
5198  else
5199  {
5200  // We just got public spend keys of all participants and deriving multisig keys (set of Mi = b * Bi).
5201  // note that derivations are public keys as DH exchange suppose it to be
5202  auto derivations = cryptonote::generate_multisig_derivations(get_account().get_keys(), spend_keys);
5203 
5204  spend_pkey = rct::identity();
5205  multisig_signers = std::vector<crypto::public_key>(spend_keys.size() + 1, crypto::null_pkey);
5206 
5207  if (threshold == spend_keys.size())
5208  {
5209  // N - 1 / N case
5210 
5211  // We need an extra step, so we package all the composite public keys
5212  // we know about, and make a signed string out of them
5213  MINFO("Creating spend key...");
5214 
5215  // Calculating set of our secret multisig keys as follows: mi = H(Mi),
5216  // where mi - secret multisig key, Mi - others' participants public multisig key
5217  multisig_keys = cryptonote::calculate_multisig_keys(derivations);
5218 
5219  // calculating current participant's spend secret key as sum of all secret multisig keys for current participant.
5220  // IMPORTANT: participant's secret spend key is not an entire wallet's secret spend!
5221  // Entire wallet's secret spend is sum of all unique secret multisig keys
5222  // among all of participants and is not held by anyone!
5223  spend_skey = rct::sk2rct(cryptonote::calculate_multisig_signer_key(multisig_keys));
5224 
5225  // Preparing data for the last round to calculate common public spend key. The data contains public multisig keys.
5226  extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, secret_keys_to_public_keys(multisig_keys), rct::rct2sk(spend_skey));
5227  }
5228  else
5229  {
5230  // M / N case
5231  MINFO("Preparing keys for next exchange round...");
5232 
5233  // Preparing data for middle round - packing new public multisig keys to exchage with others.
5234  extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, derivations, m_account.get_keys().m_spend_secret_key);
5235  spend_skey = rct::sk2rct(m_account.get_keys().m_spend_secret_key);
5236 
5237  // Need to store middle keys to be able to proceed in case of wallet shutdown.
5238  m_multisig_derivations = derivations;
5239  }
5240  }
5241 
5242  if (!m_original_keys_available)
5243  {
5244  // Save the original i.e. non-multisig keys so the MMS can continue to use them to encrypt and decrypt messages
5245  // (making a wallet multisig overwrites those keys, see account_base::make_multisig)
5246  m_original_address = m_account.get_keys().m_account_address;
5247  m_original_view_secret_key = m_account.get_keys().m_view_secret_key;
5248  m_original_keys_available = true;
5249  }
5250 
5251  clear();
5252  MINFO("Creating view key...");
5253  crypto::secret_key view_skey = cryptonote::generate_multisig_view_secret_key(get_account().get_keys().m_view_secret_key, view_keys);
5254 
5255  MINFO("Creating multisig address...");
5256  CHECK_AND_ASSERT_THROW_MES(m_account.make_multisig(view_skey, rct::rct2sk(spend_skey), rct::rct2pk(spend_pkey), multisig_keys),
5257  "Failed to create multisig wallet due to bad keys");
5258  memwipe(&spend_skey, sizeof(rct::key));
5259 
5260  init_type(hw::device::device_type::SOFTWARE);
5261  m_original_keys_available = true;
5262  m_multisig = true;
5263  m_multisig_threshold = threshold;
5264  m_multisig_signers = multisig_signers;
5265  ++m_multisig_rounds_passed;
5266 
5267  // re-encrypt keys
5268  keys_reencryptor = epee::misc_utils::auto_scope_leave_caller();
5269 
5270  create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt"));
5271 
5272  setup_new_blockchain();
5273 
5274  if (!m_wallet_file.empty())
5275  store();
5276 
5277  return extra_multisig_info;
5278 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
size_t size() const noexcept
#define MINFO(x)
Definition: misc_log_ex.h:75
::std::string string
Definition: gtest-port.h:1097
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector< crypto::secret_key > &multisig_keys)
Definition: account.cpp:250
std::vector< crypto::public_key > generate_multisig_derivations(const account_keys &keys, const std::vector< crypto::public_key > &derivations)
generate_multisig_derivations performs common DH key derivation. Each middle round in M/N scheme is D...
Definition: multisig.cpp:87
void encrypt_keys(const crypto::chacha_key &key)
Definition: account.h:104
const account_keys & get_keys() const
Definition: account.cpp:264
void generate_multisig_N_N(const account_keys &keys, const std::vector< crypto::public_key > &spend_keys, std::vector< crypto::secret_key > &multisig_keys, rct::key &spend_skey, rct::key &spend_pkey)
Definition: multisig.cpp:58
std::vector< crypto::secret_key > calculate_multisig_keys(const std::vector< crypto::public_key > &derivations)
calculate_multisig_keys. Calculates secret multisig keys from others&#39; participants ones as follows: m...
Definition: multisig.cpp:111
void decrypt_keys(const crypto::chacha_key &key)
Definition: account.h:105
const crypto::public_key null_pkey
Definition: crypto.cpp:72
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
crypto::secret_key m_view_secret_key
Definition: account.h:45
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
account_public_address m_account_address
Definition: account.h:43
key identity()
Definition: rctOps.h:73
crypto::secret_key generate_multisig_view_secret_key(const crypto::secret_key &skey, const std::vector< crypto::secret_key > &skeys)
Definition: multisig.cpp:124
crypto::secret_key m_spend_secret_key
Definition: account.h:44
cryptonote::account_base & get_account()
Definition: wallet2.h:734
void * memwipe(void *src, size_t n)
const char * data() const noexcept
void encrypt_viewkey(const crypto::chacha_key &key)
Definition: account.h:106
void decrypt_viewkey(const crypto::chacha_key &key)
Definition: account.h:107
crypto::secret_key calculate_multisig_signer_key(const std::vector< crypto::secret_key > &multisig_keys)
Definition: multisig.cpp:100
uint8_t threshold
Definition: blockchain.cpp:92
Here is the call graph for this function:

◆ make_multisig_tx_set()

wallet2::multisig_tx_set tools::wallet2::make_multisig_tx_set ( const std::vector< pending_tx > &  ptx_vector) const

Definition at line 7477 of file wallet2.cpp.

7478 {
7479  multisig_tx_set txs;
7480  txs.m_ptx = ptx_vector;
7481 
7482  for (const auto &msk: get_account().get_multisig_keys())
7483  {
7485  for (auto &ptx: txs.m_ptx) for (auto &sig: ptx.multisig_sigs) sig.signing_keys.insert(pkey);
7486  }
7487 
7488  txs.m_signers.insert(get_multisig_signer_public_key());
7489  return txs;
7490 }
crypto::public_key get_multisig_signing_public_key(size_t idx) const
Definition: wallet2.cpp:12914
POD_CLASS public_key
Definition: crypto.h:76
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
cryptonote::account_base & get_account()
Definition: wallet2.h:734

◆ make_new()

std::pair< std::unique_ptr< wallet2 >, password_container > tools::wallet2::make_new ( const boost::program_options::variables_map &  vm,
bool  unattended,
const std::function< boost::optional< password_container >(const char *, bool)> &  password_prompter 
)
static

Uses stdin and stdout. Returns a wallet2 and password for wallet with no file if no errors.

Definition at line 1250 of file wallet2.cpp.

1251 {
1252  const options opts{};
1253  auto pwd = get_password(vm, opts, password_prompter, true);
1254  if (!pwd)
1255  {
1256  return {nullptr, password_container{}};
1257  }
1258  return {make_basic(vm, unattended, opts, password_prompter), std::move(*pwd)};
1259 }
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:

◆ make_uri()

std::string tools::wallet2::make_uri ( const std::string &  address,
const std::string &  payment_id,
uint64_t  amount,
const std::string &  tx_description,
const std::string &  recipient_name,
std::string &  error 
) const

Definition at line 13255 of file wallet2.cpp.

13256 {
13259  {
13260  error = std::string("wrong address: ") + address;
13261  return std::string();
13262  }
13263 
13264  // we want only one payment id
13265  if (info.has_payment_id && !payment_id.empty())
13266  {
13267  error = "A single payment id is allowed";
13268  return std::string();
13269  }
13270 
13271  if (!payment_id.empty())
13272  {
13273  crypto::hash pid32;
13274  crypto::hash8 pid8;
13275  if (!wallet2::parse_long_payment_id(payment_id, pid32) && !parse_short_payment_id(payment_id, pid8))
13276  {
13277  error = "Invalid payment id";
13278  return std::string();
13279  }
13280  }
13281 
13282  std::string uri = "electroneum:" + address;
13283  unsigned int n_fields = 0;
13284 
13285  if (!payment_id.empty())
13286  {
13287  uri += (n_fields++ ? "&" : "?") + std::string("tx_payment_id=") + payment_id;
13288  }
13289 
13290  if (amount > 0)
13291  {
13292  // URI encoded amount is in decimal units, not atomic units
13293  uri += (n_fields++ ? "&" : "?") + std::string("tx_amount=") + cryptonote::print_etn(amount);
13294  }
13295 
13296  if (!recipient_name.empty())
13297  {
13298  uri += (n_fields++ ? "&" : "?") + std::string("recipient_name=") + epee::net_utils::conver_to_url_format(recipient_name);
13299  }
13300 
13301  if (!tx_description.empty())
13302  {
13303  uri += (n_fields++ ? "&" : "?") + std::string("tx_description=") + epee::net_utils::conver_to_url_format(tx_description);
13304  }
13305 
13306  return uri;
13307 }
static bool parse_long_payment_id(const std::string &payment_id_str, crypto::hash &payment_id)
Definition: wallet2.cpp:5712
::std::string string
Definition: gtest-port.h:1097
std::string print_etn(uint64_t amount, unsigned int decimal_point)
cryptonote::network_type nettype() const
Definition: wallet2.h:824
static bool parse_short_payment_id(const std::string &payment_id_str, crypto::hash8 &payment_id)
Definition: wallet2.cpp:5725
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
POD_CLASS hash8
Definition: hash.h:53
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
error
Tracks LMDB error codes.
Definition: error.h:44
Here is the call graph for this function:

◆ merge_destinations() [1/2]

void tools::wallet2::merge_destinations ( bool  merge)
inline

Definition at line 1085 of file wallet2.h.

1085 { m_merge_destinations = merge; }

◆ merge_destinations() [2/2]

bool tools::wallet2::merge_destinations ( ) const
inline

Definition at line 1086 of file wallet2.h.

1086 { return m_merge_destinations; }

◆ multisig()

bool tools::wallet2::multisig ( bool ready = NULL,
uint32_t threshold = NULL,
uint32_t total = NULL 
) const

Definition at line 5634 of file wallet2.cpp.

5635 {
5636  if (!m_multisig)
5637  return false;
5638  if (threshold)
5639  *threshold = m_multisig_threshold;
5640  if (total)
5641  *total = m_multisig_signers.size();
5642  if (ready)
5643  *ready = !(get_account().get_keys().m_account_address.m_spend_public_key == rct::rct2pk(rct::identity()));
5644  return true;
5645 }
const account_keys & get_keys() const
Definition: account.cpp:264
account_public_address m_account_address
Definition: account.h:43
key identity()
Definition: rctOps.h:73
cryptonote::account_base & get_account()
Definition: wallet2.h:734
uint8_t threshold
Definition: blockchain.cpp:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nettype()

cryptonote::network_type tools::wallet2::nettype ( ) const
inline

Definition at line 824 of file wallet2.h.

824 { return m_nettype; }
Here is the caller graph for this function:

◆ parse_long_payment_id()

bool tools::wallet2::parse_long_payment_id ( const std::string &  payment_id_str,
crypto::hash payment_id 
)
static

Definition at line 5712 of file wallet2.cpp.

5713 {
5714  cryptonote::blobdata payment_id_data;
5715  if(!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data))
5716  return false;
5717 
5718  if(sizeof(crypto::hash) != payment_id_data.size())
5719  return false;
5720 
5721  payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_data.data());
5722  return true;
5723 }
std::string blobdata
Definition: blobdatatype.h:39
POD_CLASS hash
Definition: hash.h:50
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_multisig_tx_from_str()

bool tools::wallet2::parse_multisig_tx_from_str ( std::string  multisig_tx_st,
multisig_tx_set exported_txs 
) const

Definition at line 7505 of file wallet2.cpp.

7506 {
7507  const size_t magiclen = strlen(MULTISIG_UNSIGNED_TX_PREFIX);
7508  if (strncmp(multisig_tx_st.c_str(), MULTISIG_UNSIGNED_TX_PREFIX, magiclen))
7509  {
7510  LOG_PRINT_L0("Bad magic from multisig tx data");
7511  return false;
7512  }
7513  try
7514  {
7515  multisig_tx_st = decrypt_with_view_secret_key(std::string(multisig_tx_st, magiclen));
7516  }
7517  catch (const std::exception &e)
7518  {
7519  LOG_PRINT_L0("Failed to decrypt multisig tx data: " << e.what());
7520  return false;
7521  }
7522  try
7523  {
7524  std::istringstream iss(multisig_tx_st);
7526  ar >> exported_txs;
7527  }
7528  catch (...)
7529  {
7530  LOG_PRINT_L0("Failed to parse multisig tx data");
7531  return false;
7532  }
7533 
7534  // sanity checks
7535  for (const auto &ptx: exported_txs.m_ptx)
7536  {
7537  CHECK_AND_ASSERT_MES(ptx.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched selected_transfers/vin sizes");
7538  for (size_t idx: ptx.selected_transfers)
7539  CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
7540  CHECK_AND_ASSERT_MES(ptx.construction_data.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
7541  for (size_t idx: ptx.construction_data.selected_transfers)
7542  CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
7543  CHECK_AND_ASSERT_MES(ptx.construction_data.sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
7544  }
7545 
7546  return true;
7547 }
::std::string string
Definition: gtest-port.h:1097
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
std::string decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated=true) const
Definition: wallet2.cpp:13250
#define MULTISIG_UNSIGNED_TX_PREFIX
Definition: wallet2.cpp:109

◆ parse_payment_id()

bool tools::wallet2::parse_payment_id ( const std::string &  payment_id_str,
crypto::hash payment_id 
)
static

Definition at line 5738 of file wallet2.cpp.

5739 {
5740  if (parse_long_payment_id(payment_id_str, payment_id))
5741  return true;
5742  crypto::hash8 payment_id8;
5743  if (parse_short_payment_id(payment_id_str, payment_id8))
5744  {
5745  memcpy(payment_id.data, payment_id8.data, 8);
5746  memset(payment_id.data + 8, 0, 24);
5747  return true;
5748  }
5749  return false;
5750 }
static bool parse_long_payment_id(const std::string &payment_id_str, crypto::hash &payment_id)
Definition: wallet2.cpp:5712
static bool parse_short_payment_id(const std::string &payment_id_str, crypto::hash8 &payment_id)
Definition: wallet2.cpp:5725
POD_CLASS hash8
Definition: hash.h:53
void * memcpy(void *a, const void *b, size_t c)
Here is the call graph for this function:

◆ parse_short_payment_id()

bool tools::wallet2::parse_short_payment_id ( const std::string &  payment_id_str,
crypto::hash8 payment_id 
)
static

Definition at line 5725 of file wallet2.cpp.

5726 {
5727  cryptonote::blobdata payment_id_data;
5728  if(!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data))
5729  return false;
5730 
5731  if(sizeof(crypto::hash8) != payment_id_data.size())
5732  return false;
5733 
5734  payment_id = *reinterpret_cast<const crypto::hash8*>(payment_id_data.data());
5735  return true;
5736 }
std::string blobdata
Definition: blobdatatype.h:39
POD_CLASS hash8
Definition: hash.h:53
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
Definition: string_tools.h:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_tx_from_str()

bool tools::wallet2::parse_tx_from_str ( const std::string &  signed_tx_st,
std::vector< tools::wallet2::pending_tx > &  ptx,
std::function< bool(const signed_tx_set &)>  accept_func 
)

Definition at line 7342 of file wallet2.cpp.

7343 {
7344  std::string s = signed_tx_st;
7345  boost::system::error_code errcode;
7346  signed_tx_set signed_txs;
7347 
7348  const size_t magiclen = strlen(SIGNED_TX_PREFIX) - 1;
7349  if (strncmp(s.c_str(), SIGNED_TX_PREFIX, magiclen))
7350  {
7351  LOG_PRINT_L0("Bad magic from signed transaction");
7352  return false;
7353  }
7354  s = s.substr(magiclen);
7355  const char version = s[0];
7356  s = s.substr(1);
7357  if (version == '\003')
7358  {
7359  try
7360  {
7361  std::istringstream iss(s);
7363  ar >> signed_txs;
7364  }
7365  catch (const std::exception &e)
7366  {
7367  LOG_PRINT_L0("Failed to parse data from signed transaction: " << e.what());
7368  return false;
7369  }
7370  catch(...)
7371  {
7372  LOG_PRINT_L0("Failed to parse data from signed transaction");
7373  return false;
7374  }
7375  }
7376  else if (version == '\004')
7377  {
7378  try
7379  {
7381  try
7382  {
7383  std::istringstream iss(s);
7385  ar >> signed_txs;
7386  }
7387  catch (const std::exception &e)
7388  {
7389  LOG_PRINT_L0("Failed to parse decrypted data from signed transaction: " << e.what());
7390  return false;
7391  }
7392  }
7393  catch (const std::exception &e)
7394  {
7395  LOG_PRINT_L0("Failed to decrypt signed transaction: " << e.what());
7396  return false;
7397  }
7398  catch(...)
7399  {
7400  LOG_PRINT_L0("Failed to decrypt signed transaction");
7401  return false;
7402  }
7403  }
7404  else
7405  {
7406  LOG_PRINT_L0("Unsupported version in signed transaction");
7407  return false;
7408  }
7409  LOG_PRINT_L0("Loaded signed tx data from binary: " << signed_txs.ptx.size() << " transactions");
7410  for (auto &c_ptx: signed_txs.ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(c_ptx.tx));
7411 
7412  if (accept_func && !accept_func(signed_txs))
7413  {
7414  LOG_PRINT_L1("Transactions rejected by callback");
7415  return false;
7416  }
7417 
7418  // import key images
7419  bool r = import_key_images(signed_txs.key_images);
7420  if (!r) return false;
7421 
7422  // remember key images for this tx, for when we get those txes from the blockchain
7423  for (const auto &e: signed_txs.tx_key_images)
7424  m_cold_key_images.insert(e);
7425 
7426  ptx = signed_txs.ptx;
7427 
7428  return true;
7429 }
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
#define SIGNED_TX_PREFIX
Definition: wallet2.cpp:108
uint64_t import_key_images(const std::vector< std::pair< crypto::key_image, crypto::signature >> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent=true)
Definition: wallet2.cpp:12333
std::string obj_to_json_str(T &obj)
std::string decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated=true) const
Definition: wallet2.cpp:13250
version
Supported socks variants.
Definition: socks.h:57
Here is the call graph for this function:

◆ parse_unsigned_tx_from_str()

bool tools::wallet2::parse_unsigned_tx_from_str ( const std::string &  unsigned_tx_st,
unsigned_tx_set exported_txs 
) const

Definition at line 7033 of file wallet2.cpp.

7034 {
7035  std::string s = unsigned_tx_st;
7036  const size_t magiclen = strlen(UNSIGNED_TX_PREFIX) - 1;
7037  if (strncmp(s.c_str(), UNSIGNED_TX_PREFIX, magiclen))
7038  {
7039  LOG_PRINT_L0("Bad magic from unsigned tx");
7040  return false;
7041  }
7042  s = s.substr(magiclen);
7043  const char version = s[0];
7044  s = s.substr(1);
7045  if (version == '\003')
7046  {
7047  try
7048  {
7049  std::istringstream iss(s);
7051  ar >> exported_txs;
7052  }
7053  catch (const std::exception &e)
7054  {
7055  LOG_PRINT_L0("Failed to parse data from unsigned tx: " << e.what());
7056  return false;
7057  }
7058  catch (...)
7059  {
7060  LOG_PRINT_L0("Failed to parse data from unsigned tx");
7061  return false;
7062  }
7063  }
7064  else if (version == '\004')
7065  {
7066  try
7067  {
7069  try
7070  {
7071  std::istringstream iss(s);
7073  ar >> exported_txs;
7074  }
7075  catch (const std::exception &e)
7076  {
7077  LOG_PRINT_L0("Failed to parse decrypted data from unsigned tx: " << e.what());
7078  return false;
7079  }
7080  }
7081  catch (const std::exception &e)
7082  {
7083  LOG_PRINT_L0("Failed to decrypt unsigned tx: " << e.what());
7084  return false;
7085  }
7086  catch(...)
7087  {
7088  LOG_PRINT_L0("Failed to parse decrypted data from unsigned tx");
7089  return false;
7090  }
7091  }
7092  else
7093  {
7094  LOG_PRINT_L0("Unsupported version in unsigned tx");
7095  return false;
7096  }
7097  LOG_PRINT_L1("Loaded tx unsigned data from binary: " << exported_txs.txes.size() << " transactions");
7098 
7099  return true;
7100 }
std::vector< tools::wallet2::tx_construction_data > txes
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
std::string decrypt_with_view_secret_key(const std::string &ciphertext, bool authenticated=true) const
Definition: wallet2.cpp:13250
version
Supported socks variants.
Definition: socks.h:57
#define UNSIGNED_TX_PREFIX
Definition: wallet2.cpp:107

◆ parse_uri()

bool tools::wallet2::parse_uri ( const std::string &  uri,
std::string &  address,
std::string &  payment_id,
uint64_t amount,
std::string &  tx_description,
std::string &  recipient_name,
std::vector< std::string > &  unknown_parameters,
std::string &  error 
)

Definition at line 13309 of file wallet2.cpp.

13310 {
13311  if (uri.substr(0, 12) != "electroneum:")
13312  {
13313  error = std::string("URI has wrong scheme (expected \"electroneum:\"): ") + uri;
13314  return false;
13315  }
13316 
13317  std::string remainder = uri.substr(12);
13318  const char *ptr = strchr(remainder.c_str(), '?');
13319  address = ptr ? remainder.substr(0, ptr-remainder.c_str()) : remainder;
13320 
13323  {
13324  error = std::string("URI has wrong address: ") + address;
13325  return false;
13326  }
13327  if (!strchr(remainder.c_str(), '?'))
13328  return true;
13329 
13330  std::vector<std::string> arguments;
13331  std::string body = remainder.substr(address.size() + 1);
13332  if (body.empty())
13333  return true;
13334  boost::split(arguments, body, boost::is_any_of("&"));
13335  std::set<std::string> have_arg;
13336  for (const auto &arg: arguments)
13337  {
13338  std::vector<std::string> kv;
13339  boost::split(kv, arg, boost::is_any_of("="));
13340  if (kv.size() != 2)
13341  {
13342  error = std::string("URI has wrong parameter: ") + arg;
13343  return false;
13344  }
13345  if (have_arg.find(kv[0]) != have_arg.end())
13346  {
13347  error = std::string("URI has more than one instance of " + kv[0]);
13348  return false;
13349  }
13350  have_arg.insert(kv[0]);
13351 
13352  if (kv[0] == "tx_amount")
13353  {
13354  amount = 0;
13355  if (!cryptonote::parse_amount(amount, kv[1]))
13356  {
13357  error = std::string("URI has invalid amount: ") + kv[1];
13358  return false;
13359  }
13360  }
13361  else if (kv[0] == "tx_payment_id")
13362  {
13363  if (info.has_payment_id)
13364  {
13365  error = "Separate payment id given with an integrated address";
13366  return false;
13367  }
13371  {
13372  error = "Invalid payment id: " + kv[1];
13373  return false;
13374  }
13375  payment_id = kv[1];
13376  }
13377  else if (kv[0] == "recipient_name")
13378  {
13379  recipient_name = epee::net_utils::convert_from_url_format(kv[1]);
13380  }
13381  else if (kv[0] == "tx_description")
13382  {
13383  tx_description = epee::net_utils::convert_from_url_format(kv[1]);
13384  }
13385  else
13386  {
13387  unknown_parameters.push_back(arg);
13388  }
13389  }
13390  return true;
13391 }
static bool parse_long_payment_id(const std::string &payment_id_str, crypto::hash &payment_id)
Definition: wallet2.cpp:5712
::std::string string
Definition: gtest-port.h:1097
cryptonote::network_type nettype() const
Definition: wallet2.h:824
bool parse_amount(uint64_t &amount, const std::string &str_amount_)
static bool parse_short_payment_id(const std::string &payment_id_str, crypto::hash8 &payment_id)
Definition: wallet2.cpp:5725
CXA_THROW_INFO_T * info
Definition: stack_trace.cpp:91
POD_CLASS hash8
Definition: hash.h:53
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
error
Tracks LMDB error codes.
Definition: error.h:44
Here is the call graph for this function:

◆ path()

std::string tools::wallet2::path ( ) const

Definition at line 6027 of file wallet2.cpp.

6028 {
6029  return m_wallet_file;
6030 }

◆ pop_best_value()

size_t tools::wallet2::pop_best_value ( std::vector< size_t > &  unused_dust_indices,
const std::vector< size_t > &  selected_transfers,
bool  smallest = false 
) const

Definition at line 6740 of file wallet2.cpp.

6741 {
6742  return pop_best_value_from(m_transfers, unused_indices, selected_transfers, smallest);
6743 }
size_t pop_best_value_from(const transfer_container &transfers, std::vector< size_t > &unused_dust_indices, const std::vector< size_t > &selected_transfers, bool smallest=false) const
Definition: wallet2.cpp:6691

◆ pop_best_value_from()

size_t tools::wallet2::pop_best_value_from ( const transfer_container transfers,
std::vector< size_t > &  unused_dust_indices,
const std::vector< size_t > &  selected_transfers,
bool  smallest = false 
) const

Definition at line 6691 of file wallet2.cpp.

6692 {
6693  std::vector<size_t> candidates;
6694  float best_relatedness = 1.0f;
6695  for (size_t n = 0; n < unused_indices.size(); ++n)
6696  {
6697  const transfer_details &candidate = transfers[unused_indices[n]];
6698  float relatedness = 0.0f;
6699  for (std::vector<size_t>::const_iterator i = selected_transfers.begin(); i != selected_transfers.end(); ++i)
6700  {
6701  float r = get_output_relatedness(candidate, transfers[*i]);
6702  if (r > relatedness)
6703  {
6704  relatedness = r;
6705  if (relatedness == 1.0f)
6706  break;
6707  }
6708  }
6709 
6710  if (relatedness < best_relatedness)
6711  {
6712  best_relatedness = relatedness;
6713  candidates.clear();
6714  }
6715 
6716  if (relatedness == best_relatedness)
6717  candidates.push_back(n);
6718  }
6719 
6720  // we have all the least related outputs in candidates, so we can pick either
6721  // the smallest, or a random one, depending on request
6722  size_t idx;
6723  if (smallest)
6724  {
6725  idx = 0;
6726  for (size_t n = 0; n < candidates.size(); ++n)
6727  {
6728  const transfer_details &td = transfers[unused_indices[candidates[n]]];
6729  if (td.amount() < transfers[unused_indices[candidates[idx]]].amount())
6730  idx = n;
6731  }
6732  }
6733  else
6734  {
6735  idx = crypto::rand_idx(candidates.size());
6736  }
6737  return pop_index (unused_indices, candidates[idx]);
6738 }
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition: crypto.h:244
Here is the call graph for this function:

◆ print_ring_members() [1/2]

bool tools::wallet2::print_ring_members ( ) const
inline

Definition at line 1067 of file wallet2.h.

1067 { return m_print_ring_members; }

◆ print_ring_members() [2/2]

void tools::wallet2::print_ring_members ( bool  value)
inline

Definition at line 1068 of file wallet2.h.

1068 { m_print_ring_members = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ public_transactions_required()

bool tools::wallet2::public_transactions_required ( ) const
inline

Definition at line 900 of file wallet2.h.

900 { return nettype() == cryptonote::network_type::MAINNET ? get_blockchain_current_height() >= (1175315 - CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS) : get_blockchain_current_height() >= (1086402 - CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS);} // prepare v2 tx if the block height is one before the fork block (which contains v2+ tx only)
cryptonote::network_type nettype() const
Definition: wallet2.h:824
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
uint64_t get_blockchain_current_height() const
Definition: wallet2.h:898
Here is the call graph for this function:

◆ query_device()

bool tools::wallet2::query_device ( hw::device::device_type device_type,
const std::string &  keys_file_name,
const epee::wipeable_string password,
uint64_t  kdf_rounds = 1 
)
static

determine the key storage for the specified wallet file

Parameters
device_type(OUT) wallet backend as enumerated in hw::device::device_type
keys_file_nameKeys file to verify password for
passwordPassword to verify
Returns
true if password correct, else false

for verification only - determines key storage hardware

Definition at line 4807 of file wallet2.cpp.

4808 {
4810  wallet2::keys_file_data keys_file_data;
4811  std::string buf;
4812  bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
4814 
4815  // Decrypt the contents
4816  r = ::serialization::parse_binary(buf, keys_file_data);
4817  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"');
4818  crypto::chacha_key key;
4819  crypto::generate_chacha_key(password.data(), password.size(), key, kdf_rounds);
4820  std::string account_data;
4821  account_data.resize(keys_file_data.account_data.size());
4822  crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
4823  if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject())
4824  crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
4825 
4826  device_type = hw::device::device_type::SOFTWARE;
4827  // The contents should be JSON if the wallet follows the new format.
4828  if (json.Parse(account_data.c_str()).HasParseError())
4829  {
4830  // old format before JSON wallet key file format
4831  }
4832  else
4833  {
4834  account_data = std::string(json["key_data"].GetString(), json["key_data"].GetString() +
4835  json["key_data"].GetStringLength());
4836 
4837  if (json.HasMember("key_on_device"))
4838  {
4839  GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, hw::device::device_type::SOFTWARE);
4840  device_type = static_cast<hw::device::device_type>(field_key_on_device);
4841  }
4842  }
4843 
4844  cryptonote::account_base account_data_check;
4845 
4846  r = epee::serialization::load_t_from_binary(account_data_check, account_data);
4847  if (!r) return false;
4848  return true;
4849 }
bool key_on_device() const
Definition: wallet2.h:830
size_t size() const noexcept
::std::string string
Definition: gtest-port.h:1097
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
const char * key
Definition: hmac_keccak.cpp:39
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
bool parse_binary(const std::string &blob, T &v)
Definition: binary_utils.h:41
void chacha8(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
bool load_t_from_binary(t_struct &out, const epee::span< const uint8_t > binary_buff)
file_error_base< file_read_error_message_index > file_read_error
GenericDocument< UTF8<> > Document
GenericDocument with UTF8 encoding.
Definition: document.h:2512
const char * buf
Definition: slow_memmem.cpp:74
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, name, type, jtype, mandatory, def)
Definition: json_util.h:32
const char * data() const noexcept
rapidjson::Document json
Definition: transport.cpp:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reconnect_device()

bool tools::wallet2::reconnect_device ( )

Definition at line 1390 of file wallet2.cpp.

1391 {
1392  bool r = true;
1393  hw::device &hwdev = lookup_device(m_device_name);
1394  hwdev.set_name(m_device_name);
1395  hwdev.set_network_type(m_nettype);
1396  hwdev.set_derivation_path(m_device_derivation_path);
1397  hwdev.set_callback(get_device_callback());
1398  r = hwdev.init();
1399  if (!r){
1400  MERROR("Could not init device");
1401  return false;
1402  }
1403 
1404  r = hwdev.connect();
1405  if (!r){
1406  MERROR("Could not connect to the device");
1407  return false;
1408  }
1409 
1410  m_account.set_device(hwdev);
1411  return true;
1412 }
#define MERROR(x)
Definition: misc_log_ex.h:73
virtual bool set_name(const std::string &name)=0
virtual void set_callback(i_device_callback *callback)
Definition: device.hpp:136
void set_device(hw::device &hwdev)
Definition: account.h:92
virtual bool connect(void)=0
virtual void set_derivation_path(const std::string &derivation_path)
Definition: device.hpp:137
virtual bool init(void)=0
virtual void set_network_type(cryptonote::network_type network_type)
Definition: device.hpp:248
Here is the call graph for this function:

◆ refresh() [1/4]

void tools::wallet2::refresh ( bool  trusted_daemon)

Definition at line 3060 of file wallet2.cpp.

3061 {
3062  uint64_t blocks_fetched = 0;
3063  refresh(trusted_daemon, 0, blocks_fetched);
3064 }
unsigned __int64 uint64_t
Definition: stdint.h:136
void refresh(bool trusted_daemon)
Definition: wallet2.cpp:3060
Here is the caller graph for this function:

◆ refresh() [2/4]

void tools::wallet2::refresh ( bool  trusted_daemon,
uint64_t  start_height,
uint64_t blocks_fetched 
)

Definition at line 3066 of file wallet2.cpp.

3067 {
3068  bool received_etn = false;
3069  refresh(trusted_daemon, start_height, blocks_fetched, received_etn);
3070 }
void refresh(bool trusted_daemon)
Definition: wallet2.cpp:3060

◆ refresh() [3/4]

void tools::wallet2::refresh ( bool  trusted_daemon,
uint64_t  start_height,
uint64_t blocks_fetched,
bool received_etn,
bool  check_pool = true 
)

Definition at line 3493 of file wallet2.cpp.

3493  {
3494  if (m_offline) {
3495  blocks_fetched = 0;
3496  received_etn = 0;
3497  return;
3498  }
3499 
3500  if (m_light_wallet) {
3501 
3502  // MyMonero get_address_info needs to be called occasionally to trigger wallet sync.
3503  // This call is not really needed for other purposes and can be removed if mymonero changes their backend.
3505 
3506  // Get basic info
3508  // Last stored block height
3509  uint64_t prev_height = m_light_wallet_blockchain_height;
3510  // Update lw heights
3511  m_light_wallet_scanned_block_height = res.scanned_block_height;
3512  m_light_wallet_blockchain_height = res.blockchain_height;
3513  // If new height - call new_block callback
3514  if (m_light_wallet_blockchain_height != prev_height) {
3515  MDEBUG("new block since last time!");
3516  m_callback->on_lw_new_block(m_light_wallet_blockchain_height - 1);
3517  }
3518  m_light_wallet_connected = true;
3519  MDEBUG("lw scanned block height: " << m_light_wallet_scanned_block_height);
3520  MDEBUG("lw blockchain height: " << m_light_wallet_blockchain_height);
3521  MDEBUG(m_light_wallet_blockchain_height - m_light_wallet_scanned_block_height << " blocks behind");
3522  // TODO: add wallet created block info
3523 
3525  } else
3526  m_light_wallet_connected = false;
3527 
3528  // Lighwallet refresh done
3529  return;
3530  }
3531  received_etn = false;
3532  blocks_fetched = 0;
3533  uint64_t added_blocks = 0;
3534  size_t try_count = 0;
3535  crypto::hash last_tx_hash_id = m_transfers.size() ? m_transfers.back().m_txid : null_hash;
3536  std::list<crypto::hash> short_chain_history;
3539  uint64_t blocks_start_height;
3540  std::vector<cryptonote::block_complete_entry> blocks;
3541  std::vector<parsed_block> parsed_blocks;
3542  bool refreshed = false;
3543  std::shared_ptr<std::pair<std::map<std::pair<uint64_t, uint64_t>, size_t>, std::map<std::pair<std::array<char, 32>, size_t>, size_t>>> output_tracker_cache; //this is where the only usage of output_tracker cache begins
3544  hw::device &hwdev = m_account.get_device();
3545 
3546  // pull the first set of blocks
3547  get_short_chain_history(short_chain_history,
3548  (m_first_refresh_done || trusted_daemon) ? 1 : FIRST_REFRESH_GRANULARITY);
3549  m_run.store(true, std::memory_order_relaxed);
3550  if (start_height > m_blockchain.size() || m_refresh_from_block_height > m_blockchain.size()) {
3551  if (!start_height)
3552  start_height = m_refresh_from_block_height;
3553  // we can shortcut by only pulling hashes up to the start_height
3554  fast_refresh(start_height, blocks_start_height, short_chain_history);
3555  // regenerate the history now that we've got a full set of hashes
3556  short_chain_history.clear();
3557  get_short_chain_history(short_chain_history,
3558  (m_first_refresh_done || trusted_daemon) ? 1 : FIRST_REFRESH_GRANULARITY);
3559  start_height = 0;
3560  // and then fall through to regular refresh processing
3561  }
3562 
3563  // If stop() is called during fast refresh we don't need to continue
3564  if (!m_run.load(std::memory_order_relaxed))
3565  return;
3566  // always reset start_height to 0 to force short_chain_ history to be used on
3567  // subsequent pulls in this refresh.
3568  start_height = 0;
3569 
3570  auto keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this]() {
3571  if (m_encrypt_keys_after_refresh) {
3572  encrypt_keys(*m_encrypt_keys_after_refresh);
3573  m_encrypt_keys_after_refresh = boost::none;
3574  }
3575  });
3576 
3577  auto scope_exit_handler_hwdev = epee::misc_utils::create_scope_leave_handler(
3578  [&]() { hwdev.computing_key_images(false); });
3579  bool first = true;
3580  while (m_run.load(std::memory_order_relaxed)) {
3581  uint64_t next_blocks_start_height;
3582  std::vector<cryptonote::block_complete_entry> next_blocks;
3583  std::vector<parsed_block> next_parsed_blocks;
3584  bool error;
3585  try {
3586  // pull the next set of blocks while we're processing the current one
3587  error = false;
3588  next_blocks.clear();
3589  next_parsed_blocks.clear();
3590  added_blocks = 0;
3591  if (!first && blocks.empty()) {
3592  refreshed = false;
3593  break;
3594  }
3595  tpool.submit(&waiter, [&] {
3596  pull_and_parse_next_blocks(start_height, next_blocks_start_height, short_chain_history, blocks,
3597  parsed_blocks, next_blocks, next_parsed_blocks, error);
3598  });
3599 
3600  if (!first) {
3601  try {
3602  process_parsed_blocks(blocks_start_height, blocks, parsed_blocks, added_blocks,
3603  output_tracker_cache.get());
3604  }
3606  MINFO("Daemon claims next refresh block is out of hash chain bounds, resetting hash chain");
3607  uint64_t stop_height = m_blockchain.offset();
3608  std::vector<crypto::hash> tip(m_blockchain.size() - m_blockchain.offset());
3609  for (size_t i = m_blockchain.offset(); i < m_blockchain.size(); ++i)
3610  tip[i - m_blockchain.offset()] = m_blockchain[i];
3612  generate_genesis(b);
3613  m_blockchain.clear();
3614  m_blockchain.push_back(get_block_hash(b));
3615  short_chain_history.clear();
3616  get_short_chain_history(short_chain_history);
3617  fast_refresh(stop_height, blocks_start_height, short_chain_history, true);
3619  (m_blockchain.size() == stop_height || (m_blockchain.size() == 1 && stop_height == 0)
3620  ? false : true), error::wallet_internal_error, "Unexpected hashchain size");
3621  THROW_WALLET_EXCEPTION_IF(m_blockchain.offset() != 0, error::wallet_internal_error,
3622  "Unexpected hashchain offset");
3623  for (const auto &h: tip)
3624  m_blockchain.push_back(h);
3625  short_chain_history.clear();
3626  get_short_chain_history(short_chain_history);
3627  start_height = stop_height;
3628  throw std::runtime_error(""); // loop again
3629  }
3630  catch (const std::exception &e) {
3631  MERROR("Error parsing blocks: " << e.what());
3632  error = true;
3633  }
3634  blocks_fetched += added_blocks;
3635  }
3636  waiter.wait(&tpool);
3637  if (!first && blocks_start_height == next_blocks_start_height) {
3638  m_node_rpc_proxy.set_height(m_blockchain.size());
3639  refreshed = true;
3640  break;
3641  }
3642 
3643  first = false;
3644 
3645  // handle error from async fetching thread
3646  if (error) {
3647  throw std::runtime_error("proxy exception in refresh thread");
3648  }
3649 
3650  // if we've got at least 10 blocks to refresh, assume we're starting
3651  // a long refresh, and setup a tracking output cache if we need to
3652  // We hit create_output_tracker_cache before doing processing our blocks in process_parsed_blocks above( see 'first' variable)
3653  if (m_track_uses && (!output_tracker_cache ||
3654  (output_tracker_cache->first.empty() && output_tracker_cache->second.empty())) &&
3655  next_blocks.size() >= 10)
3656  output_tracker_cache = create_output_tracker_cache();
3657 
3658  // switch to the new blocks from the daemon
3659  blocks_start_height = next_blocks_start_height;
3660  blocks = std::move(next_blocks);
3661  parsed_blocks = std::move(next_parsed_blocks);
3662  }
3663  catch (const tools::error::password_needed &) {
3664  blocks_fetched += added_blocks;
3665  waiter.wait(&tpool);
3666  throw;
3667  }
3668  catch (const std::exception &) {
3669  blocks_fetched += added_blocks;
3670  waiter.wait(&tpool);
3671  if (try_count < 3) {
3672  LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")...");
3673  first = true;
3674  start_height = 0;
3675  blocks.clear();
3676  parsed_blocks.clear();
3677  short_chain_history.clear();
3678  get_short_chain_history(short_chain_history, 1);
3679  ++try_count;
3680  } else {
3681  LOG_ERROR("pull_blocks failed, try_count=" << try_count);
3682  throw;
3683  }
3684  }
3685  }
3686  if (last_tx_hash_id != (m_transfers.size() ? m_transfers.back().m_txid : null_hash))
3687  received_etn = true;
3688 
3689  try {
3690  // If stop() is called we don't need to check pending transactions
3691  if (check_pool && m_run.load(std::memory_order_relaxed))
3692  update_pool_state(refreshed);
3693  }
3694  catch (...) {
3695  LOG_PRINT_L1("Failed to check pending transactions");
3696  }
3697 
3698  m_first_refresh_done = true;
3699 
3700  LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", pre v10 balance (all accounts): "
3701  << print_etn(balance_all(false)) << ", unlocked: "
3702  << print_etn(unlocked_balance_all(false))
3703  << ", post v10 balance (all accounts): "
3704  << print_etn(balance_all(true)) << ", unlocked: "
3705  << print_etn(unlocked_balance_all(true)));
3706 
3707  //get the testnet bridge address - should be same as mainnet because of our netbyte being erroneously set to the same thing when Electroneum was first created
3708  // cryptonote::account_public_address bridge_public_address;
3709  // std::string portal_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
3710  // std::string portal_address_spendkey_hex_str = "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
3711  // epee::string_tools::hex_to_pod(portal_address_viewkey_hex_str, bridge_public_address.m_view_public_key);
3712  // epee::string_tools::hex_to_pod(portal_address_spendkey_hex_str, bridge_public_address.m_spend_public_key);
3713  // std::string bridge_address = cryptonote::get_account_address_as_str(this->nettype(), false, bridge_public_address); //OK
3714 
3715  //generate the coinbase burn address. spendkey is "9511fabcb699b4f9dffc1779713d0dd7eb1ca56ba5b8ab8d3253a0a6ccf736b3", address "etnkCys4uGhSi9h48ajL9vBDJTcn2s2ttXtXq3SXWPAbiMHNhHitu5fJ8QgRfFWTzmJ8QgRfFWTzmJ8QgRfFWTzm4t51HTfCtK"
3716  //cryptonote::account_public_address coinbase_burn_address;
3717  //crypto::hash h;
3718  //crypto::ec_point point;
3719  //epee::string_tools::hex_to_pod("714c8d8eeee5243e7f266e5210f76f58b8b1d6330cedfbc4eda6d5947b212012", h); // genesis hash hex ---> hash type
3720  //crypto::hash_to_point(h, point); // generate curve point (burn address spendkey) deterministically in such a way that we can't recover the private key
3721  //crypto::public_key coinbase_burn_address_spendkey;
3722  //std::copy(std::begin(point.data), std::end(point.data), std::begin(coinbase_burn_address_spendkey.data)); // serialise point to pubkey type
3723  //std::string coinbase_burn_address_spendkey_hex_str = epee::string_tools::pod_to_hex(coinbase_burn_address_spendkey); // for testing only. pub spend =
3724  //std::string coinbase_burn_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
3725  //coinbase_burn_address.m_spend_public_key = coinbase_burn_address_spendkey;
3726  //epee::string_tools::hex_to_pod(coinbase_burn_address_viewkey_hex_str, coinbase_burn_address.m_view_public_key);
3727  //std::string coinbase_burn_address_str = cryptonote::get_account_address_as_str(this->nettype(), false, coinbase_burn_address); //OK
3728 
3729 
3730  try {
3731  // V9-->V10 PUBLIC MIGRATIONS
3732  // check that the local blockchain height is at least the v10 fork height + 5 blocks (so we know we don't need to scan for any more v1 outputs and they have all have 5 confs)
3733  //todo: write function for wallet that gets the b.major version for a given *local* blockchain height, to save hardcoding heights.
3734  uint64_t migration_minheight = this->nettype() == TESTNET ? 1086402 + 5 : 1175315 + 5;
3735  if (this->get_blockchain_current_height() > migration_minheight && this->unlocked_balance_all(false) != 0) {
3736  LOG_PRINT_L0(
3737  "You are now on the transparent version of Electroneum and so we're giving you the chance to migrate your funds via a sweep transaction back to your address.\n Don't worry, this migration is completely free of charge. Please follow the prompts to continue.");
3738  std::map<uint32_t, std::map<uint32_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress_per_account; // map of: account index ----> (subaddress index, pair(u-balance, unlock time))
3739  // for each account, grab all of the subaddress info (index, (balance, unlock))
3740  for (uint32_t account_index = 0; account_index < this->get_num_subaddress_accounts(); ++account_index) {
3741  unlocked_balance_per_subaddress_per_account[account_index] = this->unlocked_balance_per_subaddress(
3742  account_index, false);
3743  }
3744  for (uint32_t i = 0; i < this->get_num_subaddress_accounts(); i++) {
3746  index.major = i;
3747  for (auto subaddress: unlocked_balance_per_subaddress_per_account[i]) {
3748  index.minor = subaddress.first;
3749 
3750  if (subaddress.second.first != 0 &&
3751  subaddress.second.second == 0/*is there a fully unlocked nonzero balance /sanity check*/) {
3752  cryptonote::account_public_address address = get_subaddress(index); // BRIDGE PORTAL ADDRESS
3753  std::set<uint32_t> subaddress_source{index.minor};
3754  std::vector<wallet2::pending_tx> ptx_vector = this->create_transactions_all(0,
3755  address /*dest address*/,
3756  index.major !=
3757  0 ||
3758  index.minor !=
3759  0 /*is dest a subaddress*/,
3760  1 /*one output only*/,
3761  0 /* don't mix*/,
3762  0 /*default unlock time*/,
3763  4 /*highest priority*/,
3764  vector<uint8_t>() /*empty tx extra */,
3765  index.major /*account index*/,
3766  subaddress_source /*source subaddr index*/,
3767  true /*migrate*/);
3768  this->commit_tx(ptx_vector);
3769  }
3770  }
3771  }
3772  LOG_PRINT_L0("Migration to the public version of the blockchain has completed. Please use the command show_transfers (CLI Wallet) or get_transfers (RPC Wallet) to see the details of your migration transactions.");
3773  }
3774 
3775  } catch(...) {
3776  THROW_WALLET_EXCEPTION(error::wallet_internal_error, "V9 (Privatised)-->V10 (Public) wallet migration failed.");
3777  }
3778 
3779  try {
3780  // V10 Migration to Electroneum Smart Chain
3781  cryptonote::account_public_address portal_address;
3782  std::string portal_address_viewkey_hex_str;
3783  std::string portal_address_spendkey_hex_str;
3784  if(m_nettype == MAINNET){
3785  portal_address_viewkey_hex_str = "2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375";
3786  portal_address_spendkey_hex_str = "8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137";
3787  }else{
3788  portal_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
3789  portal_address_spendkey_hex_str = "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3"; //
3790  }
3791 
3792  bool portal_wallet = //if the portal address wallet ever needs opening, don't allow it to sweep to itself
3793  epee::string_tools::pod_to_hex(get_address().m_spend_public_key) ==
3794  portal_address_spendkey_hex_str &&
3795  epee::string_tools::pod_to_hex(get_address().m_view_public_key) == portal_address_viewkey_hex_str;
3796 
3797  epee::string_tools::hex_to_pod(portal_address_spendkey_hex_str, portal_address.m_spend_public_key);
3798  epee::string_tools::hex_to_pod(portal_address_viewkey_hex_str, portal_address.m_view_public_key);
3799 
3800  // ONLY do migration transactions after the fork block
3801  uint64_t smartchain_migration_minheight = this->nettype() == MAINNET ? 1811310 : 1455270;
3802  if (this->get_blockchain_current_height() > smartchain_migration_minheight) {
3803  // check that unlocked balance = unlocked balance as a best-effort to ensure that we're not migrating the funds whilst more are in transit/confirming
3804  if ((!portal_wallet) && (this->balance_all(true) != 0) &&
3805  (this->unlocked_balance_all(true) == this->balance_all(true))) {
3806  std::cout << std::endl << "You are beginning your token migration over to the Electroneum Smart Chain." << std::endl;
3807  std::cout << "This transaction is feeless. For further information, please read our documentation over at https:///developer.electroneum.com/migration-to-smart-chain/overview" << std::endl;
3808  std::map<uint32_t, std::map<uint32_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress_per_account; // map of: account index ----> (subaddress index, pair(u-balance, unlock time))
3809  // for each account, grab all of the subaddress info (index, (balance, unlock))
3810  for (uint32_t account_index = 0;
3811  account_index < this->get_num_subaddress_accounts(); ++account_index) {
3812  unlocked_balance_per_subaddress_per_account[account_index] = this->unlocked_balance_per_subaddress(
3813  account_index, true);
3814  }
3815  for (uint32_t i = 0; i < this->get_num_subaddress_accounts(); i++) {
3817  index.major = i;
3818  for (auto subaddress: unlocked_balance_per_subaddress_per_account[i]) {
3819  index.minor = subaddress.first;
3820 
3821  if (subaddress.second.first != 0 &&
3822  subaddress.second.second ==
3823  0/*is there a fully unlocked nonzero balance /sanity check*/) {
3824  std::set<uint32_t> subaddress_source{index.minor};
3825  std::vector<wallet2::pending_tx> ptx_vector = this->create_transactions_all(0,
3826  portal_address /*dest address (portal address for bridge)*/,
3827  0 /*is dest a subaddress*/,
3828  1 /*one output only*/, //???????
3829  0 /* don't mix*/,
3830  0 /*default unlock time*/,
3831  1 /*priority - set low in case they don't have fees for high priority but do for low priority*/,
3832  vector<uint8_t>() /*empty tx extra */,
3833  index.major /*account index*/,
3834  subaddress_source /*source subaddr index*/,
3835  false /*migrate to transparent chain*/);
3836  this->commit_tx(ptx_vector);
3837  }
3838  }
3839  }
3840  std::cout << std::endl;
3841  std::cout << "Migration to Smart Chain portal address completed. Please use the command show_transfers (CLI Wallet) or get_transfers (RPC Wallet) to see the details of your Smart Chain migration transactions." << std::endl;
3842  std::cout << "Please note that the entire migration process is not instant and your funds may take some time to show up in the Smart Chain." << std::endl;
3843  std::cout << "You can find your SmartChain address using the \"spendkey\" command in the CLI wallet." << std::endl;
3844  }
3845  }
3846  } catch(...) {
3847  THROW_WALLET_EXCEPTION(error::wallet_internal_error, "V10 Smart Chain migration failed.");
3848  }
3849 }
const char * res
Definition: hmac_keccak.cpp:41
uint64_t balance_all(bool public_blockchain) const
Definition: wallet2.cpp:6292
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MINFO(x)
Definition: misc_log_ex.h:75
void commit_tx(pending_tx &ptx_vector)
Definition: wallet2.cpp:6887
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
::std::string string
Definition: gtest-port.h:1097
A global thread pool.
Definition: threadpool.h:43
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
std::vector< wallet2::pending_tx > 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 bool migrate=false)
Definition: wallet2.cpp:10359
#define FIRST_REFRESH_GRANULARITY
Definition: wallet2.cpp:132
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
bool light_wallet_get_address_info(tools::COMMAND_RPC_GET_ADDRESS_INFO::response &response)
Definition: wallet2.cpp:9438
cryptonote::network_type nettype() const
Definition: wallet2.h:824
static threadpool & getInstance()
Definition: threadpool.h:46
#define MDEBUG(x)
Definition: misc_log_ex.h:76
virtual void on_lw_new_block(uint64_t height)
Definition: wallet2.h:134
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index &index) const
Definition: wallet2.cpp:1430
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
void wait(threadpool *tpool)
Definition: threadpool.cpp:115
unsigned int uint32_t
Definition: stdint.h:126
hw::device & get_device() const
Definition: account.h:91
unsigned __int64 uint64_t
Definition: stdint.h:136
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
Definition: string_tools.h:324
void clear()
Definition: wallet2.h:189
size_t size() const
Definition: wallet2.h:181
size_t offset() const
Definition: wallet2.h:182
cryptonote::account_public_address get_address() const
Definition: wallet2.h:793
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
Definition: threadpool.cpp:69
size_t get_num_subaddress_accounts() const
Definition: wallet2.h:801
void encrypt_keys(const crypto::chacha_key &key)
Definition: wallet2.cpp:4746
const T & move(const T &t)
Definition: gtest-port.h:1317
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void set_height(uint64_t h)
crypto::hash get_block_hash(uint64_t height)
POD_CLASS hash
Definition: hash.h:50
#define THROW_WALLET_EXCEPTION(err_type,...)
uint64_t get_blockchain_current_height() const
Definition: wallet2.h:898
const char * address
Definition: multisig.cpp:37
void push_back(const crypto::hash &hash)
Definition: wallet2.h:184
std::map< uint32_t, std::pair< uint64_t, uint64_t > > unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool public_blockchain=false) const
Definition: wallet2.cpp:6249
uint64_t unlocked_balance_all(bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
Definition: wallet2.cpp:6300
error
Tracks LMDB error codes.
Definition: error.h:44
void update_pool_state(bool refreshed=false)
Definition: wallet2.cpp:3164
virtual void computing_key_images(bool started)
Definition: device.hpp:247
void light_wallet_get_address_txs()
Definition: wallet2.cpp:9454

◆ refresh() [4/4]

bool tools::wallet2::refresh ( bool  trusted_daemon,
uint64_t blocks_fetched,
bool received_etn,
bool ok 
)

Definition at line 3851 of file wallet2.cpp.

3852 {
3853  try
3854  {
3855  refresh(trusted_daemon, 0, blocks_fetched, received_etn);
3856  ok = true;
3857  }
3858  catch (...)
3859  {
3860  ok = false;
3861  }
3862  return ok;
3863 }
void refresh(bool trusted_daemon)
Definition: wallet2.cpp:3060

◆ remove_obsolete_pool_txs()

void tools::wallet2::remove_obsolete_pool_txs ( const std::vector< crypto::hash > &  tx_hashes)

Definition at line 3136 of file wallet2.cpp.

3137 {
3138  // remove pool txes to us that aren't in the pool anymore
3139  std::unordered_multimap<crypto::hash, wallet2::pool_payment_details>::iterator uit = m_unconfirmed_payments.begin();
3140  while (uit != m_unconfirmed_payments.end())
3141  {
3142  const crypto::hash &txid = uit->second.m_pd.m_tx_hash;
3143  bool found = false;
3144  for (const auto &it2: tx_hashes)
3145  {
3146  if (it2 == txid)
3147  {
3148  found = true;
3149  break;
3150  }
3151  }
3152  auto pit = uit++;
3153  if (!found)
3154  {
3155  MDEBUG("Removing " << txid << " from unconfirmed payments, not found in pool");
3156  m_unconfirmed_payments.erase(pit);
3157  if (0 != m_callback)
3158  m_callback->on_pool_tx_removed(txid);
3159  }
3160  }
3161 }
virtual void on_pool_tx_removed(const crypto::hash &txid)
Definition: wallet2.h:145
#define MDEBUG(x)
Definition: misc_log_ex.h:76
POD_CLASS hash
Definition: hash.h:50

◆ rescan_blockchain()

void tools::wallet2::rescan_blockchain ( bool  hard,
bool  refresh = true,
bool  keep_key_images = false 
)

Definition at line 6540 of file wallet2.cpp.

6541 {
6542  CHECK_AND_ASSERT_THROW_MES(!hard || !keep_key_images, "Cannot preserve key images on hard rescan");
6543  const size_t transfers_cnt = m_transfers.size();
6544  crypto::hash transfers_hash{};
6545 
6546  if(hard)
6547  {
6548  clear();
6549  setup_new_blockchain();
6550  }
6551  else
6552  {
6553  if (keep_key_images && refresh)
6554  hash_m_transfers((int64_t) transfers_cnt, transfers_hash);
6555  clear_soft(keep_key_images);
6556  }
6557 
6558  if (refresh)
6559  this->refresh(false);
6560 
6561  if (refresh && keep_key_images)
6562  finish_rescan_bc_keep_key_images(transfers_cnt, transfers_hash);
6563 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
uint64_t hash_m_transfers(int64_t transfer_height, crypto::hash &hash) const
Definition: wallet2.cpp:13710
void finish_rescan_bc_keep_key_images(uint64_t transfer_height, const crypto::hash &hash)
Definition: wallet2.cpp:13734
signed __int64 int64_t
Definition: stdint.h:135
POD_CLASS hash
Definition: hash.h:50
void refresh(bool trusted_daemon)
Definition: wallet2.cpp:3060

◆ rescan_spent()

void tools::wallet2::rescan_spent ( )

Definition at line 6417 of file wallet2.cpp.

6418 {
6419  // This is RPC call that can take a long time if there are many outputs,
6420  // so we call it several times, in stripes, so we don't time out spuriously
6421 
6422  // M_TRANSFERS is a container of OUTPUTS and NOT a container of entire transfers!
6423 
6424  // The logic for dealing with publicised (v8 hf) outputs is as follows:
6425  // 1. Check the output block height in m_transfers. If it's >= v8 hard fork height, the output must be a public one,
6426  // 2. m_transfers contains the tx hash and relative out index for each output which uniquely determine
6427  // 'chainstate UTXOs' in the blockchain database; if a chainstate UTXO is present in the DB, the output is truly
6428  // unspent. However nonexistence of the UTXO in the db doesn't mean it's spent, only that it doesn't exist. So we
6429  // must first check (by some means) that the output did exist. Use the tx input db.
6430  // 3. Call the daemon for this output and ask of the spent status.
6431  // 4. Set the correct spent status of the output in m_transfers
6432 
6433  std::vector<int> spent_status;
6434  spent_status.reserve(m_transfers.size());
6435  const size_t chunk_size = 1000;
6436  for (size_t start_offset = 0; start_offset < m_transfers.size(); start_offset += chunk_size)
6437  {
6438  const size_t n_outputs = std::min<size_t>(chunk_size, m_transfers.size() - start_offset); // 1000 or less if we dont have 1000
6439  MDEBUG("Calling is_key_image_spent on " << start_offset << " - " << (start_offset + n_outputs - 1) << ", out of " << m_transfers.size());
6441  COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
6442  for (size_t n = start_offset; n < start_offset + n_outputs; ++n) //loop over key images for the outputs in m_transfers and put the key image in the request
6443  req.key_images.push_back(string_tools::pod_to_hex(m_transfers[n].m_key_image));
6444  m_daemon_rpc_mutex.lock();
6445  bool r = invoke_http_json("/is_key_image_spent", req, daemon_resp, rpc_timeout); //fire off the check command
6446  m_daemon_rpc_mutex.unlock();
6447  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
6448  THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
6449  THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::is_key_image_spent_error, get_rpc_status(daemon_resp.status));
6450  THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != n_outputs, error::wallet_internal_error,
6451  "daemon returned wrong response for is_key_image_spent, wrong amounts count = " +
6452  std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(n_outputs));
6453  std::copy(daemon_resp.spent_status.begin(), daemon_resp.spent_status.end(), std::back_inserter(spent_status));
6454  }
6455 
6456 
6457  // urgent code update so just duplicate code above for public outputs
6458  uint64_t v8height = m_nettype == TESTNET ? 446674 : 589169;
6459  for (size_t start_offset = 0; start_offset < m_transfers.size(); start_offset += chunk_size)
6460  {
6461  const size_t n_outputs = std::min<size_t>(chunk_size, m_transfers.size() - start_offset);
6462  MDEBUG("Preparing is_public_output_spent request for outputs " << start_offset << " - " << (start_offset + n_outputs - 1) << ", out of " << m_transfers.size());
6463 
6466 
6467  // Prepare the request for public outputs only for m_transfers after v8 height
6468  for (size_t k = start_offset; k < start_offset + n_outputs; ++k) {
6469  if (m_transfers[k].m_block_height >= v8height) {
6470  public_output pub_out;
6471  pub_out.txid = epee::string_tools::pod_to_hex(m_transfers[k].m_txid);
6472  pub_out.relative_out_index = static_cast<uint64_t>(m_transfers[k].m_internal_output_index);
6473  req.public_outputs.push_back(pub_out);
6474  }
6475  }
6476 
6477  if(req.public_outputs.size() == 0){
6478  MDEBUG("No public outs found in the range: " << start_offset << " - " << (start_offset + n_outputs - 1) << ", out of " << m_transfers.size() << ", skipping chunk");
6479  continue;
6480  }
6481  // We always call the daemon, but the request may be empty if no outputs meet the criteria
6482  m_daemon_rpc_mutex.lock();
6483  bool r = invoke_http_json("/is_public_output_spent", req, daemon_resp, rpc_timeout);
6484  m_daemon_rpc_mutex.unlock();
6485  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_public_output_spent");
6486  THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_public_output_spent");
6487  THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::is_public_output_spent_error, get_rpc_status(daemon_resp.status));
6488  THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != req.public_outputs.size(), error::wallet_internal_error,
6489  "daemon returned wrong response for is_public_output_spent, wrong amount count = " +
6490  std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(req.public_outputs.size()));
6491 
6492  // Update spent_status only for outputs that were included in the request. do this by iterating through m_transfers and if it's >= v8 height
6493  // then set the corresponding spent status for the same index. use a request index like so because not always does n == request index
6494  // because not all outputs are public outputs
6495  size_t request_index = 0;
6496  for (size_t k = start_offset; k < start_offset + n_outputs; ++k) {
6497  if (m_transfers[k].m_block_height >= v8height) {
6498  spent_status[k] = daemon_resp.spent_status[request_index++];
6499  }
6500  }
6501  }
6502 
6503  // update spent status in m_transfers
6504  // spent_status[i] guide:
6505  // UNSPENT = 0,
6506  // SPENT_IN_BLOCKCHAIN = 1,
6507  // SPENT_IN_POOL = 2,
6508  for (size_t i = 0; i < m_transfers.size(); ++i)
6509  {
6510  transfer_details& td = m_transfers[i];
6511  // a view wallet may not know about key images. only skip in this case IF it isn't a public output
6512  if (!(m_transfers[i].m_block_height >= v8height) && (!td.m_key_image_known || td.m_key_image_partial)) //we will hit this for all public outs, so modify here
6513  continue;
6514 
6515  if (td.m_spent != (spent_status[i] != SPENT_STATUS::UNSPENT)) // if output in m_transfers is unspent and the daemon says spent or the other way round, handle either which way
6516  {
6517  if (td.m_spent) // given parent if statement, spent means we need to change to unspent
6518  {
6519  if(!(m_transfers[i].m_block_height >= v8height)){
6520  LOG_PRINT_L0("Marking output " << i << "(" << td.m_key_image << ") as unspent, it was marked as spent");
6521  } else{
6522  LOG_PRINT_L0("Marking public output " << i << " (txid: " << td.m_txid << ", index: " << td.m_internal_output_index << ") as unspent, it was marked as spent");
6523  }
6524  set_unspent(i);
6525  td.m_spent_height = 0;
6526  }
6527  else // given parent if statement, unspent means we need to change to spent
6528  {
6529  if (!(m_transfers[i].m_block_height >= v8height)) {
6530  LOG_PRINT_L0("Marking output " << i << " (key image: " << epee::string_tools::pod_to_hex(td.m_key_image) << ") as spent, it was marked as unspent");
6531  } else {
6532  LOG_PRINT_L0("Not marking output " << i << " (txid: " << epee::string_tools::pod_to_hex(td.m_txid) << ", index: " << td.m_internal_output_index << ") as spent since block height " << td.m_block_height << " is below the threshold of " << v8height);
6533  }
6534  set_spent(i, td.m_spent_height);
6535  }
6536  }
6537  }
6538 }
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
void copy(key &AA, const key &A)
Definition: rctOps.h:79
#define CORE_RPC_STATUS_OK
#define MDEBUG(x)
Definition: misc_log_ex.h:76
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
unsigned __int64 uint64_t
Definition: stdint.h:136
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
std::string to_string(t_connection_type type)
Here is the call graph for this function:

◆ restore()

void tools::wallet2::restore ( const std::string &  wallet_,
const epee::wipeable_string password,
const std::string &  device_name,
bool  create_address_file = false 
)

Restore a wallet hold by an HW.

Creates a wallet from a device.

Parameters
wallet_Name of wallet file
passwordPassword of wallet file
device_namename of HW to use
create_address_fileWhether to create an address file
wallet_Name of wallet file
passwordPassword of wallet file
device_namedevice string address

Definition at line 5110 of file wallet2.cpp.

5111 {
5112  clear();
5113  prepare_file_names(wallet_);
5114 
5115  boost::system::error_code ignored_ec;
5116  if (!wallet_.empty()) {
5117  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
5118  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
5119  }
5120 
5121  auto &hwdev = lookup_device(device_name);
5122  hwdev.set_name(device_name);
5123  hwdev.set_network_type(m_nettype);
5124  hwdev.set_derivation_path(m_device_derivation_path);
5125  hwdev.set_callback(get_device_callback());
5126 
5127  m_account.create_from_device(hwdev);
5128  init_type(m_account.get_device().get_type());
5129  setup_keys(password);
5130  m_device_name = device_name;
5131 
5132  create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
5133  if (m_subaddress_lookahead_major == SUBADDRESS_LOOKAHEAD_MAJOR && m_subaddress_lookahead_minor == SUBADDRESS_LOOKAHEAD_MINOR)
5134  {
5135  // the default lookahead setting (50:200) is clearly too much for hardware wallet
5136  m_subaddress_lookahead_major = 5;
5137  m_subaddress_lookahead_minor = 20;
5138  }
5139  setup_new_blockchain();
5140  if (!wallet_.empty()) {
5141  store();
5142  }
5143 }
virtual device_type get_type() const =0
void create_from_device(const std::string &device_name)
Definition: account.cpp:209
#define SUBADDRESS_LOOKAHEAD_MINOR
Definition: wallet2.cpp:121
const std::string & device_name() const
Definition: wallet2.h:1109
#define SUBADDRESS_LOOKAHEAD_MAJOR
Definition: wallet2.cpp:120
hw::device & get_device() const
Definition: account.h:91
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
file_error_base< file_exists_message_index > file_exists
Here is the call graph for this function:

◆ rewrite()

void tools::wallet2::rewrite ( const std::string &  wallet_name,
const epee::wipeable_string password 
)

Rewrites to the wallet file for wallet upgrade (doesn't generate key, assumes it's already there)

Parameters
wallet_nameName of wallet file (should exist)
passwordPassword for wallet file

Definition at line 5670 of file wallet2.cpp.

5671 {
5672  if (wallet_name.empty())
5673  return;
5674  prepare_file_names(wallet_name);
5675  boost::system::error_code ignored_ec;
5676  THROW_WALLET_EXCEPTION_IF(!boost::filesystem::exists(m_keys_file, ignored_ec), error::file_not_found, m_keys_file);
5677  bool r = store_keys(m_keys_file, password, m_watch_only);
5679 }
file_error_base< file_save_error_message_index > file_save_error
file_error_base< file_not_found_message_index > file_not_found
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)

◆ sanity_check()

bool tools::wallet2::sanity_check ( const std::vector< wallet2::pending_tx > &  ptx_vector,
std::vector< cryptonote::tx_destination_entry dsts 
) const

Definition at line 10280 of file wallet2.cpp.

10281  {
10282  MDEBUG("sanity_check: " << ptx_vector.size() << " txes, " << dsts.size() << " destinations");
10283 
10284  hw::device &hwdev = m_account.get_device();
10285 
10286  THROW_WALLET_EXCEPTION_IF(ptx_vector.empty(), error::wallet_internal_error, "No transactions");
10287 
10288  if (std::all_of(ptx_vector.begin(), ptx_vector.end(), [](const pending_tx &ptx) { return ptx.tx.version == 1; })) { // we only need do tx proofs for v1
10289  // check every party in there does receive at least the required amount
10290  std::unordered_map<account_public_address, std::pair<uint64_t, bool>> required;
10291  for (const auto &d: dsts) {
10292  required[d.addr].first += d.amount;
10293  required[d.addr].second = d.is_subaddress;
10294  }
10295 
10296  // add change
10297  uint64_t change = 0;
10298  for (const auto &ptx: ptx_vector) {
10299  for (size_t idx: ptx.selected_transfers) //1:add the amount you're spending
10300  change += m_transfers[idx].amount();
10301  change -= ptx.fee; //2: take off the fee
10302  }
10303  for (const auto &r: required)
10304  change -= r.second.first; // 3: subtract the destination required amount
10305  MDEBUG("Adding " << cryptonote::print_etn(change) << " expected change");
10306 
10307  // for all txes that have actual change, check change is coming back to the sending wallet
10308  for (const pending_tx &ptx: ptx_vector) {
10309  if (ptx.change_dts.amount == 0)
10310  continue;
10312  m_subaddresses.find(ptx.change_dts.addr.m_spend_public_key) == m_subaddresses.end(),
10313  error::wallet_internal_error, "Change address is not ours");
10314  required[ptx.change_dts.addr].first += ptx.change_dts.amount;
10315  required[ptx.change_dts.addr].second = ptx.change_dts.is_subaddress;
10316  }
10317 
10318 
10319  for (const auto &r: required) {
10320  const account_public_address &address = r.first;
10321  const crypto::public_key &view_pkey = address.m_view_public_key;
10322 
10323  uint64_t total_received = 0;
10324 
10325  for (const auto &ptx: ptx_vector) {
10326  uint64_t received = 0;
10327  try {
10328  std::string proof = get_tx_proof(ptx.tx, ptx.tx_key, ptx.additional_tx_keys, address,
10329  r.second.second,
10330  "automatic-sanity-check");
10331  check_tx_proof(ptx.tx, address, r.second.second, "automatic-sanity-check", proof, received);
10332  }
10333  catch (const std::exception &e) { received = 0; }
10334  total_received += received;
10335  }
10336 
10337  std::stringstream ss;
10338  ss << "Total received by "
10339  << cryptonote::get_account_address_as_str(m_nettype, r.second.second, address)
10340  << ": "
10341  << cryptonote::print_etn(total_received) << ", expected " << cryptonote::print_etn(r.second.first);
10342  MDEBUG(ss.str());
10343  THROW_WALLET_EXCEPTION_IF(total_received < r.second.first, error::wallet_internal_error, ss.str());
10344  }
10345  } // end of v1 sanity check
10346  else {
10347  // for all txes that have actual change, check change is coming back to the sending wallet
10348  for (const pending_tx &ptx: ptx_vector) {
10349  if (ptx.change_dts.amount == 0)
10350  continue;
10352  m_subaddresses.find(ptx.change_dts.addr.m_spend_public_key) == m_subaddresses.end(),
10353  error::wallet_internal_error, "Change address is not ours");
10354  }
10355  }
10356  return true;
10357 }
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
::std::string string
Definition: gtest-port.h:1097
std::string print_etn(uint64_t amount, unsigned int decimal_point)
#define MDEBUG(x)
Definition: misc_log_ex.h:76
hw::device & get_device() const
Definition: account.h:91
unsigned __int64 uint64_t
Definition: stdint.h:136
POD_CLASS public_key
Definition: crypto.h:76
bool check_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations)
Definition: wallet2.cpp:11527
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
const char * address
Definition: multisig.cpp:37
std::string get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message)
Definition: wallet2.cpp:11371
Here is the call graph for this function:

◆ save_multisig_tx() [1/4]

std::string tools::wallet2::save_multisig_tx ( multisig_tx_set  txs)

Definition at line 7431 of file wallet2.cpp.

7432 {
7433  LOG_PRINT_L0("saving " << txs.m_ptx.size() << " multisig transactions");
7434 
7435  // txes generated, get rid of used k values
7436  for (size_t n = 0; n < txs.m_ptx.size(); ++n)
7437  for (size_t idx: txs.m_ptx[n].construction_data.selected_transfers)
7438  m_transfers[idx].m_multisig_k.clear();
7439 
7440  // zero out some data we don't want to share
7441  for (auto &ptx: txs.m_ptx)
7442  {
7443  for (auto &e: ptx.construction_data.sources)
7444  e.multisig_kLRki.k = rct::zero();
7445  }
7446 
7447  for (auto &ptx: txs.m_ptx)
7448  {
7449  // Get decrypted payment id from pending_tx
7450  ptx.construction_data = get_construction_data_with_decrypted_short_payment_id(ptx, m_account.get_device());
7451  }
7452 
7453  // save as binary
7454  std::ostringstream oss;
7456  try
7457  {
7458  ar << txs;
7459  }
7460  catch (...)
7461  {
7462  return std::string();
7463  }
7464  LOG_PRINT_L2("Saving multisig unsigned tx data: " << oss.str());
7465  std::string ciphertext = encrypt_with_view_secret_key(oss.str());
7466  return std::string(MULTISIG_UNSIGNED_TX_PREFIX) + ciphertext;
7467 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
hw::device & get_device() const
Definition: account.h:91
#define MULTISIG_UNSIGNED_TX_PREFIX
Definition: wallet2.cpp:109
key zero()
Definition: rctOps.h:70
std::string encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated=true) const
Definition: wallet2.cpp:13217
Here is the call graph for this function:

◆ save_multisig_tx() [2/4]

bool tools::wallet2::save_multisig_tx ( const multisig_tx_set txs,
const std::string &  filename 
)

Definition at line 7469 of file wallet2.cpp.

7470 {
7471  std::string ciphertext = save_multisig_tx(txs);
7472  if (ciphertext.empty())
7473  return false;
7474  return epee::file_io_utils::save_string_to_file(filename, ciphertext);
7475 }
::std::string string
Definition: gtest-port.h:1097
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
Definition: file_io_utils.h:73
std::string save_multisig_tx(multisig_tx_set txs)
Definition: wallet2.cpp:7431
Here is the call graph for this function:

◆ save_multisig_tx() [3/4]

std::string tools::wallet2::save_multisig_tx ( const std::vector< pending_tx > &  ptx_vector)

Definition at line 7492 of file wallet2.cpp.

7493 {
7494  return save_multisig_tx(make_multisig_tx_set(ptx_vector));
7495 }
std::string save_multisig_tx(multisig_tx_set txs)
Definition: wallet2.cpp:7431
multisig_tx_set make_multisig_tx_set(const std::vector< pending_tx > &ptx_vector) const
Definition: wallet2.cpp:7477

◆ save_multisig_tx() [4/4]

bool tools::wallet2::save_multisig_tx ( const std::vector< pending_tx > &  ptx_vector,
const std::string &  filename 
)

Definition at line 7497 of file wallet2.cpp.

7498 {
7499  std::string ciphertext = save_multisig_tx(ptx_vector);
7500  if (ciphertext.empty())
7501  return false;
7502  return epee::file_io_utils::save_string_to_file(filename, ciphertext);
7503 }
::std::string string
Definition: gtest-port.h:1097
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
Definition: file_io_utils.h:73
std::string save_multisig_tx(multisig_tx_set txs)
Definition: wallet2.cpp:7431
Here is the call graph for this function:

◆ save_tx()

bool tools::wallet2::save_tx ( const std::vector< pending_tx > &  ptx_vector,
const std::string &  filename 
) const

Definition at line 6975 of file wallet2.cpp.

6976 {
6977  LOG_PRINT_L0("saving " << ptx_vector.size() << " transactions");
6978  std::string ciphertext = dump_tx_to_str(ptx_vector);
6979  if (ciphertext.empty())
6980  return false;
6981  return epee::file_io_utils::save_string_to_file(filename, ciphertext);
6982 }
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
Definition: file_io_utils.h:73
std::string dump_tx_to_str(const std::vector< pending_tx > &ptx_vector) const
Definition: wallet2.cpp:6984
Here is the call graph for this function:

◆ segregate_pre_fork_outputs() [1/2]

bool tools::wallet2::segregate_pre_fork_outputs ( ) const
inline

Definition at line 1095 of file wallet2.h.

1095 { return m_segregate_pre_fork_outputs; }

◆ segregate_pre_fork_outputs() [2/2]

void tools::wallet2::segregate_pre_fork_outputs ( bool  value)
inline

Definition at line 1096 of file wallet2.h.

1096 { m_segregate_pre_fork_outputs = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ segregation_height() [1/2]

uint64_t tools::wallet2::segregation_height ( ) const
inline

Definition at line 1099 of file wallet2.h.

1099 { return m_segregation_height; }

◆ segregation_height() [2/2]

void tools::wallet2::segregation_height ( uint64_t  height)
inline

Definition at line 1100 of file wallet2.h.

1100 { m_segregation_height = height; }
uint64_t height
Definition: blockchain.cpp:91

◆ select_available_mixable_outputs()

std::vector< size_t > tools::wallet2::select_available_mixable_outputs ( )

Definition at line 10864 of file wallet2.cpp.

10865 {
10866  // request all outputs with at least as many instances as the min ring size
10867  return select_available_outputs_from_histogram(get_min_ring_size(), true, true, true);
10868 }
std::vector< size_t > select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct)
Definition: wallet2.cpp:10792
uint64_t get_min_ring_size() const
Definition: wallet2.cpp:7836

◆ select_available_outputs()

std::vector< size_t > tools::wallet2::select_available_outputs ( const std::function< bool(const transfer_details &td)> &  f) const

Definition at line 10755 of file wallet2.cpp.

10756 {
10757  std::vector<size_t> outputs;
10758  size_t n = 0;
10759  for (transfer_container::const_iterator i = m_transfers.begin(); i != m_transfers.end(); ++i, ++n)
10760  {
10761  if (i->m_spent)
10762  continue;
10763  if (i->m_frozen)
10764  continue;
10765  if (i->m_key_image_partial)
10766  continue;
10767  if (!is_transfer_unlocked(*i))
10768  continue;
10769  if (f(*i))
10770  outputs.push_back(n);
10771  }
10772  return outputs;
10773 }
bool is_transfer_unlocked(const transfer_details &td) const
Definition: wallet2.cpp:6565

◆ select_available_outputs_from_histogram()

std::vector< size_t > tools::wallet2::select_available_outputs_from_histogram ( uint64_t  count,
bool  atleast,
bool  unlocked,
bool  allow_rct 
)

Definition at line 10792 of file wallet2.cpp.

10793 {
10796  m_daemon_rpc_mutex.lock();
10797  if (is_trusted_daemon())
10798  req_t.amounts = get_unspent_amounts_vector();
10799  req_t.min_count = count;
10800  req_t.max_count = 0;
10801  req_t.unlocked = unlocked;
10802  req_t.recent_cutoff = 0;
10803  bool r = invoke_http_json_rpc("/json_rpc", "get_output_histogram", req_t, resp_t, rpc_timeout);
10804  m_daemon_rpc_mutex.unlock();
10805  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_outputs_from_histogram");
10806  THROW_WALLET_EXCEPTION_IF(resp_t.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
10807  THROW_WALLET_EXCEPTION_IF(resp_t.status != CORE_RPC_STATUS_OK, error::get_histogram_error, resp_t.status);
10808 
10809  std::set<uint64_t> mixable;
10810  for (const auto &i: resp_t.histogram)
10811  {
10812  mixable.insert(i.amount);
10813  }
10814 
10815  return select_available_outputs([mixable, atleast, allow_rct](const transfer_details &td) {
10816  if (!allow_rct && td.is_rct())
10817  return false;
10818  const uint64_t amount = td.is_rct() ? 0 : td.amount();
10819  if (atleast) {
10820  if (mixable.find(amount) != mixable.end())
10821  return true;
10822  }
10823  else {
10824  if (mixable.find(amount) == mixable.end())
10825  return true;
10826  }
10827  return false;
10828  });
10829 }
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
#define CORE_RPC_STATUS_OK
mdb_size_t count(MDB_cursor *cur)
std::vector< size_t > select_available_outputs(const std::function< bool(const transfer_details &td)> &f) const
Definition: wallet2.cpp:10755
bool is_trusted_daemon() const
Definition: wallet2.h:765
unsigned __int64 uint64_t
Definition: stdint.h:136
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
bool invoke_http_json_rpc(const boost::string_ref uri, const std::string &method_name, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET", const std::string &req_id="0")
Definition: wallet2.h:1333
Here is the call graph for this function:

◆ select_available_unmixable_outputs()

std::vector< size_t > tools::wallet2::select_available_unmixable_outputs ( )

Definition at line 10858 of file wallet2.cpp.

10859 {
10860  // request all outputs with less instances than the min ring size
10861  return select_available_outputs_from_histogram(get_min_ring_size(), false, true, false);
10862 }
std::vector< size_t > select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct)
Definition: wallet2.cpp:10792
uint64_t get_min_ring_size() const
Definition: wallet2.cpp:7836

◆ serialize()

template<class t_archive >
void tools::wallet2::serialize ( t_archive &  a,
const unsigned int  ver 
)
inline

Definition at line 910 of file wallet2.h.

911  {
912  uint64_t dummy_refresh_height = 0; // moved to keys file
913  if(ver < 5)
914  return;
915  if (ver < 19)
916  {
917  std::vector<crypto::hash> blockchain;
918  a & blockchain;
919  for (const auto &b: blockchain)
920  {
921  m_blockchain.push_back(b);
922  }
923  }
924  else
925  {
926  a & m_blockchain;
927  }
928  a & m_transfers;
929  a & m_account_public_address;
930  a & m_key_images;
931  if(ver < 6)
932  return;
933  a & m_unconfirmed_txs;
934  if(ver < 7)
935  return;
936  a & m_payments;
937  if(ver < 8)
938  return;
939  a & m_tx_keys;
940  if(ver < 9)
941  return;
942  a & m_confirmed_txs;
943  if(ver < 11)
944  return;
945  a & dummy_refresh_height;
946  if(ver < 12)
947  return;
948  a & m_tx_notes;
949  if(ver < 13)
950  return;
951  if (ver < 17)
952  {
953  // we're loading an old version, where m_unconfirmed_payments was a std::map
954  std::unordered_map<crypto::hash, payment_details> m;
955  a & m;
956  for (std::unordered_map<crypto::hash, payment_details>::const_iterator i = m.begin(); i != m.end(); ++i)
957  m_unconfirmed_payments.insert(std::make_pair(i->first, pool_payment_details{i->second, false}));
958  }
959  if(ver < 14)
960  return;
961  if(ver < 15)
962  {
963  // we're loading an older wallet without a pubkey map, rebuild it
964  for (size_t i = 0; i < m_transfers.size(); ++i)
965  {
966  const transfer_details &td = m_transfers[i];
967  const cryptonote::tx_out &out = td.m_tx.vout[td.m_internal_output_index];
968  const cryptonote::txout_to_key &o = boost::get<const cryptonote::txout_to_key>(out.target);
969  m_pub_keys.emplace(o.key, i);
970  }
971  return;
972  }
973  a & m_pub_keys;
974  if(ver < 16)
975  return;
976  a & m_address_book;
977  if(ver < 17)
978  return;
979  if (ver < 22)
980  {
981  // we're loading an old version, where m_unconfirmed_payments payload was payment_details
982  std::unordered_multimap<crypto::hash, payment_details> m;
983  a & m;
984  for (const auto &i: m)
985  m_unconfirmed_payments.insert(std::make_pair(i.first, pool_payment_details{i.second, false}));
986  }
987  if(ver < 18)
988  return;
989  a & m_scanned_pool_txs[0];
990  a & m_scanned_pool_txs[1];
991  if (ver < 20)
992  return;
993  a & m_subaddresses;
994  std::unordered_map<cryptonote::subaddress_index, crypto::public_key> dummy_subaddresses_inv;
995  a & dummy_subaddresses_inv;
996  a & m_subaddress_labels;
997  a & m_additional_tx_keys;
998  if(ver < 21)
999  return;
1000  a & m_attributes;
1001  if(ver < 22)
1002  return;
1003  a & m_unconfirmed_payments;
1004  if(ver < 23)
1005  return;
1006  a & m_account_tags;
1007  if(ver < 24)
1008  return;
1009  a & m_ring_history_saved;
1010  if(ver < 25)
1011  return;
1012  a & m_last_block_reward;
1013  if(ver < 26)
1014  return;
1015  a & m_tx_device;
1016  if(ver < 27)
1017  return;
1018  a & m_device_last_key_image_sync;
1019  if(ver < 28)
1020  return;
1021  a & m_cold_key_images;
1022  if(ver < 29)
1023  return;
1024  a & m_chainstate_indexes;
1025  }
unsigned __int64 uint64_t
Definition: stdint.h:136
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
crypto::public_key key
void push_back(const crypto::hash &hash)
Definition: wallet2.h:184

◆ set_account_tag()

void tools::wallet2::set_account_tag ( const std::set< uint32_t > &  account_indices,
const std::string &  tag 
)

Set a tag to the given accounts.

Parameters
account_indicesIndices of accounts.
tagTag's name. If empty, the accounts become untagged.

Definition at line 12056 of file wallet2.cpp.

12057 {
12058  for (uint32_t account_index : account_indices)
12059  {
12060  THROW_WALLET_EXCEPTION_IF(account_index >= get_num_subaddress_accounts(), error::wallet_internal_error, "Account index out of bound");
12061  if (m_account_tags.second[account_index] == tag)
12062  MDEBUG("This tag is already assigned to this account");
12063  else
12064  m_account_tags.second[account_index] = tag;
12065  }
12066  get_account_tags();
12067 }
#define MDEBUG(x)
Definition: misc_log_ex.h:76
unsigned int uint32_t
Definition: stdint.h:126
size_t get_num_subaddress_accounts() const
Definition: wallet2.h:801
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
const std::pair< std::map< std::string, std::string >, std::vector< std::string > > & get_account_tags()
Get the list of registered account tags.
Definition: wallet2.cpp:12036

◆ set_account_tag_description()

void tools::wallet2::set_account_tag_description ( const std::string &  tag,
const std::string &  description 
)

Set the label of the given tag.

Parameters
tagTag's name (which must be non-empty).
descriptionTag's description.

Definition at line 12069 of file wallet2.cpp.

12070 {
12071  THROW_WALLET_EXCEPTION_IF(tag.empty(), error::wallet_internal_error, "Tag must not be empty");
12072  THROW_WALLET_EXCEPTION_IF(m_account_tags.first.count(tag) == 0, error::wallet_internal_error, "Tag is unregistered");
12073  m_account_tags.first[tag] = description;
12074 }
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)

◆ set_attribute()

void tools::wallet2::set_attribute ( const std::string &  key,
const std::string &  value 
)

Definition at line 12013 of file wallet2.cpp.

12014 {
12015  m_attributes[key] = value;
12016 }
const char * key
Definition: hmac_keccak.cpp:39
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ set_blackballed_outputs()

bool tools::wallet2::set_blackballed_outputs ( const std::vector< std::pair< uint64_t, uint64_t >> &  outputs,
bool  add = false 
)

Definition at line 8183 of file wallet2.cpp.

8184 {
8185  if (!m_ringdb)
8186  return false;
8187  try
8188  {
8189  bool ret = true;
8190  if (!add)
8191  ret &= m_ringdb->clear_blackballs();
8192  ret &= m_ringdb->blackball(outputs);
8193  return ret;
8194  }
8195  catch (const std::exception &e) { return false; }
8196 }

◆ set_confirm_backlog_threshold()

void tools::wallet2::set_confirm_backlog_threshold ( uint32_t  threshold)
inline

Definition at line 1089 of file wallet2.h.

1089 { m_confirm_backlog_threshold = threshold; };
uint8_t threshold
Definition: blockchain.cpp:92

◆ set_daemon()

bool tools::wallet2::set_daemon ( std::string  daemon_address = "http://localhost:8080",
boost::optional< epee::net_utils::http::login daemon_login = boost::none,
bool  trusted_daemon = true,
epee::net_utils::ssl_options_t  ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect 
)

Definition at line 1268 of file wallet2.cpp.

1269 {
1270  boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
1271 
1272  if(m_http_client.is_connected())
1273  m_http_client.disconnect();
1274  m_daemon_address = std::move(daemon_address);
1275  m_daemon_login = std::move(daemon_login);
1276  m_trusted_daemon = trusted_daemon;
1277 
1278  MINFO("setting daemon to " << get_daemon_address());
1279  return m_http_client.set_server(get_daemon_address(), get_daemon_login(), std::move(ssl_options));
1280 }
bool set_server(const std::string &address, boost::optional< login > user, ssl_options_t ssl_options=ssl_support_t::e_ssl_support_autodetect)
Definition: http_client.h:302
const boost::optional< epee::net_utils::http::login > & get_daemon_login() const
Definition: wallet2.h:1165
#define MINFO(x)
Definition: misc_log_ex.h:75
std::string get_daemon_address() const
Definition: wallet2.cpp:11926
const T & move(const T &t)
Definition: gtest-port.h:1317
string daemon_address
Definition: transfers.cpp:42
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_default_priority()

void tools::wallet2::set_default_priority ( uint32_t  p)
inline

Definition at line 1074 of file wallet2.h.

1074 { m_default_priority = p; }

◆ set_description()

void tools::wallet2::set_description ( const std::string &  description)

Definition at line 12026 of file wallet2.cpp.

12027 {
12028  set_attribute(ATTRIBUTE_DESCRIPTION, description);
12029 }
void set_attribute(const std::string &key, const std::string &value)
Definition: wallet2.cpp:12013
const char *const ATTRIBUTE_DESCRIPTION
Definition: wallet2.h:1309

◆ set_light_wallet()

void tools::wallet2::set_light_wallet ( bool  light_wallet)
inline

Definition at line 778 of file wallet2.h.

778 { m_light_wallet = light_wallet; }
bool light_wallet() const
Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned...
Definition: wallet2.h:777
Here is the call graph for this function:

◆ set_min_output_count()

void tools::wallet2::set_min_output_count ( uint32_t  count)
inline

Definition at line 1081 of file wallet2.h.

1081 { m_min_output_count = count; }
mdb_size_t count(MDB_cursor *cur)
Here is the call graph for this function:

◆ set_min_output_value()

void tools::wallet2::set_min_output_value ( uint64_t  value)
inline

Definition at line 1083 of file wallet2.h.

1083 { m_min_output_value = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ set_offline()

void tools::wallet2::set_offline ( bool  offline = true)

Definition at line 5810 of file wallet2.cpp.

5811 {
5812  m_offline = offline;
5813  m_http_client.set_auto_connect(!offline);
5814  if (offline)
5815  {
5816  boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
5817  if(m_http_client.is_connected())
5818  m_http_client.disconnect();
5819  }
5820 }

◆ set_refresh_from_block_height()

void tools::wallet2::set_refresh_from_block_height ( uint64_t  height)
inline

Definition at line 742 of file wallet2.h.

742 {m_refresh_from_block_height = height;}
uint64_t height
Definition: blockchain.cpp:91
Here is the caller graph for this function:

◆ set_refresh_type()

void tools::wallet2::set_refresh_type ( RefreshType  refresh_type)
inline

Definition at line 821 of file wallet2.h.

821 { m_refresh_type = refresh_type; }

◆ set_ring()

bool tools::wallet2::set_ring ( const crypto::key_image key_image,
const std::vector< uint64_t > &  outs,
bool  relative 
)

Definition at line 8063 of file wallet2.cpp.

8064 {
8065  if (!m_ringdb)
8066  return false;
8067 
8068  try { return m_ringdb->set_ring(get_ringdb_key(), key_image, outs, relative); }
8069  catch (const std::exception &e) { return false; }
8070 }
POD_CLASS key_image
Definition: crypto.h:102

◆ set_ring_database()

bool tools::wallet2::set_ring_database ( const std::string &  filename)

Definition at line 7956 of file wallet2.cpp.

7957 {
7958  m_ring_database = filename;
7959  MINFO("ringdb path set to " << filename);
7960  m_ringdb.reset();
7961  if (!m_ring_database.empty())
7962  {
7963  try
7964  {
7966  generate_genesis(b);
7967  m_ringdb.reset(new tools::ringdb(m_ring_database, epee::string_tools::pod_to_hex(get_block_hash(b))));
7968  }
7969  catch (const std::exception &e)
7970  {
7971  MERROR("Failed to initialize ringdb: " << e.what());
7972  m_ring_database = "";
7973  return false;
7974  }
7975  }
7976  return true;
7977 }
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MINFO(x)
Definition: misc_log_ex.h:75
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
crypto::hash get_block_hash(uint64_t height)
Here is the call graph for this function:

◆ set_seed_language()

void tools::wallet2::set_seed_language ( const std::string &  language)

Sets the seed language.

Parameters
languageSeed language to set to

Definition at line 1425 of file wallet2.cpp.

1426 {
1427  seed_language = language;
1428 }
Here is the caller graph for this function:

◆ set_subaddress_label()

void tools::wallet2::set_subaddress_label ( const cryptonote::subaddress_index index,
const std::string &  label 
)

Definition at line 1528 of file wallet2.cpp.

1529 {
1530  THROW_WALLET_EXCEPTION_IF(index.major >= m_subaddress_labels.size(), error::account_index_outofbound);
1531  THROW_WALLET_EXCEPTION_IF(index.minor >= m_subaddress_labels[index.major].size(), error::address_index_outofbound);
1532  m_subaddress_labels[index.major][index.minor] = label;
1533 }
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
Here is the caller graph for this function:

◆ set_subaddress_lookahead()

void tools::wallet2::set_subaddress_lookahead ( size_t  major,
size_t  minor 
)

Definition at line 1535 of file wallet2.cpp.

1536 {
1537  THROW_WALLET_EXCEPTION_IF(major > 0xffffffff, error::wallet_internal_error, "Subaddress major lookahead is too large");
1538  THROW_WALLET_EXCEPTION_IF(minor > 0xffffffff, error::wallet_internal_error, "Subaddress minor lookahead is too large");
1539  m_subaddress_lookahead_major = major;
1540  m_subaddress_lookahead_minor = minor;
1541 }
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
Here is the caller graph for this function:

◆ set_trusted_daemon()

void tools::wallet2::set_trusted_daemon ( bool  trusted)
inline

Definition at line 766 of file wallet2.h.

766 { m_trusted_daemon = trusted; }

◆ set_tx_device_aux()

void tools::wallet2::set_tx_device_aux ( const crypto::hash txid,
const std::string &  aux 
)

Definition at line 12000 of file wallet2.cpp.

12001 {
12002  m_tx_device[txid] = aux;
12003 }

◆ set_tx_key()

void tools::wallet2::set_tx_key ( const crypto::hash txid,
const crypto::secret_key tx_key,
const std::vector< crypto::secret_key > &  additional_tx_keys 
)

Definition at line 11000 of file wallet2.cpp.

11001 {
11002  // fetch tx from daemon and check if secret keys agree with corresponding public keys
11004  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
11005  req.decode_as_json = false;
11006  req.prune = true;
11008  bool r;
11009  {
11010  const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
11011  r = invoke_http_json("/gettransactions", req, res, rpc_timeout);
11012  }
11013  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gettransactions");
11014  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gettransactions");
11015  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "gettransactions");
11016  THROW_WALLET_EXCEPTION_IF(res.txs.size() != 1, error::wallet_internal_error,
11017  "daemon returned wrong response for gettransactions, wrong txs count = " +
11018  std::to_string(res.txs.size()) + ", expected 1");
11020  crypto::hash tx_hash;
11021  THROW_WALLET_EXCEPTION_IF(!get_pruned_tx(res.txs[0], tx, tx_hash), error::wallet_internal_error,
11022  "Failed to get transaction from daemon");
11023  THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error, "txid mismatch");
11024  std::vector<tx_extra_field> tx_extra_fields;
11025  THROW_WALLET_EXCEPTION_IF(!parse_tx_extra(tx.extra, tx_extra_fields), error::wallet_internal_error, "Transaction extra has unsupported format");
11026  tx_extra_pub_key pub_key_field;
11027  bool found = false;
11028  size_t index = 0;
11029  while (find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, index++))
11030  {
11031  crypto::public_key calculated_pub_key;
11032  crypto::secret_key_to_public_key(tx_key, calculated_pub_key);
11033  if (calculated_pub_key == pub_key_field.pub_key)
11034  {
11035  found = true;
11036  break;
11037  }
11038  }
11039  THROW_WALLET_EXCEPTION_IF(!found, error::wallet_internal_error, "Given tx secret key doesn't agree with the tx public key in the blockchain");
11040  tx_extra_additional_pub_keys additional_tx_pub_keys;
11041  find_tx_extra_field_by_type(tx_extra_fields, additional_tx_pub_keys);
11042  THROW_WALLET_EXCEPTION_IF(additional_tx_keys.size() != additional_tx_pub_keys.data.size(), error::wallet_internal_error, "The number of additional tx secret keys doesn't agree with the number of additional tx public keys in the blockchain" );
11043  m_tx_keys.insert(std::make_pair(txid, tx_key));
11044  m_additional_tx_keys.insert(std::make_pair(txid, additional_tx_keys));
11045 }
const char * res
Definition: hmac_keccak.cpp:41
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
std::vector< crypto::public_key > data
Definition: tx_extra.h:169
crypto::public_key pub_key
Definition: tx_extra.h:101
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
std::vector< uint8_t > extra
#define CORE_RPC_STATUS_OK
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
POD_CLASS public_key
Definition: crypto.h:76
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
POD_CLASS hash
Definition: hash.h:50
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
std::string to_string(t_connection_type type)
Here is the call graph for this function:

◆ set_tx_note()

void tools::wallet2::set_tx_note ( const crypto::hash txid,
const std::string &  note 
)

Definition at line 11987 of file wallet2.cpp.

11988 {
11989  m_tx_notes[txid] = note;
11990 }

◆ set_tx_notify()

void tools::wallet2::set_tx_notify ( const std::shared_ptr< tools::Notify > &  notify)
inline

Definition at line 1377 of file wallet2.h.

1377 { m_tx_notify = notify; }

◆ setup_background_mining() [1/2]

BackgroundMiningSetupType tools::wallet2::setup_background_mining ( ) const
inline

Definition at line 1107 of file wallet2.h.

1107 { return m_setup_background_mining; }

◆ setup_background_mining() [2/2]

void tools::wallet2::setup_background_mining ( BackgroundMiningSetupType  value)
inline

Definition at line 1108 of file wallet2.h.

1108 { m_setup_background_mining = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ sign()

std::string tools::wallet2::sign ( const std::string &  data) const

Definition at line 12076 of file wallet2.cpp.

12077 {
12079  crypto::cn_fast_hash(data.data(), data.size(), hash);
12080  const cryptonote::account_keys &keys = m_account.get_keys();
12082  crypto::generate_signature(hash, keys.m_account_address.m_spend_public_key, keys.m_spend_secret_key, signature);
12083  return std::string("SigV1") + tools::base58::encode(std::string((const char *)&signature, sizeof(signature)));
12084 }
::std::string string
Definition: gtest-port.h:1097
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:292
std::string encode(const std::string &data)
Definition: base58.cpp:173
const account_keys & get_keys() const
Definition: account.cpp:264
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ sign_multisig_participant()

std::string tools::wallet2::sign_multisig_participant ( const std::string &  data) const

sign_multisig_participant signs given message with the multisig public signer key

Parameters
datamessage to sign
Exceptions
ifwallet is not multisig
Returns
signature

Definition at line 12109 of file wallet2.cpp.

12110 {
12111  CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
12112 
12114  crypto::cn_fast_hash(data.data(), data.size(), hash);
12115  const cryptonote::account_keys &keys = m_account.get_keys();
12118  return MULTISIG_SIGNATURE_MAGIC + tools::base58::encode(std::string((const char *)&signature, sizeof(signature)));
12119 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
::std::string string
Definition: gtest-port.h:1097
void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig)
Definition: crypto.h:292
std::string encode(const std::string &data)
Definition: base58.cpp:173
const account_keys & get_keys() const
Definition: account.cpp:264
void cn_fast_hash(const void *data, size_t length, char *hash)
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
POD_CLASS signature
Definition: crypto.h:108
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ sign_multisig_tx()

bool tools::wallet2::sign_multisig_tx ( multisig_tx_set exported_txs,
std::vector< crypto::hash > &  txids 
)

Definition at line 7607 of file wallet2.cpp.

7608 {
7609  THROW_WALLET_EXCEPTION_IF(exported_txs.m_ptx.empty(), error::wallet_internal_error, "No tx found");
7610 
7611  const crypto::public_key local_signer = get_multisig_signer_public_key();
7612 
7613  THROW_WALLET_EXCEPTION_IF(exported_txs.m_signers.find(local_signer) != exported_txs.m_signers.end(),
7614  error::wallet_internal_error, "Transaction already signed by this private key");
7615  THROW_WALLET_EXCEPTION_IF(exported_txs.m_signers.size() > m_multisig_threshold,
7616  error::wallet_internal_error, "Transaction was signed by too many signers");
7617  THROW_WALLET_EXCEPTION_IF(exported_txs.m_signers.size() == m_multisig_threshold,
7618  error::wallet_internal_error, "Transaction is already fully signed");
7619 
7620  txids.clear();
7621 
7622  // sign the transactions
7623  for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n)
7624  {
7625  tools::wallet2::pending_tx &ptx = exported_txs.m_ptx[n];
7626  THROW_WALLET_EXCEPTION_IF(ptx.multisig_sigs.empty(), error::wallet_internal_error, "No signatures found in multisig tx");
7628  LOG_PRINT_L1(" " << (n+1) << ": " << sd.sources.size() << " inputs, mixin " << (sd.sources[0].outputs.size()-1) <<
7629  ", signed by " << exported_txs.m_signers.size() << "/" << m_multisig_threshold);
7631  rct::multisig_out msout = ptx.multisig_sigs.front().msout;
7632  auto sources = sd.sources;
7633  rct::RCTConfig rct_config = sd.rct_config;
7634  bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, rct_config, &msout, false, 0 /*===default value*/, this->m_nettype);
7635  THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
7636 
7638  error::wallet_internal_error, "Transaction prefix does not match data");
7639 
7640  // Tests passed, sign
7641  std::vector<unsigned int> indices;
7642  for (const auto &source: sources)
7643  indices.push_back(source.real_output);
7644 
7645  for (auto &sig: ptx.multisig_sigs)
7646  {
7647  if (sig.ignore.find(local_signer) == sig.ignore.end())
7648  {
7649  ptx.tx.rct_signatures = sig.sigs;
7650 
7651  rct::keyV k;
7652  for (size_t idx: sd.selected_transfers)
7653  k.push_back(get_multisig_k(idx, sig.used_L));
7654 
7655  rct::key skey = rct::zero();
7656  for (const auto &msk: get_account().get_multisig_keys())
7657  {
7659 
7660  if (sig.signing_keys.find(pmsk) == sig.signing_keys.end())
7661  {
7662  sc_add(skey.bytes, skey.bytes, rct::sk2rct(msk).bytes);
7663  sig.signing_keys.insert(pmsk);
7664  }
7665  }
7666  THROW_WALLET_EXCEPTION_IF(!rct::signMultisig(ptx.tx.rct_signatures, indices, k, sig.msout, skey),
7667  error::wallet_internal_error, "Failed signing, transaction likely malformed");
7668 
7669  sig.sigs = ptx.tx.rct_signatures;
7670  }
7671  }
7672 
7673  const bool is_last = exported_txs.m_signers.size() + 1 >= m_multisig_threshold;
7674  if (is_last)
7675  {
7676  // when the last signature on a multisig tx is made, we select the right
7677  // signature to plug into the final tx
7678  bool found = false;
7679  for (const auto &sig: ptx.multisig_sigs)
7680  {
7681  if (sig.ignore.find(local_signer) == sig.ignore.end() && !keys_intersect(sig.ignore, exported_txs.m_signers))
7682  {
7683  THROW_WALLET_EXCEPTION_IF(found, error::wallet_internal_error, "More than one transaction is final");
7684  ptx.tx.rct_signatures = sig.sigs;
7685  found = true;
7686  }
7687  }
7688  THROW_WALLET_EXCEPTION_IF(!found, error::wallet_internal_error,
7689  "Final signed transaction not found: this transaction was likely made without our export data, so we cannot sign it");
7690  const crypto::hash txid = get_transaction_hash(ptx.tx);
7691  if (store_tx_info())
7692  {
7693  m_tx_keys.insert(std::make_pair(txid, ptx.tx_key));
7694  m_additional_tx_keys.insert(std::make_pair(txid, ptx.additional_tx_keys));
7695  }
7696  txids.push_back(txid);
7697  }
7698  }
7699 
7700  // txes generated, get rid of used k values
7701  for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n)
7702  for (size_t idx: exported_txs.m_ptx[n].construction_data.selected_transfers)
7703  m_transfers[idx].m_multisig_k.clear();
7704 
7705  exported_txs.m_signers.insert(get_multisig_signer_public_key());
7706 
7707  return true;
7708 }
cryptonote::transaction tx
Definition: wallet2.h:466
const CharType(& source)[N]
Definition: pointer.h:1147
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, const std::vector< uint8_t > &extra, transaction &tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, bool shuffle_outs, const uint32_t account_major_offset, const cryptonote::network_type nettype)
std::vector< crypto::secret_key > additional_tx_keys
Definition: wallet2.h:473
crypto::public_key get_multisig_signing_public_key(size_t idx) const
Definition: wallet2.cpp:12914
std::vector< key > keyV
Definition: rctTypes.h:88
const account_keys & get_keys() const
Definition: account.cpp:264
std::vector< multisig_sig > multisig_sigs
Definition: wallet2.h:475
bool store_tx_info() const
Definition: wallet2.h:1069
bool signMultisig(rctSig &rv, const std::vector< unsigned int > &indices, const keyV &k, const multisig_out &msout, const key &secret_key)
Definition: rctSigs.cpp:1210
tx_construction_data construction_data
Definition: wallet2.h:477
POD_CLASS public_key
Definition: crypto.h:76
account_public_address addr
crypto::public_key get_multisig_signer_public_key() const
Definition: wallet2.cpp:12898
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
unsigned char bytes[32]
Definition: rctTypes.h:86
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::hash get_transaction_hash(const transaction &t)
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
cryptonote::tx_destination_entry change_dts
Definition: wallet2.h:469
crypto::secret_key tx_key
Definition: wallet2.h:472
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
key zero()
Definition: rctOps.h:70
Here is the call graph for this function:

◆ sign_multisig_tx_from_file()

bool tools::wallet2::sign_multisig_tx_from_file ( const std::string &  filename,
std::vector< crypto::hash > &  txids,
std::function< bool(const multisig_tx_set &)>  accept_func 
)

Definition at line 7718 of file wallet2.cpp.

7719 {
7720  multisig_tx_set exported_txs;
7721  if(!load_multisig_tx_from_file(filename, exported_txs))
7722  return false;
7723 
7724  if (accept_func && !accept_func(exported_txs))
7725  {
7726  LOG_PRINT_L1("Transactions rejected by callback");
7727  return false;
7728  }
7729  return sign_multisig_tx_to_file(exported_txs, filename, txids);
7730 }
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
bool load_multisig_tx_from_file(const std::string &filename, multisig_tx_set &exported_txs, std::function< bool(const multisig_tx_set &)> accept_func=NULL)
Definition: wallet2.cpp:7583
bool sign_multisig_tx_to_file(multisig_tx_set &exported_txs, const std::string &filename, std::vector< crypto::hash > &txids)
Definition: wallet2.cpp:7710

◆ sign_multisig_tx_to_file()

bool tools::wallet2::sign_multisig_tx_to_file ( multisig_tx_set exported_txs,
const std::string &  filename,
std::vector< crypto::hash > &  txids 
)

Definition at line 7710 of file wallet2.cpp.

7711 {
7712  bool r = sign_multisig_tx(exported_txs, txids);
7713  if (!r)
7714  return false;
7715  return save_multisig_tx(exported_txs, filename);
7716 }
bool sign_multisig_tx(multisig_tx_set &exported_txs, std::vector< crypto::hash > &txids)
Definition: wallet2.cpp:7607
std::string save_multisig_tx(multisig_tx_set txs)
Definition: wallet2.cpp:7431

◆ sign_tx() [1/3]

bool tools::wallet2::sign_tx ( const std::string &  unsigned_filename,
const std::string &  signed_filename,
std::vector< wallet2::pending_tx > &  ptx,
std::function< bool(const unsigned_tx_set &)>  accept_func = NULL,
bool  export_raw = false 
)

Definition at line 7102 of file wallet2.cpp.

7103 {
7104  unsigned_tx_set exported_txs;
7105  if(!load_unsigned_tx(unsigned_filename, exported_txs))
7106  return false;
7107 
7108  if (accept_func && !accept_func(exported_txs))
7109  {
7110  LOG_PRINT_L1("Transactions rejected by callback");
7111  return false;
7112  }
7113  return sign_tx(exported_txs, signed_filename, txs, export_raw);
7114 }
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
bool sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::vector< wallet2::pending_tx > &ptx, std::function< bool(const unsigned_tx_set &)> accept_func=NULL, bool export_raw=false)
Definition: wallet2.cpp:7102
bool load_unsigned_tx(const std::string &unsigned_filename, unsigned_tx_set &exported_txs) const
Definition: wallet2.cpp:7014
Here is the caller graph for this function:

◆ sign_tx() [2/3]

bool tools::wallet2::sign_tx ( unsigned_tx_set exported_txs,
const std::string &  signed_filename,
std::vector< wallet2::pending_tx > &  ptx,
bool  export_raw = false 
)

Definition at line 7262 of file wallet2.cpp.

7263 {
7264  // sign the transactions
7265  signed_tx_set signed_txes;
7266  std::string ciphertext = sign_tx_dump_to_str(exported_txs, txs, signed_txes);
7267  if (ciphertext.empty())
7268  {
7269  LOG_PRINT_L0("Failed to sign unsigned_tx_set");
7270  return false;
7271  }
7272 
7273  if (!epee::file_io_utils::save_string_to_file(signed_filename, ciphertext))
7274  {
7275  LOG_PRINT_L0("Failed to save file to " << signed_filename);
7276  return false;
7277  }
7278  // export signed raw tx without encryption
7279  if (export_raw)
7280  {
7281  for (size_t i = 0; i < signed_txes.ptx.size(); ++i)
7282  {
7283  std::string tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(signed_txes.ptx[i].tx));
7284  std::string raw_filename = signed_filename + "_raw" + (signed_txes.ptx.size() == 1 ? "" : ("_" + std::to_string(i)));
7285  if (!epee::file_io_utils::save_string_to_file(raw_filename, tx_as_hex))
7286  {
7287  LOG_PRINT_L0("Failed to save file to " << raw_filename);
7288  return false;
7289  }
7290  }
7291  }
7292  return true;
7293 }
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
blobdata tx_to_blob(const transaction &tx)
std::string sign_tx_dump_to_str(unsigned_tx_set &exported_txs, std::vector< wallet2::pending_tx > &ptx, signed_tx_set &signed_txes)
Definition: wallet2.cpp:7295
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
Definition: file_io_utils.h:73
std::string buff_to_hex_nodelimer(const std::string &src)
Definition: string_tools.h:87
std::string to_string(t_connection_type type)
Here is the call graph for this function:

◆ sign_tx() [3/3]

bool tools::wallet2::sign_tx ( unsigned_tx_set exported_txs,
std::vector< wallet2::pending_tx > &  ptx,
signed_tx_set signed_txs 
)

Definition at line 7116 of file wallet2.cpp.

7117 {
7118  import_outputs(exported_txs.transfers);
7119 
7120  // sign the transactions
7121  for (size_t n = 0; n < exported_txs.txes.size(); ++n)
7122  {
7123  tools::wallet2::tx_construction_data &sd = exported_txs.txes[n];
7124  THROW_WALLET_EXCEPTION_IF(sd.sources.empty(), error::wallet_internal_error, "Empty sources");
7125  LOG_PRINT_L1(" " << (n+1) << ": " << sd.sources.size() << " inputs, ring size " << sd.sources[0].outputs.size());
7126  signed_txes.ptx.push_back(pending_tx());
7127  tools::wallet2::pending_tx &ptx = signed_txes.ptx.back();
7128  rct::RCTConfig rct_config = sd.rct_config;
7129  crypto::secret_key tx_key;
7130  std::vector<crypto::secret_key> additional_tx_keys;
7131  rct::multisig_out msout;
7132 
7133  // NB no early blocks this time for v3 transactions, as nobody should be sending v3 transactions before their v2 (migration) tx have confirmed. V2 confirmations always take place at, or after, the fork block.
7134  // todo: 4.0.0.0 Migrate vs send regular tx.
7136  bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, rct_config, m_multisig ? &msout : NULL, m_account_major_offset, this->m_nettype);
7137  THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
7138  // we don't test tx size, because we don't know the current limit, due to not having a blockchain,
7139  // and it's a bit pointless to fail there anyway, since it'd be a (good) guess only. We sign anyway,
7140  // and if we really go over limit, the daemon will reject when it gets submitted. Chances are it's
7141  // OK anyway since it was generated in the first place, and rerolling should be within a few bytes.
7142 
7143  // normally, the tx keys are saved in commit_tx, when the tx is actually sent to the daemon.
7144  // we can't do that here since the tx will be sent from the compromised wallet, which we don't want
7145  // to see that info, so we save it here
7146  if (store_tx_info())
7147  {
7148  const crypto::hash txid = get_transaction_hash(ptx.tx);
7149  m_tx_keys.insert(std::make_pair(txid, tx_key));
7150  m_additional_tx_keys.insert(std::make_pair(txid, additional_tx_keys));
7151  }
7152 
7153  std::string key_images;
7154 
7155  if(ptx.tx.version < 3) {
7156  bool all_are_txin_to_key = std::all_of(ptx.tx.vin.begin(), ptx.tx.vin.end(), [&](const txin_v &s_e) -> bool {
7157  CHECKED_GET_SPECIFIC_VARIANT(s_e, const txin_to_key, in, false);
7158  key_images += boost::to_string(in.k_image) + " ";
7159  return true;
7160  });
7161  THROW_WALLET_EXCEPTION_IF(!all_are_txin_to_key, error::unexpected_txin_type, ptx.tx);
7162  }else{
7163  bool all_are_txin_to_key_public = std::all_of(ptx.tx.vin.begin(), ptx.tx.vin.end(), [&](const txin_v &s_e) -> bool {
7164  CHECKED_GET_SPECIFIC_VARIANT(s_e, const txin_to_key_public, in, false);
7165  return true;
7166  });
7167  THROW_WALLET_EXCEPTION_IF(!all_are_txin_to_key_public, error::unexpected_txin_type, ptx.tx);
7168  }
7169  if(ptx.tx.version > 1) {
7170  bool all_are_txout_to_key_public = std::all_of(ptx.tx.vout.begin(), ptx.tx.vout.end(), [&](const tx_out &s_e) -> bool {
7171  CHECKED_GET_SPECIFIC_VARIANT(s_e.target, const txout_to_key_public, in, false);
7172  return true;
7173  });
7174  THROW_WALLET_EXCEPTION_IF(!all_are_txout_to_key_public, error::unexpected_txout_type, ptx.tx);
7175  }
7176  ptx.key_images = key_images;
7177  ptx.fee = 0;
7178  for (const auto &i: sd.sources) ptx.fee += i.amount;
7179  for (const auto &i: sd.splitted_dsts) ptx.fee -= i.amount;
7180  ptx.dust = 0;
7181  ptx.dust_added_to_fee = false;
7182  ptx.change_dts = sd.change_dts;
7184  ptx.tx_key = rct::rct2sk(rct::identity()); // don't send it back to the untrusted view wallet
7185  ptx.dests = sd.dests;
7186  ptx.construction_data = sd;
7187 
7188  txs.push_back(ptx);
7189 
7190  // add tx keys only to ptx
7191  txs.back().tx_key = tx_key;
7192  txs.back().additional_tx_keys = additional_tx_keys;
7193  }
7194 
7195  // add key image mapping for these txes
7196  const account_keys &keys = get_account().get_keys();
7197  hw::device &hwdev = m_account.get_device();
7198  for (size_t n = 0; n < exported_txs.txes.size(); ++n)
7199  {
7200  const cryptonote::transaction &tx = signed_txes.ptx[n].tx;
7201 
7202  crypto::key_derivation derivation;
7203  std::vector<crypto::key_derivation> additional_derivations;
7204 
7205  // compute public keys from out secret keys
7206  crypto::public_key tx_pub_key;
7207  crypto::secret_key_to_public_key(txs[n].tx_key, tx_pub_key);
7208  std::vector<crypto::public_key> additional_tx_pub_keys;
7209  for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
7210  {
7211  additional_tx_pub_keys.resize(additional_tx_pub_keys.size() + 1);
7212  crypto::secret_key_to_public_key(skey, additional_tx_pub_keys.back());
7213  }
7214 
7215  // compute derivations
7217  if (!hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation))
7218  {
7219  MWARNING("Failed to generate key derivation from tx pubkey in " << cryptonote::get_transaction_hash(tx) << ", skipping");
7220  static_assert(sizeof(derivation) == sizeof(rct::key), "Mismatched sizes of key_derivation and rct::key");
7221  memcpy(&derivation, rct::identity().bytes, sizeof(derivation));
7222  }
7223  for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
7224  {
7225  additional_derivations.push_back({});
7226  if (!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back()))
7227  {
7228  MWARNING("Failed to generate key derivation from additional tx pubkey in " << cryptonote::get_transaction_hash(tx) << ", skipping");
7229  memcpy(&additional_derivations.back(), rct::identity().bytes, sizeof(crypto::key_derivation));
7230  }
7231  }
7232 
7233  for (size_t i = 0; i < tx.vout.size(); ++i)
7234  {
7235  if (tx.vout[i].target.type() != typeid(cryptonote::txout_to_key))
7236  continue;
7237  const cryptonote::txout_to_key &out = boost::get<cryptonote::txout_to_key>(tx.vout[i].target);
7238  // if this output is back to this wallet, we can calculate its key image already
7239  if (!is_out_to_acc_precomp(m_subaddresses, out.key, derivation, additional_derivations, i, hwdev))
7240  continue;
7241  crypto::key_image ki;
7242  cryptonote::keypair in_ephemeral;
7243  if (generate_key_image_helper(keys, m_subaddresses, out.key, tx_pub_key, additional_tx_pub_keys, i, in_ephemeral, ki, hwdev))
7244  signed_txes.tx_key_images[out.key] = ki;
7245  else
7246  MERROR("Failed to calculate key image");
7247  }
7248  }
7249 
7250  // add key images
7251  signed_txes.key_images.resize(m_transfers.size());
7252  for (size_t i = 0; i < m_transfers.size(); ++i)
7253  {
7254  if (!m_transfers[i].m_key_image_known || m_transfers[i].m_key_image_partial)
7255  LOG_PRINT_L0("WARNING: key image not known in signing wallet at index " << i);
7256  signed_txes.key_images[i] = m_transfers[i].m_key_image;
7257  }
7258 
7259  return true;
7260 }
#define MERROR(x)
Definition: misc_log_ex.h:73
cryptonote::transaction tx
Definition: wallet2.h:466
std::vector< tools::wallet2::tx_construction_data > txes
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
std::vector< cryptonote::tx_destination_entry > dests
Definition: wallet2.h:474
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
std::vector< size_t > selected_transfers
Definition: wallet2.h:470
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
virtual bool set_mode(device_mode mode)
Definition: device.hpp:130
std::string key_images
Definition: wallet2.h:471
cryptonote::tx_destination_entry change_dts
Definition: wallet2.h:423
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
unsigned short uint16_t
Definition: stdint.h:125
virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation)=0
bool use_fork_rules(uint8_t version, int64_t early_blocks=0) const
Definition: wallet2.cpp:10720
std::vector< cryptonote::tx_source_entry > sources
Definition: wallet2.h:422
const account_keys & get_keys() const
Definition: account.cpp:264
boost::optional< subaddress_receive_info > is_out_to_acc_precomp(const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::vector< crypto::key_derivation > &additional_derivations, size_t output_index, hw::device &hwdev)
hw::device & get_device() const
Definition: account.h:91
bool generate_key_image_helper(const account_keys &ack, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, const crypto::public_key &out_key, const crypto::public_key &tx_public_key, const std::vector< crypto::public_key > &additional_tx_public_keys, size_t real_output_index, keypair &in_ephemeral, crypto::key_image &ki, hw::device &hwdev, const uint32_t account_major_offset)
std::vector< cryptonote::tx_destination_entry > splitted_dsts
Definition: wallet2.h:424
bool store_tx_info() const
Definition: wallet2.h:1069
std::vector< uint8_t > extra
Definition: wallet2.h:426
tx_construction_data construction_data
Definition: wallet2.h:477
POD_CLASS public_key
Definition: crypto.h:76
#define MWARNING(x)
Definition: misc_log_ex.h:74
crypto::secret_key m_view_secret_key
Definition: account.h:45
account_public_address addr
unsigned char bytes[32]
Definition: rctTypes.h:86
key identity()
Definition: rctOps.h:73
POD_CLASS key_image
Definition: crypto.h:102
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
void * memcpy(void *a, const void *b, size_t c)
std::vector< cryptonote::tx_destination_entry > dests
Definition: wallet2.h:430
crypto::hash get_transaction_hash(const transaction &t)
tools::wallet2::transfer_container transfers
#define CURRENT_HARDFORK_VERSION
size_t import_outputs(const std::pair< size_t, std::vector< tools::wallet2::transfer_details >> &outputs)
Definition: wallet2.cpp:12763
cryptonote::account_base & get_account()
Definition: wallet2.h:734
POD_CLASS hash
Definition: hash.h:50
cryptonote::tx_destination_entry change_dts
Definition: wallet2.h:469
crypto::secret_key tx_key
Definition: wallet2.h:472
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
std::string to_string(t_connection_type type)
bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, const std::vector< uint8_t > &extra, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, const uint32_t account_major_offset, const cryptonote::network_type nettype)
std::vector< size_t > selected_transfers
Definition: wallet2.h:425
Here is the call graph for this function:

◆ sign_tx_dump_to_str()

std::string tools::wallet2::sign_tx_dump_to_str ( unsigned_tx_set exported_txs,
std::vector< wallet2::pending_tx > &  ptx,
signed_tx_set signed_txes 
)

Definition at line 7295 of file wallet2.cpp.

7296 {
7297  // sign the transactions
7298  bool r = sign_tx(exported_txs, ptx, signed_txes);
7299  if (!r)
7300  {
7301  LOG_PRINT_L0("Failed to sign unsigned_tx_set");
7302  return std::string();
7303  }
7304 
7305  // save as binary
7306  std::ostringstream oss;
7308  try
7309  {
7310  ar << signed_txes;
7311  }
7312  catch(...)
7313  {
7314  return std::string();
7315  }
7316  LOG_PRINT_L3("Saving signed tx data (with encryption): " << oss.str());
7317  std::string ciphertext = encrypt_with_view_secret_key(oss.str());
7318  return std::string(SIGNED_TX_PREFIX) + ciphertext;
7319 }
bool sign_tx(const std::string &unsigned_filename, const std::string &signed_filename, std::vector< wallet2::pending_tx > &ptx, std::function< bool(const unsigned_tx_set &)> accept_func=NULL, bool export_raw=false)
Definition: wallet2.cpp:7102
::std::string string
Definition: gtest-port.h:1097
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
#define SIGNED_TX_PREFIX
Definition: wallet2.cpp:108
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
std::string encrypt_with_view_secret_key(const std::string &plaintext, bool authenticated=true) const
Definition: wallet2.cpp:13217

◆ stop()

void tools::wallet2::stop ( )
inline

Definition at line 760 of file wallet2.h.

760 { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
Here is the caller graph for this function:

◆ store()

void tools::wallet2::store ( )

Definition at line 6032 of file wallet2.cpp.

6033 {
6034  if (!m_wallet_file.empty())
6036 }
void store_to(const std::string &path, const epee::wipeable_string &password)
store_to Stores wallet to another file(s), deleting old ones
Definition: wallet2.cpp:6038
Here is the caller graph for this function:

◆ store_to()

void tools::wallet2::store_to ( const std::string &  path,
const epee::wipeable_string password 
)

store_to Stores wallet to another file(s), deleting old ones

Parameters
pathPath to the wallet file (keys and address filenames will be generated based on this filename)
passwordPassword to protect new wallet (TODO: probably better save the password in the wallet object?)

Definition at line 6038 of file wallet2.cpp.

6039 {
6040  trim_hashchain();
6041 
6042  // if file is the same, we do:
6043  // 1. save wallet to the *.new file
6044  // 2. remove old wallet file
6045  // 3. rename *.new to wallet_name
6046 
6047  // handle if we want just store wallet state to current files (ex store() replacement);
6048  bool same_file = true;
6049  if (!path.empty())
6050  {
6051  std::string canonical_path = boost::filesystem::canonical(m_wallet_file).string();
6052  size_t pos = canonical_path.find(path);
6053  same_file = pos != std::string::npos;
6054  }
6055 
6056 
6057  if (!same_file)
6058  {
6059  // check if we want to store to directory which doesn't exists yet
6060  boost::filesystem::path parent_path = boost::filesystem::path(path).parent_path();
6061 
6062  // if path is not exists, try to create it
6063  if (!parent_path.empty() && !boost::filesystem::exists(parent_path))
6064  {
6065  boost::system::error_code ec;
6066  if (!boost::filesystem::create_directories(parent_path, ec))
6067  {
6068  throw std::logic_error(ec.message());
6069  }
6070  }
6071  }
6072  // preparing wallet data
6073  std::stringstream oss;
6075  ar << *this;
6076 
6077  wallet2::cache_file_data cache_file_data = boost::value_initialized<wallet2::cache_file_data>();
6078  cache_file_data.cache_data = oss.str();
6079  std::string cipher;
6080  cipher.resize(cache_file_data.cache_data.size());
6081  cache_file_data.iv = crypto::rand<crypto::chacha_iv>();
6082  crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cipher[0]);
6083  cache_file_data.cache_data = cipher;
6084 
6085  const std::string new_file = same_file ? m_wallet_file + ".new" : path;
6086  const std::string old_file = m_wallet_file;
6087  const std::string old_keys_file = m_keys_file;
6088  const std::string old_address_file = m_wallet_file + ".address.txt";
6089  const std::string old_mms_file = m_mms_file;
6090 
6091  // save keys to the new file
6092  // if we here, main wallet file is saved and we only need to save keys and address files
6093  if (!same_file) {
6094  prepare_file_names(path);
6095  bool r = store_keys(m_keys_file, password, false);
6097  if (boost::filesystem::exists(old_address_file))
6098  {
6099  // save address to the new file
6100  const std::string address_file = m_wallet_file + ".address.txt";
6101  r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype));
6103  }
6104  // remove old wallet file
6105  r = boost::filesystem::remove(old_file);
6106  if (!r) {
6107  LOG_ERROR("error removing file: " << old_file);
6108  }
6109  // remove old keys file
6110  r = boost::filesystem::remove(old_keys_file);
6111  if (!r) {
6112  LOG_ERROR("error removing file: " << old_keys_file);
6113  }
6114  // remove old address file
6115  r = boost::filesystem::remove(old_address_file);
6116  if (!r) {
6117  LOG_ERROR("error removing file: " << old_address_file);
6118  }
6119  // remove old message store file
6120  if (boost::filesystem::exists(old_mms_file))
6121  {
6122  r = boost::filesystem::remove(old_mms_file);
6123  if (!r) {
6124  LOG_ERROR("error removing file: " << old_mms_file);
6125  }
6126  }
6127  } else {
6128  // save to new file
6129 #ifdef WIN32
6130  // On Windows avoid using std::ofstream which does not work with UTF-8 filenames
6131  // The price to pay is temporary higher memory consumption for string stream + binary archive
6132  std::ostringstream oss;
6133  binary_archive<true> oar(oss);
6134  bool success = ::serialization::serialize(oar, cache_file_data);
6135  if (success) {
6136  success = epee::file_io_utils::save_string_to_file(new_file, oss.str());
6137  }
6139 #else
6140  std::ofstream ostr;
6141  ostr.open(new_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
6142  binary_archive<true> oar(ostr);
6143  bool success = ::serialization::serialize(oar, cache_file_data);
6144  ostr.close();
6145  THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file);
6146 #endif
6147 
6148  // here we have "*.new" file, we need to rename it to be without ".new"
6149  std::error_code e = tools::replace_file(new_file, m_wallet_file);
6150  THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e);
6151  }
6152 
6153  if (m_message_store.get_active())
6154  {
6155  // While the "m_message_store" object of course always exist, a file for the message
6156  // store should only exist if the MMS is really active
6157  m_message_store.write_to_file(get_multisig_wallet_state(), m_mms_file);
6158  }
6159 
6160 }
void write_to_file(const multisig_wallet_state &state, const std::string &filename)
mms::multisig_wallet_state get_multisig_wallet_state() const
Definition: wallet2.cpp:13615
::std::string string
Definition: gtest-port.h:1097
std::string path() const
Definition: wallet2.cpp:6027
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
std::string get_public_address_str(network_type nettype) const
Definition: account.cpp:269
file_error_base< file_save_error_message_index > file_save_error
void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization::version_type ver)
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
Definition: file_io_utils.h:73
std::error_code replace_file(const std::string &old_name, const std::string &new_name)
std::rename wrapper for nix and something strange for windows.
Definition: util.cpp:648
expect< void > success() noexcept
Definition: expect.h:397
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
bool get_active() const
Here is the call graph for this function:

◆ store_tx_info() [1/2]

bool tools::wallet2::store_tx_info ( ) const
inline

Definition at line 1069 of file wallet2.h.

1069 { return m_store_tx_info; }

◆ store_tx_info() [2/2]

void tools::wallet2::store_tx_info ( bool  store)
inline

Definition at line 1070 of file wallet2.h.

1070 { m_store_tx_info = store; }
Here is the call graph for this function:

◆ synced_to_v10()

bool tools::wallet2::synced_to_v10 ( ) const
inline

Definition at line 899 of file wallet2.h.

cryptonote::network_type nettype() const
Definition: wallet2.h:824
uint64_t get_blockchain_current_height() const
Definition: wallet2.h:898
Here is the call graph for this function:

◆ thaw() [1/2]

void tools::wallet2::thaw ( size_t  idx)

Definition at line 1591 of file wallet2.cpp.

1592 {
1593  CHECK_AND_ASSERT_THROW_MES(idx < m_transfers.size(), "Invalid transfer_details index");
1594  transfer_details &td = m_transfers[idx];
1595  td.m_frozen = false;
1596 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
Here is the caller graph for this function:

◆ thaw() [2/2]

void tools::wallet2::thaw ( const crypto::key_image ki)

Definition at line 1610 of file wallet2.cpp.

1611 {
1613 }
void thaw(size_t idx)
Definition: wallet2.cpp:1591
const transfer_details & get_transfer_details(size_t idx) const
Definition: wallet2.cpp:10852
Here is the call graph for this function:

◆ tr()

const char * tools::wallet2::tr ( const char *  str)
static

Definition at line 994 of file wallet2.cpp.

994 { return i18n_translate(str, "tools::wallet2"); }
const char * i18n_translate(const char *s, const std::string &context)
Definition: i18n.cpp:323
Here is the call graph for this function:

◆ track_uses() [1/2]

bool tools::wallet2::track_uses ( ) const
inline

Definition at line 1105 of file wallet2.h.

1105 { return m_track_uses; }

◆ track_uses() [2/2]

void tools::wallet2::track_uses ( bool  value)
inline

Definition at line 1106 of file wallet2.h.

1106 { m_track_uses = value; }
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225

◆ transfer_selected()

template<typename T >
void tools::wallet2::transfer_selected ( const std::vector< cryptonote::tx_destination_entry > &  dsts,
const std::vector< size_t > &  selected_transfers,
size_t  fake_outputs_count,
std::vector< std::vector< tools::wallet2::get_outs_entry >> &  outs,
uint64_t  unlock_time,
uint64_t  fee,
const std::vector< uint8_t > &  extra,
T  destination_split_strategy,
const tx_dust_policy dust_policy,
cryptonote::transaction tx,
pending_tx ptx 
)

Definition at line 8952 of file wallet2.cpp.

8955 {
8956  using namespace cryptonote;
8957  // throw if attempting a transaction with no destinations
8958  THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
8959 
8960  THROW_WALLET_EXCEPTION_IF(m_multisig, error::wallet_internal_error, "Multisig wallets cannot spend non rct outputs");
8961 
8962  uint64_t upper_transaction_weight_limit = get_upper_transaction_weight_limit();
8963  uint64_t needed_etn = fee;
8964  LOG_PRINT_L2("transfer: starting with fee " << print_etn (needed_etn));
8965 
8966  // calculate total amount being sent to all destinations
8967  // throw if total amount overflows uint64_t
8968  for(auto& dt: dsts)
8969  {
8970  THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
8971  needed_etn += dt.amount;
8972  LOG_PRINT_L2("transfer: adding " << print_etn(dt.amount) << ", for a total of " << print_etn (needed_etn));
8973  THROW_WALLET_EXCEPTION_IF(needed_etn < dt.amount, error::tx_sum_overflow, dsts, fee, m_nettype);
8974  }
8975 
8976  uint64_t found_etn = 0;
8977  for(size_t idx: selected_transfers)
8978  {
8979  found_etn += m_transfers[idx].amount();
8980  }
8981 
8982  LOG_PRINT_L2("wanted " << print_etn(needed_etn) << ", found " << print_etn(found_etn) << ", fee " << print_etn(fee));
8983  THROW_WALLET_EXCEPTION_IF(found_etn < needed_etn, error::not_enough_unlocked_etn, found_etn, needed_etn - fee, fee);
8984 
8985  uint32_t subaddr_account = m_transfers[*selected_transfers.begin()].m_subaddr_index.major;
8986  for (auto i = ++selected_transfers.begin(); i != selected_transfers.end(); ++i)
8987  THROW_WALLET_EXCEPTION_IF(subaddr_account != m_transfers[*i].m_subaddr_index.major, error::wallet_internal_error, "the tx uses funds from multiple accounts");
8988 
8989  if (outs.empty())
8990  get_outs(outs, selected_transfers, fake_outputs_count, tx.version); // may throw
8991 
8992  //prepare inputs
8993  LOG_PRINT_L2("preparing outputs");
8994  typedef cryptonote::tx_source_entry::output_entry tx_output_entry;
8995  size_t i = 0, out_index = 0;
8996  std::vector<cryptonote::tx_source_entry> sources;
8997  for(size_t idx: selected_transfers)
8998  {
8999  sources.resize(sources.size()+1);
9000  cryptonote::tx_source_entry& src = sources.back();
9001  const transfer_details& td = m_transfers[idx];
9002  src.amount = td.amount();
9003  src.rct = td.is_rct();
9004  if(tx.version < 3) {
9005  //paste keys (fake and real)
9006  // adding pairs of global index & stealth address to our vector of source outs (needed forold ins only)
9007  for (size_t n = 0; n < fake_outputs_count + 1; ++n) {
9008  tx_output_entry oe;
9009  oe.first = std::get<0>(outs[out_index][n]);
9010  oe.second.dest = rct::pk2rct(std::get<1>(outs[out_index][n]));
9011  oe.second.mask = std::get<2>(outs[out_index][n]);
9012 
9013  src.outputs.push_back(oe);
9014  ++i;
9015  }
9016 
9017  //paste real transaction to the random index
9018  auto it_to_replace = std::find_if(src.outputs.begin(), src.outputs.end(), [&](const tx_output_entry &a) {
9019  return a.first == td.m_global_output_index;
9020  });
9021  THROW_WALLET_EXCEPTION_IF(it_to_replace == src.outputs.end(), error::wallet_internal_error,
9022  "real output not found");
9023 
9024  tx_output_entry real_oe;
9025  real_oe.first = td.m_global_output_index;
9026  real_oe.second.dest = rct::pk2rct(
9027  boost::get<txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key);
9028  real_oe.second.mask = rct::commit(td.amount(), td.m_mask);
9029  *it_to_replace = real_oe;
9030  src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_tx, td.m_pk_index);
9032  src.real_output = it_to_replace - src.outputs.begin();
9034  }
9035  src.real_output_in_tx_index = td.m_internal_output_index; // these two are all we really need for v3 sources
9036  src.tx_hash = td.m_txid;
9037  src.subaddr_index = td.m_subaddr_index;
9039  ++out_index;
9040  }
9041  LOG_PRINT_L2("outputs prepared");
9042 
9043  cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts);
9044  if (needed_etn < found_etn)
9045  {
9046  // send change to the first input's address for v3+ tx
9047  uint32_t change_subaddress_minor = tx.version > 2 ? sources.front().subaddr_index.minor : 0;
9048  change_dts.addr = get_subaddress({subaddr_account, change_subaddress_minor});
9049  change_dts.is_subaddress = (subaddr_account != 0 || change_subaddress_minor != 0);
9050  change_dts.amount = found_etn - needed_etn;
9051  }
9052 
9053  std::vector<cryptonote::tx_destination_entry> splitted_dsts, dust_dsts;
9054  uint64_t dust = 0;
9055  destination_split_strategy(dsts, change_dts, dust_policy.dust_threshold, splitted_dsts, dust_dsts);
9056  for(auto& d: dust_dsts) {
9057  THROW_WALLET_EXCEPTION_IF(dust_policy.dust_threshold < d.amount, error::wallet_internal_error, "invalid dust value: dust = " +
9058  std::to_string(d.amount) + ", dust_threshold = " + std::to_string(dust_policy.dust_threshold));
9059  }
9060  for(auto& d: dust_dsts) {
9061  if (!dust_policy.add_to_fee)
9062  splitted_dsts.push_back(cryptonote::tx_destination_entry(d.amount, dust_policy.addr_for_dust, d.is_subaddress));
9063  dust += d.amount;
9064  }
9065 
9066  crypto::secret_key tx_key;
9067  std::vector<crypto::secret_key> additional_tx_keys;
9068  rct::multisig_out msout;
9069 
9070  LOG_PRINT_L2("constructing tx");
9071  bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, {}, m_multisig ? &msout : NULL, m_account_major_offset, this->m_nettype);
9072  LOG_PRINT_L2("constructed tx, r="<<r);
9073  THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_nettype);
9074  THROW_WALLET_EXCEPTION_IF(upper_transaction_weight_limit <= get_transaction_weight(tx), error::tx_too_big, tx, upper_transaction_weight_limit);
9075 
9076  std::string key_images;
9077  bool are_ins_correct_type = tx.version >= 3 ?
9078  std::all_of(tx.vin.begin(), tx.vin.end(), [&](const txin_v& s_e) -> bool
9079  {
9080  CHECKED_GET_SPECIFIC_VARIANT(s_e, const txin_to_key_public, in, false);
9081  return true;
9082  })
9083  :
9084  std::all_of(tx.vin.begin(), tx.vin.end(), [&](const txin_v& s_e) -> bool
9085  {
9086  CHECKED_GET_SPECIFIC_VARIANT(s_e, const txin_to_key, in, false);
9087  key_images += boost::to_string(in.k_image) + " ";
9088  return true;
9089  });
9090 
9091  THROW_WALLET_EXCEPTION_IF(!are_ins_correct_type, error::unexpected_txin_type, tx);
9092 
9093 
9094  bool dust_sent_elsewhere = (dust_policy.addr_for_dust.m_view_public_key != change_dts.addr.m_view_public_key
9095  || dust_policy.addr_for_dust.m_spend_public_key != change_dts.addr.m_spend_public_key);
9096 
9097  if (dust_policy.add_to_fee || dust_sent_elsewhere) change_dts.amount -= dust;
9098 
9099  ptx.key_images = key_images;
9100  ptx.fee = (dust_policy.add_to_fee ? fee+dust : fee);
9101  ptx.dust = ((dust_policy.add_to_fee || dust_sent_elsewhere) ? dust : 0);
9102  ptx.dust_added_to_fee = dust_policy.add_to_fee;
9103  ptx.tx = tx;
9104  ptx.change_dts = change_dts;
9105  ptx.selected_transfers = selected_transfers;
9106  ptx.tx_key = tx_key;
9107  ptx.additional_tx_keys = additional_tx_keys;
9108  ptx.dests = dsts;
9109  ptx.construction_data.sources = sources;
9110  ptx.construction_data.change_dts = change_dts;
9111  ptx.construction_data.splitted_dsts = splitted_dsts;
9112  ptx.construction_data.selected_transfers = selected_transfers;
9113  ptx.construction_data.extra = tx.extra;
9114  ptx.construction_data.unlock_time = unlock_time;
9115  ptx.construction_data.use_rct = false;
9116  ptx.construction_data.rct_config = { rct::RangeProofBorromean, 0 };
9117  ptx.construction_data.dests = dsts;
9118  // record which subaddress indices are being used as inputs
9119  ptx.construction_data.subaddr_account = subaddr_account;
9120  ptx.construction_data.subaddr_indices.clear();
9121  for (size_t idx: selected_transfers)
9122  ptx.construction_data.subaddr_indices.insert(m_transfers[idx].m_subaddr_index.minor);
9123  LOG_PRINT_L2("transfer_selected done");
9124 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
crypto::public_key real_out_tx_key
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
::std::string string
Definition: gtest-port.h:1097
std::string print_etn(uint64_t amount, unsigned int decimal_point)
key commit(etn_amount amount, const key &mask)
Definition: rctOps.cpp:336
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
void print_source_entry(const cryptonote::tx_source_entry &src)
Definition: wallet2.h:2137
bool rct
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
uint64_t amount
size_t real_output
Holds cryptonote related classes and helpers.
Definition: ban.cpp:40
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index &index) const
Definition: wallet2.cpp:1430
unsigned int uint32_t
Definition: stdint.h:126
unsigned __int64 uint64_t
Definition: stdint.h:136
crypto::public_key get_tx_pub_key_from_extra(const std::vector< uint8_t > &tx_extra, size_t pk_index)
uint64_t amount
bool is_subaddress
crypto::hash tx_hash
rct::multisig_kLRki multisig_kLRki
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
account_public_address addr
std::vector< crypto::public_key > real_out_additional_tx_keys
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
size_t real_output_in_tx_index
std::vector< output_entry > outputs
#define AUTO_VAL_INIT(v)
Definition: misc_language.h:53
std::string to_string(t_connection_type type)
std::pair< uint64_t, rct::ctkey > output_entry
std::vector< crypto::public_key > get_additional_tx_pub_keys_from_extra(const std::vector< uint8_t > &tx_extra)
bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map< crypto::public_key, subaddress_index > &subaddresses, std::vector< tx_source_entry > &sources, std::vector< tx_destination_entry > &destinations, const boost::optional< cryptonote::account_public_address > &change_addr, const std::vector< uint8_t > &extra, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector< crypto::secret_key > &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, rct::multisig_out *msout, const uint32_t account_major_offset, const cryptonote::network_type nettype)
key zero()
Definition: rctOps.h:70
subaddress_index subaddr_index
Here is the call graph for this function:

◆ unblackball_output()

bool tools::wallet2::unblackball_output ( const std::pair< uint64_t, uint64_t > &  output)

Definition at line 8198 of file wallet2.cpp.

8199 {
8200  if (!m_ringdb)
8201  return false;
8202  try { return m_ringdb->unblackball(output); }
8203  catch (const std::exception &e) { return false; }
8204 }

◆ unlock_keys_file()

bool tools::wallet2::unlock_keys_file ( )

Definition at line 8225 of file wallet2.cpp.

8226 {
8227  if (!m_keys_file_locker)
8228  {
8229  MDEBUG(m_keys_file << " is already unlocked.");
8230  return false;
8231  }
8232  m_keys_file_locker.reset();
8233  return true;
8234 }
#define MDEBUG(x)
Definition: misc_log_ex.h:76

◆ unlocked_balance()

uint64_t tools::wallet2::unlocked_balance ( uint32_t  subaddr_index_major,
bool  public_blockchain,
uint64_t blocks_to_unlock = NULL 
) const

Definition at line 6172 of file wallet2.cpp.

6173 {
6174  uint64_t amount = 0;
6175  if (blocks_to_unlock)
6176  *blocks_to_unlock = 0;
6177  if(m_light_wallet)
6178  return m_light_wallet_balance;
6179  for (const auto& i : unlocked_balance_per_subaddress(index_major, public_blockchain))
6180  {
6181  amount += i.second.first;
6182  if (blocks_to_unlock && i.second.second > *blocks_to_unlock)
6183  *blocks_to_unlock = i.second.second;
6184  }
6185  return amount;
6186 }
unsigned __int64 uint64_t
Definition: stdint.h:136
std::map< uint32_t, std::pair< uint64_t, uint64_t > > unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool public_blockchain=false) const
Definition: wallet2.cpp:6249
Here is the caller graph for this function:

◆ unlocked_balance_all()

uint64_t tools::wallet2::unlocked_balance_all ( bool  public_blockchain,
uint64_t blocks_to_unlock = NULL 
) const

Definition at line 6300 of file wallet2.cpp.

6301 {
6302  uint64_t r = 0;
6303  if (blocks_to_unlock)
6304  *blocks_to_unlock = 0;
6305  for (uint32_t index_major = 0; index_major < get_num_subaddress_accounts(); ++index_major)
6306  {
6307  uint64_t local_blocks_to_unlock;
6308  r += unlocked_balance(index_major, public_blockchain ,blocks_to_unlock ? &local_blocks_to_unlock : NULL);
6309  if (blocks_to_unlock)
6310  *blocks_to_unlock = std::max(*blocks_to_unlock, local_blocks_to_unlock);
6311  }
6312  return r;
6313 }
uint64_t unlocked_balance(uint32_t subaddr_index_major, bool public_blockchain, uint64_t *blocks_to_unlock=NULL) const
Definition: wallet2.cpp:6172
unsigned int uint32_t
Definition: stdint.h:126
unsigned __int64 uint64_t
Definition: stdint.h:136
size_t get_num_subaddress_accounts() const
Definition: wallet2.h:801

◆ unlocked_balance_per_subaddress()

std::map< uint32_t, std::pair< uint64_t, uint64_t > > tools::wallet2::unlocked_balance_per_subaddress ( uint32_t  subaddr_index_major,
bool  public_blockchain = false 
) const

Definition at line 6249 of file wallet2.cpp.

6250 {
6251  std::map<uint32_t, std::pair<uint64_t, uint64_t>> amount_per_subaddr; //map of subaddr minor index : <amount,unlock t>
6252  const uint64_t blockchain_height = get_blockchain_current_height();
6253  //Figure out amount & blocks_to_unlock for the major subaddress index for each transfer
6254  for(const transfer_details& td: m_transfers)
6255  {
6256  if((public_blockchain && td.m_tx.version == 1) || (!public_blockchain && td.m_tx.version > 1))
6257  continue;
6258 
6259  if(td.m_subaddr_index.major == index_major && !td.m_spent && !td.m_frozen)
6260  {
6261  uint64_t amount = 0, blocks_to_unlock = 0;
6262  if (is_transfer_unlocked(td))
6263  {
6264  amount = td.amount();
6265  blocks_to_unlock = 0;
6266  }
6267  else
6268  {
6269 
6270  uint64_t v8height = m_nettype == TESTNET ? 446674 : 589169;
6271  uint16_t UNLOCK_WINDOW = td.m_block_height > v8height ? ETN_DEFAULT_TX_SPENDABLE_AGE_V8 : CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE;
6272  uint64_t unlock_height = td.m_block_height + std::max<uint64_t>(UNLOCK_WINDOW, CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS);
6273  if (td.m_tx.unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER && td.m_tx.unlock_time > unlock_height)
6274  unlock_height = td.m_tx.unlock_time;
6275  blocks_to_unlock = unlock_height > blockchain_height ? unlock_height - blockchain_height : 0;
6276  amount = 0;
6277  }
6278  auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
6279  // if we don't have this subaddress index (key) in our map, create a new entry, otherwise just add a new pair
6280  if (found == amount_per_subaddr.end())
6281  amount_per_subaddr[td.m_subaddr_index.minor] = std::make_pair(amount, blocks_to_unlock);
6282  else
6283  {
6284  found->second.first += amount;
6285  found->second.second = std::max(found->second.second, blocks_to_unlock);
6286  }
6287  }
6288  }
6289  return amount_per_subaddr;
6290 }
bool is_transfer_unlocked(const transfer_details &td) const
Definition: wallet2.cpp:6565
#define CRYPTONOTE_MAX_BLOCK_NUMBER
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
unsigned short uint16_t
Definition: stdint.h:125
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
uint64_t get_blockchain_current_height() const
Definition: wallet2.h:898

◆ unset_ring() [1/2]

bool tools::wallet2::unset_ring ( const std::vector< crypto::key_image > &  key_images)

Definition at line 8072 of file wallet2.cpp.

8073 {
8074  if (!m_ringdb)
8075  return false;
8076 
8077  try { return m_ringdb->remove_rings(get_ringdb_key(), key_images); }
8078  catch (const std::exception &e) { return false; }
8079 }

◆ unset_ring() [2/2]

bool tools::wallet2::unset_ring ( const crypto::hash txid)

Definition at line 8081 of file wallet2.cpp.

8082 {
8083  if (!m_ringdb)
8084  return false;
8085 
8088  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
8089  req.decode_as_json = false;
8090  req.prune = true;
8091  m_daemon_rpc_mutex.lock();
8092  bool ok = invoke_http_json("/gettransactions", req, res, rpc_timeout);
8093  m_daemon_rpc_mutex.unlock();
8094  THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to get transaction from daemon");
8095  if (res.txs.empty())
8096  return false;
8097  THROW_WALLET_EXCEPTION_IF(res.txs.size(), error::wallet_internal_error, "Failed to get transaction from daemon");
8098 
8100  crypto::hash tx_hash;
8101  if (!get_pruned_tx(res.txs.front(), tx, tx_hash))
8102  return false;
8103  THROW_WALLET_EXCEPTION_IF(tx_hash != txid, error::wallet_internal_error, "Failed to get the right transaction from daemon");
8104 
8105  try { return m_ringdb->remove_rings(get_ringdb_key(), tx); }
8106  catch (const std::exception &e) { return false; }
8107 }
const char * res
Definition: hmac_keccak.cpp:41
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ update_pool_state()

void tools::wallet2::update_pool_state ( bool  refreshed = false)

Definition at line 3164 of file wallet2.cpp.

3165 {
3166  MTRACE("update_pool_state start");
3167 
3168  auto keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this]() {
3169  if (m_encrypt_keys_after_refresh)
3170  {
3171  encrypt_keys(*m_encrypt_keys_after_refresh);
3172  m_encrypt_keys_after_refresh = boost::none;
3173  }
3174  });
3175 
3176  // get the pool state
3179  m_daemon_rpc_mutex.lock();
3180  bool r = invoke_http_json("/get_transaction_pool_hashes.bin", req, res, rpc_timeout);
3181  m_daemon_rpc_mutex.unlock();
3182  THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool_hashes.bin");
3183  THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool_hashes.bin");
3184  THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
3185  MTRACE("update_pool_state got pool");
3186 
3187  // remove any pending tx that's not in the pool
3188  std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
3189  while (it != m_unconfirmed_txs.end())
3190  {
3191  const crypto::hash &txid = it->first;
3192  bool found = false;
3193  for (const auto &it2: res.tx_hashes)
3194  {
3195  if (it2 == txid)
3196  {
3197  found = true;
3198  break;
3199  }
3200  }
3201  auto pit = it++;
3202  if (!found)
3203  {
3204  // we want to avoid a false positive when we ask for the pool just after
3205  // a tx is removed from the pool due to being found in a new block, but
3206  // just before the block is visible by refresh. So we keep a boolean, so
3207  // that the first time we don't see the tx, we set that boolean, and only
3208  // delete it the second time it is checked (but only when refreshed, so
3209  // we're sure we've seen the blockchain state first)
3210  if (pit->second.m_state == wallet2::unconfirmed_transfer_details::pending)
3211  {
3212  LOG_PRINT_L1("Pending txid " << txid << " not in pool, marking as not in pool");
3214  }
3215  else if (pit->second.m_state == wallet2::unconfirmed_transfer_details::pending_not_in_pool && refreshed)
3216  {
3217  LOG_PRINT_L1("Pending txid " << txid << " not in pool, marking as failed");
3218  pit->second.m_state = wallet2::unconfirmed_transfer_details::failed;
3219 
3220  // the inputs aren't spent anymore, since the tx failed
3221  remove_rings(pit->second.m_tx);
3222  for (size_t vini = 0; vini < pit->second.m_tx.vin.size(); ++vini)
3223  {
3224  if (pit->second.m_tx.vin[vini].type() == typeid(txin_to_key))
3225  {
3226  txin_to_key &tx_in_to_key = boost::get<txin_to_key>(pit->second.m_tx.vin[vini]);
3227  for (size_t i = 0; i < m_transfers.size(); ++i)
3228  {
3229  const transfer_details &td = m_transfers[i];
3230  if (td.m_key_image == tx_in_to_key.k_image)
3231  {
3232  LOG_PRINT_L1("Resetting spent status for output " << vini << ": " << td.m_key_image);
3233  set_unspent(i);
3234  break;
3235  }
3236  }
3237  }
3238  }
3239  }
3240  }
3241  }
3242  MTRACE("update_pool_state done first loop");
3243 
3244  // remove pool txes to us that aren't in the pool anymore
3245  // but only if we just refreshed, so that the tx can go in
3246  // the in transfers list instead (or nowhere if it just
3247  // disappeared without being mined)
3248  if (refreshed)
3249  remove_obsolete_pool_txs(res.tx_hashes);
3250 
3251  MTRACE("update_pool_state done second loop");
3252 
3253  // gather txids of new pool txes to us
3254  std::vector<std::pair<crypto::hash, bool>> txids;
3255  for (const auto &txid: res.tx_hashes)
3256  {
3257  bool txid_found_in_up = false;
3258  for (const auto &up: m_unconfirmed_payments)
3259  {
3260  if (up.second.m_pd.m_tx_hash == txid)
3261  {
3262  txid_found_in_up = true;
3263  break;
3264  }
3265  }
3266  if (m_scanned_pool_txs[0].find(txid) != m_scanned_pool_txs[0].end() || m_scanned_pool_txs[1].find(txid) != m_scanned_pool_txs[1].end())
3267  {
3268  // if it's for us, we want to keep track of whether we saw a double spend, so don't bail out
3269  if (!txid_found_in_up)
3270  {
3271  LOG_PRINT_L2("Already seen " << txid << ", and not for us, skipped");
3272  continue;
3273  }
3274  }
3275  if (!txid_found_in_up)
3276  {
3277  LOG_PRINT_L1("Found new pool tx: " << txid);
3278  bool found = false;
3279  for (const auto &i: m_unconfirmed_txs)
3280  {
3281  if (i.first == txid)
3282  {
3283  found = true;
3284  // if this is a payment to yourself at a different subaddress account, don't skip it
3285  // so that you can see the incoming pool tx with 'show_transfers' on that receiving subaddress account
3286  const unconfirmed_transfer_details& utd = i.second;
3287  for (const auto& dst : utd.m_dests)
3288  {
3289  auto subaddr_index = m_subaddresses.find(dst.addr.m_spend_public_key);
3290  if (subaddr_index != m_subaddresses.end() && subaddr_index->second.major != utd.m_subaddr_account)
3291  {
3292  found = false;
3293  break;
3294  }
3295  }
3296  break;
3297  }
3298  }
3299  if (!found)
3300  {
3301  // not one of those we sent ourselves
3302  txids.push_back({txid, false});
3303  }
3304  else
3305  {
3306  LOG_PRINT_L1("We sent that one");
3307  }
3308  }
3309  else
3310  {
3311  LOG_PRINT_L1("Already saw that one, it's for us");
3312  txids.push_back({txid, true});
3313  }
3314  }
3315 
3316  // get those txes
3317  if (!txids.empty())
3318  {
3321  for (const auto &p: txids)
3322  req.txs_hashes.push_back(epee::string_tools::pod_to_hex(p.first));
3323  MDEBUG("asking for " << txids.size() << " transactions");
3324  req.decode_as_json = false;
3325  req.prune = true;
3326  m_daemon_rpc_mutex.lock();
3327  bool r = invoke_http_json("/gettransactions", req, res, rpc_timeout);
3328  m_daemon_rpc_mutex.unlock();
3329  MDEBUG("Got " << r << " and " << res.status);
3330  if (r && res.status == CORE_RPC_STATUS_OK)
3331  {
3332  if (res.txs.size() == txids.size())
3333  {
3334  for (const auto &tx_entry: res.txs)
3335  {
3336  if (tx_entry.in_pool)
3337  {
3340  crypto::hash tx_hash;
3341 
3342  if (get_pruned_tx(tx_entry, tx, tx_hash))
3343  {
3344  const std::vector<std::pair<crypto::hash, bool>>::const_iterator i = std::find_if(txids.begin(), txids.end(),
3345  [tx_hash](const std::pair<crypto::hash, bool> &e) { return e.first == tx_hash; });
3346  if (i != txids.end())
3347  {
3348  process_new_transaction(tx_hash, tx, std::vector<uint64_t>(), 0, time(NULL), false, true, tx_entry.double_spend_seen, false, {});
3349  m_scanned_pool_txs[0].insert(tx_hash);
3350  if (m_scanned_pool_txs[0].size() > 5000)
3351  {
3352  std::swap(m_scanned_pool_txs[0], m_scanned_pool_txs[1]);
3353  m_scanned_pool_txs[0].clear();
3354  }
3355  }
3356  else
3357  {
3358  MERROR("Got txid " << tx_hash << " which we did not ask for");
3359  }
3360  }
3361  else
3362  {
3363  LOG_PRINT_L0("Failed to parse transaction from daemon");
3364  }
3365  }
3366  else
3367  {
3368  LOG_PRINT_L1("Transaction from daemon was in pool, but is no more");
3369  }
3370  }
3371  }
3372  else
3373  {
3374  LOG_PRINT_L0("Expected " << txids.size() << " tx(es), got " << res.txs.size());
3375  }
3376  }
3377  else
3378  {
3379  LOG_PRINT_L0("Error calling gettransactions daemon RPC: r " << r << ", status " << get_rpc_status(res.status));
3380  }
3381  }
3382  MTRACE("update_pool_state end");
3383 }
const char * res
Definition: hmac_keccak.cpp:41
#define MERROR(x)
Definition: misc_log_ex.h:73
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
bool invoke_http_json(const boost::string_ref uri, const t_request &req, t_response &res, std::chrono::milliseconds timeout=std::chrono::seconds(15), const boost::string_ref http_method="GET")
Definition: wallet2.h:1319
#define MTRACE(x)
Definition: misc_log_ex.h:77
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
static constexpr const std::chrono::seconds rpc_timeout
Definition: wallet2.h:216
#define CORE_RPC_STATUS_BUSY
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
#define CORE_RPC_STATUS_OK
#define MDEBUG(x)
Definition: misc_log_ex.h:76
time_t time
Definition: blockchain.cpp:93
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
void remove_obsolete_pool_txs(const std::vector< crypto::hash > &tx_hashes)
Definition: wallet2.cpp:3136
std::string blobdata
Definition: blobdatatype.h:39
void encrypt_keys(const crypto::chacha_key &key)
Definition: wallet2.cpp:4746
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
crypto::key_image k_image
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ use_fork_rules()

bool tools::wallet2::use_fork_rules ( uint8_t  version,
int64_t  early_blocks = 0 
) const

Definition at line 10720 of file wallet2.cpp.

10721 {
10722  // TODO: How to get fork rule info from light wallet node?
10723  if(m_light_wallet)
10724  return true;
10725  uint64_t height, earliest_height;
10726  boost::optional<std::string> result = m_node_rpc_proxy.get_height(height);
10727  throw_on_rpc_response_error(result, "get_info");
10728  result = m_node_rpc_proxy.get_earliest_height(version, earliest_height);
10729  throw_on_rpc_response_error(result, "get_hard_fork_info");
10730 
10731  bool close_enough = (int64_t)height >= (int64_t)earliest_height - early_blocks && earliest_height != std::numeric_limits<uint64_t>::max() && version <= CURRENT_HARDFORK_VERSION; // start using the rules that many blocks beforehand
10732  if (close_enough)
10733  LOG_PRINT_L2("Using v" << (unsigned)version << " rules");
10734  else
10735  LOG_PRINT_L2("Not using v" << (unsigned)version << " rules");
10736  return close_enough;
10737 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
boost::optional< std::string > get_earliest_height(uint8_t version, uint64_t &earliest_height) const
uint64_t height
Definition: blockchain.cpp:91
unsigned __int64 uint64_t
Definition: stdint.h:136
version
Supported socks variants.
Definition: socks.h:57
signed __int64 int64_t
Definition: stdint.h:135
#define CURRENT_HARDFORK_VERSION
boost::optional< std::string > get_height(uint64_t &height) const

◆ verify()

bool tools::wallet2::verify ( const std::string &  data,
const cryptonote::account_public_address address,
const std::string &  signature 
) const

Definition at line 12086 of file wallet2.cpp.

12087 {
12088  const size_t header_len = strlen("SigV1");
12089  if (signature.size() < header_len || signature.substr(0, header_len) != "SigV1") {
12090  LOG_PRINT_L0("Signature header check error");
12091  return false;
12092  }
12094  crypto::cn_fast_hash(data.data(), data.size(), hash);
12095  std::string decoded;
12096  if (!tools::base58::decode(signature.substr(header_len), decoded)) {
12097  LOG_PRINT_L0("Signature decoding error");
12098  return false;
12099  }
12101  if (sizeof(s) != decoded.size()) {
12102  LOG_PRINT_L0("Signature decoding error");
12103  return false;
12104  }
12105  memcpy(&s, decoded.data(), sizeof(s));
12106  return crypto::check_signature(hash, address.m_spend_public_key, s);
12107 }
::std::string string
Definition: gtest-port.h:1097
bool decode(const std::string &enc, std::string &data)
Definition: base58.cpp:196
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
void * memcpy(void *a, const void *b, size_t c)
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:295
Here is the call graph for this function:
Here is the caller graph for this function:

◆ verify_extra_multisig_info()

bool tools::wallet2::verify_extra_multisig_info ( const std::string &  data,
std::unordered_set< crypto::public_key > &  pkeys,
crypto::public_key signer 
)
static

Verifies and extracts keys from a packaged multisig information string

Definition at line 5586 of file wallet2.cpp.

5587 {
5588  if (data.size() < MULTISIG_EXTRA_INFO_MAGIC.size() || data.substr(0, MULTISIG_EXTRA_INFO_MAGIC.size()) != MULTISIG_EXTRA_INFO_MAGIC)
5589  {
5590  MERROR("Multisig info header check error");
5591  return false;
5592  }
5593  std::string decoded;
5594  if (!tools::base58::decode(data.substr(MULTISIG_EXTRA_INFO_MAGIC.size()), decoded))
5595  {
5596  MERROR("Multisig info decoding error");
5597  return false;
5598  }
5599  if (decoded.size() < sizeof(crypto::public_key) + sizeof(crypto::signature))
5600  {
5601  MERROR("Multisig info is corrupt");
5602  return false;
5603  }
5604  if ((decoded.size() - (sizeof(crypto::public_key) + sizeof(crypto::signature))) % sizeof(crypto::public_key))
5605  {
5606  MERROR("Multisig info is corrupt");
5607  return false;
5608  }
5609 
5610  const size_t n_keys = (decoded.size() - (sizeof(crypto::public_key) + sizeof(crypto::signature))) / sizeof(crypto::public_key);
5611  size_t offset = 0;
5612  signer = *(const crypto::public_key*)(decoded.data() + offset);
5613  offset += sizeof(signer);
5614  const crypto::signature &signature = *(const crypto::signature*)(decoded.data() + offset + n_keys * sizeof(crypto::public_key));
5615 
5617  crypto::cn_fast_hash(decoded.data(), decoded.size() - sizeof(signature), hash);
5618  if (!crypto::check_signature(hash, signer, signature))
5619  {
5620  MERROR("Multisig info signature is invalid");
5621  return false;
5622  }
5623 
5624  for (size_t n = 0; n < n_keys; ++n)
5625  {
5626  crypto::public_key mspk = *(const crypto::public_key*)(decoded.data() + offset);
5627  pkeys.insert(mspk);
5628  offset += sizeof(mspk);
5629  }
5630 
5631  return true;
5632 }
#define MERROR(x)
Definition: misc_log_ex.h:73
::std::string string
Definition: gtest-port.h:1097
bool decode(const std::string &enc, std::string &data)
Definition: base58.cpp:196
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
POD_CLASS hash
Definition: hash.h:50
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:295

◆ verify_multisig_info()

bool tools::wallet2::verify_multisig_info ( const std::string &  data,
crypto::secret_key skey,
crypto::public_key pkey 
)
static

Verifies and extracts keys from a packaged multisig information string

Definition at line 5548 of file wallet2.cpp.

5549 {
5550  const size_t header_len = strlen("MultisigV1");
5551  if (data.size() < header_len || data.substr(0, header_len) != "MultisigV1")
5552  {
5553  MERROR("Multisig info header check error");
5554  return false;
5555  }
5556  std::string decoded;
5557  if (!tools::base58::decode(data.substr(header_len), decoded))
5558  {
5559  MERROR("Multisig info decoding error");
5560  return false;
5561  }
5562  if (decoded.size() != sizeof(crypto::secret_key) + sizeof(crypto::public_key) + sizeof(crypto::signature))
5563  {
5564  MERROR("Multisig info is corrupt");
5565  return false;
5566  }
5567 
5568  size_t offset = 0;
5569  skey = *(const crypto::secret_key*)(decoded.data() + offset);
5570  offset += sizeof(skey);
5571  pkey = *(const crypto::public_key*)(decoded.data() + offset);
5572  offset += sizeof(pkey);
5573  const crypto::signature &signature = *(const crypto::signature*)(decoded.data() + offset);
5574 
5576  crypto::cn_fast_hash(decoded.data(), decoded.size() - sizeof(signature), hash);
5577  if (!crypto::check_signature(hash, pkey, signature))
5578  {
5579  MERROR("Multisig info signature is invalid");
5580  return false;
5581  }
5582 
5583  return true;
5584 }
#define MERROR(x)
Definition: misc_log_ex.h:73
::std::string string
Definition: gtest-port.h:1097
bool decode(const std::string &enc, std::string &data)
Definition: base58.cpp:196
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
POD_CLASS hash
Definition: hash.h:50
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:295
Here is the call graph for this function:

◆ verify_password() [1/2]

bool tools::wallet2::verify_password ( const std::string &  keys_file_name,
const epee::wipeable_string password,
bool  no_spend_key,
hw::device hwdev,
uint64_t  kdf_rounds 
)
static

verify password for specified wallet keys file.

Parameters
keys_file_nameKeys file to verify password for
passwordPassword to verify
no_spend_keyIf set = only verify view keys, otherwise also spend keys
hwdevThe hardware device to use
Returns
true if password is correct

for verification only should not mutate state, unlike load_keys() can be used prior to rewriting wallet keys file, to ensure user has entered the correct password

Definition at line 4699 of file wallet2.cpp.

4700 {
4702  wallet2::keys_file_data keys_file_data;
4703  std::string buf;
4704  bool encrypted_secret_keys = false;
4705  bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
4707 
4708  // Decrypt the contents
4709  r = ::serialization::parse_binary(buf, keys_file_data);
4710  THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"');
4711  crypto::chacha_key key;
4712  crypto::generate_chacha_key(password.data(), password.size(), key, kdf_rounds);
4713  std::string account_data;
4714  account_data.resize(keys_file_data.account_data.size());
4715  crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
4716  if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject())
4717  crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
4718 
4719  // The contents should be JSON if the wallet follows the new format.
4720  if (json.Parse(account_data.c_str()).HasParseError())
4721  {
4722  // old format before JSON wallet key file format
4723  }
4724  else
4725  {
4726  account_data = std::string(json["key_data"].GetString(), json["key_data"].GetString() +
4727  json["key_data"].GetStringLength());
4728  GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, encrypted_secret_keys, uint32_t, Uint, false, false);
4729  encrypted_secret_keys = field_encrypted_secret_keys;
4730  }
4731 
4732  cryptonote::account_base account_data_check;
4733 
4734  r = epee::serialization::load_t_from_binary(account_data_check, account_data);
4735 
4736  if (encrypted_secret_keys)
4737  account_data_check.decrypt_keys(key);
4738 
4739  const cryptonote::account_keys& keys = account_data_check.get_keys();
4741  if(!no_spend_key)
4743  return r;
4744 }
size_t size() const noexcept
virtual bool verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key)=0
::std::string string
Definition: gtest-port.h:1097
void chacha20(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
const char * key
Definition: hmac_keccak.cpp:39
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
bool parse_binary(const std::string &blob, T &v)
Definition: binary_utils.h:41
void chacha8(const void *data, size_t length, const uint8_t *key, const uint8_t *iv, char *cipher)
const account_keys & get_keys() const
Definition: account.cpp:264
void decrypt_keys(const crypto::chacha_key &key)
Definition: account.h:105
bool load_t_from_binary(t_struct &out, const epee::span< const uint8_t > binary_buff)
unsigned int uint32_t
Definition: stdint.h:126
file_error_base< file_read_error_message_index > file_read_error
GenericDocument< UTF8<> > Document
GenericDocument with UTF8 encoding.
Definition: document.h:2512
const char * buf
Definition: slow_memmem.cpp:74
crypto::secret_key m_view_secret_key
Definition: account.h:45
account_public_address m_account_address
Definition: account.h:43
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)
#define GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, name, type, jtype, mandatory, def)
Definition: json_util.h:32
crypto::secret_key m_spend_secret_key
Definition: account.h:44
const char * data() const noexcept
rapidjson::Document json
Definition: transport.cpp:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ verify_password() [2/2]

bool tools::wallet2::verify_password ( const epee::wipeable_string password)

verifies given password is correct for default wallet keys file

verify password for default wallet keys file.

Parameters
passwordPassword to verify
Returns
true if password is correct

for verification only should not mutate state, unlike load_keys() can be used prior to rewriting wallet keys file, to ensure user has entered the correct password

Definition at line 4677 of file wallet2.cpp.

4678 {
4679  // this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded).
4680  unlock_keys_file();
4681  bool r = verify_password(m_keys_file, password, m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds);
4682  lock_keys_file();
4683  return r;
4684 }
virtual device_protocol_t device_protocol() const
Definition: device.hpp:135
bool unlock_keys_file()
Definition: wallet2.cpp:8225
hw::device & get_device() const
Definition: account.h:91
static bool verify_password(const std::string &keys_file_name, const epee::wipeable_string &password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds)
verify password for specified wallet keys file.
Definition: wallet2.cpp:4699
bool lock_keys_file()
Definition: wallet2.cpp:8214

◆ verify_with_public_key()

bool tools::wallet2::verify_with_public_key ( const std::string &  data,
const crypto::public_key public_key,
const std::string &  signature 
) const

verify_with_public_key verifies message was signed with given public key

Parameters
datamessage
public_keypublic key to check signature
signaturesignature of the message
Returns
true if the signature is correct

Definition at line 12121 of file wallet2.cpp.

12122 {
12123  if (signature.size() < MULTISIG_SIGNATURE_MAGIC.size() || signature.substr(0, MULTISIG_SIGNATURE_MAGIC.size()) != MULTISIG_SIGNATURE_MAGIC) {
12124  MERROR("Signature header check error");
12125  return false;
12126  }
12128  crypto::cn_fast_hash(data.data(), data.size(), hash);
12129  std::string decoded;
12130  if (!tools::base58::decode(signature.substr(MULTISIG_SIGNATURE_MAGIC.size()), decoded)) {
12131  MERROR("Signature decoding error");
12132  return false;
12133  }
12135  if (sizeof(s) != decoded.size()) {
12136  MERROR("Signature decoding error");
12137  return false;
12138  }
12139  memcpy(&s, decoded.data(), sizeof(s));
12141 }
#define MERROR(x)
Definition: misc_log_ex.h:73
::std::string string
Definition: gtest-port.h:1097
bool decode(const std::string &enc, std::string &data)
Definition: base58.cpp:196
POD_CLASS public_key
Definition: crypto.h:76
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS signature
Definition: crypto.h:108
void * memcpy(void *a, const void *b, size_t c)
POD_CLASS hash
Definition: hash.h:50
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition: crypto.h:295

◆ wallet_exists()

void tools::wallet2::wallet_exists ( const std::string &  file_path,
bool keys_file_exists,
bool wallet_file_exists 
)
static

Check if wallet keys and bin files exist.

Parameters
file_pathWallet file path
keys_file_existsWhether keys file exists
wallet_file_existsWhether bin file exists

Definition at line 5697 of file wallet2.cpp.

5698 {
5699  std::string keys_file, wallet_file, mms_file;
5700  do_prepare_file_names(file_path, keys_file, wallet_file, mms_file);
5701 
5702  boost::system::error_code ignore;
5703  keys_file_exists = boost::filesystem::exists(keys_file, ignore);
5704  wallet_file_exists = boost::filesystem::exists(wallet_file, ignore);
5705 }
::std::string string
Definition: gtest-port.h:1097
Here is the caller graph for this function:

◆ wallet_valid_path_format()

bool tools::wallet2::wallet_valid_path_format ( const std::string &  file_path)
static

Definition at line 5707 of file wallet2.cpp.

5708 {
5709  return !file_path.empty();
5710 }

◆ watch_only()

bool tools::wallet2::watch_only ( ) const
inline

Definition at line 825 of file wallet2.h.

825 { return m_watch_only; }
Here is the caller graph for this function:

◆ write_watch_only_wallet()

void tools::wallet2::write_watch_only_wallet ( const std::string &  wallet_name,
const epee::wipeable_string password,
std::string &  new_keys_filename 
)

Writes to a file named based on the normal wallet (doesn't generate key, assumes it's already there)

Parameters
wallet_nameBase name of wallet file
passwordPassword for wallet file
new_keys_filename[OUT] Name of new keys file

Definition at line 5686 of file wallet2.cpp.

5687 {
5688  prepare_file_names(wallet_name);
5689  boost::system::error_code ignored_ec;
5690  new_keys_filename = m_wallet_file + "-watchonly.keys";
5691  bool watch_only_keys_file_exists = boost::filesystem::exists(new_keys_filename, ignored_ec);
5692  THROW_WALLET_EXCEPTION_IF(watch_only_keys_file_exists, error::file_save_error, new_keys_filename);
5693  bool r = store_keys(new_keys_filename, password, true);
5694  THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, new_keys_filename);
5695 }
file_error_base< file_save_error_message_index > file_save_error
#define THROW_WALLET_EXCEPTION_IF(cond, err_type,...)

Friends And Related Function Documentation

◆ ::Serialization_portability_wallet_Test

friend class ::Serialization_portability_wallet_Test
friend

Definition at line 211 of file wallet2.h.

◆ ::wallet_accessor_test

friend class ::wallet_accessor_test
friend

Definition at line 212 of file wallet2.h.

◆ wallet_device_callback

friend class wallet_device_callback
friend

Definition at line 214 of file wallet2.h.

◆ wallet_keys_unlocker

friend class wallet_keys_unlocker
friend

Definition at line 213 of file wallet2.h.

Member Data Documentation

◆ ATTRIBUTE_DESCRIPTION

const char* const tools::wallet2::ATTRIBUTE_DESCRIPTION = "wallet2.description"

Definition at line 1309 of file wallet2.h.

◆ rpc_timeout

constexpr const std::chrono::seconds tools::wallet2::rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30)
static

Definition at line 216 of file wallet2.h.


The documentation for this class was generated from the following files: