void WalletLegacy::doSave(std::ostream& destination, bool saveDetailed, bool saveCache) { ContextCounterHolder counterHolder(m_asyncContextCounter); try { m_blockchainSync.stop(); std::unique_lock<std::mutex> lock(m_cacheMutex); WalletLegacySerializer serializer(m_account, m_transactionsCache); std::string cache; if (saveCache) { std::stringstream stream; m_transfersSync.save(stream); cache = stream.str(); } serializer.serialize(destination, m_password, saveDetailed, cache); m_state = INITIALIZED; m_blockchainSync.start(); //XXX: start can throw. what to do in this case? } catch (std::system_error& e) { runAtomic(m_cacheMutex, [this] () {this->m_state = WalletLegacy::INITIALIZED;} ); m_observerManager.notify(&IWalletLegacyObserver::saveCompleted, e.code()); return; } catch (std::exception&) { runAtomic(m_cacheMutex, [this] () {this->m_state = WalletLegacy::INITIALIZED;} ); m_observerManager.notify(&IWalletLegacyObserver::saveCompleted, make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR)); return; } m_observerManager.notify(&IWalletLegacyObserver::saveCompleted, std::error_code()); }
void WalletLegacy::doLoad(std::istream& source) { ContextCounterHolder counterHolder(m_asyncContextCounter); try { std::unique_lock<std::mutex> lock(m_cacheMutex); std::string cache; WalletLegacySerializer serializer(m_account, m_transactionsCache); serializer.deserialize(source, m_password, cache); initSync(); try { if (!cache.empty()) { std::stringstream stream(cache); m_transfersSync.load(stream); } } catch (const std::exception&) { // ignore cache loading errors } } catch (std::system_error& e) { runAtomic(m_cacheMutex, [this] () {this->m_state = WalletLegacy::NOT_INITIALIZED;} ); m_observerManager.notify(&IWalletLegacyObserver::initCompleted, e.code()); return; } catch (std::exception&) { runAtomic(m_cacheMutex, [this] () {this->m_state = WalletLegacy::NOT_INITIALIZED;} ); m_observerManager.notify(&IWalletLegacyObserver::initCompleted, make_error_code(CryptoNote::error::INTERNAL_WALLET_ERROR)); return; } m_observerManager.notify(&IWalletLegacyObserver::initCompleted, std::error_code()); }
void Wallet::doLoad(std::istream& source) { try { std::unique_lock<std::mutex> lock(m_cacheMutex); boost::archive::binary_iarchive ar(source); crypto::chacha8_iv iv; std::string chacha_str;; ar >> chacha_str; ::serialization::parse_binary(chacha_str, iv); std::string cipher; ar >> cipher; std::string plain; decrypt(cipher, plain, iv, m_password); std::stringstream restore(plain); try { //boost archive ctor throws an exception if password is wrong (i.e. there's garbage in a stream) boost::archive::binary_iarchive dataArchive(restore); dataArchive >> m_account; throwIfKeysMissmatch(m_account.get_keys().m_view_secret_key, m_account.get_keys().m_account_address.m_view_public_key); throwIfKeysMissmatch(m_account.get_keys().m_spend_secret_key, m_account.get_keys().m_account_address.m_spend_public_key); dataArchive >> m_blockchain; m_transferDetails.load(dataArchive); m_unconfirmedTransactions.load(dataArchive); m_transactionsCache.load(dataArchive); } catch (std::exception&) { throw std::system_error(make_error_code(cryptonote::error::WRONG_PASSWORD)); } m_sender.init(m_account.get_keys()); } catch (std::system_error& e) { runAtomic(m_cacheMutex, [this] () {this->m_state = Wallet::NOT_INITIALIZED;} ); m_observerManager.notify(&IWalletObserver::initCompleted, e.code()); return; } catch (std::exception&) { runAtomic(m_cacheMutex, [this] () {this->m_state = Wallet::NOT_INITIALIZED;} ); m_observerManager.notify(&IWalletObserver::initCompleted, make_error_code(cryptonote::error::INTERNAL_WALLET_ERROR)); return; } runAtomic(m_cacheMutex, [this] () {this->m_state = Wallet::INITIALIZED;} ); m_observerManager.notify(&IWalletObserver::initCompleted, std::error_code()); refresh(); }
void Wallet::doSave(std::ostream& destination, bool saveDetailed, bool saveCache) { ContextCounterHolder counterHolder(m_asyncContextCounter); try { //TODO: exception safety: leave destination stream empty in case of errors boost::archive::binary_oarchive ar(destination); std::stringstream original; std::unique_lock<std::mutex> lock(m_cacheMutex); boost::archive::binary_oarchive archive(original); archive << m_account; const BlockchainContainer& blockchain = saveCache ? m_blockchain : BlockchainContainer(); archive << blockchain; m_transferDetails.save(archive, saveCache); m_unconfirmedTransactions.save(archive, saveCache); m_transactionsCache.save(archive, saveDetailed, saveCache); std::string plain = original.str(); std::string cipher; crypto::chacha8_iv iv = encrypt(plain, cipher); std::string chacha_str; ::serialization::dump_binary(iv, chacha_str); ar << chacha_str; ar << cipher; m_state = INITIALIZED; } catch (std::system_error& e) { runAtomic(m_cacheMutex, [this] () {this->m_state = Wallet::INITIALIZED;} ); m_observerManager.notify(&IWalletObserver::saveCompleted, e.code()); return; } catch (std::exception&) { runAtomic(m_cacheMutex, [this] () {this->m_state = Wallet::INITIALIZED;} ); m_observerManager.notify(&IWalletObserver::saveCompleted, make_error_code(cryptonote::error::INTERNAL_WALLET_ERROR)); return; } m_observerManager.notify(&IWalletObserver::saveCompleted, std::error_code()); }