Merge pull request #1484 from jagerman/disable-mms-light

Disable MMS and light wallet support by default
This commit is contained in:
Sean 2021-09-06 13:45:16 +10:00 committed by GitHub
commit 578c1c235f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1410 additions and 1303 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -169,8 +169,8 @@ namespace cryptonote
// lock_time_in_blocks: Only required if making a locked transfer, only for displaying to the user, it should be the lock time specified by the sender
// unlock_block: Only required if lock_time_in_blocks is specified, only for displaying to the user, the height at which the transfer will unlock
bool confirm_and_send_tx(std::vector<cryptonote::address_parse_info> const &dests, std::vector<tools::wallet2::pending_tx> &ptx_vector, bool blink, uint64_t lock_time_in_blocks = 0, uint64_t unlock_block = 0, bool called_by_mms = false);
bool transfer_main(Transfer transfer_type, const std::vector<std::string> &args, bool called_by_mms);
bool confirm_and_send_tx(std::vector<cryptonote::address_parse_info> const &dests, std::vector<tools::wallet2::pending_tx> &ptx_vector, bool blink, uint64_t lock_time_in_blocks = 0, uint64_t unlock_block = 0 ENABLE_IF_MMS(, bool called_by_mms = false));
bool transfer_main(Transfer transfer_type, const std::vector<std::string> &args ENABLE_IF_MMS(, bool called_by_mms));
bool transfer(const std::vector<std::string> &args);
bool locked_transfer(const std::vector<std::string> &args);
@ -251,23 +251,25 @@ namespace cryptonote
bool payment_id(const std::vector<std::string> &args);
bool print_fee_info(const std::vector<std::string> &args);
bool prepare_multisig(const std::vector<std::string>& args);
bool prepare_multisig_main(const std::vector<std::string>& args, bool called_by_mms);
bool prepare_multisig_main(const std::vector<std::string>& args ENABLE_IF_MMS(, bool called_by_mms));
bool make_multisig(const std::vector<std::string>& args);
bool make_multisig_main(const std::vector<std::string>& args, bool called_by_mms);
bool make_multisig_main(const std::vector<std::string>& args ENABLE_IF_MMS(, bool called_by_mms));
bool finalize_multisig(const std::vector<std::string> &args);
bool exchange_multisig_keys(const std::vector<std::string> &args);
bool exchange_multisig_keys_main(const std::vector<std::string> &args, bool called_by_mms);
bool exchange_multisig_keys_main(const std::vector<std::string> &args ENABLE_IF_MMS(, bool called_by_mms));
bool export_multisig(const std::vector<std::string>& args);
bool export_multisig_main(const std::vector<std::string>& args, bool called_by_mms);
bool export_multisig_main(const std::vector<std::string>& args ENABLE_IF_MMS(, bool called_by_mms));
bool import_multisig(const std::vector<std::string>& args);
bool import_multisig_main(const std::vector<std::string>& args, bool called_by_mms);
bool import_multisig_main(const std::vector<std::string>& args ENABLE_IF_MMS(, bool called_by_mms));
bool accept_loaded_tx(const tools::wallet2::multisig_tx_set &txs);
bool sign_multisig(const std::vector<std::string>& args);
bool sign_multisig_main(const std::vector<std::string>& args, bool called_by_mms);
bool sign_multisig_main(const std::vector<std::string>& args ENABLE_IF_MMS(, bool called_by_mms));
bool submit_multisig(const std::vector<std::string>& args);
bool submit_multisig_main(const std::vector<std::string>& args, bool called_by_mms);
bool submit_multisig_main(const std::vector<std::string>& args ENABLE_IF_MMS(, bool called_by_mms));
bool export_raw_multisig(const std::vector<std::string>& args);
#ifdef WALLET_ENABLE_MMS
bool mms(const std::vector<std::string>& args);
#endif
bool print_ring(const std::vector<std::string>& args);
bool set_ring(const std::vector<std::string>& args);
bool unset_ring(const std::vector<std::string>& args);
@ -339,7 +341,9 @@ namespace cryptonote
// idle thread workers
bool check_inactivity();
bool check_refresh(bool long_poll_trigger);
#ifdef WALLET_ENABLE_MMS
bool check_mms();
#endif
//----------------- i_wallet2_callback ---------------------
virtual void on_new_block(uint64_t height, const cryptonote::block& block);
@ -457,9 +461,11 @@ namespace cryptonote
tools::periodic_task m_inactivity_checker{std::chrono::seconds(0), true /*start_immediately*/, {80 * 1000000, 100 * 1000000}};
tools::periodic_task m_refresh_checker{std::chrono::seconds(0), true /*start_immediately*/, {90 * 1000000, 110 * 1000000}};
#ifdef WALLET_ENABLE_MMS
// MMS
tools::periodic_task m_mms_checker{std::chrono::seconds(0), true /*start_immediately*/, {90 * 1000000, 115 * 1000000}};
// MMS
mms::message_store& get_message_store() const { return m_wallet->get_message_store(); };
mms::multisig_wallet_state get_multisig_wallet_state() const { return m_wallet->get_multisig_wallet_state(); };
bool mms_active() const { return get_message_store().get_active(); };
@ -493,5 +499,6 @@ namespace cryptonote
void mms_start_auto_config(const std::vector<std::string> &args);
void mms_stop_auto_config(const std::vector<std::string> &args);
void mms_auto_config(const std::vector<std::string> &args);
#endif
};
}

View File

@ -32,11 +32,21 @@ add_library(wallet
wallet_args.cpp
ringdb.cpp
node_rpc_proxy.cpp
message_store.cpp
message_transporter.cpp
transfer_view.cpp
)
# Unmaintained wallet features, disabled by default
option(ENABLE_LIGHT_WALLET "Enable (unsupported) light wallet support" OFF)
option(ENABLE_WALLET_MMS "Enable (unsupported) monero Multisig Messaging System" OFF)
if (ENABLE_LIGHT_WALLET)
target_compile_definitions(wallet PUBLIC ENABLE_LIGHT_WALLET)
endif()
if (ENABLE_WALLET_MMS)
target_compile_definitions(wallet PUBLIC ENABLE_WALLET_MMS)
target_sources(wallet PRIVATE message_store.cpp message_transporter.cpp)
endif()
target_link_libraries(wallet
PUBLIC
multisig

View File

@ -991,15 +991,18 @@ std::string WalletImpl::keysFilename() const
}
EXPORT
bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl, bool lightWallet)
bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl ENABLE_IF_LIGHT_WALLET(, bool lightWallet))
{
clearStatus();
#ifdef ENABLE_LIGHT_WALLET
wallet()->set_light_wallet(lightWallet);
#endif
if(daemon_username != "")
m_daemon_login.emplace(daemon_username, daemon_password);
return doInit(daemon_address, upper_transaction_size_limit, use_ssl);
}
#ifdef ENABLE_LIGHT_WALLET
EXPORT
bool WalletImpl::lightWalletLogin(bool &isNewWallet) const
{
@ -1031,6 +1034,7 @@ bool WalletImpl::lightWalletImportWalletRequest(std::string &payment_id, uint64_
}
return true;
}
#endif
EXPORT
void WalletImpl::setRefreshFromBlockHeight(uint64_t refresh_from_block_height)
@ -1090,9 +1094,11 @@ uint64_t WalletImpl::blockChainHeight() const
{
// This call is thread-safe
auto& w = m_wallet_ptr;
#ifdef ENABLE_LIGHT_WALLET
if(w->light_wallet()) {
return w->get_light_wallet_scanned_block_height();
}
#endif
return w->get_blockchain_current_height();
}
EXPORT
@ -1114,9 +1120,11 @@ uint64_t WalletImpl::daemonBlockChainHeight() const
//auto w = wallet();
auto& w = m_wallet_ptr;
#ifdef ENABLE_LIGHT_WALLET
if(w->light_wallet()) {
return w->get_light_wallet_scanned_block_height();
}
#endif
if (!m_is_connected)
return 0;
std::string err;
@ -1138,9 +1146,11 @@ uint64_t WalletImpl::daemonBlockChainTargetHeight() const
//auto w = wallet();
auto& w = m_wallet_ptr;
#ifdef ENABLE_LIGHT_WALLET
if(w->light_wallet()) {
return w->get_light_wallet_blockchain_height();
}
#endif
if (!m_is_connected)
return 0;
std::string err;
@ -1623,7 +1633,7 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<std:
std::optional<uint8_t> hf_version = w->get_hard_fork_version();
if (!hf_version)
{
setStatusError(tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED);
setStatusError(tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED);
return transaction;
}
@ -2201,8 +2211,12 @@ Wallet::ConnectionStatus WalletImpl::connected() const
m_is_connected = w->check_connection(&version, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS);
if (!m_is_connected)
return Wallet::ConnectionStatus_Disconnected;
if (
#ifdef ENABLE_LIGHT_WALLET
// Version check is not implemented in light wallets nodes/wallets
if (!w->light_wallet() && version.first != rpc::VERSION.first)
!w->light_wallet() &&
#endif
version.first != rpc::VERSION.first)
return Wallet::ConnectionStatus_WrongVersion;
return Wallet::ConnectionStatus_Connected;
}
@ -2299,7 +2313,11 @@ void WalletImpl::doRefresh()
// Syncing daemon and refreshing wallet simultaneously is very resource intensive.
// Disable refresh if wallet is disconnected or daemon isn't synced.
if (w->light_wallet() || daemonSynced()) {
if (
#ifdef ENABLE_LIGHT_WALLET
w->light_wallet() ||
#endif
daemonSynced()) {
if(rescan)
w->rescan_blockchain(false);
w->refresh(trustedDaemon());

View File

@ -111,7 +111,7 @@ public:
bool store(std::string_view path) override;
std::string filename() const override;
std::string keysFilename() const override;
bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false) override;
bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false ENABLE_IF_LIGHT_WALLET(, bool lightWallet = false)) override;
bool connectToDaemon() override;
ConnectionStatus connected() const override;
void setTrustedDaemon(bool arg) override;
@ -213,8 +213,10 @@ public:
void pauseRefresh() override;
bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) override;
std::string getDefaultDataDir() const override;
#ifdef ENABLE_LIGHT_WALLET
bool lightWalletLogin(bool &isNewWallet) const override;
bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override;
#endif
bool blackballOutputs(const std::vector<std::string> &outputs, bool add) override;
bool blackballOutput(const std::string &amount, const std::string &offset) override;
bool unblackballOutput(const std::string &amount, const std::string &offset) override;

View File

@ -528,7 +528,11 @@ struct Wallet
* \param lightWallet - start wallet in light mode, connect to a openmonero compatible server.
* \return - true on success
*/
virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false) = 0;
virtual bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false
#ifdef ENABLE_LIGHT_WALLET
, bool lightWallet = false
#endif
) = 0;
/*!
* \brief createWatchOnly - Creates a watch only wallet
@ -1015,11 +1019,13 @@ struct Wallet
//! secondary key reuse mitigation
virtual void keyReuseMitigation2(bool mitigation) = 0;
#ifdef ENABLE_LIGHT_WALLET
//! Light wallet authenticate and login
virtual bool lightWalletLogin(bool &isNewWallet) const = 0;
//! Initiates a light wallet import wallet request
virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) = 0;
#endif
//! locks/unlocks the keys file; returns true on success
virtual bool lockKeysFile() = 0;

View File

@ -28,6 +28,10 @@
#pragma once
#ifndef ENABLE_WALLET_MMS
#error message_storage.h requires -DENABLE_WALLET_MMS
#endif
#include <cstdlib>
#include <string>
#include <vector>

View File

@ -27,6 +27,11 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#ifndef ENABLE_WALLET_MMS
#error message_storage.h requires -DENABLE_WALLET_MMS
#endif
#include "epee/serialization/keyvalue_serialization.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/cryptonote_boost_serialization.h"

View File

@ -288,7 +288,11 @@ struct options {
const command_line::arg_descriptor<std::string> extra_entropy = {"extra-entropy", tools::wallet2::tr("File containing extra entropy to initialize the PRNG (any data, aim for 256 bits of entropy to be useful, wihch typically means more than 256 bits of data)")};
};
void do_prepare_file_names(const fs::path& file_path, fs::path& keys_file, fs::path& wallet_file, fs::path &mms_file)
void do_prepare_file_names(const fs::path& file_path, fs::path& keys_file, fs::path& wallet_file
#ifdef WALLET_ENABLE_MMS
, fs::path &mms_file
#endif
)
{
keys_file = file_path;
wallet_file = file_path;
@ -298,7 +302,9 @@ void do_prepare_file_names(const fs::path& file_path, fs::path& keys_file, fs::p
else // provided wallet file name
keys_file += ".keys";
#ifdef WALLET_ENABLE_MMS
(mms_file = keys_file).replace_extension(".mms");
#endif
}
uint64_t calculate_fee_from_weight(byte_and_output_fees base_fees, uint64_t weight, uint64_t outputs, uint64_t fee_percent, uint64_t fee_fixed, uint64_t fee_quantization_mask)
@ -409,7 +415,9 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
wallet->init(std::move(daemon_address), std::move(login), std::move(proxy), 0, trusted_daemon);
auto ringdb_path = fs::u8path(command_line::get_arg(vm, opts.shared_ringdb_dir));
wallet->set_ring_database(ringdb_path);
#ifdef WALLET_ENABLE_MMS
wallet->get_message_store().set_options(vm);
#endif
wallet->device_name(device_name);
wallet->device_derivation_path(device_derivation_path);
wallet->m_long_poll_disabled = command_line::get_arg(vm, opts.disable_rpc_long_poll);
@ -675,20 +683,6 @@ std::pair<std::unique_ptr<tools::wallet2>, tools::password_container> generate_f
return {nullptr, tools::password_container{}};
}
std::string strjoin(const std::vector<size_t> &V, const char *sep)
{
std::stringstream ss;
bool first = true;
for (const auto &v: V)
{
if (!first)
ss << sep;
ss << std::to_string(v);
first = false;
}
return ss.str();
}
bool emplace_or_replace(std::unordered_multimap<crypto::hash, tools::wallet2::pool_payment_details> &container,
const crypto::hash &key, const tools::wallet2::pool_payment_details &pd)
{
@ -892,6 +886,12 @@ bool get_pruned_tx(const rpc::GET_TRANSACTIONS::entry &entry, cryptonote::transa
namespace tools
{
const char *wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED = tr("Could not query the current network version, try later");
const char *wallet2::ERR_MSG_NETWORK_HEIGHT_QUERY_FAILED = tr("Could not query the current network block height, try later: ");
const char *wallet2::ERR_MSG_SERVICE_NODE_LIST_QUERY_FAILED = tr("Failed to query daemon for service node list");
const char *wallet2::ERR_MSG_TOO_MANY_TXS_CONSTRUCTED = tr("Constructed too many transations, please sweep_all first");
const char *wallet2::ERR_MSG_EXCEPTION_THROWN = tr("Exception thrown, staking process could not be completed: ");
const char* wallet2::tr(const char* str) { return i18n_translate(str, "tools::wallet2"); }
gamma_picker::gamma_picker(const std::vector<uint64_t> &rct_offsets, double shape, double scale):
@ -1063,14 +1063,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_account_public_address{crypto::null_pkey, crypto::null_pkey},
m_subaddress_lookahead_major(SUBADDRESS_LOOKAHEAD_MAJOR),
m_subaddress_lookahead_minor(SUBADDRESS_LOOKAHEAD_MINOR),
m_light_wallet(false),
m_light_wallet_scanned_block_height(0),
m_light_wallet_blockchain_height(0),
m_light_wallet_connected(false),
m_light_wallet_balance(0),
m_light_wallet_unlocked_balance(0),
m_original_keys_available(false),
m_message_store(),
m_key_device_type(hw::device::device_type::SOFTWARE),
m_ring_history_saved(false),
m_ringdb(),
@ -1154,7 +1147,9 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.regtest);
command_line::add_arg(desc_params, opts.shared_ringdb_dir);
command_line::add_arg(desc_params, opts.kdf_rounds);
#ifdef WALLET_ENABLE_MMS
mms::message_store::init_options(desc_params);
#endif
command_line::add_arg(desc_params, opts.hw_device);
command_line::add_arg(desc_params, opts.hw_device_derivation_path);
command_line::add_arg(desc_params, opts.tx_notify);
@ -1822,6 +1817,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
if (!tx.is_transfer() || tx.version <= txversion::v1)
return;
MERROR("PROC NEW TX " << txid);
PERF_TIMER(process_new_transaction);
// In this function, tx (probably) only contains the base information
// (that is, the prunable stuff may or may not be included)
@ -2116,6 +2112,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
error::wallet_internal_error,
"Sanity check failed: An output replacing a unmined blink output must not be from the pool.");
LOG_ERROR(+transfer.m_spent << " || " << transfer.amount() << " >= " << tx_scan_info[o].amount);
if (transfer.m_spent || transfer.amount() >= tx_scan_info[o].amount)
{
if (transfer.amount() > tx_scan_info[o].amount)
@ -3428,38 +3425,6 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
return;
}
if(m_light_wallet) {
// MyMonero get_address_info needs to be called occasionally to trigger wallet sync.
// This call is not really needed for other purposes and can be removed if mymonero changes their backend.
light_rpc::GET_ADDRESS_INFO::response res{};
// Get basic info
if(light_wallet_get_address_info(res)) {
// Last stored block height
uint64_t prev_height = m_light_wallet_blockchain_height;
// Update lw heights
m_light_wallet_scanned_block_height = res.scanned_block_height;
m_light_wallet_blockchain_height = res.blockchain_height;
// If new height - call new_block callback
if(m_light_wallet_blockchain_height != prev_height)
{
MDEBUG("new block since last time!");
m_callback->on_lw_new_block(m_light_wallet_blockchain_height - 1);
}
m_light_wallet_connected = true;
MDEBUG("lw scanned block height: " << m_light_wallet_scanned_block_height);
MDEBUG("lw blockchain height: " << m_light_wallet_blockchain_height);
MDEBUG(m_light_wallet_blockchain_height-m_light_wallet_scanned_block_height << " blocks behind");
// TODO: add wallet created block info
light_wallet_get_address_txs();
} else
m_light_wallet_connected = false;
// Lighwallet refresh done
return;
}
received_money = false;
blocks_fetched = 0;
uint64_t added_blocks = 0;
@ -5572,8 +5537,13 @@ void wallet2::write_watch_only_wallet(const fs::path& wallet_name, const epee::w
//----------------------------------------------------------------------------------------------------
void wallet2::wallet_exists(const fs::path& file_path, bool& keys_file_exists, bool& wallet_file_exists)
{
fs::path keys_file, wallet_file, mms_file;
do_prepare_file_names(file_path, keys_file, wallet_file, mms_file);
fs::path keys_file, wallet_file;
[[maybe_unused]] fs::path mms_file;
do_prepare_file_names(file_path, keys_file, wallet_file
#ifdef WALLET_ENABLE_MMS
, mms_file
#endif
);
std::error_code ignore;
keys_file_exists = fs::exists(keys_file, ignore);
@ -5596,7 +5566,11 @@ bool wallet2::parse_payment_id(std::string_view payment_id_str, crypto::hash& pa
//----------------------------------------------------------------------------------------------------
bool wallet2::prepare_file_names(const fs::path& file_path)
{
do_prepare_file_names(file_path, m_keys_file, m_wallet_file, m_mms_file);
do_prepare_file_names(file_path, m_keys_file, m_wallet_file
#ifdef WALLET_ENABLE_MMS
, m_mms_file
#endif
);
return true;
}
//----------------------------------------------------------------------------------------------------
@ -5615,15 +5589,6 @@ bool wallet2::check_connection(rpc::version_t *version, bool *ssl, bool throw_on
return false;
}
// TODO: Add light wallet version check.
if(m_light_wallet) {
m_rpc_version = 0;
if (version)
*version = {};
if (ssl)
*ssl = m_light_wallet_connected; // light wallet is always SSL
return m_light_wallet_connected;
}
if (ssl)
*ssl = tools::starts_with(m_http_client.get_base_url(), "https://");
@ -5821,6 +5786,7 @@ void wallet2::load(const fs::path& wallet_, const epee::wipeable_string& passwor
MERROR("Failed to save rings, will try again next time");
}
#ifdef WALLET_ENABLE_MMS
try
{
if (use_fs)
@ -5830,6 +5796,7 @@ void wallet2::load(const fs::path& wallet_, const epee::wipeable_string& passwor
{
MERROR("Failed to initialize MMS, it will be unusable");
}
#endif
}
//----------------------------------------------------------------------------------------------------
void wallet2::trim_hashchain()
@ -5916,7 +5883,6 @@ void wallet2::store_to(const fs::path &path, const epee::wipeable_string &passwo
const auto& old_keys_file = m_keys_file;
fs::path old_address_file = m_wallet_file;
old_address_file += ".address.txt";
const auto& old_mms_file = m_mms_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
@ -5941,9 +5907,11 @@ void wallet2::store_to(const fs::path &path, const epee::wipeable_string &passwo
// remove old keys file
if (!fs::remove(old_keys_file, ec))
LOG_ERROR("error removing file: " << old_keys_file << ": " << ec.message());
#ifdef WALLET_ENABLE_MMS
// remove old message store file
if (fs::exists(old_mms_file, ec) && !fs::remove(old_mms_file, ec))
LOG_ERROR("error removing file: " << old_mms_file << ": " << ec.message());
if (fs::exists(m_mms_file, ec) && !fs::remove(m_mms_file, ec))
LOG_ERROR("error removing file: " << m_mms_file << ": " << ec.message());
#endif
} else {
// save to new file
fs::path new_file = m_wallet_file;
@ -5969,12 +5937,14 @@ void wallet2::store_to(const fs::path &path, const epee::wipeable_string &passwo
THROW_WALLET_EXCEPTION_IF(e, error::file_save_error, m_wallet_file, e);
}
#ifdef WALLET_ENABLE_MMS
if (m_message_store.get_active())
{
// While the "m_message_store" object of course always exist, a file for the message
// store should only exist if the MMS is really active
m_message_store.write_to_file(get_multisig_wallet_state(), m_mms_file);
}
#endif
}
//----------------------------------------------------------------------------------------------------
std::optional<wallet2::cache_file_data> wallet2::get_cache_file_data(const epee::wipeable_string &passwords)
@ -6004,8 +5974,10 @@ std::optional<wallet2::cache_file_data> wallet2::get_cache_file_data(const epee:
uint64_t wallet2::balance(uint32_t index_major, bool strict) const
{
uint64_t amount = 0;
#ifdef ENABLE_LIGHT_WALLET
if(m_light_wallet)
return m_light_wallet_unlocked_balance;
#endif
for (const auto& i : balance_per_subaddress(index_major, strict))
amount += i.second;
return amount;
@ -6018,8 +5990,10 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *
*blocks_to_unlock = 0;
if (time_to_unlock)
*time_to_unlock = 0;
#ifdef ENABLE_LIGHT_WALLET
if(m_light_wallet)
return m_light_wallet_balance;
#endif
for (const auto& i : unlocked_balance_per_subaddress(index_major, strict))
{
amount += i.second.first;
@ -6962,6 +6936,7 @@ crypto::hash wallet2::get_payment_id(const pending_tx &ptx) const
// take a pending tx and actually send it to the daemon
void wallet2::commit_tx(pending_tx& ptx, bool blink)
{
#ifdef ENABLE_LIGHT_WALLET
if(m_light_wallet)
{
light_rpc::SUBMIT_RAW_TX::request oreq{};
@ -6975,6 +6950,9 @@ void wallet2::commit_tx(pending_tx& ptx, bool blink)
// MyMonero and OpenMonero use different status strings
THROW_WALLET_EXCEPTION_IF(ores.status != "OK" && ores.status != "success" , error::tx_rejected, ptx.tx, get_rpc_status(ores.status), ores.error);
}
#else
if (false) {}
#endif
else
{
// Normal submit
@ -7833,10 +7811,12 @@ byte_and_output_fees wallet2::get_base_fees() const
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::get_fee_quantization_mask() const
{
#ifdef ENABLE_LIGHT_WALLET
if(m_light_wallet)
{
return 1; // TODO
}
#endif
uint64_t fee_quantization_mask;
if (m_node_rpc_proxy.get_fee_quantization_mask(fee_quantization_mask))
@ -9118,109 +9098,6 @@ bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_out
return true;
}
void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count) {
MDEBUG("LIGHTWALLET - Getting random outs");
light_rpc::GET_RANDOM_OUTS::request oreq{};
light_rpc::GET_RANDOM_OUTS::response ores{};
size_t light_wallet_requested_outputs_count = (size_t)((fake_outputs_count + 1) * 1.5 + 1);
// Amounts to ask for
// MyMonero api handle amounts and fees as strings
for(size_t idx: selected_transfers) {
const uint64_t ask_amount = m_transfers[idx].is_rct() ? 0 : m_transfers[idx].amount();
std::ostringstream amount_ss;
amount_ss << ask_amount;
oreq.amounts.push_back(amount_ss.str());
}
oreq.count = light_wallet_requested_outputs_count;
bool r = invoke_http<light_rpc::GET_RANDOM_OUTS>(oreq, ores);
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_random_outs");
THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs received from light wallet node. Error: " + ores.Error);
// Check if we got enough outputs for each amount
for(auto& out: ores.amount_outs) {
const uint64_t out_amount = boost::lexical_cast<uint64_t>(out.amount);
THROW_WALLET_EXCEPTION_IF(out.outputs.size() < light_wallet_requested_outputs_count , error::wallet_internal_error, "Not enough outputs for amount: " + boost::lexical_cast<std::string>(out.amount));
MDEBUG(out.outputs.size() << " outputs for amount "+ boost::lexical_cast<std::string>(out.amount) + " received from light wallet node");
}
MDEBUG("selected transfers size: " << selected_transfers.size());
for(size_t idx: selected_transfers)
{
// Create new index
outs.push_back(std::vector<get_outs_entry>());
outs.back().reserve(fake_outputs_count + 1);
// add real output first
const transfer_details &td = m_transfers[idx];
const uint64_t amount = td.is_rct() ? 0 : td.amount();
outs.back().push_back(std::make_tuple(td.m_global_output_index, td.get_public_key(), rct::commit(td.amount(), td.m_mask)));
MDEBUG("added real output " << tools::type_to_hex(td.get_public_key()));
// Even if the lightwallet server returns random outputs, we pick them randomly.
std::vector<size_t> order;
order.resize(light_wallet_requested_outputs_count);
for (size_t n = 0; n < order.size(); ++n)
order[n] = n;
std::shuffle(order.begin(), order.end(), crypto::random_device{});
LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs with amounts " << print_money(td.is_rct() ? 0 : td.amount()));
MDEBUG("OUTS SIZE: " << outs.back().size());
for (size_t o = 0; o < light_wallet_requested_outputs_count && outs.back().size() < fake_outputs_count + 1; ++o)
{
// Random pick
size_t i = order[o];
// Find which random output key to use
bool found_amount = false;
size_t amount_key;
for(amount_key = 0; amount_key < ores.amount_outs.size(); ++amount_key)
{
if(boost::lexical_cast<uint64_t>(ores.amount_outs[amount_key].amount) == amount) {
found_amount = true;
break;
}
}
THROW_WALLET_EXCEPTION_IF(!found_amount , error::wallet_internal_error, "Outputs for amount " + boost::lexical_cast<std::string>(ores.amount_outs[amount_key].amount) + " not found" );
LOG_PRINT_L2("Index " << i << "/" << light_wallet_requested_outputs_count << ": idx " << ores.amount_outs[amount_key].outputs[i].global_index << " (real " << td.m_global_output_index << "), unlocked " << "(always in light)" << ", key " << ores.amount_outs[0].outputs[i].public_key);
// Convert light wallet string data to proper data structures
crypto::public_key tx_public_key;
rct::key mask{}; // decrypted mask - not used here
rct::key rct_commit{};
const auto& pkey = ores.amount_outs[amount_key].outputs[i].public_key;
THROW_WALLET_EXCEPTION_IF(pkey.size() != 64 || !oxenmq::is_hex(pkey), error::wallet_internal_error, "Invalid public_key");
tools::hex_to_type(ores.amount_outs[amount_key].outputs[i].public_key, tx_public_key);
const uint64_t global_index = ores.amount_outs[amount_key].outputs[i].global_index;
if(!light_wallet_parse_rct_str(ores.amount_outs[amount_key].outputs[i].rct, tx_public_key, 0, mask, rct_commit, false))
rct_commit = rct::zeroCommit(td.amount());
if (tx_add_fake_output(outs, global_index, tx_public_key, rct_commit, td.m_global_output_index, true)) {
MDEBUG("added fake output " << ores.amount_outs[amount_key].outputs[i].public_key);
MDEBUG("index " << global_index);
}
}
THROW_WALLET_EXCEPTION_IF(outs.back().size() < fake_outputs_count + 1 , error::wallet_internal_error, "Not enough fake outputs found" );
// Real output is the first. Shuffle outputs
MTRACE(outs.back().size() << " outputs added. Sorting outputs by index:");
std::sort(outs.back().begin(), outs.back().end(), [](const get_outs_entry &a, const get_outs_entry &b) { return std::get<0>(a) < std::get<0>(b); });
// Print output order
for(auto added_out: outs.back())
MTRACE(std::get<0>(added_out));
}
}
std::pair<std::set<uint64_t>, size_t> outs_unique(const std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs)
{
std::set<uint64_t> unique;
@ -9268,10 +9145,12 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
LOG_PRINT_L2("fake_outputs_count: " << fake_outputs_count);
outs.clear();
#ifdef ENABLE_LIGHT_WALLET
if(m_light_wallet && fake_outputs_count > 0) {
light_wallet_get_outs(outs, selected_transfers, fake_outputs_count);
return;
}
#endif
if (fake_outputs_count > 0)
{
@ -9897,7 +9776,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
uint64_t upper_transaction_weight_limit = get_upper_transaction_weight_limit();
uint64_t needed_money = fee;
LOG_PRINT_L2("transfer_selected_rct: starting with fee " << print_money (needed_money));
LOG_PRINT_L2("selected transfers: " << strjoin(selected_transfers, " "));
LOG_PRINT_L2("selected transfers: " << tools::join(" ", selected_transfers));
// calculate total amount being sent to all destinations
// throw if total amount overflows uint64_t
@ -10360,6 +10239,110 @@ static uint32_t get_count_above(const std::vector<wallet2::transfer_details> &tr
return count;
}
#ifdef ENABLE_LIGHT_WALLET
void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count) {
MDEBUG("LIGHTWALLET - Getting random outs");
light_rpc::GET_RANDOM_OUTS::request oreq{};
light_rpc::GET_RANDOM_OUTS::response ores{};
size_t light_wallet_requested_outputs_count = (size_t)((fake_outputs_count + 1) * 1.5 + 1);
// Amounts to ask for
// MyMonero api handle amounts and fees as strings
for(size_t idx: selected_transfers) {
const uint64_t ask_amount = m_transfers[idx].is_rct() ? 0 : m_transfers[idx].amount();
std::ostringstream amount_ss;
amount_ss << ask_amount;
oreq.amounts.push_back(amount_ss.str());
}
oreq.count = light_wallet_requested_outputs_count;
bool r = invoke_http<light_rpc::GET_RANDOM_OUTS>(oreq, ores);
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_random_outs");
THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs received from light wallet node. Error: " + ores.Error);
// Check if we got enough outputs for each amount
for(auto& out: ores.amount_outs) {
const uint64_t out_amount = boost::lexical_cast<uint64_t>(out.amount);
THROW_WALLET_EXCEPTION_IF(out.outputs.size() < light_wallet_requested_outputs_count , error::wallet_internal_error, "Not enough outputs for amount: " + boost::lexical_cast<std::string>(out.amount));
MDEBUG(out.outputs.size() << " outputs for amount "+ boost::lexical_cast<std::string>(out.amount) + " received from light wallet node");
}
MDEBUG("selected transfers size: " << selected_transfers.size());
for(size_t idx: selected_transfers)
{
// Create new index
outs.push_back(std::vector<get_outs_entry>());
outs.back().reserve(fake_outputs_count + 1);
// add real output first
const transfer_details &td = m_transfers[idx];
const uint64_t amount = td.is_rct() ? 0 : td.amount();
outs.back().push_back(std::make_tuple(td.m_global_output_index, td.get_public_key(), rct::commit(td.amount(), td.m_mask)));
MDEBUG("added real output " << tools::type_to_hex(td.get_public_key()));
// Even if the lightwallet server returns random outputs, we pick them randomly.
std::vector<size_t> order;
order.resize(light_wallet_requested_outputs_count);
for (size_t n = 0; n < order.size(); ++n)
order[n] = n;
std::shuffle(order.begin(), order.end(), crypto::random_device{});
LOG_PRINT_L2("Looking for " << (fake_outputs_count+1) << " outputs with amounts " << print_money(td.is_rct() ? 0 : td.amount()));
MDEBUG("OUTS SIZE: " << outs.back().size());
for (size_t o = 0; o < light_wallet_requested_outputs_count && outs.back().size() < fake_outputs_count + 1; ++o)
{
// Random pick
size_t i = order[o];
// Find which random output key to use
bool found_amount = false;
size_t amount_key;
for(amount_key = 0; amount_key < ores.amount_outs.size(); ++amount_key)
{
if(boost::lexical_cast<uint64_t>(ores.amount_outs[amount_key].amount) == amount) {
found_amount = true;
break;
}
}
THROW_WALLET_EXCEPTION_IF(!found_amount , error::wallet_internal_error, "Outputs for amount " + boost::lexical_cast<std::string>(ores.amount_outs[amount_key].amount) + " not found" );
LOG_PRINT_L2("Index " << i << "/" << light_wallet_requested_outputs_count << ": idx " << ores.amount_outs[amount_key].outputs[i].global_index << " (real " << td.m_global_output_index << "), unlocked " << "(always in light)" << ", key " << ores.amount_outs[0].outputs[i].public_key);
// Convert light wallet string data to proper data structures
crypto::public_key tx_public_key;
rct::key mask{}; // decrypted mask - not used here
rct::key rct_commit{};
const auto& pkey = ores.amount_outs[amount_key].outputs[i].public_key;
THROW_WALLET_EXCEPTION_IF(pkey.size() != 64 || !oxenmq::is_hex(pkey), error::wallet_internal_error, "Invalid public_key");
tools::hex_to_type(ores.amount_outs[amount_key].outputs[i].public_key, tx_public_key);
const uint64_t global_index = ores.amount_outs[amount_key].outputs[i].global_index;
if(!light_wallet_parse_rct_str(ores.amount_outs[amount_key].outputs[i].rct, tx_public_key, 0, mask, rct_commit, false))
rct_commit = rct::zeroCommit(td.amount());
if (tx_add_fake_output(outs, global_index, tx_public_key, rct_commit, td.m_global_output_index, true)) {
MDEBUG("added fake output " << ores.amount_outs[amount_key].outputs[i].public_key);
MDEBUG("index " << global_index);
}
}
THROW_WALLET_EXCEPTION_IF(outs.back().size() < fake_outputs_count + 1 , error::wallet_internal_error, "Not enough fake outputs found" );
// Real output is the first. Shuffle outputs
MTRACE(outs.back().size() << " outputs added. Sorting outputs by index:");
std::sort(outs.back().begin(), outs.back().end(), [](const get_outs_entry &a, const get_outs_entry &b) { return std::get<0>(a) < std::get<0>(b); });
// Print output order
for(auto added_out: outs.back())
MTRACE(std::get<0>(added_out));
}
}
bool wallet2::light_wallet_login(bool &new_address)
{
MDEBUG("Light wallet login request");
@ -10825,6 +10808,7 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image,
m_key_image_cache.emplace(tx_public_key, index_keyimage_map);
return key_image == calculated_key_image;
}
#endif
// Another implementation of transaction creation that is hopefully better
// While there is anything left to pay, it goes through random outputs and tries
@ -10856,14 +10840,16 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
dsts.emplace_back(0, account_public_address{} /*address*/, false /*is_subaddress*/); // NOTE: Create a dummy dest that gets repurposed into the change output.
}
#ifdef ENABLE_LIGHT_WALLET
if(m_light_wallet) {
// Populate m_transfers
light_wallet_get_unspent_outs();
}
#endif
std::vector<std::pair<uint32_t, std::vector<size_t>>> unused_transfers_indices_per_subaddr;
std::vector<std::pair<uint32_t, std::vector<size_t>>> unused_dust_indices_per_subaddr;
uint64_t needed_money;
uint64_t accumulated_fee, accumulated_outputs, accumulated_change;
uint64_t accumulated_fee, accumulated_change;
struct TX {
std::vector<size_t> selected_transfers;
std::vector<cryptonote::tx_destination_entry> dsts;
@ -11061,7 +11047,6 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// start with an empty tx
txes.push_back(TX());
accumulated_fee = 0;
accumulated_outputs = 0;
accumulated_change = 0;
adding_fee = false;
needed_fee = 0;
@ -11074,8 +11059,6 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// the destination, and one for change.
LOG_PRINT_L2("checking preferred");
std::vector<size_t> preferred_inputs;
uint64_t rct_outs_needed = 2 * (fake_outs_count + 1);
rct_outs_needed += 100; // some fudge factor since we don't know how many are locked
{
// this is used to build a tx that's 1 or 2 inputs, and 1 or 2 outputs, which will get us a known fee.
uint64_t estimated_fee = estimate_fee(2, fake_outs_count, min_outputs, extra.size(), clsag, base_fee, fee_percent, fixed_fee, fee_quantization_mask);
@ -11121,8 +11104,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
TX &tx = txes.back();
LOG_PRINT_L2("Start of loop with " << unused_transfers_indices->size() << " " << unused_dust_indices->size() << ", tx.dsts.size() " << tx.dsts.size());
LOG_PRINT_L2("unused_transfers_indices: " << strjoin(*unused_transfers_indices, " "));
LOG_PRINT_L2("unused_dust_indices: " << strjoin(*unused_dust_indices, " "));
LOG_PRINT_L2("unused_transfers_indices: " << tools::join(" ", *unused_transfers_indices));
LOG_PRINT_L2("unused_dust_indices: " << tools::join(" ", *unused_dust_indices));
LOG_PRINT_L2("dsts size " << dsts.size() << ", first " << (dsts.empty() ? "-" : cryptonote::print_money(dsts[0].amount)));
LOG_PRINT_L2("adding_fee " << adding_fee);
@ -11183,7 +11166,6 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// add this output to the list to spend
tx.selected_transfers.push_back(idx);
uint64_t available_amount = td.amount();
accumulated_outputs += available_amount;
// clear any fake outs we'd already gathered, since we'll need a new set
outs.clear();
@ -11851,9 +11833,11 @@ void wallet2::get_hard_fork_info(uint8_t version, uint64_t &earliest_height) con
//----------------------------------------------------------------------------------------------------
bool wallet2::use_fork_rules(uint8_t version, uint64_t early_blocks) const
{
#ifdef ENABLE_LIGHT_WALLET
// TODO: How to get fork rule info from light wallet node?
if(m_light_wallet)
return true;
#endif
uint64_t height, earliest_height{0};
if (!m_node_rpc_proxy.get_height(height))
THROW_WALLET_EXCEPTION(tools::error::no_connection_to_daemon, __func__);
@ -14410,9 +14394,7 @@ std::string wallet2::make_uri(const std::string &address, const std::string &pay
return uri;
}
namespace {
std::string uri_decode(std::string_view encoded)
static std::string uri_decode(std::string_view encoded)
{
std::string decoded;
for (auto it = encoded.begin(); it != encoded.end(); )
@ -14428,8 +14410,6 @@ std::string uri_decode(std::string_view encoded)
return decoded;
}
}
//----------------------------------------------------------------------------------------------------
bool wallet2::parse_uri(std::string_view uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error)
{
@ -14678,6 +14658,7 @@ bool wallet2::generate_signature_for_request_stake_unlock(const crypto::key_imag
error::wallet_internal_error, "Hardware device failed to sign the unlock request");
return true;
}
#ifdef WALLET_ENABLE_MMS
//----------------------------------------------------------------------------------------------------
mms::multisig_wallet_state wallet2::get_multisig_wallet_state() const
{
@ -14701,6 +14682,7 @@ mms::multisig_wallet_state wallet2::get_multisig_wallet_state() const
state.mms_file=m_mms_file;
return state;
}
#endif
//----------------------------------------------------------------------------------------------------
wallet_device_callback * wallet2::get_device_callback()
{

View File

@ -60,8 +60,22 @@
#include "wallet_errors.h"
#include "common/password.h"
#include "node_rpc_proxy.h"
#ifdef WALLET_ENABLE_MMS
#include "message_store.h"
// Intended to make the ifdefs a bit less cumbersome where we need to pass an extra arg with MMS.
// E.g. `foo(a, b IF_MMS(, c))` becomes `foo(a, b, c)` undef MMS and `foo(a,b)` without MMS.
#define ENABLE_IF_MMS(...) __VA_ARGS__
#else
#define ENABLE_IF_MMS(...)
#endif
#ifdef ENABLE_LIGHT_WALLET
#include "wallet_light_rpc.h"
// Same as above, but for light wallet args
#define ENABLE_IF_LIGHT_WALLET(...) __VA_ARGS__
#else
#define ENABLE_IF_LIGHT_WALLET(...)
#endif
#include "tx_construction_data.h"
#include "tx_sets.h"
@ -88,12 +102,6 @@ class wallet_accessor_test;
OXEN_RPC_DOC_INTROSPECT
namespace tools
{
static const char *ERR_MSG_NETWORK_VERSION_QUERY_FAILED = tr("Could not query the current network version, try later");
static const char *ERR_MSG_NETWORK_HEIGHT_QUERY_FAILED = tr("Could not query the current network block height, try later: ");
static const char *ERR_MSG_SERVICE_NODE_LIST_QUERY_FAILED = tr("Failed to query daemon for service node list");
static const char *ERR_MSG_TOO_MANY_TXS_CONSTRUCTED = tr("Constructed too many transations, please sweep_all first");
static const char *ERR_MSG_EXCEPTION_THROWN = tr("Exception thrown, staking process could not be completed: ");
class ringdb;
class wallet2;
class Notify;
@ -256,6 +264,11 @@ private:
};
static const char* tr(const char* str);
static const char *ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
static const char *ERR_MSG_NETWORK_HEIGHT_QUERY_FAILED;
static const char *ERR_MSG_SERVICE_NODE_LIST_QUERY_FAILED;
static const char *ERR_MSG_TOO_MANY_TXS_CONSTRUCTED;
static const char *ERR_MSG_EXCEPTION_THROWN;
static bool has_testnet_option(const boost::program_options::variables_map& vm);
static bool has_devnet_option(const boost::program_options::variables_map& vm);
@ -648,7 +661,12 @@ private:
std::string proxy = "",
bool trusted_daemon = true);
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
void stop() {
m_run.store(false, std::memory_order_relaxed);
#ifdef WALLET_ENABLE_MMS
m_message_store.stop();
#endif
}
i_wallet2_callback* callback() const { return m_callback; }
void callback(i_wallet2_callback* callback) { m_callback = callback; }
@ -662,6 +680,7 @@ private:
bool is_deterministic() const;
bool get_seed(epee::wipeable_string& electrum_words, const epee::wipeable_string &passphrase = epee::wipeable_string()) const;
#ifdef ENABLE_LIGHT_WALLET
/*!
* \brief Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned.
*/
@ -669,6 +688,7 @@ private:
void set_light_wallet(bool light_wallet) { m_light_wallet = light_wallet; }
uint64_t get_light_wallet_scanned_block_height() const { return m_light_wallet_scanned_block_height; }
uint64_t get_light_wallet_blockchain_height() const { return m_light_wallet_blockchain_height; }
#endif
/*!
* \brief Gets the seed language
@ -1232,6 +1252,7 @@ private:
bool is_unattended() const { return m_unattended; }
#ifdef ENABLE_LIGHT_WALLET
// Light wallet specific functions
// fetch unspent outs from lw node and store in m_transfers
void light_wallet_get_unspent_outs();
@ -1249,6 +1270,7 @@ private:
bool light_wallet_parse_rct_str(const std::string& rct_string, const crypto::public_key& tx_pub_key, uint64_t internal_output_index, rct::key& decrypted_mask, rct::key& rct_commit, bool decrypt) const;
// check if key image is ours
bool light_wallet_key_image_is_ours(const crypto::key_image& key_image, const crypto::public_key& tx_public_key, uint64_t out_index);
#endif
/*
* "attributes" are a mechanism to store an arbitrary number of string values
@ -1278,7 +1300,11 @@ private:
bool invoke_http(const typename RPC::request& req, typename RPC::response& res, bool throw_on_error = false)
{
using namespace cryptonote::rpc;
static_assert(std::is_base_of_v<RPC_COMMAND, RPC> || std::is_base_of_v<tools::light_rpc::LIGHT_RPC_COMMAND, RPC>);
static_assert(std::is_base_of_v<RPC_COMMAND, RPC>
#ifdef ENABLE_LIGHT_WALLET
|| std::is_base_of_v<tools::light_rpc::LIGHT_RPC_COMMAND, RPC>
#endif
);
if (m_offline) return false;
@ -1426,10 +1452,12 @@ private:
uint64_t get_bytes_sent() const;
uint64_t get_bytes_received() const;
#ifdef WALLET_ENABLE_MMS
// MMS -------------------------------------------------------------------------------------------------
mms::message_store& get_message_store() { return m_message_store; };
const mms::message_store& get_message_store() const { return m_message_store; };
mms::multisig_wallet_state get_multisig_wallet_state() const;
#endif
bool lock_keys_file();
bool unlock_keys_file();
@ -1575,7 +1603,9 @@ private:
cryptonote::account_base m_account;
fs::path m_wallet_file;
fs::path m_keys_file;
#ifdef WALLET_ENABLE_MMS
fs::path m_mms_file;
#endif
hashchain m_blockchain;
std::atomic<uint64_t> m_cached_height; // Tracks m_blockchain.size(), but thread-safe.
std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs;
@ -1661,6 +1691,7 @@ private:
// Aux transaction data from device
std::unordered_map<crypto::hash, std::string> m_tx_device;
#ifdef ENABLE_LIGHT_WALLET
// Light wallet
bool m_light_wallet; /* sends view key to daemon for scanning */
uint64_t m_light_wallet_scanned_block_height;
@ -1672,6 +1703,9 @@ private:
// Light wallet info needed to populate m_payment requires 2 separate api calls (get_address_txs and get_unspent_outs)
// We save the info from the first call in m_light_wallet_address_txs for easier lookup.
std::unordered_map<crypto::hash, address_tx> m_light_wallet_address_txs;
#endif
// FIXME should this be with the light wallet stuff?
// store calculated key image for faster lookup
std::unordered_map<crypto::public_key, std::map<uint64_t, crypto::key_image> > m_key_image_cache;
@ -1683,7 +1717,9 @@ private:
uint64_t m_last_block_reward;
std::unique_ptr<tools::file_locker> m_keys_file_locker;
#ifdef WALLET_ENABLE_MMS
mms::message_store m_message_store;
#endif
bool m_original_keys_available;
cryptonote::account_public_address m_original_address;
crypto::secret_key m_original_view_secret_key;

View File

@ -1048,7 +1048,7 @@ namespace tools
uint32_t priority = convert_priority(req.priority);
std::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
if (!hf_version)
throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
cryptonote::oxen_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, cryptonote::txtype::standard, priority);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, CRYPTONOTE_DEFAULT_TX_MIXIN, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, tx_params);
@ -1082,7 +1082,7 @@ namespace tools
uint32_t priority = convert_priority(req.priority);
std::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
if (!hf_version)
throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
cryptonote::oxen_construct_tx_params tx_params = tools::wallet2::construct_params(*hf_version, cryptonote::txtype::standard, priority);
LOG_PRINT_L2("on_transfer_split calling create_transactions_2");
@ -3233,7 +3233,7 @@ namespace {
std::string reason;
ons::mapping_type type;
std::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
if (!ons::validate_mapping_type(req.type, *hf_version, ons::ons_tx_type::update, &type, &reason))
throw wallet_rpc_error{error_code::WRONG_ONS_TYPE, "Wrong ons type given=" + reason};
@ -3260,7 +3260,7 @@ namespace {
std::string reason;
ons::mapping_type type;
std::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
if (!ons::validate_mapping_type(req.type, *hf_version, ons::ons_tx_type::lookup, &type, &reason))
throw wallet_rpc_error{error_code::WRONG_ONS_TYPE, "Wrong ons type given=" + reason};
@ -3368,7 +3368,7 @@ namespace {
require_open();
std::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
std::string reason;
for (auto& rec : req.names)
@ -3415,7 +3415,7 @@ namespace {
ons::mapping_type type = {};
std::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
{
if (!ons::validate_mapping_type(req.type, *hf_version, ons::ons_tx_type::lookup, &type, &reason))
throw wallet_rpc_error{error_code::WRONG_ONS_TYPE, "Invalid ONS type: " + reason};
@ -3450,7 +3450,7 @@ namespace {
std::string reason;
std::optional<uint8_t> hf_version = m_wallet->get_hard_fork_version();
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
if (!hf_version) throw wallet_rpc_error{error_code::HF_QUERY_FAILED, tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED};
ons::mapping_type type;
if (!ons::validate_mapping_type(req.type, *hf_version, ons::ons_tx_type::lookup, &type, &reason))