mirror of
https://github.com/monero-project/monero.git
synced 2025-08-08 13:52:20 -04:00
wallet: background sync with just the view key
- When background syncing, the wallet wipes the spend key from memory and processes all new transactions. The wallet saves all receives, spends, and "plausible" spends of receives the wallet does not know key images for. - When background sync disabled, the wallet processes all background synced txs and then clears the background sync cache. - Adding "plausible" spends to the background sync cache ensures that the wallet does not need to query the daemon to see if any received outputs were spent while background sync was enabled. This would harm privacy especially for users of 3rd party daemons. - To enable the feature in the CLI wallet, the user can set background-sync to reuse-wallet-password or custom-background-password and the wallet automatically syncs in the background when the wallet locks, then processes all background synced txs when the wallet is unlocked. - The custom-background-password option enables the user to open a distinct background wallet that only has a view key saved and can be opened/closed/synced separately from the main wallet. When the main wallet opens, it processes the background wallet's cache. - To enable the feature in the RPC wallet, there is a new `/setup_background_sync` endpoint. - HW, multsig and view-only wallets cannot background sync.
This commit is contained in:
parent
cc73fe7116
commit
e71c8bf190
20 changed files with 2340 additions and 132 deletions
|
@ -73,6 +73,54 @@ using namespace epee;
|
|||
} \
|
||||
} while(0)
|
||||
|
||||
#define CHECK_IF_BACKGROUND_SYNCING() \
|
||||
do \
|
||||
{ \
|
||||
if (!m_wallet) { return not_open(er); } \
|
||||
if (m_wallet->is_background_wallet()) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_IS_BACKGROUND_WALLET; \
|
||||
er.message = "This command is disabled for background wallets."; \
|
||||
return false; \
|
||||
} \
|
||||
if (m_wallet->is_background_syncing()) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_IS_BACKGROUND_SYNCING; \
|
||||
er.message = "This command is disabled while background syncing. Stop background syncing to use this command."; \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define PRE_VALIDATE_BACKGROUND_SYNC() \
|
||||
do \
|
||||
{ \
|
||||
if (!m_wallet) { return not_open(er); } \
|
||||
if (m_restricted) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED; \
|
||||
er.message = "Command unavailable in restricted mode."; \
|
||||
return false; \
|
||||
} \
|
||||
if (m_wallet->key_on_device()) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; \
|
||||
er.message = "Command not supported by HW wallet"; \
|
||||
return false; \
|
||||
} \
|
||||
if (m_wallet->get_multisig_status().multisig_is_active) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; \
|
||||
er.message = "Multisig wallet cannot enable background sync"; \
|
||||
return false; \
|
||||
} \
|
||||
if (m_wallet->watch_only()) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_WATCH_ONLY; \
|
||||
er.message = "Watch-only wallet cannot enable background sync"; \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
namespace
|
||||
{
|
||||
const command_line::arg_descriptor<std::string, true> arg_rpc_bind_port = {"rpc-bind-port", "Sets bind port for server"};
|
||||
|
@ -291,6 +339,9 @@ namespace tools
|
|||
{
|
||||
if (!m_wallet)
|
||||
return;
|
||||
// Background mining can be toggled from the main wallet
|
||||
if (m_wallet->is_background_wallet() || m_wallet->is_background_syncing())
|
||||
return;
|
||||
|
||||
tools::wallet2::BackgroundMiningSetupType setup = m_wallet->setup_background_mining();
|
||||
if (setup == tools::wallet2::BackgroundMiningNo)
|
||||
|
@ -581,6 +632,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_create_address(const wallet_rpc::COMMAND_RPC_CREATE_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_CREATE_ADDRESS::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
if (req.count < 1 || req.count > 65536) {
|
||||
|
@ -618,6 +670,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_label_address(const wallet_rpc::COMMAND_RPC_LABEL_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_LABEL_ADDRESS::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
m_wallet->set_subaddress_label(req.index, req.label);
|
||||
|
@ -680,6 +733,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_create_account(const wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
m_wallet->add_subaddress_account(req.label);
|
||||
|
@ -697,6 +751,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_label_account(const wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
m_wallet->set_subaddress_label({req.account_index, 0}, req.label);
|
||||
|
@ -712,6 +767,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_get_account_tags(const wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
const std::pair<std::map<std::string, std::string>, std::vector<std::string>> account_tags = m_wallet->get_account_tags();
|
||||
for (const std::pair<const std::string, std::string>& p : account_tags.first)
|
||||
{
|
||||
|
@ -731,6 +787,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_tag_accounts(const wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
m_wallet->set_account_tag(req.accounts, req.tag);
|
||||
|
@ -746,6 +803,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
m_wallet->set_account_tag(req.accounts, "");
|
||||
|
@ -761,6 +819,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
m_wallet->set_account_tag_description(req.tag, req.description);
|
||||
|
@ -791,6 +850,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_freeze(const wallet_rpc::COMMAND_RPC_FREEZE::request& req, wallet_rpc::COMMAND_RPC_FREEZE::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
if (req.key_image.empty())
|
||||
|
@ -819,6 +879,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_thaw(const wallet_rpc::COMMAND_RPC_THAW::request& req, wallet_rpc::COMMAND_RPC_THAW::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
if (req.key_image.empty())
|
||||
|
@ -847,6 +908,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_frozen(const wallet_rpc::COMMAND_RPC_FROZEN::request& req, wallet_rpc::COMMAND_RPC_FROZEN::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
if (req.key_image.empty())
|
||||
|
@ -874,6 +936,8 @@ namespace tools
|
|||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, bool at_least_one_destination, epee::json_rpc::error& er)
|
||||
{
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
crypto::hash8 integrated_payment_id = crypto::null_hash8;
|
||||
std::string extra_nonce;
|
||||
for (auto it = destinations.begin(); it != destinations.end(); it++)
|
||||
|
@ -1203,6 +1267,7 @@ namespace tools
|
|||
}
|
||||
|
||||
CHECK_MULTISIG_ENABLED();
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
cryptonote::blobdata blob;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob))
|
||||
|
@ -1284,6 +1349,7 @@ namespace tools
|
|||
er.message = "command not supported by watch-only wallet";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
if(req.unsigned_txset.empty() && req.multisig_txset.empty())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
|
@ -1553,6 +1619,7 @@ namespace tools
|
|||
}
|
||||
|
||||
CHECK_MULTISIG_ENABLED();
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -2115,6 +2182,7 @@ namespace tools
|
|||
er.message = "The wallet is watch-only. Cannot retrieve seed.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
if (!m_wallet->is_deterministic())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_NON_DETERMINISTIC;
|
||||
|
@ -2143,6 +2211,7 @@ namespace tools
|
|||
er.message = "The wallet is watch-only. Cannot retrieve spend key.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().m_spend_secret_key);
|
||||
res.key = std::string(key.data(), key.size());
|
||||
}
|
||||
|
@ -2164,6 +2233,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -2177,6 +2247,79 @@ namespace tools
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_setup_background_sync(const wallet_rpc::COMMAND_RPC_SETUP_BACKGROUND_SYNC::request& req, wallet_rpc::COMMAND_RPC_SETUP_BACKGROUND_SYNC::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
PRE_VALIDATE_BACKGROUND_SYNC();
|
||||
const tools::wallet2::BackgroundSyncType background_sync_type = tools::wallet2::background_sync_type_from_str(req.background_sync_type);
|
||||
boost::optional<epee::wipeable_string> background_cache_password = boost::none;
|
||||
if (background_sync_type == tools::wallet2::BackgroundSyncCustomPassword)
|
||||
background_cache_password = boost::optional<epee::wipeable_string>(req.background_cache_password);
|
||||
m_wallet->setup_background_sync(background_sync_type, req.wallet_password, background_cache_password);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_start_background_sync(const wallet_rpc::COMMAND_RPC_START_BACKGROUND_SYNC::request& req, wallet_rpc::COMMAND_RPC_START_BACKGROUND_SYNC::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
PRE_VALIDATE_BACKGROUND_SYNC();
|
||||
m_wallet->start_background_sync();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_stop_background_sync(const wallet_rpc::COMMAND_RPC_STOP_BACKGROUND_SYNC::request& req, wallet_rpc::COMMAND_RPC_STOP_BACKGROUND_SYNC::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
PRE_VALIDATE_BACKGROUND_SYNC();
|
||||
crypto::secret_key spend_secret_key = crypto::null_skey;
|
||||
|
||||
// Load the spend key from seed if seed is provided
|
||||
if (!req.seed.empty())
|
||||
{
|
||||
crypto::secret_key recovery_key;
|
||||
std::string language;
|
||||
|
||||
if (!crypto::ElectrumWords::words_to_bytes(req.seed, recovery_key, language))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "Electrum-style word list failed verification";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!req.seed_offset.empty())
|
||||
recovery_key = cryptonote::decrypt_key(recovery_key, req.seed_offset);
|
||||
|
||||
// generate spend key
|
||||
cryptonote::account_base account;
|
||||
account.generate(recovery_key, true, false);
|
||||
spend_secret_key = account.get_keys().m_spend_secret_key;
|
||||
}
|
||||
|
||||
m_wallet->stop_background_sync(req.wallet_password, spend_secret_key);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_sign(const wallet_rpc::COMMAND_RPC_SIGN::request& req, wallet_rpc::COMMAND_RPC_SIGN::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
|
@ -2186,6 +2329,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
tools::wallet2::message_signature_type_t signature_type = tools::wallet2::sign_with_spend_key;
|
||||
if (req.signature_type == "spend" || req.signature_type == "")
|
||||
|
@ -2278,6 +2422,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
if (req.txids.size() != req.notes.size())
|
||||
{
|
||||
|
@ -2350,6 +2495,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
m_wallet->set_attribute(req.key, req.value);
|
||||
|
||||
|
@ -2377,6 +2523,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_get_tx_key(const wallet_rpc::COMMAND_RPC_GET_TX_KEY::request& req, wallet_rpc::COMMAND_RPC_GET_TX_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
crypto::hash txid;
|
||||
if (!epee::string_tools::hex_to_pod(req.txid, txid))
|
||||
|
@ -2468,6 +2615,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_get_tx_proof(const wallet_rpc::COMMAND_RPC_GET_TX_PROOF::request& req, wallet_rpc::COMMAND_RPC_GET_TX_PROOF::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
crypto::hash txid;
|
||||
if (!epee::string_tools::hex_to_pod(req.txid, txid))
|
||||
|
@ -2584,6 +2732,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_get_reserve_proof(const wallet_rpc::COMMAND_RPC_GET_RESERVE_PROOF::request& req, wallet_rpc::COMMAND_RPC_GET_RESERVE_PROOF::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
boost::optional<std::pair<uint32_t, uint64_t>> account_minreserve;
|
||||
if (!req.all)
|
||||
|
@ -2826,6 +2975,7 @@ namespace tools
|
|||
er.message = "command not supported by HW wallet";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -2855,6 +3005,7 @@ namespace tools
|
|||
er.message = "command not supported by HW wallet";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
cryptonote::blobdata blob;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.outputs_data_hex, blob))
|
||||
|
@ -2880,6 +3031,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_export_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
|
||||
|
@ -2916,6 +3068,7 @@ namespace tools
|
|||
er.message = "This command requires a trusted daemon.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
|
||||
|
@ -2984,6 +3137,7 @@ namespace tools
|
|||
bool wallet_rpc_server::on_get_address_book(const wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
const auto ab = m_wallet->get_address_book();
|
||||
if (req.entries.empty())
|
||||
{
|
||||
|
@ -3029,6 +3183,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
cryptonote::address_parse_info info;
|
||||
er.message = "";
|
||||
|
@ -3071,6 +3226,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
const auto ab = m_wallet->get_address_book();
|
||||
if (req.index >= ab.size())
|
||||
|
@ -3133,6 +3289,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
const auto ab = m_wallet->get_address_book();
|
||||
if (req.index >= ab.size())
|
||||
|
@ -3203,6 +3360,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
std::unordered_set<crypto::hash> txids;
|
||||
std::list<std::string>::const_iterator i = req.txids.begin();
|
||||
|
@ -3242,6 +3400,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
try
|
||||
{
|
||||
m_wallet->rescan_spent();
|
||||
|
@ -3506,6 +3665,7 @@ namespace tools
|
|||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
if (m_wallet->verify_password(req.old_password))
|
||||
{
|
||||
try
|
||||
|
@ -4039,6 +4199,7 @@ namespace tools
|
|||
er.message = "wallet is watch-only and cannot be made multisig";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
res.multisig_info = m_wallet->get_multisig_first_kex_msg();
|
||||
return true;
|
||||
|
@ -4066,6 +4227,7 @@ namespace tools
|
|||
er.message = "wallet is watch-only and cannot be made multisig";
|
||||
return false;
|
||||
}
|
||||
CHECK_IF_BACKGROUND_SYNCING();
|
||||
|
||||
try
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue