mirror of
				https://git.wownero.com/wownero/wownero.git
				synced 2024-08-15 01:03:23 +00:00 
			
		
		
		
	Merge pull request #34 from tewinget/master
Add electrum-seed wallet backup/recovery
This commit is contained in:
		
						commit
						c3203c86c6
					
				
					 15 changed files with 3567 additions and 35 deletions
				
			
		
							
								
								
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,7 @@
 | 
			
		|||
.DS_Store
 | 
			
		||||
/build
 | 
			
		||||
/tags
 | 
			
		||||
 | 
			
		||||
# vim swap files
 | 
			
		||||
*.swp
 | 
			
		||||
*.swo
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,21 @@
 | 
			
		|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
 | 
			
		||||
 | 
			
		||||
#include "command_line.h"
 | 
			
		||||
#include "string_tools.h"
 | 
			
		||||
 | 
			
		||||
namespace command_line
 | 
			
		||||
{
 | 
			
		||||
  std::string input_line(const std::string& prompt)
 | 
			
		||||
  {
 | 
			
		||||
    std::cout << prompt;
 | 
			
		||||
 | 
			
		||||
    std::string buf;
 | 
			
		||||
    std::getline(std::cin, buf);
 | 
			
		||||
 | 
			
		||||
    return epee::string_tools::trim(buf);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const arg_descriptor<bool> arg_help = {"help", "Produce help message"};
 | 
			
		||||
  const arg_descriptor<bool> arg_version = {"version", "Output version information"};
 | 
			
		||||
  const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,9 @@
 | 
			
		|||
 | 
			
		||||
namespace command_line
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  std::string input_line(const std::string& prompt);
 | 
			
		||||
 | 
			
		||||
  template<typename T, bool required = false>
 | 
			
		||||
  struct arg_descriptor;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,14 @@
 | 
			
		|||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// FIXME: Why is this ifdef needed?  Hopefully making it struct won't break things.
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
#define POD_CLASS struct
 | 
			
		||||
#else
 | 
			
		||||
#define POD_CLASS class
 | 
			
		||||
#endif
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define POD_CLASS struct
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,6 +50,7 @@ namespace crypto {
 | 
			
		|||
    return &reinterpret_cast<const unsigned char &>(scalar);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* generate a random 32-byte (256-bit) integer and copy it to res */
 | 
			
		||||
  static inline void random_scalar(ec_scalar &res) {
 | 
			
		||||
    unsigned char tmp[64];
 | 
			
		||||
    generate_random_bytes(64, tmp);
 | 
			
		||||
| 
						 | 
				
			
			@ -62,12 +63,32 @@ namespace crypto {
 | 
			
		|||
    sc_reduce32(&res);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void crypto_ops::generate_keys(public_key &pub, secret_key &sec) {
 | 
			
		||||
  /* 
 | 
			
		||||
   * generate public and secret keys from a random 256-bit integer
 | 
			
		||||
   * TODO: allow specifiying random value (for wallet recovery)
 | 
			
		||||
   * 
 | 
			
		||||
   */
 | 
			
		||||
  secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) {
 | 
			
		||||
    lock_guard<mutex> lock(random_lock);
 | 
			
		||||
    ge_p3 point;
 | 
			
		||||
    random_scalar(sec);
 | 
			
		||||
 | 
			
		||||
    secret_key rng;
 | 
			
		||||
 | 
			
		||||
    if (recover)
 | 
			
		||||
    {
 | 
			
		||||
      rng = recovery_key;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      random_scalar(rng);
 | 
			
		||||
    }
 | 
			
		||||
    sec = rng;
 | 
			
		||||
    sc_reduce32(&sec);  // reduce in case second round of keys (sendkeys)
 | 
			
		||||
 | 
			
		||||
    ge_scalarmult_base(&point, &sec);
 | 
			
		||||
    ge_p3_tobytes(&pub, &point);
 | 
			
		||||
 | 
			
		||||
    return rng;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool crypto_ops::check_key(const public_key &key) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,8 +62,8 @@ namespace crypto {
 | 
			
		|||
    void operator=(const crypto_ops &);
 | 
			
		||||
    ~crypto_ops();
 | 
			
		||||
 | 
			
		||||
    static void generate_keys(public_key &, secret_key &);
 | 
			
		||||
    friend void generate_keys(public_key &, secret_key &);
 | 
			
		||||
    static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
 | 
			
		||||
    friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
 | 
			
		||||
    static bool check_key(const public_key &);
 | 
			
		||||
    friend bool check_key(const public_key &);
 | 
			
		||||
    static bool secret_key_to_public_key(const secret_key &, public_key &);
 | 
			
		||||
| 
						 | 
				
			
			@ -102,8 +102,8 @@ namespace crypto {
 | 
			
		|||
 | 
			
		||||
  /* Generate a new key pair
 | 
			
		||||
   */
 | 
			
		||||
  inline void generate_keys(public_key &pub, secret_key &sec) {
 | 
			
		||||
    crypto_ops::generate_keys(pub, sec);
 | 
			
		||||
  inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
 | 
			
		||||
    return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Check a public key. Returns true if it is valid, false otherwise.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										110
									
								
								src/crypto/electrum-words.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/crypto/electrum-words.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,110 @@
 | 
			
		|||
/*
 | 
			
		||||
 * This file and its header file are for translating Electrum-style word lists
 | 
			
		||||
 * into their equivalent byte representations for cross-compatibility with
 | 
			
		||||
 * that method of "backing up" one's wallet keys.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <boost/algorithm/string.hpp>
 | 
			
		||||
#include "crypto/crypto.h"  // for declaration of crypto::secret_key
 | 
			
		||||
 | 
			
		||||
#include "crypto/electrum-words.h"
 | 
			
		||||
 | 
			
		||||
namespace crypto
 | 
			
		||||
{
 | 
			
		||||
  namespace ElectrumWords
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
    /* convert words to bytes, 3 words -> 4 bytes
 | 
			
		||||
     * returns:
 | 
			
		||||
     *    false if not a multiple of 3 words, or if a words is not in the
 | 
			
		||||
     *    words list
 | 
			
		||||
     *
 | 
			
		||||
     *    true otherwise
 | 
			
		||||
     */
 | 
			
		||||
    bool words_to_bytes(const std::string& words, crypto::secret_key& dst)
 | 
			
		||||
    {
 | 
			
		||||
      int n = NUMWORDS; // hardcoded because this is what electrum uses
 | 
			
		||||
 | 
			
		||||
      std::vector<std::string> wlist;
 | 
			
		||||
 | 
			
		||||
      boost::split(wlist, words, boost::is_any_of(" "));
 | 
			
		||||
 | 
			
		||||
      // error on non-compliant word list
 | 
			
		||||
      if (wlist.size() != 12 && wlist.size() != 24) return false;
 | 
			
		||||
 | 
			
		||||
      for (unsigned int i=0; i < wlist.size() / 3; i++)
 | 
			
		||||
      {
 | 
			
		||||
        uint32_t val;
 | 
			
		||||
        uint32_t w1, w2, w3;
 | 
			
		||||
 | 
			
		||||
        // verify all three words exist in the word list
 | 
			
		||||
        if (wordsMap.count(wlist[i*3]) == 0 ||
 | 
			
		||||
            wordsMap.count(wlist[i*3 + 1]) == 0 ||
 | 
			
		||||
            wordsMap.count(wlist[i*3 + 2]) == 0)
 | 
			
		||||
        {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        w1 = wordsMap.at(wlist[i*3]);
 | 
			
		||||
        w2 = wordsMap.at(wlist[i*3 + 1]);
 | 
			
		||||
        w3 = wordsMap.at(wlist[i*3 + 2]);
 | 
			
		||||
 | 
			
		||||
        val = w1 + n * (((n - w1) + w2) % n) + n * n * (((n - w2) + w3) % n);
 | 
			
		||||
 | 
			
		||||
        if (!(val % n == w1)) return false;
 | 
			
		||||
 | 
			
		||||
        memcpy(dst.data + i * 4, &val, 4);  // copy 4 bytes to position
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      std::string wlist_copy = words;
 | 
			
		||||
      if (wlist.size() == 12)
 | 
			
		||||
      {
 | 
			
		||||
        memcpy(dst.data, dst.data + 16, 16);  // if electrum 12-word seed, duplicate
 | 
			
		||||
        wlist_copy += ' ';
 | 
			
		||||
        wlist_copy += words;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* convert bytes to words, 4 bytes-> 3 words
 | 
			
		||||
     * returns:
 | 
			
		||||
     *    false if wrong number of bytes (shouldn't be possible)
 | 
			
		||||
     *    true otherwise
 | 
			
		||||
     */
 | 
			
		||||
    bool bytes_to_words(const crypto::secret_key& src, std::string& words)
 | 
			
		||||
    {
 | 
			
		||||
      int n = NUMWORDS; // hardcoded because this is what electrum uses
 | 
			
		||||
 | 
			
		||||
      if (sizeof(src.data) % 4 != 0) return false;
 | 
			
		||||
 | 
			
		||||
      // 8 bytes -> 3 words.  8 digits base 16 -> 3 digits base 1626
 | 
			
		||||
      for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
 | 
			
		||||
      {
 | 
			
		||||
        uint32_t w1, w2, w3;
 | 
			
		||||
        
 | 
			
		||||
        uint32_t val;
 | 
			
		||||
 | 
			
		||||
        memcpy(&val, (src.data) + (i * 4), 4);
 | 
			
		||||
 | 
			
		||||
        w1 = val % n;
 | 
			
		||||
        w2 = ((val / n) + w1) % n;
 | 
			
		||||
        w3 = (((val / n) / n) + w2) % n;
 | 
			
		||||
 | 
			
		||||
        words += wordsArray[w1];
 | 
			
		||||
        words += ' ';
 | 
			
		||||
        words += wordsArray[w2];
 | 
			
		||||
        words += ' ';
 | 
			
		||||
        words += wordsArray[w3];
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }  // namespace ElectrumWords
 | 
			
		||||
 | 
			
		||||
}  // namespace crypto
 | 
			
		||||
							
								
								
									
										3280
									
								
								src/crypto/electrum-words.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3280
									
								
								src/crypto/electrum-words.h
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -10,6 +10,10 @@
 | 
			
		|||
#include "account.h"
 | 
			
		||||
#include "warnings.h"
 | 
			
		||||
#include "crypto/crypto.h"
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#include "crypto/blake256.h"
 | 
			
		||||
}
 | 
			
		||||
#include "cryptonote_core/cryptonote_basic_impl.h"
 | 
			
		||||
#include "cryptonote_core/cryptonote_format_utils.h"
 | 
			
		||||
using namespace std;
 | 
			
		||||
| 
						 | 
				
			
			@ -29,11 +33,17 @@ DISABLE_VS_WARNINGS(4244 4345)
 | 
			
		|||
    m_keys = account_keys();
 | 
			
		||||
  }
 | 
			
		||||
  //-----------------------------------------------------------------
 | 
			
		||||
  void account_base::generate()
 | 
			
		||||
  crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
 | 
			
		||||
  {
 | 
			
		||||
    generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key);
 | 
			
		||||
    generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key);
 | 
			
		||||
    crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);
 | 
			
		||||
 | 
			
		||||
    // rng for generating second set of keys is hash of first rng.  means only one set of electrum-style words needed for recovery
 | 
			
		||||
    crypto::secret_key second;
 | 
			
		||||
    blake256_hash((uint8_t *)&second, (uint8_t *)&first, sizeof(crypto::secret_key));
 | 
			
		||||
 | 
			
		||||
    generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, two_random ? false : true);
 | 
			
		||||
    m_creation_timestamp = time(NULL);
 | 
			
		||||
    return first;
 | 
			
		||||
  }
 | 
			
		||||
  //-----------------------------------------------------------------
 | 
			
		||||
  const account_keys& account_base::get_keys() const
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ namespace cryptonote
 | 
			
		|||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    account_base();
 | 
			
		||||
    void generate();
 | 
			
		||||
    crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
 | 
			
		||||
    const account_keys& get_keys() const;
 | 
			
		||||
    std::string get_public_address_str();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,8 @@
 | 
			
		|||
#include "rpc/core_rpc_server_commands_defs.h"
 | 
			
		||||
#include "wallet/wallet_rpc_server.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
#include "crypto/crypto.h"  // for crypto::secret_key definition
 | 
			
		||||
#include "crypto/electrum-words.h"
 | 
			
		||||
 | 
			
		||||
#if defined(WIN32)
 | 
			
		||||
#include <crtdbg.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +40,9 @@ namespace
 | 
			
		|||
  const command_line::arg_descriptor<std::string> arg_daemon_address = {"daemon-address", "Use daemon instance at <host>:<port>", ""};
 | 
			
		||||
  const command_line::arg_descriptor<std::string> arg_daemon_host = {"daemon-host", "Use daemon instance at host <arg> instead of localhost", ""};
 | 
			
		||||
  const command_line::arg_descriptor<std::string> arg_password = {"password", "Wallet password", "", true};
 | 
			
		||||
  const command_line::arg_descriptor<std::string> arg_electrum_seed = {"electrum-seed", "Specify electrum seed for wallet recovery/creation", ""};
 | 
			
		||||
  const command_line::arg_descriptor<bool> arg_restore_deterministic_wallet = {"restore-deterministic-wallet", "Recover wallet using electrum-style mnemonic", false};
 | 
			
		||||
  const command_line::arg_descriptor<bool> arg_non_deterministic = {"non-deterministic", "requires --generate-new-wallet, uses old generation method", false};
 | 
			
		||||
  const command_line::arg_descriptor<int> arg_daemon_port = {"daemon-port", "Use daemon instance at port <arg> instead of 8081", 0};
 | 
			
		||||
  const command_line::arg_descriptor<uint32_t> arg_log_level = {"set_log", "", 0, true};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -208,17 +213,25 @@ bool simple_wallet::ask_wallet_create_if_needed()
 | 
			
		|||
{
 | 
			
		||||
  std::string wallet_path;
 | 
			
		||||
 | 
			
		||||
  std::cout << "Specify wallet file name (e.g., wallet.bin). If the wallet doesn't exist, it will be created.\n";
 | 
			
		||||
  std::cout << "Wallet file name: ";
 | 
			
		||||
 | 
			
		||||
  std::getline(std::cin, wallet_path);
 | 
			
		||||
 | 
			
		||||
  wallet_path = string_tools::trim(wallet_path);
 | 
			
		||||
  wallet_path = command_line::input_line(
 | 
			
		||||
      "Specify wallet file name (e.g., wallet.bin). If the wallet doesn't exist, it will be created.\n"
 | 
			
		||||
      "Wallet file name: "
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  bool keys_file_exists;
 | 
			
		||||
  bool wallet_file_exists;
 | 
			
		||||
  tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exists);
 | 
			
		||||
 | 
			
		||||
  // add logic to error out if new wallet requested but named wallet file exists
 | 
			
		||||
  if (keys_file_exists || wallet_file_exists)
 | 
			
		||||
  {
 | 
			
		||||
    if (!m_generate_new.empty() || m_restore_deterministic_wallet)
 | 
			
		||||
    {
 | 
			
		||||
      fail_msg_writer() << "Attempting to generate or restore wallet, but specified file(s) exist.  Exiting to not risk overwriting.";
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool r;
 | 
			
		||||
  if(keys_file_exists)
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -251,13 +264,14 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
 | 
			
		|||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  size_t c = 0;
 | 
			
		||||
  if(!m_generate_new.empty()) ++c;
 | 
			
		||||
  if(!m_wallet_file.empty()) ++c;
 | 
			
		||||
  if (1 != c)
 | 
			
		||||
  if(!m_generate_new.empty() && !m_wallet_file.empty())
 | 
			
		||||
  {
 | 
			
		||||
    if(!ask_wallet_create_if_needed())
 | 
			
		||||
      return false;
 | 
			
		||||
    fail_msg_writer() << "Specifying both --generate-new-wallet=\"wallet_name\" and --wallet-file=\"wallet_name\" doesn't make sense!";
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  else if (m_generate_new.empty() && m_wallet_file.empty())
 | 
			
		||||
  {
 | 
			
		||||
    if(!ask_wallet_create_if_needed()) return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (m_daemon_host.empty())
 | 
			
		||||
| 
						 | 
				
			
			@ -282,9 +296,36 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!m_generate_new.empty())
 | 
			
		||||
  if (!m_generate_new.empty() || m_restore_deterministic_wallet)
 | 
			
		||||
  {
 | 
			
		||||
    bool r = new_wallet(m_generate_new, pwd_container.password());
 | 
			
		||||
    if (m_wallet_file.empty()) m_wallet_file = m_generate_new;  // alias for simplicity later
 | 
			
		||||
 | 
			
		||||
    // check for recover flag.  if present, require electrum word list (only recovery option for now).
 | 
			
		||||
    if (m_restore_deterministic_wallet)
 | 
			
		||||
    {
 | 
			
		||||
      if (m_non_deterministic)
 | 
			
		||||
      {
 | 
			
		||||
        fail_msg_writer() << "Cannot specify both --restore-deterministic-wallet and --non-deterministic";
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (m_electrum_seed.empty())
 | 
			
		||||
      {
 | 
			
		||||
        m_electrum_seed = command_line::input_line("Specify electrum seed: ");
 | 
			
		||||
        if (m_electrum_seed.empty())
 | 
			
		||||
        {
 | 
			
		||||
          fail_msg_writer() << "specify a recovery parameter with the --electrum-seed=\"words list here\"";
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key))
 | 
			
		||||
      {
 | 
			
		||||
          fail_msg_writer() << "electrum-style word list failed verification";
 | 
			
		||||
          return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic);
 | 
			
		||||
    CHECK_AND_ASSERT_MES(r, false, "account creation failed");
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
| 
						 | 
				
			
			@ -306,11 +347,14 @@ bool simple_wallet::deinit()
 | 
			
		|||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
void simple_wallet::handle_command_line(const boost::program_options::variables_map& vm)
 | 
			
		||||
{
 | 
			
		||||
  m_wallet_file    = command_line::get_arg(vm, arg_wallet_file);
 | 
			
		||||
  m_generate_new   = command_line::get_arg(vm, arg_generate_new_wallet);
 | 
			
		||||
  m_daemon_address = command_line::get_arg(vm, arg_daemon_address);
 | 
			
		||||
  m_daemon_host    = command_line::get_arg(vm, arg_daemon_host);
 | 
			
		||||
  m_daemon_port    = command_line::get_arg(vm, arg_daemon_port);
 | 
			
		||||
  m_wallet_file                   = command_line::get_arg(vm, arg_wallet_file);
 | 
			
		||||
  m_generate_new                  = command_line::get_arg(vm, arg_generate_new_wallet);
 | 
			
		||||
  m_daemon_address                = command_line::get_arg(vm, arg_daemon_address);
 | 
			
		||||
  m_daemon_host                   = command_line::get_arg(vm, arg_daemon_host);
 | 
			
		||||
  m_daemon_port                   = command_line::get_arg(vm, arg_daemon_port);
 | 
			
		||||
  m_electrum_seed                 = command_line::get_arg(vm, arg_electrum_seed);
 | 
			
		||||
  m_restore_deterministic_wallet  = command_line::get_arg(vm, arg_restore_deterministic_wallet);
 | 
			
		||||
  m_non_deterministic             = command_line::get_arg(vm, arg_non_deterministic);
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
bool simple_wallet::try_connect_to_daemon()
 | 
			
		||||
| 
						 | 
				
			
			@ -324,16 +368,19 @@ bool simple_wallet::try_connect_to_daemon()
 | 
			
		|||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password)
 | 
			
		||||
bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key, bool recover, bool two_random)
 | 
			
		||||
{
 | 
			
		||||
  m_wallet_file = wallet_file;
 | 
			
		||||
 | 
			
		||||
  m_wallet.reset(new tools::wallet2());
 | 
			
		||||
  m_wallet->callback(this);
 | 
			
		||||
 | 
			
		||||
  crypto::secret_key recovery_val;
 | 
			
		||||
  try
 | 
			
		||||
  {
 | 
			
		||||
    m_wallet->generate(wallet_file, password);
 | 
			
		||||
    recovery_val = m_wallet->generate(wallet_file, password, recovery_key, recover, two_random);
 | 
			
		||||
    message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
 | 
			
		||||
  }
 | 
			
		||||
  catch (const std::exception& e)
 | 
			
		||||
| 
						 | 
				
			
			@ -344,6 +391,19 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
 | 
			
		|||
 | 
			
		||||
  m_wallet->init(m_daemon_address);
 | 
			
		||||
 | 
			
		||||
  // convert rng value to electrum-style word list
 | 
			
		||||
  std::string electrum_words;
 | 
			
		||||
  crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words);
 | 
			
		||||
 | 
			
		||||
  std::string print_electrum = "";
 | 
			
		||||
 | 
			
		||||
  if (!two_random)
 | 
			
		||||
  {
 | 
			
		||||
    print_electrum = "\nYour wallet can be recovered using the following electrum-style word list:\n";
 | 
			
		||||
    print_electrum += electrum_words;
 | 
			
		||||
    print_electrum += "\n";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  success_msg_writer() <<
 | 
			
		||||
    "**********************************************************************\n" <<
 | 
			
		||||
    "Your wallet has been generated.\n" <<
 | 
			
		||||
| 
						 | 
				
			
			@ -352,6 +412,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
 | 
			
		|||
    "Always use \"exit\" command when closing simplewallet to save\n" <<
 | 
			
		||||
    "current session's state. Otherwise, you will possibly need to synchronize \n" <<
 | 
			
		||||
    "your wallet again. Your wallet key is NOT under risk anyway.\n" <<
 | 
			
		||||
    print_electrum << 
 | 
			
		||||
    "**********************************************************************";
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -916,6 +977,9 @@ int main(int argc, char* argv[])
 | 
			
		|||
  command_line::add_arg(desc_params, arg_daemon_port);
 | 
			
		||||
  command_line::add_arg(desc_params, arg_command);
 | 
			
		||||
  command_line::add_arg(desc_params, arg_log_level);
 | 
			
		||||
  command_line::add_arg(desc_params, arg_restore_deterministic_wallet );
 | 
			
		||||
  command_line::add_arg(desc_params, arg_non_deterministic );
 | 
			
		||||
  command_line::add_arg(desc_params, arg_electrum_seed );
 | 
			
		||||
  tools::wallet_rpc_server::init_options(desc_params);
 | 
			
		||||
 | 
			
		||||
  po::positional_options_description positional_options;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
#include "wallet/wallet2.h"
 | 
			
		||||
#include "console_handler.h"
 | 
			
		||||
#include "password_container.h"
 | 
			
		||||
#include "crypto/crypto.h"  // for definition of crypto::secret_key
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace cryptonote
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +40,7 @@ namespace cryptonote
 | 
			
		|||
 | 
			
		||||
    bool run_console_handler();
 | 
			
		||||
 | 
			
		||||
    bool new_wallet(const std::string &wallet_file, const std::string& password);
 | 
			
		||||
    bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
 | 
			
		||||
    bool open_wallet(const std::string &wallet_file, const std::string& password);
 | 
			
		||||
    bool close_wallet();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +126,12 @@ namespace cryptonote
 | 
			
		|||
    std::string m_generate_new;
 | 
			
		||||
    std::string m_import_path;
 | 
			
		||||
 | 
			
		||||
    std::string m_electrum_seed;  // electrum-style seed parameter
 | 
			
		||||
 | 
			
		||||
    crypto::secret_key m_recovery_key;  // recovery key (used as random for wallet gen)
 | 
			
		||||
    bool m_restore_deterministic_wallet;  // recover flag
 | 
			
		||||
    bool m_non_deterministic;  // old 2-random generation
 | 
			
		||||
 | 
			
		||||
    std::string m_daemon_address;
 | 
			
		||||
    std::string m_daemon_host;
 | 
			
		||||
    int m_daemon_port;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ void do_prepare_file_names(const std::string& file_path, std::string& keys_file,
 | 
			
		|||
    keys_file += ".keys";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //namespace
 | 
			
		||||
 | 
			
		||||
namespace tools
 | 
			
		||||
| 
						 | 
				
			
			@ -435,7 +436,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa
 | 
			
		|||
  THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password);
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
void wallet2::generate(const std::string& wallet_, const std::string& password)
 | 
			
		||||
crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover, bool two_random)
 | 
			
		||||
{
 | 
			
		||||
  clear();
 | 
			
		||||
  prepare_file_names(wallet_);
 | 
			
		||||
| 
						 | 
				
			
			@ -444,7 +445,8 @@ void wallet2::generate(const std::string& wallet_, const std::string& password)
 | 
			
		|||
  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
 | 
			
		||||
  THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file,   ignored_ec), error::file_exists, m_keys_file);
 | 
			
		||||
 | 
			
		||||
  m_account.generate();
 | 
			
		||||
  crypto::secret_key retval = m_account.generate(recovery_param, recover, two_random);
 | 
			
		||||
 | 
			
		||||
  m_account_public_address = m_account.get_keys().m_account_address;
 | 
			
		||||
 | 
			
		||||
  bool r = store_keys(m_keys_file, password);
 | 
			
		||||
| 
						 | 
				
			
			@ -454,6 +456,7 @@ void wallet2::generate(const std::string& wallet_, const std::string& password)
 | 
			
		|||
  if(!r) LOG_PRINT_RED_L0("String with address text not saved");
 | 
			
		||||
 | 
			
		||||
  store();
 | 
			
		||||
  return retval;
 | 
			
		||||
}
 | 
			
		||||
//----------------------------------------------------------------------------------------------------
 | 
			
		||||
void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,7 +97,7 @@ namespace tools
 | 
			
		|||
      END_SERIALIZE()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    void generate(const std::string& wallet, const std::string& password);
 | 
			
		||||
    crypto::secret_key generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false, bool two_random = false);
 | 
			
		||||
    void load(const std::string& wallet, const std::string& password);
 | 
			
		||||
    void store();
 | 
			
		||||
    cryptonote::account_base& get_account(){return m_account;}
 | 
			
		||||
| 
						 | 
				
			
			@ -227,6 +227,7 @@ namespace boost
 | 
			
		|||
 | 
			
		||||
namespace tools
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  namespace detail
 | 
			
		||||
  {
 | 
			
		||||
    //----------------------------------------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -188,6 +188,17 @@ namespace tools
 | 
			
		|||
 | 
			
		||||
      std::string to_string() const { return wallet_logic_error::to_string(); }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------------
 | 
			
		||||
    struct invalid_pregenerated_random : public wallet_logic_error
 | 
			
		||||
    {
 | 
			
		||||
      explicit invalid_pregenerated_random (std::string&& loc)
 | 
			
		||||
        : wallet_logic_error(std::move(loc), "invalid pregenerated random for wallet creation/recovery")
 | 
			
		||||
      {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      std::string to_string() const { return wallet_logic_error::to_string(); }
 | 
			
		||||
    };
 | 
			
		||||
    //----------------------------------------------------------------------------------------------------
 | 
			
		||||
    struct refresh_error : public wallet_logic_error
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue