mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
openssl is a miserable dependency to fight with, especially for iOS/Android, and we use it for very little: - it gets (mis)used to write base64 data to a file in wallet2 for things like multisig data. However this mode is *not* enabled by default, basically completely unknown, completely unused, only exists in the cli wallet, and is just dumb. (Honestly the justification given in the PR is that "Windows users might want it", presupposing that there exists Windows users who are capable of generating a multisig wallet in a CLI-only application and yet are incapable of dealing with binary files). - it's a dependency of unbound (in order to do dnssec, I believe). Unbound itself is fairly useless for Oxen, so I've removed it too: - it does OpenAlias lookups, which are a Monero thing that has never been used outside Monero, doesn't work reliably (because it fails if the result isn't DNSSEC validated) and is pointless when we have ONS. - it does DNS resolution on seed nodes, but we have never set seed nodes by name and just use seed node IPs instead (which seems a bit better anyway since the DNS lookup leaks some metadata). - it *was* being used for sha256, but an earlier commit in this PR already replaced that with libsodium (entirely coincidentally). - for static deps, it enables HTTPS support for the wallet. However only the CLI wallet actually supports this (the GUI and mobile wallets don't), and since oxend hasn't support this for a while I have strong doubts it is being used anywhere. (Plus wallet3 will do everything encrypted using zmq/libsodium, so doesn't need this to be secure). Note here that it is *only* removed by this commit for static builds: if doing a system build that links to libcurl supporting HTTPS then HTTPS support will still work. Libexpat is also gone because it was only there for libunbound.
302 lines
9.9 KiB
C++
302 lines
9.9 KiB
C++
// Copyright (c) 2014-2019, The Monero Project
|
|
// Copyright (c) 2018, The Loki Project
|
|
//
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without modification, are
|
|
// permitted provided that the following conditions are met:
|
|
//
|
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
// conditions and the following disclaimer.
|
|
//
|
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
// of conditions and the following disclaimer in the documentation and/or other
|
|
// materials provided with the distribution.
|
|
//
|
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
// used to endorse or promote products derived from this software without specific
|
|
// prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
|
|
|
|
|
#include "wallet_manager.h"
|
|
#include "common/string_util.h"
|
|
#include "rpc/core_rpc_server_commands_defs.h"
|
|
#include "wallet.h"
|
|
#include "common_defines.h"
|
|
#include "common/util.h"
|
|
#include "version.h"
|
|
#include "common/fs.h"
|
|
|
|
#undef OXEN_DEFAULT_LOG_CATEGORY
|
|
#define OXEN_DEFAULT_LOG_CATEGORY "WalletAPI"
|
|
|
|
namespace Wallet {
|
|
|
|
EXPORT
|
|
Wallet* WalletManagerImpl::createWallet(std::string_view path, const std::string &password,
|
|
const std::string &language, NetworkType nettype, uint64_t kdf_rounds)
|
|
{
|
|
WalletImpl* wallet = new WalletImpl(nettype, kdf_rounds);
|
|
wallet->create(path, password, language);
|
|
return wallet;
|
|
}
|
|
|
|
EXPORT
|
|
Wallet* WalletManagerImpl::openWallet(std::string_view path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds, WalletListener * listener)
|
|
{
|
|
WalletImpl* wallet = new WalletImpl(nettype, kdf_rounds);
|
|
wallet->setListener(listener);
|
|
if (listener){
|
|
listener->onSetWallet(wallet);
|
|
}
|
|
|
|
wallet->open(path, password);
|
|
//Refresh addressBook
|
|
wallet->addressBook()->refresh();
|
|
return wallet;
|
|
}
|
|
|
|
EXPORT
|
|
Wallet* WalletManagerImpl::recoveryWallet(std::string_view path,
|
|
const std::string &password,
|
|
const std::string &mnemonic,
|
|
NetworkType nettype,
|
|
uint64_t restoreHeight,
|
|
uint64_t kdf_rounds,
|
|
const std::string &seed_offset/* = {}*/)
|
|
{
|
|
WalletImpl* wallet = new WalletImpl(nettype, kdf_rounds);
|
|
if(restoreHeight > 0){
|
|
wallet->setRefreshFromBlockHeight(restoreHeight);
|
|
}
|
|
wallet->recover(path, password, mnemonic, seed_offset);
|
|
return wallet;
|
|
}
|
|
|
|
EXPORT
|
|
Wallet* WalletManagerImpl::createWalletFromKeys(std::string_view path,
|
|
const std::string &password,
|
|
const std::string &language,
|
|
NetworkType nettype,
|
|
uint64_t restoreHeight,
|
|
const std::string &addressString,
|
|
const std::string &viewKeyString,
|
|
const std::string &spendKeyString,
|
|
uint64_t kdf_rounds)
|
|
{
|
|
WalletImpl* wallet = new WalletImpl(nettype, kdf_rounds);
|
|
if(restoreHeight > 0){
|
|
wallet->setRefreshFromBlockHeight(restoreHeight);
|
|
}
|
|
wallet->recoverFromKeysWithPassword(path, password, language, addressString, viewKeyString, spendKeyString);
|
|
return wallet;
|
|
}
|
|
|
|
EXPORT
|
|
Wallet* WalletManagerImpl::createWalletFromDevice(std::string_view path,
|
|
const std::string &password,
|
|
NetworkType nettype,
|
|
const std::string &deviceName,
|
|
uint64_t restoreHeight,
|
|
const std::string &subaddressLookahead,
|
|
uint64_t kdf_rounds,
|
|
WalletListener * listener)
|
|
{
|
|
WalletImpl* wallet = new WalletImpl(nettype, kdf_rounds);
|
|
wallet->setListener(listener);
|
|
if (listener){
|
|
listener->onSetWallet(wallet);
|
|
}
|
|
|
|
if(restoreHeight > 0){
|
|
wallet->setRefreshFromBlockHeight(restoreHeight);
|
|
} else {
|
|
wallet->setRefreshFromBlockHeight(wallet->estimateBlockChainHeight());
|
|
}
|
|
auto lookahead = tools::parse_subaddress_lookahead(subaddressLookahead);
|
|
if (lookahead)
|
|
{
|
|
wallet->setSubaddressLookahead(lookahead->first, lookahead->second);
|
|
}
|
|
wallet->recoverFromDevice(path, password, deviceName);
|
|
return wallet;
|
|
}
|
|
|
|
EXPORT
|
|
bool WalletManagerImpl::closeWallet(Wallet* wallet, bool store)
|
|
{
|
|
WalletImpl* wallet_ = dynamic_cast<WalletImpl*>(wallet);
|
|
if (!wallet_)
|
|
return false;
|
|
bool result = wallet_->close(store);
|
|
if (!result) {
|
|
m_errorString = wallet_->status().second;
|
|
} else {
|
|
delete wallet_;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
EXPORT
|
|
bool WalletManagerImpl::walletExists(std::string_view path)
|
|
{
|
|
bool keys_file_exists;
|
|
bool wallet_file_exists;
|
|
tools::wallet2::wallet_exists(fs::u8path(path), keys_file_exists, wallet_file_exists);
|
|
if(keys_file_exists){
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
EXPORT
|
|
bool WalletManagerImpl::verifyWalletPassword(std::string_view keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds) const
|
|
{
|
|
return tools::wallet2::verify_password(fs::u8path(keys_file_name), password, no_spend_key, hw::get_device("default"), kdf_rounds);
|
|
}
|
|
|
|
EXPORT
|
|
bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, std::string_view keys_file_name, const std::string &password, uint64_t kdf_rounds) const
|
|
{
|
|
hw::device::type type;
|
|
bool r = tools::wallet2::query_device(type, fs::u8path(keys_file_name), password, kdf_rounds);
|
|
device_type = static_cast<Wallet::Device>(type);
|
|
return r;
|
|
}
|
|
|
|
EXPORT
|
|
std::vector<std::string> WalletManagerImpl::findWallets(std::string_view path_)
|
|
{
|
|
auto path = fs::u8path(path_);
|
|
std::vector<std::string> result;
|
|
// return empty result if path doesn't exist
|
|
if (!fs::is_directory(path)){
|
|
return result;
|
|
}
|
|
for (auto& p : fs::recursive_directory_iterator{path}) {
|
|
// Skip if not a file
|
|
if (!p.is_regular_file())
|
|
continue;
|
|
auto filename = p.path();
|
|
|
|
LOG_PRINT_L3("Checking filename: " << filename);
|
|
|
|
if (filename.extension() == ".keys") {
|
|
// if keys file found, checking if there's wallet file itself
|
|
filename.replace_extension();
|
|
if (fs::exists(filename)) {
|
|
LOG_PRINT_L3("Found wallet: " << filename);
|
|
result.push_back(filename.u8string());
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
EXPORT
|
|
std::string WalletManagerImpl::errorString() const
|
|
{
|
|
return m_errorString;
|
|
}
|
|
|
|
EXPORT
|
|
void WalletManagerImpl::setDaemonAddress(std::string address)
|
|
{
|
|
if (!tools::starts_with(address, "https://") && !tools::starts_with(address, "http://"))
|
|
address.insert(0, "http://");
|
|
m_http_client.set_base_url(std::move(address));
|
|
}
|
|
|
|
EXPORT
|
|
bool WalletManagerImpl::connected(uint32_t *version)
|
|
{
|
|
using namespace cryptonote::rpc;
|
|
try {
|
|
auto res = m_http_client.json_rpc<GET_VERSION>(GET_VERSION::names()[0], {});
|
|
if (version) *version = res.version;
|
|
return true;
|
|
} catch (...) {}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <typename RPC>
|
|
static std::optional<typename RPC::response> json_rpc(cryptonote::rpc::http_client& http, const typename RPC::request& req = {})
|
|
{
|
|
using namespace cryptonote::rpc;
|
|
try { return http.json_rpc<RPC>(RPC::names()[0], req); }
|
|
catch (...) {}
|
|
return std::nullopt;
|
|
}
|
|
|
|
static std::optional<cryptonote::rpc::GET_INFO::response> get_info(cryptonote::rpc::http_client& http)
|
|
{
|
|
return json_rpc<cryptonote::rpc::GET_INFO>(http);
|
|
}
|
|
|
|
|
|
EXPORT
|
|
uint64_t WalletManagerImpl::blockchainHeight()
|
|
{
|
|
auto res = get_info(m_http_client);
|
|
return res ? res->height : 0;
|
|
}
|
|
|
|
EXPORT
|
|
uint64_t WalletManagerImpl::blockchainTargetHeight()
|
|
{
|
|
auto res = get_info(m_http_client);
|
|
if (!res)
|
|
return 0;
|
|
return std::max(res->target_height, res->height);
|
|
}
|
|
|
|
EXPORT
|
|
uint64_t WalletManagerImpl::blockTarget()
|
|
{
|
|
auto res = get_info(m_http_client);
|
|
return res ? res->target : 0;
|
|
}
|
|
|
|
///////////////////// WalletManagerFactory implementation //////////////////////
|
|
EXPORT
|
|
WalletManagerBase *WalletManagerFactory::getWalletManager()
|
|
{
|
|
|
|
static WalletManagerImpl * g_walletManager = nullptr;
|
|
|
|
if (!g_walletManager) {
|
|
g_walletManager = new WalletManagerImpl();
|
|
}
|
|
|
|
return g_walletManager;
|
|
}
|
|
|
|
EXPORT
|
|
void WalletManagerFactory::setLogLevel(int level)
|
|
{
|
|
mlog_set_log_level(level);
|
|
}
|
|
|
|
EXPORT
|
|
void WalletManagerFactory::setLogCategories(const std::string &categories)
|
|
{
|
|
mlog_set_log(categories.c_str());
|
|
}
|
|
|
|
|
|
|
|
}
|