diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index c0974f880..7afc1f449 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -379,7 +379,32 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas const cryptonote::account_public_address address = m_wallet->get_account().get_keys().m_account_address; try { + // Generate view only wallet view_wallet->generate(path, password, address, viewkey); + + // Export/Import outputs + auto outputs = m_wallet->export_outputs(); + view_wallet->import_outputs(outputs); + + // Copy scanned blockchain + auto bc = m_wallet->export_blockchain(); + view_wallet->import_blockchain(bc); + + // copy payments + auto payments = m_wallet->export_payments(); + view_wallet->import_payments(payments); + + // copy confirmed outgoing payments + std::list> out_payments; + m_wallet->get_payments_out(out_payments, 0); + view_wallet->import_payments_out(out_payments); + + // Export/Import key images + // We already know the spent status from the outputs we exported, thus no need to check them again + auto key_images = m_wallet->export_key_images(); + uint64_t spent = 0; + uint64_t unspent = 0; + view_wallet->import_key_images(key_images,spent,unspent,false); m_status = Status_Ok; } catch (const std::exception &e) { LOG_ERROR("Error creating view only wallet: " << e.what()); @@ -387,6 +412,8 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas m_errorString = e.what(); return false; } + // Store wallet + view_wallet->store(); return true; } @@ -862,6 +889,11 @@ bool WalletImpl::exportKeyImages(const string &filename) bool WalletImpl::importKeyImages(const string &filename) { + if (!trustedDaemon()) { + m_status = Status_Error; + m_errorString = tr("Key images can only be imported with a trusted daemon"); + return false; + } try { uint64_t spent = 0, unspent = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 09ca8efe1..4f21e3e77 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5330,7 +5330,7 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent) +uint64_t wallet2::import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent) { COMMAND_RPC_IS_KEY_IMAGE_SPENT::request req = AUTO_VAL_INIT(req); COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp); @@ -5379,34 +5379,88 @@ uint64_t wallet2::import_key_images(const std::vector> &confirmed_payments) +{ + m_confirmed_txs.clear(); + for (auto const &p : confirmed_payments) + { + m_confirmed_txs.emplace(p); + } +} + +std::vector wallet2::export_blockchain() const +{ + std::vector bc; + for (auto const &b : m_blockchain) + { + bc.push_back(b); + } + return bc; +} + +void wallet2::import_blockchain(const std::vector &bc) +{ + m_blockchain.clear(); + for (auto const &b : bc) + { + m_blockchain.push_back(b); + } + cryptonote::block genesis; + generate_genesis(genesis); + crypto::hash genesis_hash = get_block_hash(genesis); + check_genesis(genesis_hash); + m_local_bc_height = m_blockchain.size(); +} //---------------------------------------------------------------------------------------------------- std::vector wallet2::export_outputs() const { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f30c97635..3d5033535 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -582,12 +582,17 @@ namespace tools std::string sign(const std::string &data) const; bool verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const; + // Import/Export wallet data std::vector export_outputs() const; size_t import_outputs(const std::vector &outputs); - + payment_container export_payments() const; + void import_payments(const payment_container &payments); + void import_payments_out(const std::list> &confirmed_payments); + std::vector export_blockchain() const; + void import_blockchain(const std::vector &bc); bool export_key_images(const std::string filename); std::vector> export_key_images() const; - uint64_t import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent); + uint64_t import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent = true); uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent); void update_pool_state(bool refreshed = false);