Electroneum
cryptonote::simple_wallet Class Reference

Manages wallet operations. This is the most abstracted wallet class. More...

#include <simplewallet.h>

Inheritance diagram for cryptonote::simple_wallet:
Collaboration diagram for cryptonote::simple_wallet:

Public Types

typedef std::vector< std::string > command_type
 

Public Member Functions

 simple_wallet ()
 
bool init (const boost::program_options::variables_map &vm)
 
bool deinit ()
 
bool run ()
 
void stop ()
 
void interrupt ()
 
bool process_command (const std::vector< std::string > &args)
 
std::string get_commands_str ()
 
std::string get_command_usage (const std::vector< std::string > &args)
 
- Public Member Functions inherited from tools::i_wallet2_callback
virtual void on_new_block (uint64_t height, const cryptonote::block &block)
 
virtual void on_etn_received (uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t amount, const cryptonote::subaddress_index &subaddr_index, uint64_t unlock_time)
 
virtual void on_unconfirmed_etn_received (uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t amount, const cryptonote::subaddress_index &subaddr_index)
 
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)
 
virtual void on_skip_transaction (uint64_t height, const crypto::hash &txid, const cryptonote::transaction &tx)
 
virtual void on_lw_new_block (uint64_t height)
 
virtual void on_lw_etn_received (uint64_t height, const crypto::hash &txid, uint64_t amount)
 
virtual void on_lw_unconfirmed_etn_received (uint64_t height, const crypto::hash &txid, uint64_t amount)
 
virtual void on_lw_etn_spent (uint64_t height, const crypto::hash &txid, uint64_t amount)
 
virtual void on_device_button_request (uint64_t code)
 
virtual void on_device_button_pressed ()
 
virtual void on_device_progress (const hw::device_progress &event)
 
virtual void on_pool_tx_removed (const crypto::hash &txid)
 
virtual ~i_wallet2_callback ()
 

Static Public Member Functions

static const char * tr (const char *str)
 

Friends

class refresh_progress_reporter_t
 

Detailed Description

Manages wallet operations. This is the most abstracted wallet class.

Definition at line 67 of file simplewallet.h.

Member Typedef Documentation

◆ command_type

typedef std::vector<std::string> cryptonote::simple_wallet::command_type

Definition at line 73 of file simplewallet.h.

Constructor & Destructor Documentation

◆ simple_wallet()

simple_wallet::simple_wallet ( )

Definition at line 2744 of file simplewallet.cpp.

2745  : m_allow_mismatched_daemon_version(false)
2746  , m_refresh_progress_reporter(*this)
2747  , m_idle_run(true)
2748  , m_auto_refresh_enabled(false)
2749  , m_auto_refresh_refreshing(false)
2750  , m_in_manual_refresh(false)
2751  , m_current_subaddress_account(0)
2752 {
2753  /*
2754  m_cmd_binder.set_handler("start_mining",
2755  boost::bind(&simple_wallet::start_mining, this, _1),
2756  tr(USAGE_START_MINING),
2757  tr("Start mining in the daemon (bg_mining and ignore_battery are optional booleans)."));
2758  m_cmd_binder.set_handler("stop_mining",
2759  boost::bind(&simple_wallet::stop_mining, this, _1),
2760  tr("Stop mining in the daemon."));
2761  */
2762  m_cmd_binder.set_handler("set_daemon",
2763  boost::bind(&simple_wallet::set_daemon, this, _1),
2764  tr(USAGE_SET_DAEMON),
2765  tr("Set another daemon to connect to."));
2766  m_cmd_binder.set_handler("save_bc",
2767  boost::bind(&simple_wallet::save_bc, this, _1),
2768  tr("Save the current blockchain data."));
2769  m_cmd_binder.set_handler("refresh",
2770  boost::bind(&simple_wallet::refresh, this, _1),
2771  tr("Synchronize the transactions and balance."));
2772  m_cmd_binder.set_handler("balance",
2773  boost::bind(&simple_wallet::show_balance, this, _1),
2774  tr(USAGE_SHOW_BALANCE),
2775  tr("Show the wallet's balance of the currently selected account."));
2776  m_cmd_binder.set_handler("incoming_transfers",
2777  boost::bind(&simple_wallet::show_incoming_transfers, this, _1),
2778  tr(USAGE_INCOMING_TRANSFERS),
2779  tr("Show the incoming transfers, all or filtered by availability and address index.\n\n"
2780  "Output format:\n"
2781  "Amount, Spent(\"T\"|\"F\"), \"frozen\"|\"locked\"|\"unlocked\", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] "));
2782  m_cmd_binder.set_handler("payments",
2783  boost::bind(&simple_wallet::show_payments, this, _1),
2784  tr(USAGE_PAYMENTS),
2785  tr("Show the payments for the given payment IDs."));
2786  m_cmd_binder.set_handler("bc_height",
2787  boost::bind(&simple_wallet::show_blockchain_height, this, _1),
2788  tr("Show the blockchain height."));
2789  m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer, this, _1),
2790  tr(USAGE_TRANSFER),
2791  tr("Transfer <amount> to <address>. If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs in the ring signature. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
2792  m_cmd_binder.set_handler("locked_transfer",
2793  boost::bind(&simple_wallet::locked_transfer, this, _1),
2794  tr(USAGE_LOCKED_TRANSFER),
2795  tr("Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs in the ring signature. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
2796  m_cmd_binder.set_handler("locked_sweep_all",
2797  boost::bind(&simple_wallet::locked_sweep_all, this, _1),
2798  tr(USAGE_LOCKED_SWEEP_ALL),
2799  tr("Send all unlocked balance to an address and lock it for <lockblocks> (max. 1000000). If the parameter \"index=<N1>[,<N2>,...]\" or \"index=all\" is specified, the wallet sweeps outputs received by those or all address indices, respectively. If omitted, the wallet randomly chooses an address index to be used. <priority> is the priority of the sweep. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used."));
2800  m_cmd_binder.set_handler("sweep_unmixable",
2801  boost::bind(&simple_wallet::sweep_unmixable, this, _1),
2802  tr("Send all unmixable outputs to yourself with ring_size 1"));
2803  m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1),
2804  tr(USAGE_SWEEP_ALL),
2805  tr("Send all unlocked balance to an address. If the parameter \"index=<N1>[,<N2>,...]\" or \"index=all\" is specified, the wallet sweeps outputs received by those or all address indices, respectively. If omitted, the wallet randomly chooses an address index to be used. If the parameter \"outputs=<N>\" is specified and N > 0, wallet splits the transaction into N even outputs."));
2806  m_cmd_binder.set_handler("sweep_below",
2807  boost::bind(&simple_wallet::sweep_below, this, _1),
2808  tr(USAGE_SWEEP_BELOW),
2809  tr("Send all unlocked outputs below the threshold to an address."));
2810  m_cmd_binder.set_handler("sweep_single",
2811  boost::bind(&simple_wallet::sweep_single, this, _1),
2812  tr(USAGE_SWEEP_SINGLE),
2813  tr("Send a single output of the given key image to an address without change."));
2814  /*
2815  m_cmd_binder.set_handler("donate",
2816  boost::bind(&simple_wallet::donate, this, _1),
2817  tr(USAGE_DONATE),
2818  tr("Donate <amount> to the development team."));
2819  */
2820  m_cmd_binder.set_handler("sign_transfer",
2821  boost::bind(&simple_wallet::sign_transfer, this, _1),
2822  tr(USAGE_SIGN_TRANSFER),
2823  tr("Sign a transaction from a file. If the parameter \"export_raw\" is specified, transaction raw hex data suitable for the daemon RPC /sendrawtransaction is exported."));
2824  m_cmd_binder.set_handler("submit_transfer",
2825  boost::bind(&simple_wallet::submit_transfer, this, _1),
2826  tr("Submit a signed transaction from a file."));
2827  m_cmd_binder.set_handler("set_log",
2828  boost::bind(&simple_wallet::set_log, this, _1),
2829  tr(USAGE_SET_LOG),
2830  tr("Change the current log detail (level must be <0-4>)."));
2831  m_cmd_binder.set_handler("account",
2832  boost::bind(&simple_wallet::account, this, _1),
2833  tr(USAGE_ACCOUNT),
2834  tr("If no arguments are specified, the wallet shows all the existing accounts along with their balances.\n"
2835  "If the \"new\" argument is specified, the wallet creates a new account with its label initialized by the provided label text (which can be empty).\n"
2836  "If the \"switch\" argument is specified, the wallet switches to the account specified by <index>.\n"
2837  "If the \"label\" argument is specified, the wallet sets the label of the account specified by <index> to the provided label text.\n"
2838  "If the \"tag\" argument is specified, a tag <tag_name> is assigned to the specified accounts <account_index_1>, <account_index_2>, ....\n"
2839  "If the \"untag\" argument is specified, the tags assigned to the specified accounts <account_index_1>, <account_index_2> ..., are removed.\n"
2840  "If the \"tag_description\" argument is specified, the tag <tag_name> is assigned an arbitrary text <description>."));
2841  m_cmd_binder.set_handler("address",
2842  boost::bind(&simple_wallet::print_address, this, _1),
2843  tr(USAGE_ADDRESS),
2844  tr("If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If \"all\" is specified, the wallet shows all the existing addresses in the currently selected account. If \"new \" is specified, the wallet creates a new address with the provided label text (which can be empty). If \"label\" is specified, the wallet sets the label of the address specified by <index> to the provided label text."));
2845  m_cmd_binder.set_handler("integrated_address",
2846  boost::bind(&simple_wallet::print_integrated_address, this, _1),
2847  tr(USAGE_INTEGRATED_ADDRESS),
2848  tr("Encode a payment ID into an integrated address for the current wallet public address (no argument uses a random payment ID), or decode an integrated address to standard address and payment ID"));
2849  m_cmd_binder.set_handler("address_book",
2850  boost::bind(&simple_wallet::address_book, this, _1),
2851  tr(USAGE_ADDRESS_BOOK),
2852  tr("Print all entries in the address book, optionally adding/deleting an entry to/from it."));
2853  m_cmd_binder.set_handler("save",
2854  boost::bind(&simple_wallet::save, this, _1),
2855  tr("Save the wallet data."));
2856  m_cmd_binder.set_handler("save_watch_only",
2857  boost::bind(&simple_wallet::save_watch_only, this, _1),
2858  tr("Save a watch-only keys file."));
2859  m_cmd_binder.set_handler("viewkey",
2860  boost::bind(&simple_wallet::viewkey, this, _1),
2861  tr("Display the private view key."));
2862  m_cmd_binder.set_handler("spendkey",
2863  boost::bind(&simple_wallet::spendkey, this, _1),
2864  tr("Display the private spend key."));
2865  m_cmd_binder.set_handler("seed",
2866  boost::bind(&simple_wallet::seed, this, _1),
2867  tr("Display the Electrum-style mnemonic seed"));
2868  m_cmd_binder.set_handler("set",
2869  boost::bind(&simple_wallet::set_variable, this, _1),
2870  tr(USAGE_SET_VARIABLE),
2871  tr("Available options:\n "
2872  "seed language\n "
2873  " Set the wallet's seed language.\n "
2874  "always-confirm-transfers <1|0>\n "
2875  " Whether to confirm unsplit txes.\n "
2876  "print-ring-members <1|0>\n "
2877  " Whether to print detailed information about ring members during confirmation.\n "
2878  "store-tx-info <1|0>\n "
2879  " Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference.\n "
2880  "default-ring-size <n>\n "
2881  " Set the default ring size (obsolete).\n "
2882  "auto-refresh <1|0>\n "
2883  " Whether to automatically synchronize new blocks from the daemon.\n "
2884  "refresh-type <full|optimize-coinbase|no-coinbase|default>\n "
2885  " Set the wallet's refresh behaviour.\n "
2886  "priority [0|1|2|3|4]\n "
2887  " Set the fee to default/unimportant/normal/elevated/priority.\n "
2888  "confirm-missing-payment-id <1|0> (obsolete)\n "
2889  "ask-password <0|1|2 (or never|action|decrypt)>\n "
2890  " action: ask the password before many actions such as transfer, etc\n "
2891  " decrypt: same as action, but keeps the spend key encrypted in memory when not needed\n "
2892  "unit <ETN|cent>\n "
2893  " Set the default Electroneum (sub-)unit.\n "
2894  "min-outputs-count [n]\n "
2895  " Try to keep at least that many outputs of value at least min-outputs-value.\n "
2896  "min-outputs-value [n]\n "
2897  " Try to keep at least min-outputs-count outputs of at least that value.\n "
2898  "merge-destinations <1|0>\n "
2899  " Whether to merge multiple payments to the same destination address.\n "
2900  "confirm-backlog <1|0>\n "
2901  " Whether to warn if there is transaction backlog.\n "
2902  "confirm-backlog-threshold [n]\n "
2903  " Set a threshold for confirm-backlog to only warn if the transaction backlog is greater than n blocks.\n "
2904  "refresh-from-block-height [n]\n "
2905  " Set the height before which to ignore blocks.\n "
2906  "auto-low-priority <1|0>\n "
2907  " Whether to automatically use the low priority fee level when it's safe to do so.\n "
2908  "segregate-pre-fork-outputs <1|0>\n "
2909  " Set this if you intend to spend outputs on both Electroneum AND a key reusing fork.\n "
2910  "key-reuse-mitigation2 <1|0>\n "
2911  " Set this if you are not sure whether you will spend on a key reusing Electroneum fork later.\n"
2912  "subaddress-lookahead <major>:<minor>\n "
2913  " Set the lookahead sizes for the subaddress hash table.\n "
2914  " Set this if you are not sure whether you will spend on a key reusing Electroneum fork later.\n "
2915  "segregation-height <n>\n "
2916  " Set to the height of a key reusing fork you want to use, 0 to use default."));
2917  m_cmd_binder.set_handler("encrypted_seed",
2918  boost::bind(&simple_wallet::encrypted_seed, this, _1),
2919  tr("Display the encrypted Electrum-style mnemonic seed."));
2920  m_cmd_binder.set_handler("rescan_spent",
2921  boost::bind(&simple_wallet::rescan_spent, this, _1),
2922  tr("Rescan the blockchain for spent outputs."));
2923  m_cmd_binder.set_handler("get_tx_key",
2924  boost::bind(&simple_wallet::get_tx_key, this, _1),
2925  tr(USAGE_GET_TX_KEY),
2926  tr("Get the transaction key (r) for a given <txid>."));
2927  m_cmd_binder.set_handler("set_tx_key",
2928  boost::bind(&simple_wallet::set_tx_key, this, _1),
2929  tr(USAGE_SET_TX_KEY),
2930  tr("Set the transaction key (r) for a given <txid> in case the tx was made by some other device or 3rd party wallet."));
2931  m_cmd_binder.set_handler("check_tx_key",
2932  boost::bind(&simple_wallet::check_tx_key, this, _1),
2933  tr(USAGE_CHECK_TX_KEY),
2934  tr("Check the amount going to <address> in <txid>."));
2935  m_cmd_binder.set_handler("get_tx_proof",
2936  boost::bind(&simple_wallet::get_tx_proof, this, _1),
2937  tr(USAGE_GET_TX_PROOF),
2938  tr("Generate a signature proving funds sent to <address> in <txid>, optionally with a challenge string <message>, using either the transaction secret key (when <address> is not your wallet's address) or the view secret key (otherwise), which does not disclose the secret key."));
2939  m_cmd_binder.set_handler("check_tx_proof",
2940  boost::bind(&simple_wallet::check_tx_proof, this, _1),
2941  tr(USAGE_CHECK_TX_PROOF),
2942  tr("Check the proof for funds going to <address> in <txid> with the challenge string <message> if any."));
2943  m_cmd_binder.set_handler("get_spend_proof",
2944  boost::bind(&simple_wallet::get_spend_proof, this, _1),
2945  tr(USAGE_GET_SPEND_PROOF),
2946  tr("Generate a signature proving that you generated <txid> using the spend secret key, optionally with a challenge string <message>."));
2947  m_cmd_binder.set_handler("check_spend_proof",
2948  boost::bind(&simple_wallet::check_spend_proof, this, _1),
2949  tr(USAGE_CHECK_SPEND_PROOF),
2950  tr("Check a signature proving that the signer generated <txid>, optionally with a challenge string <message>."));
2951  m_cmd_binder.set_handler("get_reserve_proof",
2952  boost::bind(&simple_wallet::get_reserve_proof, this, _1),
2953  tr(USAGE_GET_RESERVE_PROOF),
2954  tr("Generate a signature proving that you own at least this much, optionally with a challenge string <message>.\n"
2955  "If 'all' is specified, you prove the entire sum of all of your existing accounts' balances.\n"
2956  "Otherwise, you prove the reserve of the smallest possible amount above <amount> available in your current account."));
2957  m_cmd_binder.set_handler("check_reserve_proof",
2958  boost::bind(&simple_wallet::check_reserve_proof, this, _1),
2959  tr(USAGE_CHECK_RESERVE_PROOF),
2960  tr("Check a signature proving that the owner of <address> holds at least this much, optionally with a challenge string <message>."));
2961  m_cmd_binder.set_handler("show_transfers",
2962  boost::bind(&simple_wallet::show_transfers, this, _1),
2963  tr(USAGE_SHOW_TRANSFERS),
2964  // Seemingly broken formatting to compensate for the backslash before the quotes.
2965  tr("Show the incoming/outgoing transfers within an optional height range.\n\n"
2966  "Output format:\n"
2967  "In or Coinbase: Block Number, \"block\"|\"in\", Time, Amount, Transaction Hash, Payment ID, Subaddress Index, \"-\", Note\n"
2968  "Out: Block Number, \"out\", Time, Amount*, Transaction Hash, Payment ID, Fee, Destinations, Input addresses**, \"-\", Note\n"
2969  "Pool: \"pool\", \"in\", Time, Amount, Transaction Hash, Payment Id, Subaddress Index, \"-\", Note, Double Spend Note\n"
2970  "Pending or Failed: \"failed\"|\"pending\", \"out\", Time, Amount*, Transaction Hash, Payment ID, Fee, Input addresses**, \"-\", Note\n\n"
2971  "* Excluding change and fee.\n"
2972  "** Set of address indices used as inputs in this transfer."));
2973  m_cmd_binder.set_handler("export_transfers",
2974  boost::bind(&simple_wallet::export_transfers, this, _1),
2975  tr("export_transfers [in|out|all|pending|failed|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<filepath>]"),
2976  tr("Export to CSV the incoming/outgoing transfers within an optional height range."));
2977  m_cmd_binder.set_handler("unspent_outputs",
2978  boost::bind(&simple_wallet::unspent_outputs, this, _1),
2979  tr(USAGE_UNSPENT_OUTPUTS),
2980  tr("Show the unspent outputs of a specified address within an optional amount range."));
2981  m_cmd_binder.set_handler("rescan_bc",
2982  boost::bind(&simple_wallet::rescan_blockchain, this, _1),
2983  tr(USAGE_RESCAN_BC),
2984  tr("Rescan the blockchain from scratch. If \"hard\" is specified, you will lose any information which can not be recovered from the blockchain itself."));
2985  m_cmd_binder.set_handler("set_tx_note",
2986  boost::bind(&simple_wallet::set_tx_note, this, _1),
2987  tr(USAGE_SET_TX_NOTE),
2988  tr("Set an arbitrary string note for a <txid>."));
2989  m_cmd_binder.set_handler("get_tx_note",
2990  boost::bind(&simple_wallet::get_tx_note, this, _1),
2991  tr(USAGE_GET_TX_NOTE),
2992  tr("Get a string note for a txid."));
2993  m_cmd_binder.set_handler("set_description",
2994  boost::bind(&simple_wallet::set_description, this, _1),
2995  tr(USAGE_SET_DESCRIPTION),
2996  tr("Set an arbitrary description for the wallet."));
2997  m_cmd_binder.set_handler("get_description",
2998  boost::bind(&simple_wallet::get_description, this, _1),
2999  tr(USAGE_GET_DESCRIPTION),
3000  tr("Get the description of the wallet."));
3001  m_cmd_binder.set_handler("status",
3002  boost::bind(&simple_wallet::status, this, _1),
3003  tr("Show the wallet's status."));
3004  m_cmd_binder.set_handler("wallet_info",
3005  boost::bind(&simple_wallet::wallet_info, this, _1),
3006  tr("Show the wallet's information."));
3007  m_cmd_binder.set_handler("sign",
3008  boost::bind(&simple_wallet::sign, this, _1),
3009  tr(USAGE_SIGN),
3010  tr("Sign the contents of a file."));
3011  m_cmd_binder.set_handler("verify",
3012  boost::bind(&simple_wallet::verify, this, _1),
3013  tr(USAGE_VERIFY),
3014  tr("Verify a signature on the contents of a file."));
3015  m_cmd_binder.set_handler("export_key_images",
3016  boost::bind(&simple_wallet::export_key_images, this, _1),
3017  tr(USAGE_EXPORT_KEY_IMAGES),
3018  tr("Export a signed set of key images to a <filename>."));
3019  m_cmd_binder.set_handler("import_key_images",
3020  boost::bind(&simple_wallet::import_key_images, this, _1),
3021  tr(USAGE_IMPORT_KEY_IMAGES),
3022  tr("Import a signed key images list and verify their spent status."));
3023  m_cmd_binder.set_handler("hw_key_images_sync",
3024  boost::bind(&simple_wallet::hw_key_images_sync, this, _1),
3025  tr(USAGE_HW_KEY_IMAGES_SYNC),
3026  tr("Synchronizes key images with the hw wallet."));
3027  m_cmd_binder.set_handler("hw_reconnect",
3028  boost::bind(&simple_wallet::hw_reconnect, this, _1),
3029  tr(USAGE_HW_RECONNECT),
3030  tr("Attempts to reconnect HW wallet."));
3031  m_cmd_binder.set_handler("export_outputs",
3032  boost::bind(&simple_wallet::export_outputs, this, _1),
3033  tr(USAGE_EXPORT_OUTPUTS),
3034  tr("Export a set of outputs owned by this wallet."));
3035  m_cmd_binder.set_handler("import_outputs",
3036  boost::bind(&simple_wallet::import_outputs, this, _1),
3037  tr(USAGE_IMPORT_OUTPUTS),
3038  tr("Import a set of outputs owned by this wallet."));
3039  m_cmd_binder.set_handler("show_transfer",
3040  boost::bind(&simple_wallet::show_transfer, this, _1),
3041  tr(USAGE_SHOW_TRANSFER),
3042  tr("Show information about a transfer to/from this address."));
3043  m_cmd_binder.set_handler("password",
3044  boost::bind(&simple_wallet::change_password, this, _1),
3045  tr("Change the wallet's password."));
3046  m_cmd_binder.set_handler("payment_id",
3047  boost::bind(&simple_wallet::payment_id, this, _1),
3048  tr(USAGE_PAYMENT_ID),
3049  tr("Generate a new random full size payment id (obsolete). These will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids."));
3050  m_cmd_binder.set_handler("fee",
3051  boost::bind(&simple_wallet::print_fee_info, this, _1),
3052  tr("Print the information about the current fee and transaction backlog."));
3053  m_cmd_binder.set_handler("prepare_multisig", boost::bind(&simple_wallet::prepare_multisig, this, _1),
3054  tr("Export data needed to create a multisig wallet"));
3055  m_cmd_binder.set_handler("make_multisig", boost::bind(&simple_wallet::make_multisig, this, _1),
3056  tr(USAGE_MAKE_MULTISIG),
3057  tr("Turn this wallet into a multisig wallet"));
3058  m_cmd_binder.set_handler("finalize_multisig",
3059  boost::bind(&simple_wallet::finalize_multisig, this, _1),
3060  tr(USAGE_FINALIZE_MULTISIG),
3061  tr("Turn this wallet into a multisig wallet, extra step for N-1/N wallets"));
3062  m_cmd_binder.set_handler("exchange_multisig_keys",
3063  boost::bind(&simple_wallet::exchange_multisig_keys, this, _1),
3064  tr(USAGE_EXCHANGE_MULTISIG_KEYS),
3065  tr("Performs extra multisig keys exchange rounds. Needed for arbitrary M/N multisig wallets"));
3066  m_cmd_binder.set_handler("export_multisig_info",
3067  boost::bind(&simple_wallet::export_multisig, this, _1),
3068  tr(USAGE_EXPORT_MULTISIG_INFO),
3069  tr("Export multisig info for other participants"));
3070  m_cmd_binder.set_handler("import_multisig_info",
3071  boost::bind(&simple_wallet::import_multisig, this, _1),
3072  tr(USAGE_IMPORT_MULTISIG_INFO),
3073  tr("Import multisig info from other participants"));
3074  m_cmd_binder.set_handler("sign_multisig",
3075  boost::bind(&simple_wallet::sign_multisig, this, _1),
3076  tr(USAGE_SIGN_MULTISIG),
3077  tr("Sign a multisig transaction from a file"));
3078  m_cmd_binder.set_handler("submit_multisig",
3079  boost::bind(&simple_wallet::submit_multisig, this, _1),
3080  tr(USAGE_SUBMIT_MULTISIG),
3081  tr("Submit a signed multisig transaction from a file"));
3082  m_cmd_binder.set_handler("export_raw_multisig_tx",
3083  boost::bind(&simple_wallet::export_raw_multisig, this, _1),
3084  tr(USAGE_EXPORT_RAW_MULTISIG_TX),
3085  tr("Export a signed multisig transaction to a file"));
3086  m_cmd_binder.set_handler("mms",
3087  boost::bind(&simple_wallet::mms, this, _1),
3088  tr(USAGE_MMS),
3089  tr("Interface with the MMS (Multisig Messaging System)\n"
3090  "<subcommand> is one of:\n"
3091  " init, info, signer, list, next, sync, transfer, delete, send, receive, export, note, show, set, help\n"
3092  " send_signer_config, start_auto_config, stop_auto_config, auto_config\n"
3093  "Get help about a subcommand with: help mms <subcommand>, or mms help <subcommand>"));
3094  m_cmd_binder.set_handler("mms init",
3095  boost::bind(&simple_wallet::mms, this, _1),
3096  tr(USAGE_MMS_INIT),
3097  tr("Initialize and configure the MMS for M/N = number of required signers/number of authorized signers multisig"));
3098  m_cmd_binder.set_handler("mms info",
3099  boost::bind(&simple_wallet::mms, this, _1),
3100  tr(USAGE_MMS_INFO),
3101  tr("Display current MMS configuration"));
3102  m_cmd_binder.set_handler("mms signer",
3103  boost::bind(&simple_wallet::mms, this, _1),
3104  tr(USAGE_MMS_SIGNER),
3105  tr("Set or modify authorized signer info (single-word label, transport address, Electroneum address), or list all signers"));
3106  m_cmd_binder.set_handler("mms list",
3107  boost::bind(&simple_wallet::mms, this, _1),
3108  tr(USAGE_MMS_LIST),
3109  tr("List all messages"));
3110  m_cmd_binder.set_handler("mms next",
3111  boost::bind(&simple_wallet::mms, this, _1),
3112  tr(USAGE_MMS_NEXT),
3113  tr("Evaluate the next possible multisig-related action(s) according to wallet state, and execute or offer for choice\n"
3114  "By using 'sync' processing of waiting messages with multisig sync info can be forced regardless of wallet state"));
3115  m_cmd_binder.set_handler("mms sync",
3116  boost::bind(&simple_wallet::mms, this, _1),
3117  tr(USAGE_MMS_SYNC),
3118  tr("Force generation of multisig sync info regardless of wallet state, to recover from special situations like \"stale data\" errors"));
3119  m_cmd_binder.set_handler("mms transfer",
3120  boost::bind(&simple_wallet::mms, this, _1),
3121  tr(USAGE_MMS_TRANSFER),
3122  tr("Initiate transfer with MMS support; arguments identical to normal 'transfer' command arguments, for info see there"));
3123  m_cmd_binder.set_handler("mms delete",
3124  boost::bind(&simple_wallet::mms, this, _1),
3125  tr(USAGE_MMS_DELETE),
3126  tr("Delete a single message by giving its id, or delete all messages by using 'all'"));
3127  m_cmd_binder.set_handler("mms send",
3128  boost::bind(&simple_wallet::mms, this, _1),
3129  tr(USAGE_MMS_SEND),
3130  tr("Send a single message by giving its id, or send all waiting messages"));
3131  m_cmd_binder.set_handler("mms receive",
3132  boost::bind(&simple_wallet::mms, this, _1),
3133  tr(USAGE_MMS_RECEIVE),
3134  tr("Check right away for new messages to receive"));
3135  m_cmd_binder.set_handler("mms export",
3136  boost::bind(&simple_wallet::mms, this, _1),
3137  tr(USAGE_MMS_EXPORT),
3138  tr("Write the content of a message to a file \"mms_message_content\""));
3139  m_cmd_binder.set_handler("mms note",
3140  boost::bind(&simple_wallet::mms, this, _1),
3141  tr(USAGE_MMS_NOTE),
3142  tr("Send a one-line message to an authorized signer, identified by its label, or show any waiting unread notes"));
3143  m_cmd_binder.set_handler("mms show",
3144  boost::bind(&simple_wallet::mms, this, _1),
3145  tr(USAGE_MMS_SHOW),
3146  tr("Show detailed info about a single message"));
3147  m_cmd_binder.set_handler("mms set",
3148  boost::bind(&simple_wallet::mms, this, _1),
3149  tr(USAGE_MMS_SET),
3150  tr("Available options:\n "
3151  "auto-send <1|0>\n "
3152  " Whether to automatically send newly generated messages right away.\n "));
3153  m_cmd_binder.set_handler("mms send_message_config",
3154  boost::bind(&simple_wallet::mms, this, _1),
3155  tr(USAGE_MMS_SEND_SIGNER_CONFIG),
3156  tr("Send completed signer config to all other authorized signers"));
3157  m_cmd_binder.set_handler("mms start_auto_config",
3158  boost::bind(&simple_wallet::mms, this, _1),
3159  tr(USAGE_MMS_START_AUTO_CONFIG),
3160  tr("Start auto-config at the auto-config manager's wallet by issuing auto-config tokens and optionally set others' labels"));
3161  m_cmd_binder.set_handler("mms stop_auto_config",
3162  boost::bind(&simple_wallet::mms, this, _1),
3163  tr(USAGE_MMS_STOP_AUTO_CONFIG),
3164  tr("Delete any auto-config tokens and abort a auto-config process"));
3165  m_cmd_binder.set_handler("mms auto_config",
3166  boost::bind(&simple_wallet::mms, this, _1),
3167  tr(USAGE_MMS_AUTO_CONFIG),
3168  tr("Start auto-config by using the token received from the auto-config manager"));
3169  m_cmd_binder.set_handler("print_ring",
3170  boost::bind(&simple_wallet::print_ring, this, _1),
3171  tr(USAGE_PRINT_RING),
3172  tr("Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1)\n\n"
3173  "Output format:\n"
3174  "Key Image, \"absolute\", list of rings"));
3175  m_cmd_binder.set_handler("set_ring",
3176  boost::bind(&simple_wallet::set_ring, this, _1),
3177  tr(USAGE_SET_RING),
3178  tr("Set the ring used for a given key image, so it can be reused in a fork"));
3179  m_cmd_binder.set_handler("unset_ring",
3180  boost::bind(&simple_wallet::unset_ring, this, _1),
3181  tr(USAGE_UNSET_RING),
3182  tr("Unsets the ring used for a given key image or transaction"));
3183  m_cmd_binder.set_handler("save_known_rings",
3184  boost::bind(&simple_wallet::save_known_rings, this, _1),
3185  tr(USAGE_SAVE_KNOWN_RINGS),
3186  tr("Save known rings to the shared rings database"));
3187  m_cmd_binder.set_handler("mark_output_spent",
3188  boost::bind(&simple_wallet::blackball, this, _1),
3189  tr(USAGE_MARK_OUTPUT_SPENT),
3190  tr("Mark output(s) as spent so they never get selected as fake outputs in a ring"));
3191  m_cmd_binder.set_handler("mark_output_unspent",
3192  boost::bind(&simple_wallet::unblackball, this, _1),
3193  tr(USAGE_MARK_OUTPUT_UNSPENT),
3194  tr("Marks an output as unspent so it may get selected as a fake output in a ring"));
3195  m_cmd_binder.set_handler("is_output_spent",
3196  boost::bind(&simple_wallet::blackballed, this, _1),
3197  tr(USAGE_IS_OUTPUT_SPENT),
3198  tr("Checks whether an output is marked as spent"));
3199  m_cmd_binder.set_handler("freeze",
3200  boost::bind(&simple_wallet::freeze, this, _1),
3201  tr(USAGE_FREEZE),
3202  tr("Freeze a single output by key image so it will not be used"));
3203  m_cmd_binder.set_handler("thaw",
3204  boost::bind(&simple_wallet::thaw, this, _1),
3205  tr(USAGE_THAW),
3206  tr("Thaw a single output by key image so it may be used again"));
3207  m_cmd_binder.set_handler("frozen",
3208  boost::bind(&simple_wallet::frozen, this, _1),
3209  tr(USAGE_FROZEN),
3210  tr("Checks whether a given output is currently frozen by key image"));
3211  m_cmd_binder.set_handler("net_stats",
3212  boost::bind(&simple_wallet::net_stats, this, _1),
3213  tr(USAGE_NET_STATS),
3214  tr("Prints simple network stats"));
3215  m_cmd_binder.set_handler("welcome",
3216  boost::bind(&simple_wallet::welcome, this, _1),
3217  tr(USAGE_WELCOME),
3218  tr("Prints basic info about Electroneum for first time users"));
3219  m_cmd_binder.set_handler("version",
3220  boost::bind(&simple_wallet::version, this, _1),
3221  tr(USAGE_VERSION),
3222  tr("Returns version information"));
3223  m_cmd_binder.set_handler("help",
3224  boost::bind(&simple_wallet::help, this, _1),
3225  tr(USAGE_HELP),
3226  tr("Show the help section or the documentation about a <command>."));
3227 }
static const char * tr(const char *str)
Definition: simplewallet.h:70
void set_handler(const std::string &cmd, const callback &hndlr, const std::string &usage="", const std::string &description="")
Here is the call graph for this function:

Member Function Documentation

◆ deinit()

bool simple_wallet::deinit ( )

Definition at line 4133 of file simplewallet.cpp.

4134 {
4135  if (!m_wallet.get())
4136  return true;
4137 
4138  return close_wallet();
4139 }
Here is the caller graph for this function:

◆ get_command_usage()

std::string simple_wallet::get_command_usage ( const std::vector< std::string > &  args)

Definition at line 686 of file simplewallet.cpp.

687 {
688  std::pair<std::string, std::string> documentation = m_cmd_binder.get_documentation(args);
689  std::stringstream ss;
690  if(documentation.first.empty())
691  {
692  ss << tr("Unknown command: ") << args.front();
693  }
694  else
695  {
696  std::string usage = documentation.second.empty() ? args.front() : documentation.first;
697  std::string description = documentation.second.empty() ? documentation.first : documentation.second;
698  usage.insert(0, " ");
699  ss << tr("Command usage: ") << ENDL << usage << ENDL << ENDL;
700  boost::replace_all(description, "\n", "\n ");
701  description.insert(0, " ");
702  ss << tr("Command description: ") << ENDL << description << ENDL;
703  }
704  return ss.str();
705 }
static const char * tr(const char *str)
Definition: simplewallet.h:70
::std::string string
Definition: gtest-port.h:1097
std::pair< std::string, std::string > get_documentation(const std::vector< std::string > &cmd)
#define ENDL
Definition: misc_log_ex.h:149

◆ get_commands_str()

std::string simple_wallet::get_commands_str ( )

Definition at line 675 of file simplewallet.cpp.

676 {
677  std::stringstream ss;
678  ss << tr("Commands: ") << ENDL;
679  std::string usage = m_cmd_binder.get_usage();
680  boost::replace_all(usage, "\n", "\n ");
681  usage.insert(0, " ");
682  ss << usage << ENDL;
683  return ss.str();
684 }
static const char * tr(const char *str)
Definition: simplewallet.h:70
::std::string string
Definition: gtest-port.h:1097
#define ENDL
Definition: misc_log_ex.h:149

◆ init()

bool simple_wallet::init ( const boost::program_options::variables_map &  vm)

Definition at line 3520 of file simplewallet.cpp.

3521 {
3523  m_electrum_seed.wipe();
3524  });
3525 
3526  const bool testnet = tools::wallet2::has_testnet_option(vm);
3527  const bool stagenet = tools::wallet2::has_stagenet_option(vm);
3528  if (testnet && stagenet)
3529  {
3530  fail_msg_writer() << tr("Can't specify more than one of --testnet and --stagenet");
3531  return false;
3532  }
3533  const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET;
3534 
3535  epee::wipeable_string multisig_keys;
3536  epee::wipeable_string password;
3537 
3538  if (!handle_command_line(vm))
3539  return false;
3540 
3541  bool welcome = false;
3542 
3543  if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_device.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_spend_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_multisig_keys.empty()) + (!m_generate_from_json.empty()) > 1)
3544  {
3545  fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", --generate-from-spend-key=\"wallet_name\", --generate-from-keys=\"wallet_name\", --generate-from-multisig-keys=\"wallet_name\", --generate-from-json=\"jsonfilename\" and --generate-from-device=\"wallet_name\"");
3546  return false;
3547  }
3548  else if (m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_device.empty() && m_generate_from_view_key.empty() && m_generate_from_spend_key.empty() && m_generate_from_keys.empty() && m_generate_from_multisig_keys.empty() && m_generate_from_json.empty())
3549  {
3550  if(!ask_wallet_create_if_needed()) return false;
3551  }
3552 
3553  if (!m_generate_new.empty() || m_restoring)
3554  {
3555  if (!m_subaddress_lookahead.empty() && !parse_subaddress_lookahead(m_subaddress_lookahead))
3556  return false;
3557 
3558  std::string old_language;
3559  // check for recover flag. if present, require electrum word list (only recovery option for now).
3560  if (m_restore_deterministic_wallet || m_restore_multisig_wallet)
3561  {
3562  if (m_non_deterministic)
3563  {
3564  fail_msg_writer() << tr("can't specify both --restore-deterministic-wallet or --restore-multisig-wallet and --non-deterministic");
3565  return false;
3566  }
3567  if (!m_wallet_file.empty())
3568  {
3569  if (m_restore_multisig_wallet)
3570  fail_msg_writer() << tr("--restore-multisig-wallet uses --generate-new-wallet, not --wallet-file");
3571  else
3572  fail_msg_writer() << tr("--restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file");
3573  return false;
3574  }
3575 
3576  if (m_electrum_seed.empty())
3577  {
3578  if (m_restore_multisig_wallet)
3579  {
3580  const char *prompt = "Specify multisig seed";
3581  m_electrum_seed = input_secure_line(prompt);
3582  if (std::cin.eof())
3583  return false;
3584  if (m_electrum_seed.empty())
3585  {
3586  fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"multisig seed here\"");
3587  return false;
3588  }
3589  }
3590  else
3591  {
3592  m_electrum_seed = "";
3593  do
3594  {
3595  const char *prompt = m_electrum_seed.empty() ? "Specify Electrum seed" : "Electrum seed continued";
3596  epee::wipeable_string electrum_seed = input_secure_line(prompt);
3597  if (std::cin.eof())
3598  return false;
3599  if (electrum_seed.empty())
3600  {
3601  fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"words list here\"");
3602  return false;
3603  }
3604  m_electrum_seed += electrum_seed;
3605  m_electrum_seed += ' ';
3606  } while (might_be_partial_seed(m_electrum_seed));
3607  }
3608  }
3609 
3610  if (m_restore_multisig_wallet)
3611  {
3612  const boost::optional<epee::wipeable_string> parsed = m_electrum_seed.parse_hexstr();
3613  if (!parsed)
3614  {
3615  fail_msg_writer() << tr("Multisig seed failed verification");
3616  return false;
3617  }
3618  multisig_keys = *parsed;
3619  }
3620  else
3621  {
3622  if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key, old_language))
3623  {
3624  fail_msg_writer() << tr("Electrum-style word list failed verification");
3625  return false;
3626  }
3627  }
3628 
3629  auto pwd_container = password_prompter(tr("Enter seed offset passphrase, empty if none"), false);
3630  if (std::cin.eof() || !pwd_container)
3631  return false;
3632  epee::wipeable_string seed_pass = pwd_container->password();
3633  if (!seed_pass.empty())
3634  {
3635  if (m_restore_multisig_wallet)
3636  {
3638  crypto::cn_slow_hash(seed_pass.data(), seed_pass.size(), (crypto::hash&)key);
3639  sc_reduce32((unsigned char*)key.data);
3640  multisig_keys = m_wallet->decrypt<epee::wipeable_string>(std::string(multisig_keys.data(), multisig_keys.size()), key, true);
3641  }
3642  else
3643  m_recovery_key = cryptonote::decrypt_key(m_recovery_key, seed_pass);
3644  }
3645  }
3646  if (!m_generate_from_view_key.empty())
3647  {
3648  m_wallet_file = m_generate_from_view_key;
3649  // parse address
3650  std::string address_string = input_line("Standard address");
3651  if (std::cin.eof())
3652  return false;
3653  if (address_string.empty()) {
3654  fail_msg_writer() << tr("No data supplied, cancelled");
3655  return false;
3656  }
3658  if(!get_account_address_from_str(info, nettype, address_string))
3659  {
3660  fail_msg_writer() << tr("failed to parse address");
3661  return false;
3662  }
3663  if (info.is_subaddress)
3664  {
3665  fail_msg_writer() << tr("This address is a subaddress which cannot be used here.");
3666  return false;
3667  }
3668 
3669  // parse view secret key
3670  epee::wipeable_string viewkey_string = input_secure_line("Secret view key");
3671  if (std::cin.eof())
3672  return false;
3673  if (viewkey_string.empty()) {
3674  fail_msg_writer() << tr("No data supplied, cancelled");
3675  return false;
3676  }
3677  crypto::secret_key viewkey;
3678  if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
3679  {
3680  fail_msg_writer() << tr("failed to parse view key secret key");
3681  return false;
3682  }
3683 
3684  m_wallet_file=m_generate_from_view_key;
3685 
3686  // check the view key matches the given address
3687  crypto::public_key pkey;
3688  if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
3689  fail_msg_writer() << tr("failed to verify view key secret key");
3690  return false;
3691  }
3692  if (info.address.m_view_public_key != pkey) {
3693  fail_msg_writer() << tr("view key does not match standard address");
3694  return false;
3695  }
3696 
3697  auto r = new_wallet(vm, info.address, boost::none, viewkey);
3698  CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
3699  password = *r;
3700  welcome = true;
3701  }
3702  else if (!m_generate_from_spend_key.empty())
3703  {
3704  m_wallet_file = m_generate_from_spend_key;
3705  // parse spend secret key
3706  epee::wipeable_string spendkey_string = input_secure_line("Secret spend key");
3707  if (std::cin.eof())
3708  return false;
3709  if (spendkey_string.empty()) {
3710  fail_msg_writer() << tr("No data supplied, cancelled");
3711  return false;
3712  }
3713  if (!spendkey_string.hex_to_pod(unwrap(unwrap(m_recovery_key))))
3714  {
3715  fail_msg_writer() << tr("failed to parse spend key secret key");
3716  return false;
3717  }
3718  auto r = new_wallet(vm, m_recovery_key, true, false, "");
3719  CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
3720  password = *r;
3721  welcome = true;
3722  }
3723  else if (!m_generate_from_keys.empty())
3724  {
3725  m_wallet_file = m_generate_from_keys;
3726  // parse address
3727  std::string address_string = input_line("Standard address");
3728  if (std::cin.eof())
3729  return false;
3730  if (address_string.empty()) {
3731  fail_msg_writer() << tr("No data supplied, cancelled");
3732  return false;
3733  }
3735  if(!get_account_address_from_str(info, nettype, address_string))
3736  {
3737  fail_msg_writer() << tr("failed to parse address");
3738  return false;
3739  }
3740  if (info.is_subaddress)
3741  {
3742  fail_msg_writer() << tr("This address is a subaddress which cannot be used here.");
3743  return false;
3744  }
3745 
3746  // parse spend secret key
3747  epee::wipeable_string spendkey_string = input_secure_line("Secret spend key");
3748  if (std::cin.eof())
3749  return false;
3750  if (spendkey_string.empty()) {
3751  fail_msg_writer() << tr("No data supplied, cancelled");
3752  return false;
3753  }
3754  crypto::secret_key spendkey;
3755  if (!spendkey_string.hex_to_pod(unwrap(unwrap(spendkey))))
3756  {
3757  fail_msg_writer() << tr("failed to parse spend key secret key");
3758  return false;
3759  }
3760 
3761  // parse view secret key
3762  epee::wipeable_string viewkey_string = input_secure_line("Secret view key");
3763  if (std::cin.eof())
3764  return false;
3765  if (viewkey_string.empty()) {
3766  fail_msg_writer() << tr("No data supplied, cancelled");
3767  return false;
3768  }
3769  crypto::secret_key viewkey;
3770  if(!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
3771  {
3772  fail_msg_writer() << tr("failed to parse view key secret key");
3773  return false;
3774  }
3775 
3776  m_wallet_file=m_generate_from_keys;
3777 
3778  // check the spend and view keys match the given address
3779  crypto::public_key pkey;
3780  if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
3781  fail_msg_writer() << tr("failed to verify spend key secret key");
3782  return false;
3783  }
3784  if (info.address.m_spend_public_key != pkey) {
3785  fail_msg_writer() << tr("spend key does not match standard address");
3786  return false;
3787  }
3788  if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
3789  fail_msg_writer() << tr("failed to verify view key secret key");
3790  return false;
3791  }
3792  if (info.address.m_view_public_key != pkey) {
3793  fail_msg_writer() << tr("view key does not match standard address");
3794  return false;
3795  }
3796  auto r = new_wallet(vm, info.address, spendkey, viewkey);
3797  CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
3798  password = *r;
3799  welcome = true;
3800  }
3801 
3802  // Asks user for all the data required to merge secret keys from multisig wallets into one master wallet, which then gets full control of the multisig wallet. The resulting wallet will be the same as any other regular wallet.
3803  else if (!m_generate_from_multisig_keys.empty())
3804  {
3805  m_wallet_file = m_generate_from_multisig_keys;
3806  unsigned int multisig_m;
3807  unsigned int multisig_n;
3808 
3809  // parse multisig type
3810  std::string multisig_type_string = input_line("Multisig type (input as M/N with M <= N and M > 1)");
3811  if (std::cin.eof())
3812  return false;
3813  if (multisig_type_string.empty())
3814  {
3815  fail_msg_writer() << tr("No data supplied, cancelled");
3816  return false;
3817  }
3818  if (sscanf(multisig_type_string.c_str(), "%u/%u", &multisig_m, &multisig_n) != 2)
3819  {
3820  fail_msg_writer() << tr("Error: expected M/N, but got: ") << multisig_type_string;
3821  return false;
3822  }
3823  if (multisig_m <= 1 || multisig_m > multisig_n)
3824  {
3825  fail_msg_writer() << tr("Error: expected N > 1 and N <= M, but got: ") << multisig_type_string;
3826  return false;
3827  }
3828  if (multisig_m != multisig_n)
3829  {
3830  fail_msg_writer() << tr("Error: M/N is currently unsupported. ");
3831  return false;
3832  }
3833  message_writer() << boost::format(tr("Generating master wallet from %u of %u multisig wallet keys")) % multisig_m % multisig_n;
3834 
3835  // parse multisig address
3836  std::string address_string = input_line("Multisig wallet address");
3837  if (std::cin.eof())
3838  return false;
3839  if (address_string.empty()) {
3840  fail_msg_writer() << tr("No data supplied, cancelled");
3841  return false;
3842  }
3844  if(!get_account_address_from_str(info, nettype, address_string))
3845  {
3846  fail_msg_writer() << tr("failed to parse address");
3847  return false;
3848  }
3849 
3850  // parse secret view key
3851  epee::wipeable_string viewkey_string = input_secure_line("Secret view key");
3852  if (std::cin.eof())
3853  return false;
3854  if (viewkey_string.empty())
3855  {
3856  fail_msg_writer() << tr("No data supplied, cancelled");
3857  return false;
3858  }
3859  crypto::secret_key viewkey;
3860  if(!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
3861  {
3862  fail_msg_writer() << tr("failed to parse secret view key");
3863  return false;
3864  }
3865 
3866  // check that the view key matches the given address
3867  crypto::public_key pkey;
3868  if (!crypto::secret_key_to_public_key(viewkey, pkey))
3869  {
3870  fail_msg_writer() << tr("failed to verify secret view key");
3871  return false;
3872  }
3873  if (info.address.m_view_public_key != pkey)
3874  {
3875  fail_msg_writer() << tr("view key does not match standard address");
3876  return false;
3877  }
3878 
3879  // parse multisig spend keys
3881  // parsing N/N
3882  if(multisig_m == multisig_n)
3883  {
3884  std::vector<crypto::secret_key> multisig_secret_spendkeys(multisig_n);
3885  epee::wipeable_string spendkey_string;
3886  cryptonote::blobdata spendkey_data;
3887  // get N secret spend keys from user
3888  for(unsigned int i=0; i<multisig_n; ++i)
3889  {
3890  spendkey_string = input_secure_line(tr((boost::format(tr("Secret spend key (%u of %u)")) % (i+1) % multisig_m).str().c_str()));
3891  if (std::cin.eof())
3892  return false;
3893  if (spendkey_string.empty())
3894  {
3895  fail_msg_writer() << tr("No data supplied, cancelled");
3896  return false;
3897  }
3898  if(!spendkey_string.hex_to_pod(unwrap(unwrap(multisig_secret_spendkeys[i]))))
3899  {
3900  fail_msg_writer() << tr("failed to parse spend key secret key");
3901  return false;
3902  }
3903  }
3904 
3905  // sum the spend keys together to get the master spend key
3906  spendkey = multisig_secret_spendkeys[0];
3907  for(unsigned int i=1; i<multisig_n; ++i)
3908  sc_add(reinterpret_cast<unsigned char*>(&spendkey), reinterpret_cast<unsigned char*>(&spendkey), reinterpret_cast<unsigned char*>(&multisig_secret_spendkeys[i]));
3909  }
3910  // parsing M/N
3911  else
3912  {
3913  fail_msg_writer() << tr("Error: M/N is currently unsupported");
3914  return false;
3915  }
3916 
3917  // check that the spend key matches the given address
3918  if (!crypto::secret_key_to_public_key(spendkey, pkey))
3919  {
3920  fail_msg_writer() << tr("failed to verify spend key secret key");
3921  return false;
3922  }
3923  if (info.address.m_spend_public_key != pkey)
3924  {
3925  fail_msg_writer() << tr("spend key does not match standard address");
3926  return false;
3927  }
3928 
3929  // create wallet
3930  auto r = new_wallet(vm, info.address, spendkey, viewkey);
3931  CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
3932  password = *r;
3933  welcome = true;
3934  }
3935 
3936  else if (!m_generate_from_json.empty())
3937  {
3938  try
3939  {
3940  auto rc = tools::wallet2::make_from_json(vm, false, m_generate_from_json, password_prompter);
3941  m_wallet = std::move(rc.first);
3942  password = rc.second.password();
3943  m_wallet_file = m_wallet->path();
3944  }
3945  catch (const std::exception &e)
3946  {
3947  fail_msg_writer() << e.what();
3948  return false;
3949  }
3950  if (!m_wallet)
3951  return false;
3952  }
3953  else if (!m_generate_from_device.empty())
3954  {
3955  m_wallet_file = m_generate_from_device;
3956  // create wallet
3957  auto r = new_wallet(vm);
3958  CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
3959  password = *r;
3960  welcome = true;
3961  // if no block_height is specified, assume its a new account and start it "now"
3962  if(m_wallet->get_refresh_from_block_height() == 0) {
3963  {
3965  wrt << tr("No restore height is specified.") << " ";
3966  wrt << tr("Assumed you are creating a new account, restore will be done from current estimated blockchain height.") << " ";
3967  wrt << tr("Use --restore-height or --restore-date if you want to restore an already setup account from a specific height.");
3968  }
3969  std::string confirm = input_line(tr("Is this okay?"), true);
3970  if (std::cin.eof() || !command_line::is_yes(confirm))
3971  CHECK_AND_ASSERT_MES(false, false, tr("account creation aborted"));
3972 
3973  m_wallet->set_refresh_from_block_height(m_wallet->estimate_blockchain_height());
3974  m_wallet->explicit_refresh_from_block_height(true);
3975  m_restore_height = m_wallet->get_refresh_from_block_height();
3976  m_wallet->always_confirm_transfers(true);
3977  }
3978  }
3979  else
3980  {
3981  if (m_generate_new.empty()) {
3982  fail_msg_writer() << tr("specify a wallet path with --generate-new-wallet (not --wallet-file)");
3983  return false;
3984  }
3985  m_wallet_file = m_generate_new;
3986  boost::optional<epee::wipeable_string> r;
3987  if (m_restore_multisig_wallet)
3988  r = new_wallet(vm, multisig_keys, old_language);
3989  else
3990  r = new_wallet(vm, m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic, old_language);
3991  CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
3992  password = *r;
3993  welcome = true;
3994  }
3995 
3996  if (m_restoring && m_generate_from_json.empty() && m_generate_from_device.empty())
3997  {
3998  m_wallet->explicit_refresh_from_block_height(!(command_line::is_arg_defaulted(vm, arg_restore_height) ||
3999  command_line::is_arg_defaulted(vm, arg_restore_date)));
4000  if (command_line::is_arg_defaulted(vm, arg_restore_height) && !command_line::is_arg_defaulted(vm, arg_restore_date))
4001  {
4002  uint16_t year;
4003  uint8_t month;
4004  uint8_t day;
4005  if (!datestr_to_int(m_restore_date, year, month, day))
4006  return false;
4007  try
4008  {
4009  m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day);
4010  success_msg_writer() << tr("Restore height is: ") << m_restore_height;
4011  }
4012  catch (const std::runtime_error& e)
4013  {
4014  fail_msg_writer() << e.what();
4015  return false;
4016  }
4017  }
4018  }
4019  if (!m_wallet->explicit_refresh_from_block_height() && m_restoring)
4020  {
4021  uint32_t version;
4022  bool connected = try_connect_to_daemon(false, &version);
4023  while (true)
4024  {
4025  std::string heightstr;
4026  if (!connected || version < MAKE_CORE_RPC_VERSION(1, 6))
4027  heightstr = input_line("Restore from specific blockchain height (optional, default 0)");
4028  else
4029  heightstr = input_line("Restore from specific blockchain height (optional, default 0),\nor alternatively from specific date (YYYY-MM-DD)");
4030  if (std::cin.eof())
4031  return false;
4032  if (heightstr.empty())
4033  {
4034  m_restore_height = 0;
4035  break;
4036  }
4037  try
4038  {
4039  m_restore_height = boost::lexical_cast<uint64_t>(heightstr);
4040  break;
4041  }
4042  catch (const boost::bad_lexical_cast &)
4043  {
4044  if (!connected || version < MAKE_CORE_RPC_VERSION(1, 6))
4045  {
4046  fail_msg_writer() << tr("bad m_restore_height parameter: ") << heightstr;
4047  continue;
4048  }
4049  uint16_t year;
4050  uint8_t month; // 1, 2, ..., 12
4051  uint8_t day; // 1, 2, ..., 31
4052  try
4053  {
4054  if (!datestr_to_int(heightstr, year, month, day))
4055  return false;
4056  m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day);
4057  success_msg_writer() << tr("Restore height is: ") << m_restore_height;
4058  std::string confirm = input_line(tr("Is this okay?"), true);
4059  if (std::cin.eof())
4060  return false;
4061  if(command_line::is_yes(confirm))
4062  break;
4063  }
4064  catch (const boost::bad_lexical_cast &)
4065  {
4066  fail_msg_writer() << tr("bad m_restore_height parameter: ") << heightstr;
4067  }
4068  catch (const std::runtime_error& e)
4069  {
4070  fail_msg_writer() << e.what();
4071  }
4072  }
4073  }
4074  }
4075  if (m_restoring)
4076  {
4077  uint64_t estimate_height = m_wallet->estimate_blockchain_height();
4078  if (m_restore_height >= estimate_height)
4079  {
4080  success_msg_writer() << tr("Restore height ") << m_restore_height << (" is not yet reached. The current estimated height is ") << estimate_height;
4081  std::string confirm = input_line(tr("Still apply restore height?"), true);
4082  if (std::cin.eof() || command_line::is_no(confirm))
4083  m_restore_height = 0;
4084  }
4085  m_wallet->set_refresh_from_block_height(m_restore_height);
4086  }
4087  m_wallet->rewrite(m_wallet_file, password);
4088  }
4089  else // OPENING A WALLET FROM A WALLET FILE
4090  {
4091  assert(!m_wallet_file.empty());
4092  if (!m_subaddress_lookahead.empty())
4093  {
4094  fail_msg_writer() << tr("can't specify --subaddress-lookahead and --wallet-file at the same time");
4095  return false;
4096  }
4097  auto r = open_wallet(vm);
4098  CHECK_AND_ASSERT_MES(r, false, tr("failed to open account"));
4099  password = *r;
4100  }
4101  if (!m_wallet)
4102  {
4103  fail_msg_writer() << tr("wallet is null");
4104  return false;
4105  }
4106 
4107  if (!m_wallet->is_trusted_daemon())
4108  message_writer() << (boost::format(tr("Warning: using an untrusted daemon at %s, privacy will be lessened")) % m_wallet->get_daemon_address()).str();
4109 
4110  if (m_wallet->get_ring_database().empty())
4111  fail_msg_writer() << tr("Failed to initialize ring database: privacy enhancing features will be inactive");
4112 
4113  m_wallet->callback(this);
4114 
4115  check_background_mining(password);
4116 
4117  if (welcome)
4118  message_writer(console_color_yellow, true) << tr("If you are new to Electroneum, type \"welcome\" for a brief overview.");
4119 
4120  /* Comment out this warning message for now
4121  if (m_long_payment_id_support)
4122  {
4123  message_writer(console_color_red, false) <<
4124  tr("WARNING: obsolete long payment IDs are enabled. Sending transactions with those payment IDs are bad for your privacy.");
4125  message_writer(console_color_red, false) <<
4126  tr("It is recommended that you do not use them, and ask recipients who ask for one to not endanger your privacy.");
4127  }
4128  */
4129 
4130  return true;
4131 }
static const char * tr(const char *str)
Definition: simplewallet.h:70
bool is_no(const std::string &str)
boost::optional< wipeable_string > parse_hexstr() const
size_t size() const noexcept
::std::string string
Definition: gtest-port.h:1097
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
bool is_yes(const std::string &str)
const char * key
Definition: hmac_keccak.cpp:39
static std::pair< std::unique_ptr< wallet2 >, password_container > 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)
Uses stdin and stdout. Returns a wallet2 if no errors.
Definition: wallet2.cpp:1227
unsigned short uint16_t
Definition: stdint.h:125
bool words_to_bytes(const epee::wipeable_string &words, epee::wipeable_string &dst, size_t len, bool duplicate, std::string &language_name)
Converts seed words to bytes (secret key).
unsigned char uint8_t
Definition: stdint.h:124
bool hex_to_pod(T &pod) const
#define MAKE_CORE_RPC_VERSION(major, minor)
unsigned int uint32_t
Definition: stdint.h:126
void sc_reduce32(unsigned char *)
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
bool empty() const noexcept
unsigned __int64 uint64_t
Definition: stdint.h:136
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
boost::optional< std::pair< uint32_t, uint32_t > > parse_subaddress_lookahead(const std::string &str)
Definition: util.cpp:977
scoped_message_writer success_msg_writer(bool color=true)
scoped_message_writer fail_msg_writer()
const T & move(const T &t)
Definition: gtest-port.h:1317
static bool has_testnet_option(const boost::program_options::variables_map &vm)
Definition: wallet2.cpp:1173
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
static bool has_stagenet_option(const boost::program_options::variables_map &vm)
Definition: wallet2.cpp:1178
T & unwrap(mlocked< T > &src)
Definition: mlocker.h:80
crypto::secret_key decrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase)
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)
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
const char * spendkey
Definition: multisig.cpp:38
scoped_message_writer msg_writer(epee::console_colors color=epee::console_color_default)
const char * data() const noexcept
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
bool is_arg_defaulted(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
Definition: command_line.h:265
Here is the call graph for this function:
Here is the caller graph for this function:

◆ interrupt()

void simple_wallet::interrupt ( )

Definition at line 9567 of file simplewallet.cpp.

9568 {
9569  if (m_in_manual_refresh.load(std::memory_order_relaxed))
9570  {
9571  m_wallet->stop();
9572  }
9573  else
9574  {
9575  stop();
9576  }
9577 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_command()

bool simple_wallet::process_command ( const std::vector< std::string > &  args)

Definition at line 9562 of file simplewallet.cpp.

9563 {
9564  return m_cmd_binder.process_command_vec(args);
9565 }
bool process_command_vec(const std::vector< std::string > &cmd)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

bool simple_wallet::run ( )

Definition at line 8428 of file simplewallet.cpp.

8429 {
8430  // check and display warning, but go on anyway
8431  try_connect_to_daemon();
8432 
8433  //initial refresh
8434  refresh_main(0, ResetNone, true);
8435 
8436  m_auto_refresh_enabled = m_wallet->auto_refresh();
8437 
8438  // Idle thread which scans if m_auto_refresh_enabled, and listens to daemon
8439  m_idle_thread = boost::thread([&]{wallet_idle_thread();});
8440 
8441  message_writer(console_color_green, false) << "Background refresh thread started";
8442 
8443  //Indefinitely runs and listens on commands until user says to close wallet or an exception is thrown
8444  return m_cmd_binder.run_handling([this](){return get_prompt();}, "");
8445 }
bool run_handling(std::function< std::string(void)> prompt, const std::string &usage_string, std::function< void(void)> exit_handler=NULL)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ stop()

void simple_wallet::stop ( )

Definition at line 8447 of file simplewallet.cpp.

8448 {
8449  m_cmd_binder.stop_handling();
8450 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr()

static const char* cryptonote::simple_wallet::tr ( const char *  str)
inlinestatic

Definition at line 70 of file simplewallet.h.

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

Friends And Related Function Documentation

◆ refresh_progress_reporter_t

friend class refresh_progress_reporter_t
friend

Definition at line 326 of file simplewallet.h.


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