aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/wallet.cpp10
-rw-r--r--src/wallet/api/wallet.h2
-rw-r--r--src/wallet/api/wallet2_api.h3
-rw-r--r--src/wallet/wallet2.cpp42
-rw-r--r--src/wallet/wallet2.h5
-rw-r--r--src/wallet/wallet_rpc_payments.cpp2
-rw-r--r--src/wallet/wallet_rpc_server.cpp27
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h4
8 files changed, 55 insertions, 40 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 470206bc5..c4d3856d4 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -63,8 +63,8 @@ namespace {
static const int MAX_REFRESH_INTERVAL_MILLIS = 1000 * 60 * 1;
// Default refresh interval when connected to remote node
static const int DEFAULT_REMOTE_NODE_REFRESH_INTERVAL_MILLIS = 1000 * 10;
- // Connection timeout 30 sec
- static const int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 1000 * 30;
+ // Connection timeout 20 sec
+ static const int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 1000 * 20;
std::string get_default_ringdb_path(cryptonote::network_type nettype)
{
@@ -1396,12 +1396,12 @@ string WalletImpl::makeMultisig(const vector<string>& info, const uint32_t thres
return string();
}
-std::string WalletImpl::exchangeMultisigKeys(const std::vector<std::string> &info) {
+std::string WalletImpl::exchangeMultisigKeys(const std::vector<std::string> &info, const bool force_update_use_with_caution /*= false*/) {
try {
clearStatus();
checkMultisigWalletNotReady(m_wallet);
- return m_wallet->exchange_multisig_keys(epee::wipeable_string(m_password), info);
+ return m_wallet->exchange_multisig_keys(epee::wipeable_string(m_password), info, force_update_use_with_caution);
} catch (const exception& e) {
LOG_ERROR("Error on exchanging multisig keys: " << e.what());
setStatusError(string(tr("Failed to exchange multisig keys: ")) + e.what());
@@ -2173,7 +2173,7 @@ bool WalletImpl::connectToDaemon()
Wallet::ConnectionStatus WalletImpl::connected() const
{
uint32_t version = 0;
- bool wallet_is_outdated, daemon_is_outdated = false;
+ bool wallet_is_outdated = false, daemon_is_outdated = false;
m_is_connected = m_wallet->check_connection(&version, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS, &wallet_is_outdated, &daemon_is_outdated);
if (!m_is_connected)
{
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 018b2a0ed..ec2d7e9b3 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -146,7 +146,7 @@ public:
MultisigState multisig() const override;
std::string getMultisigInfo() const override;
std::string makeMultisig(const std::vector<std::string>& info, uint32_t threshold) override;
- std::string exchangeMultisigKeys(const std::vector<std::string> &info) override;
+ std::string exchangeMultisigKeys(const std::vector<std::string> &info, const bool force_update_use_with_caution = false) override;
bool exportMultisigImages(std::string& images) override;
size_t importMultisigImages(const std::vector<std::string>& images) override;
bool hasMultisigPartialKeyImages() const override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index b67bce60c..0ae84adb9 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -796,9 +796,10 @@ struct Wallet
/**
* @brief exchange_multisig_keys - provides additional key exchange round for arbitrary multisig schemes (like N-1/N, M/N)
* @param info - base58 encoded key derivations returned by makeMultisig or exchangeMultisigKeys function call
+ * @param force_update_use_with_caution - force multisig account to update even if not all signers contribute round messages
* @return new info string if more rounds required or an empty string if wallet creation is done
*/
- virtual std::string exchangeMultisigKeys(const std::vector<std::string> &info) = 0;
+ virtual std::string exchangeMultisigKeys(const std::vector<std::string> &info, const bool force_update_use_with_caution) = 0;
/**
* @brief exportMultisigImages - exports transfers' key images
* @param images - output paramter for hex encoded array of images
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index d6b05e5b4..a1a51f7de 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1346,6 +1346,7 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
}
m_rpc_payment_state.expected_spent = 0;
m_rpc_payment_state.discrepancy = 0;
+ m_rpc_version = 0;
m_node_rpc_proxy.invalidate();
}
@@ -2724,7 +2725,7 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
THROW_WALLET_EXCEPTION_IF(blocks.size() != parsed_blocks.size(), error::wallet_internal_error, "size mismatch");
THROW_WALLET_EXCEPTION_IF(!m_blockchain.is_in_bounds(current_index), error::out_of_hashchain_bounds_error);
- tools::threadpool& tpool = tools::threadpool::getInstance();
+ tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
tools::threadpool::waiter waiter(tpool);
size_t num_txes = 0;
@@ -2967,7 +2968,7 @@ void wallet2::pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks
pull_blocks(start_height, blocks_start_height, short_chain_history, blocks, o_indices, current_height);
THROW_WALLET_EXCEPTION_IF(blocks.size() != o_indices.size(), error::wallet_internal_error, "Mismatched sizes of blocks and o_indices");
- tools::threadpool& tpool = tools::threadpool::getInstance();
+ tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
tools::threadpool::waiter waiter(tpool);
parsed_blocks.resize(blocks.size());
for (size_t i = 0; i < blocks.size(); ++i)
@@ -3417,7 +3418,7 @@ std::shared_ptr<std::map<std::pair<uint64_t, uint64_t>, size_t>> wallet2::create
return cache;
}
//----------------------------------------------------------------------------------------------------
-void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched, bool& received_money, bool check_pool)
+void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched, bool& received_money, bool check_pool, uint64_t max_blocks)
{
if (m_offline)
{
@@ -3464,7 +3465,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
size_t try_count = 0;
crypto::hash last_tx_hash_id = m_transfers.size() ? m_transfers.back().m_txid : null_hash;
std::list<crypto::hash> short_chain_history;
- tools::threadpool& tpool = tools::threadpool::getInstance();
+ tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
tools::threadpool::waiter waiter(tpool);
uint64_t blocks_start_height;
std::vector<cryptonote::block_complete_entry> blocks;
@@ -3513,7 +3514,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
update_pool_state(process_pool_txs, true);
bool first = true, last = false;
- while(m_run.load(std::memory_order_relaxed))
+ while(m_run.load(std::memory_order_relaxed) && blocks_fetched < max_blocks)
{
uint64_t next_blocks_start_height;
std::vector<cryptonote::block_complete_entry> next_blocks;
@@ -5130,12 +5131,11 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &password,
- const std::vector<std::string> &kex_messages)
+ const std::vector<std::string> &kex_messages,
+ const bool force_update_use_with_caution /*= false*/)
{
bool ready{false};
CHECK_AND_ASSERT_THROW_MES(multisig(&ready), "The wallet is not multisig");
- CHECK_AND_ASSERT_THROW_MES(!ready, "Multisig wallet creation process has already been finished");
- CHECK_AND_ASSERT_THROW_MES(kex_messages.size() > 0, "No key exchange messages passed in.");
// decrypt account keys
epee::misc_utils::auto_scope_leave_caller keys_reencryptor;
@@ -5154,13 +5154,6 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
);
}
- // open kex messages
- std::vector<multisig::multisig_kex_msg> expanded_msgs;
- expanded_msgs.reserve(kex_messages.size());
-
- for (const auto &msg : kex_messages)
- expanded_msgs.emplace_back(msg);
-
// reconstruct multisig account
multisig::multisig_keyset_map_memsafe_t kex_origins_map;
@@ -5181,8 +5174,25 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
""
};
+ // KLUDGE: early return if there are no kex messages and main kex is complete (will return the post-kex verification round
+ // message) (it's a kludge because this behavior would be more appropriate for a standalone wallet method)
+ if (kex_messages.size() == 0)
+ {
+ CHECK_AND_ASSERT_THROW_MES(multisig_account.main_kex_rounds_done(),
+ "Exchange multisig keys: there are no kex messages but the main kex rounds are not done.");
+
+ return multisig_account.get_next_kex_round_msg();
+ }
+
+ // open kex messages
+ std::vector<multisig::multisig_kex_msg> expanded_msgs;
+ expanded_msgs.reserve(kex_messages.size());
+
+ for (const auto &msg : kex_messages)
+ expanded_msgs.emplace_back(msg);
+
// update multisig kex
- multisig_account.kex_update(expanded_msgs);
+ multisig_account.kex_update(expanded_msgs, force_update_use_with_caution);
// update wallet state
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 115651e3b..3ee40a5f0 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -886,7 +886,8 @@ private:
* to other participants
*/
std::string exchange_multisig_keys(const epee::wipeable_string &password,
- const std::vector<std::string> &kex_messages);
+ const std::vector<std::string> &kex_messages,
+ const bool force_update_use_with_caution = false);
/*!
* \brief Get initial message to start multisig key exchange (before 'make_multisig()' is called)
* \return string to send to other participants
@@ -1022,7 +1023,7 @@ private:
bool is_deprecated() const;
void refresh(bool trusted_daemon);
void refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched);
- void refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched, bool& received_money, bool check_pool = true);
+ void refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blocks_fetched, bool& received_money, bool check_pool = true, uint64_t max_blocks = std::numeric_limits<uint64_t>::max());
bool refresh(bool trusted_daemon, uint64_t & blocks_fetched, bool& received_money, bool& ok);
void set_refresh_type(RefreshType refresh_type) { m_refresh_type = refresh_type; }
diff --git a/src/wallet/wallet_rpc_payments.cpp b/src/wallet/wallet_rpc_payments.cpp
index 61eaa8070..8474fb568 100644
--- a/src/wallet/wallet_rpc_payments.cpp
+++ b/src/wallet/wallet_rpc_payments.cpp
@@ -144,7 +144,7 @@ bool wallet2::search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads
n_threads = boost::thread::hardware_concurrency();
std::vector<crypto::hash> hash(n_threads);
- tools::threadpool& tpool = tools::threadpool::getInstance();
+ tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
tools::threadpool::waiter waiter(tpool);
const uint32_t local_nonce = nonce += n_threads; // wrapping's OK
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index a8684d633..cecf24289 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -60,6 +60,7 @@ using namespace epee;
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.rpc"
#define DEFAULT_AUTO_REFRESH_PERIOD 20 // seconds
+#define REFRESH_INFICATIVE_BLOCK_CHUNK_SIZE 256 // just to split refresh in separate calls to play nicer with other threads
#define CHECK_MULTISIG_ENABLED() \
do \
@@ -79,6 +80,7 @@ namespace
const command_line::arg_descriptor<bool> arg_restricted = {"restricted-rpc", "Restricts to view-only commands", false};
const command_line::arg_descriptor<std::string> arg_wallet_dir = {"wallet-dir", "Directory for newly created wallets"};
const command_line::arg_descriptor<bool> arg_prompt_for_password = {"prompt-for-password", "Prompts for password when not provided", false};
+ const command_line::arg_descriptor<bool> arg_no_initial_sync = {"no-initial-sync", "Skips the initial sync before listening for connections", false};
constexpr const char default_rpc_username[] = "monero";
@@ -149,12 +151,17 @@ namespace tools
return true;
if (boost::posix_time::microsec_clock::universal_time() < m_last_auto_refresh_time + boost::posix_time::seconds(m_auto_refresh_period))
return true;
+ uint64_t blocks_fetched = 0;
try {
- if (m_wallet) m_wallet->refresh(m_wallet->is_trusted_daemon());
+ bool received_money = false;
+ if (m_wallet) m_wallet->refresh(m_wallet->is_trusted_daemon(), 0, blocks_fetched, received_money, true, REFRESH_INFICATIVE_BLOCK_CHUNK_SIZE);
} catch (const std::exception& ex) {
LOG_ERROR("Exception at while refreshing, what=" << ex.what());
}
- m_last_auto_refresh_time = boost::posix_time::microsec_clock::universal_time();
+ // if we got the max amount of blocks, do not set the last refresh time, we did only part of the refresh and will
+ // continue asap, and only set the last refresh time once the refresh is actually finished
+ if (blocks_fetched < REFRESH_INFICATIVE_BLOCK_CHUNK_SIZE)
+ m_last_auto_refresh_time = boost::posix_time::microsec_clock::universal_time();
return true;
}, 1000);
m_net_server.add_idle_handler([this](){
@@ -397,7 +404,6 @@ namespace tools
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
entry.txid = string_tools::pod_to_hex(txid);
entry.payment_id = string_tools::pod_to_hex(pd.m_payment_id);
- entry.payment_id = string_tools::pod_to_hex(pd.m_payment_id);
if (entry.payment_id.substr(16).find_first_not_of('0') == std::string::npos)
entry.payment_id = entry.payment_id.substr(0,16);
entry.height = 0;
@@ -3530,7 +3536,6 @@ namespace tools
cryptonote::print_money(e.tx_amount() + e.fee()) %
cryptonote::print_money(e.tx_amount()) %
cryptonote::print_money(e.fee())).str();
- er.message = e.what();
}
catch (const tools::error::not_enough_outs_to_mix& e)
{
@@ -4146,13 +4151,6 @@ namespace tools
er.message = "This wallet is not multisig";
return false;
}
-
- if (ready)
- {
- er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG;
- er.message = "This wallet is multisig, and already finalized";
- return false;
- }
CHECK_MULTISIG_ENABLED();
if (req.multisig_info.size() + 1 < total)
@@ -4164,7 +4162,7 @@ namespace tools
try
{
- res.multisig_info = m_wallet->exchange_multisig_keys(req.password, req.multisig_info);
+ res.multisig_info = m_wallet->exchange_multisig_keys(req.password, req.multisig_info, req.force_update_use_with_caution);
m_wallet->multisig(&ready);
if (ready)
{
@@ -4528,6 +4526,7 @@ public:
const auto password_file = command_line::get_arg(vm, arg_password_file);
const auto prompt_for_password = command_line::get_arg(vm, arg_prompt_for_password);
const auto password_prompt = prompt_for_password ? password_prompter : nullptr;
+ const auto no_initial_sync = command_line::get_arg(vm, arg_no_initial_sync);
if(!wallet_file.empty() && !from_json.empty())
{
@@ -4596,7 +4595,8 @@ public:
try
{
- wal->refresh(wal->is_trusted_daemon());
+ if (!no_initial_sync)
+ wal->refresh(wal->is_trusted_daemon());
}
catch (const std::exception& e)
{
@@ -4707,6 +4707,7 @@ int main(int argc, char** argv) {
command_line::add_arg(desc_params, arg_wallet_dir);
command_line::add_arg(desc_params, arg_prompt_for_password);
command_line::add_arg(desc_params, arg_rpc_client_secret_key);
+ command_line::add_arg(desc_params, arg_no_initial_sync);
daemonizer::init_options(hidden_options, desc_params);
desc_params.add(hidden_options);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 2cca323ee..60df6296f 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -47,7 +47,7 @@
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define WALLET_RPC_VERSION_MAJOR 1
-#define WALLET_RPC_VERSION_MINOR 25
+#define WALLET_RPC_VERSION_MINOR 26
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
namespace tools
@@ -2535,10 +2535,12 @@ namespace wallet_rpc
{
std::string password;
std::vector<std::string> multisig_info;
+ bool force_update_use_with_caution;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(password)
KV_SERIALIZE(multisig_info)
+ KV_SERIALIZE_OPT(force_update_use_with_caution, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;