From 2cce32995b840901ce656dd8ec3fcefefff706bf Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Mon, 21 Mar 2016 16:17:03 +0300 Subject: wallet2::store() implemented within wallet2::store_to --- src/wallet/wallet2.cpp | 122 +++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 69 deletions(-) (limited to 'src/wallet/wallet2.cpp') diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 2afe08cb1..9592810e7 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1424,6 +1424,42 @@ void wallet2::check_genesis(const crypto::hash& genesis_hash) const { //---------------------------------------------------------------------------------------------------- void wallet2::store() { + store_to("", ""); +} +//---------------------------------------------------------------------------------------------------- +void wallet2::store_to(const std::string &path, const std::string &password) +{ + // if file is the same, we do: + // 1. save wallet to the *.new file + // 2. remove old wallet file + // 3. rename *.new to wallet_name + + // handle if we want just store wallet state to current files (ex store() replacement); + bool same_file = true; + if (!path.empty()) + { + std::string canonical_path = boost::filesystem::canonical(m_wallet_file).string(); + size_t pos = canonical_path.find(path); + same_file = pos != std::string::npos; + } + + + if (!same_file) + { + // check if we want to store to directory which doesn't exists yet + boost::filesystem::path parent_path = boost::filesystem::path(path).parent_path(); + + // if path is not exists, try to create it + if (!parent_path.empty() && !boost::filesystem::exists(parent_path)) + { + boost::system::error_code ec; + if (!boost::filesystem::create_directories(parent_path, ec)) + { + throw std::logic_error(ec.message()); + } + } + } + // preparing wallet data std::stringstream oss; boost::archive::binary_oarchive ar(oss); ar << *this; @@ -1438,10 +1474,10 @@ void wallet2::store() crypto::chacha8(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cipher[0]); cache_file_data.cache_data = cipher; - // save to new file, rename main to old, rename new to main - // at all times, there should be a valid file on disk - const std::string new_file = m_wallet_file + ".new"; - const std::string old_file = m_wallet_file + ".old"; + const std::string new_file = same_file ? m_wallet_file + ".new" : path; + const std::string old_file = m_wallet_file; + const std::string old_keys_file = m_keys_file; + const std::string old_address_file = m_wallet_file + ".address.txt"; // save to new file std::ofstream ostr; @@ -1451,87 +1487,35 @@ void wallet2::store() ostr.close(); THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file); - // rename - boost::filesystem::remove(old_file); // probably does not exist - if (boost::filesystem::exists(m_wallet_file)) { - std::error_code e = tools::replace_file(m_wallet_file, old_file); - THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e); - } - std::error_code e = tools::replace_file(new_file, m_wallet_file); - THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e); - boost::filesystem::remove(old_file); -} - -void wallet2::store_to(const std::string &path, const std::string &password) -{ - // TODO: merge it with wallet2::store() function - - // check if we want to store to directory which doesn't exists yet - boost::filesystem::path parent_path = boost::filesystem::path(path).parent_path(); - - // if path is not exists, try to create it - if (!parent_path.empty() && !boost::filesystem::exists(parent_path)) { - boost::system::error_code ec; - if (!boost::filesystem::create_directories(parent_path, ec)) { - throw std::logic_error(ec.message()); - } - } - - - std::stringstream oss; - boost::archive::binary_oarchive ar(oss); - ar << *this; - - wallet2::cache_file_data cache_file_data = boost::value_initialized(); - cache_file_data.cache_data = oss.str(); - crypto::chacha8_key key; - generate_chacha8_key_from_secret_keys(key); - std::string cipher; - cipher.resize(cache_file_data.cache_data.size()); - cache_file_data.iv = crypto::rand(); - crypto::chacha8(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), key, cache_file_data.iv, &cipher[0]); - cache_file_data.cache_data = cipher; - - - const std::string new_file = path; - const std::string old_file = m_wallet_file; - const std::string old_keys_file = m_keys_file; - const std::string old_address_file = m_wallet_file + ".address.txt"; - - // save to new file - std::ofstream ostr; - ostr.open(new_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); - binary_archive oar(ostr); - bool success = ::serialization::serialize(oar, cache_file_data); - ostr.close(); - THROW_WALLET_EXCEPTION_IF(!success || !ostr.good(), error::file_save_error, new_file); - - // save keys to the new file - // if we here, main wallet file is saved and we only need to save keys and address files + // save keys to the new file + // if we here, main wallet file is saved and we only need to save keys and address files + if (!same_file) { prepare_file_names(path); store_keys(m_keys_file, password, false); - // save address to the new file const std::string address_file = m_wallet_file + ".address.txt"; bool r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_testnet)); THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file); - - // remove old wallet file r = boost::filesystem::remove(old_file); if (!r) { - LOG_ERROR("error removing file: " << old_file); + LOG_ERROR("error removing file: " << old_file); } // remove old keys file r = boost::filesystem::remove(old_keys_file); if (!r) { - LOG_ERROR("error removing file: " << old_keys_file); + LOG_ERROR("error removing file: " << old_keys_file); } // remove old address file r = boost::filesystem::remove(old_address_file); if (!r) { - LOG_ERROR("error removing file: " << old_address_file); + LOG_ERROR("error removing file: " << old_address_file); } + } else { + // here we have "*.new" file, we need to rename it to be without ".new" + std::error_code e = tools::replace_file(new_file, m_wallet_file); + THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e); + } } //---------------------------------------------------------------------------------------------------- uint64_t wallet2::unlocked_balance() const @@ -2769,12 +2753,12 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) c std::string wallet2::get_wallet_file() const { - return m_wallet_file; + return m_wallet_file; } std::string wallet2::get_keys_file() const { - return m_keys_file; + return m_keys_file; } //---------------------------------------------------------------------------------------------------- -- cgit v1.2.3 From 8790904cf9ccba56a1cbab51b01f2cbb0a5cb143 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Fri, 25 Mar 2016 17:06:30 +0300 Subject: - testnet option added to api; --- src/wallet/wallet2.cpp | 5 +++ src/wallet/wallet2.h | 1 + src/wallet/wallet2_api.cpp | 50 +++++++++++++++++++++++----- src/wallet/wallet2_api.h | 11 +++--- tests/libwallet_api_tests/main.cpp | 68 ++++++++++++++++++++++++-------------- 5 files changed, 98 insertions(+), 37 deletions(-) (limited to 'src/wallet/wallet2.cpp') diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 9592810e7..f263346a7 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2761,6 +2761,11 @@ std::string wallet2::get_keys_file() const return m_keys_file; } +std::string wallet2::get_daemon_address() const +{ + return m_daemon_address; +} + //---------------------------------------------------------------------------------------------------- void wallet2::generate_genesis(cryptonote::block& b) { if (m_testnet) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f798f404d..60814b7ed 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -359,6 +359,7 @@ namespace tools std::string get_wallet_file() const; std::string get_keys_file() const; + std::string get_daemon_address() const; private: /*! * \brief Stores wallet information to wallet file. diff --git a/src/wallet/wallet2_api.cpp b/src/wallet/wallet2_api.cpp index cf1a2bf24..31015b355 100644 --- a/src/wallet/wallet2_api.cpp +++ b/src/wallet/wallet2_api.cpp @@ -54,7 +54,7 @@ Wallet::~Wallet() {} class WalletImpl : public Wallet { public: - WalletImpl(); + WalletImpl(bool testnet = false); ~WalletImpl(); bool create(const std::string &path, const std::string &password, const std::string &language); @@ -70,6 +70,9 @@ public: bool setPassword(const std::string &password); std::string address() const; bool store(const std::string &path); + bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit); + uint64_t balance() const; + bool connectToDaemon(); private: void clearStatus(); @@ -82,10 +85,10 @@ private: std::string m_password; }; -WalletImpl::WalletImpl() +WalletImpl::WalletImpl(bool testnet) :m_wallet(nullptr), m_status(Wallet::Status_Ok) { - m_wallet = new tools::wallet2(); + m_wallet = new tools::wallet2(testnet); } WalletImpl::~WalletImpl() @@ -257,6 +260,35 @@ bool WalletImpl::store(const std::string &path) return m_status == Status_Ok; } +bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) +{ + clearStatus(); + try { + m_wallet->init(daemon_address, upper_transaction_size_limit); + } catch (const std::exception &e) { + LOG_ERROR("Error initializing wallet: " << e.what()); + m_status = Status_Error; + m_errorString = e.what(); + } + + return m_status == Status_Ok; +} + +uint64_t WalletImpl::balance() const +{ + return m_wallet->balance(); +} + +bool WalletImpl::connectToDaemon() +{ + bool result = m_wallet->check_connection(); + m_status = result ? Status_Ok : Status_Error; + if (!result) { + m_errorString = "Error connecting to daemon at " + m_wallet->get_daemon_address(); + } + return result; +} + void WalletImpl::clearStatus() { m_status = Status_Ok; @@ -270,8 +302,8 @@ class WalletManagerImpl : public WalletManager { public: Wallet * createWallet(const std::string &path, const std::string &password, - const std::string &language); - Wallet * openWallet(const std::string &path, const std::string &password); + const std::string &language, bool testnet); + Wallet * openWallet(const std::string &path, const std::string &password, bool testnet); virtual Wallet * recoveryWallet(const std::string &path, const std::string &memo); virtual bool closeWallet(Wallet *wallet); bool walletExists(const std::string &path); @@ -287,16 +319,16 @@ private: }; Wallet *WalletManagerImpl::createWallet(const std::string &path, const std::string &password, - const std::string &language) + const std::string &language, bool testnet) { - WalletImpl * wallet = new WalletImpl(); + WalletImpl * wallet = new WalletImpl(testnet); wallet->create(path, password, language); return wallet; } -Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password) +Wallet *WalletManagerImpl::openWallet(const std::string &path, const std::string &password, bool testnet) { - WalletImpl * wallet = new WalletImpl(); + WalletImpl * wallet = new WalletImpl(testnet); wallet->open(path, password); return wallet; } diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 013a260b7..ad1e08fe3 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -67,6 +67,9 @@ struct Wallet virtual bool setPassword(const std::string &password) = 0; virtual std::string address() const = 0; virtual bool store(const std::string &path) = 0; + virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit) = 0; + virtual bool connectToDaemon() = 0; + virtual uint64_t balance() const = 0; }; /** @@ -82,7 +85,7 @@ struct WalletManager * \param language Language to be used to generate electrum seed memo * \return Wallet instance (Wallet::status() needs to be called to check if created successfully) */ - virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language) = 0; + virtual Wallet * createWallet(const std::string &path, const std::string &password, const std::string &language, bool testnet) = 0; /*! * \brief Opens existing wallet @@ -90,7 +93,7 @@ struct WalletManager * \param password Password of wallet file * \return Wallet instance (Wallet::status() needs to be called to check if opened successfully) */ - virtual Wallet * openWallet(const std::string &path, const std::string &password) = 0; + virtual Wallet * openWallet(const std::string &path, const std::string &password, bool testnet) = 0; /*! * \brief recovers existing wallet using memo (electrum seed) @@ -111,8 +114,8 @@ struct WalletManager virtual bool walletExists(const std::string &path) = 0; virtual std::string errorString() const = 0; - - virtual void setDaemonHost(const std::string &hostname) = 0; +// //! set +// virtual void setDaemonAddress(const std::string &address) = 0; }; diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index da2624387..841b5df27 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -41,6 +41,23 @@ using namespace std; //unsigned int epee::g_test_dbg_lock_sleep = 0; +struct Utils +{ + static void deleteWallet(const std::string & walletname) + { + std::cout << "** deleting wallet: " << walletname << std::endl; + boost::filesystem::remove(walletname); + boost::filesystem::remove(walletname + ".address.txt"); + boost::filesystem::remove(walletname + ".keys"); + } + + static void deleteDir(const std::string &path) + { + std::cout << "** removing dir recursively: " << path << std::endl; + boost::filesystem::remove_all(path); + } +}; + struct WalletManagerTest : public testing::Test { @@ -54,12 +71,16 @@ struct WalletManagerTest : public testing::Test const char * WALLET_PASS2 = "password22"; const char * WALLET_LANG = "English"; + // TODO: add test wallets to the source tree (as they have some balance mined)? + const char * TESTNET_WALLET_NAME = "/home/mbg033/dev/monero/testnet/wallet_01.bin"; + const char * TESTNET_WALLET_PASS = ""; + WalletManagerTest() { std::cout << __FUNCTION__ << std::endl; wmgr = Bitmonero::WalletManagerFactory::getWalletManager(); - deleteWallet(WALLET_NAME); - deleteDir(boost::filesystem::path(WALLET_NAME_WITH_DIR).parent_path().string()); + Utils::deleteWallet(WALLET_NAME); + Utils::deleteDir(boost::filesystem::path(WALLET_NAME_WITH_DIR).parent_path().string()); } @@ -68,29 +89,13 @@ struct WalletManagerTest : public testing::Test std::cout << __FUNCTION__ << std::endl; //deleteWallet(WALLET_NAME); } - - - void deleteWallet(const std::string & walletname) - { - std::cout << "** deleting wallet: " << walletname << std::endl; - boost::filesystem::remove(walletname); - boost::filesystem::remove(walletname + ".address.txt"); - boost::filesystem::remove(walletname + ".keys"); - } - - void deleteDir(const std::string &path) - { - std::cout << "** removing dir recursively: " << path << std::endl; - boost::filesystem::remove_all(path); - } - }; TEST_F(WalletManagerTest, WalletManagerCreatesWallet) { - Bitmonero::Wallet * wallet = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); + Bitmonero::Wallet * wallet = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG, true); ASSERT_TRUE(wallet->status() == Bitmonero::Wallet::Status_Ok); ASSERT_TRUE(!wallet->seed().empty()); std::vector words; @@ -107,16 +112,16 @@ TEST_F(WalletManagerTest, WalletManagerCreatesWallet) TEST_F(WalletManagerTest, WalletManagerOpensWallet) { - Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); + Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG, true); std::string seed1 = wallet1->seed(); ASSERT_TRUE(wmgr->closeWallet(wallet1)); - Bitmonero::Wallet * wallet2 = wmgr->openWallet(WALLET_NAME, WALLET_PASS); + Bitmonero::Wallet * wallet2 = wmgr->openWallet(WALLET_NAME, WALLET_PASS, true); ASSERT_TRUE(wallet2->status() == Bitmonero::Wallet::Status_Ok); ASSERT_TRUE(wallet2->seed() == seed1); std::cout << "** seed: " << wallet2->seed() << std::endl; } - +/* TEST_F(WalletManagerTest, WalletManagerChangesPassword) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); @@ -182,7 +187,6 @@ TEST_F(WalletManagerTest, WalletManagerStoresWallet2) ASSERT_TRUE(wmgr->closeWallet(wallet1)); } - TEST_F(WalletManagerTest, WalletManagerStoresWallet3) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); @@ -205,7 +209,6 @@ TEST_F(WalletManagerTest, WalletManagerStoresWallet3) } - TEST_F(WalletManagerTest, WalletManagerStoresWallet4) { Bitmonero::Wallet * wallet1 = wmgr->createWallet(WALLET_NAME, WALLET_PASS, WALLET_LANG); @@ -225,7 +228,24 @@ TEST_F(WalletManagerTest, WalletManagerStoresWallet4) ASSERT_TRUE(wallet1->seed() == seed1); ASSERT_TRUE(wallet1->address() == address1); ASSERT_TRUE(wmgr->closeWallet(wallet1)); +} +*/ + +TEST_F(WalletManagerTest, WalletShowsBalance) +{ + Bitmonero::Wallet * wallet1 = wmgr->openWallet(TESTNET_WALLET_NAME, TESTNET_WALLET_PASS, true); + std::string seed1 = wallet1->seed(); + std::string address1 = wallet1->address(); + ASSERT_TRUE(wallet1->balance() > 0); + + uint64_t balance1 = wallet1->balance(); + ASSERT_TRUE(wmgr->closeWallet(wallet1)); + Bitmonero::Wallet * wallet2 = wmgr->openWallet(TESTNET_WALLET_NAME, TESTNET_WALLET_PASS, true); + ASSERT_TRUE(seed1 == wallet2->seed()); + ASSERT_TRUE(address1 == wallet2->address()); + ASSERT_TRUE(balance1 == wallet2->balance()); + ASSERT_TRUE(wmgr->closeWallet(wallet2)); } -- cgit v1.2.3