aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/api/wallet.cpp29
-rw-r--r--src/wallet/api/wallet2_api.h3
-rw-r--r--src/wallet/message_store.h7
-rw-r--r--src/wallet/wallet2.cpp56
-rw-r--r--src/wallet/wallet2.h3
-rw-r--r--src/wallet/wallet_rpc_server.cpp73
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h2
7 files changed, 107 insertions, 66 deletions
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 7f4dbbc79..572079182 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -38,6 +38,7 @@
#include "subaddress_account.h"
#include "common_defines.h"
#include "common/util.h"
+#include "multisig/multisig_account.h"
#include "mnemonics/electrum-words.h"
#include "mnemonics/english.h"
@@ -87,12 +88,13 @@ namespace {
throw runtime_error("Wallet is not initialized yet");
}
- bool ready;
- if (!wallet->multisig(&ready)) {
+ const multisig::multisig_account_status ms_status{wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active) {
throw runtime_error("Wallet is not multisig");
}
- if (!ready) {
+ if (!ms_status.is_ready) {
throw runtime_error("Multisig wallet is not finalized yet");
}
}
@@ -105,12 +107,13 @@ namespace {
throw runtime_error("Wallet is not initialized yet");
}
- bool ready;
- if (!wallet->multisig(&ready)) {
+ const multisig::multisig_account_status ms_status{wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active) {
throw runtime_error("Wallet is not multisig");
}
- if (ready) {
+ if (ms_status.is_ready) {
throw runtime_error("Multisig wallet is already finalized");
}
}
@@ -1297,7 +1300,13 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex
MultisigState WalletImpl::multisig() const {
MultisigState state;
- state.isMultisig = m_wallet->multisig(&state.isReady, &state.threshold, &state.total);
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ state.isMultisig = ms_status.multisig_is_active;
+ state.kexIsDone = ms_status.kex_is_done;
+ state.isReady = ms_status.is_ready;
+ state.threshold = ms_status.threshold;
+ state.total = ms_status.total;
return state;
}
@@ -1318,7 +1327,7 @@ string WalletImpl::makeMultisig(const vector<string>& info, const uint32_t thres
try {
clearStatus();
- if (m_wallet->multisig()) {
+ if (m_wallet->get_multisig_status().multisig_is_active) {
throw runtime_error("Wallet is already multisig");
}
@@ -2053,8 +2062,8 @@ std::string WalletImpl::signMultisigParticipant(const std::string &message) cons
{
clearStatus();
- bool ready = false;
- if (!m_wallet->multisig(&ready) || !ready) {
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+ if (!ms_status.multisig_is_active || !ms_status.is_ready) {
m_status = Status_Error;
m_errorString = tr("The wallet must be in multisig ready state");
return {};
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index df86da847..53210832b 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -322,9 +322,10 @@ struct SubaddressAccount
};
struct MultisigState {
- MultisigState() : isMultisig(false), isReady(false), threshold(0), total(0) {}
+ MultisigState() : isMultisig(false), kexIsDone(false), isReady(false), threshold(0), total(0) {}
bool isMultisig;
+ bool kexIsDone;
bool isReady;
uint32_t threshold;
uint32_t total;
diff --git a/src/wallet/message_store.h b/src/wallet/message_store.h
index 202d77be6..c0afa2afa 100644
--- a/src/wallet/message_store.h
+++ b/src/wallet/message_store.h
@@ -245,18 +245,23 @@ namespace mms
crypto::secret_key view_secret_key;
bool multisig;
bool multisig_is_ready;
+ bool multisig_kex_is_done;
bool has_multisig_partial_key_images;
uint32_t multisig_rounds_passed;
size_t num_transfer_details;
std::string mms_file;
BEGIN_SERIALIZE_OBJECT()
- VERSION_FIELD(0)
+ VERSION_FIELD(1)
FIELD(address)
VARINT_FIELD(nettype)
FIELD(view_secret_key)
FIELD(multisig)
FIELD(multisig_is_ready)
+ if (version > 0)
+ FIELD(multisig_kex_is_done)
+ else
+ multisig_kex_is_done = multisig_is_ready;
FIELD(has_multisig_partial_key_images)
VARINT_FIELD(multisig_rounds_passed)
VARINT_FIELD(num_transfer_details)
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 5a739d50d..867e8201f 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1438,14 +1438,14 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
//----------------------------------------------------------------------------------------------------
bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase) const
{
- bool ready;
- uint32_t threshold, total;
- if (!multisig(&ready, &threshold, &total))
+ const multisig::multisig_account_status ms_status{get_multisig_status()};
+
+ if (!ms_status.multisig_is_active)
{
std::cout << "This is not a multisig wallet" << std::endl;
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
std::cout << "This multisig wallet is not yet finalized" << std::endl;
return false;
@@ -1459,8 +1459,8 @@ bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeabl
THROW_WALLET_EXCEPTION_IF(num_expected_ms_keys != keys.m_multisig_keys.size(),
error::wallet_internal_error, "Unexpected number of private multisig keys")
epee::wipeable_string data;
- data.append((const char*)&threshold, sizeof(uint32_t));
- data.append((const char*)&total, sizeof(uint32_t));
+ data.append((const char*)&ms_status.threshold, sizeof(uint32_t));
+ data.append((const char*)&ms_status.total, sizeof(uint32_t));
skey = keys.m_spend_secret_key;
data.append((const char*)&skey, sizeof(skey));
pkey = keys.m_account_address.m_spend_public_key;
@@ -5617,8 +5617,8 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
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");
+ const multisig::multisig_account_status ms_status{get_multisig_status()};
+ CHECK_AND_ASSERT_THROW_MES(ms_status.multisig_is_active, "The wallet is not multisig");
// decrypt account keys
epee::misc_utils::auto_scope_leave_caller keys_reencryptor;
@@ -5745,20 +5745,30 @@ std::string wallet2::get_multisig_first_kex_msg() const
return multisig_account.get_next_kex_round_msg();
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::multisig(bool *ready, uint32_t *threshold, uint32_t *total) const
+multisig::multisig_account_status wallet2::get_multisig_status() const
{
- if (!m_multisig)
- return false;
- if (threshold)
- *threshold = m_multisig_threshold;
- if (total)
- *total = m_multisig_signers.size();
- if (ready)
+ multisig::multisig_account_status ret;
+
+ if (m_multisig)
{
- *ready = !(get_account().get_keys().m_account_address.m_spend_public_key == rct::rct2pk(rct::identity())) &&
+ ret.multisig_is_active = true;
+ ret.threshold = m_multisig_threshold;
+ ret.total = m_multisig_signers.size();
+ ret.kex_is_done = !(get_account().get_keys().m_account_address.m_spend_public_key == rct::rct2pk(rct::identity())) &&
+ (m_multisig_rounds_passed >= multisig::multisig_kex_rounds_required(m_multisig_signers.size(), m_multisig_threshold));
+ ret.is_ready = ret.kex_is_done &&
(m_multisig_rounds_passed == multisig::multisig_setup_rounds_required(m_multisig_signers.size(), m_multisig_threshold));
}
- return true;
+ else
+ {
+ ret.multisig_is_active = false;
+ ret.threshold = 0;
+ ret.total = 0;
+ ret.kex_is_done = false;
+ ret.is_ready = false;
+ }
+
+ return ret;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::has_multisig_partial_key_images() const
@@ -8118,7 +8128,7 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
else if (blocks[0].first > 0)
{
MINFO("We don't use the low priority because there's a backlog in the tx pool.");
- return priority;
+ return 2;
}
// get the current full reward zone
@@ -8163,7 +8173,7 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
if (P > 80)
{
MINFO("We don't use the low priority because recent blocks are quite full.");
- return priority;
+ return 2;
}
MINFO("We'll use the low priority because probably it's safe to do so.");
return 1;
@@ -14302,9 +14312,13 @@ void wallet2::generate_genesis(cryptonote::block& b) const {
//----------------------------------------------------------------------------------------------------
mms::multisig_wallet_state wallet2::get_multisig_wallet_state() const
{
+ const multisig::multisig_account_status ms_status{get_multisig_status()};
+
mms::multisig_wallet_state state;
state.nettype = m_nettype;
- state.multisig = multisig(&state.multisig_is_ready);
+ state.multisig = ms_status.multisig_is_active;
+ state.multisig_is_ready = ms_status.is_ready;
+ state.multisig_kex_is_done = ms_status.kex_is_done;
state.has_multisig_partial_key_images = has_multisig_partial_key_images();
state.multisig_rounds_passed = m_multisig_rounds_passed;
state.num_transfer_details = m_transfers.size();
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 5f884e374..3d17bec57 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -57,6 +57,7 @@
#include "common/util.h"
#include "crypto/chacha.h"
#include "crypto/hash.h"
+#include "multisig/multisig_account.h"
#include "ringct/rctTypes.h"
#include "ringct/rctOps.h"
#include "checkpoints/checkpoints.h"
@@ -1059,7 +1060,7 @@ private:
cryptonote::network_type nettype() const { return m_nettype; }
bool watch_only() const { return m_watch_only; }
- bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
+ multisig::multisig_account_status get_multisig_status() const;
bool has_multisig_partial_key_images() const;
bool has_unknown_key_images() const;
bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string()) const;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index d7aa80e0a..da02e1e83 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -65,7 +65,7 @@ using namespace epee;
#define CHECK_MULTISIG_ENABLED() \
do \
{ \
- if (m_wallet->multisig() && !m_wallet->is_multisig_enabled()) \
+ if (m_wallet->get_multisig_status().multisig_is_active && !m_wallet->is_multisig_enabled()) \
{ \
er.code = WALLET_RPC_ERROR_CODE_DISABLED; \
er.message = "This wallet is multisig, and multisig is disabled. Multisig is an experimental feature and may have bugs. Things that could go wrong include: funds sent to a multisig wallet can't be spent at all, can only be spent with the participation of a malicious group member, or can be stolen by a malicious group member. You can enable it by running this once in monero-wallet-cli: set enable-multisig-experimental 1"; \
@@ -459,7 +459,7 @@ namespace tools
{
res.balance = req.all_accounts ? m_wallet->balance_all(req.strict) : m_wallet->balance(req.account_index, req.strict);
res.unlocked_balance = req.all_accounts ? m_wallet->unlocked_balance_all(req.strict, &res.blocks_to_unlock, &res.time_to_unlock) : m_wallet->unlocked_balance(req.account_index, req.strict, &res.blocks_to_unlock, &res.time_to_unlock);
- res.multisig_import_needed = m_wallet->multisig() && m_wallet->has_multisig_partial_key_images();
+ res.multisig_import_needed = m_wallet->get_multisig_status().multisig_is_active && m_wallet->has_multisig_partial_key_images();
std::map<uint32_t, std::map<uint32_t, uint64_t>> balance_per_subaddress_per_account;
std::map<uint32_t, std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>>> unlocked_balance_per_subaddress_per_account;
if (req.all_accounts)
@@ -1024,7 +1024,7 @@ namespace tools
fill(spent_key_images, key_image_list);
}
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
multisig_txset = epee::string_tools::buff_to_hex_nodelimer(m_wallet->save_multisig_tx(ptx_vector));
if (multisig_txset.empty())
@@ -2066,10 +2066,11 @@ namespace tools
if (req.key_type.compare("mnemonic") == 0)
{
epee::wipeable_string seed;
- bool ready;
- if (m_wallet->multisig(&ready))
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ if (ms_status.multisig_is_active)
{
- if (!ready)
+ if (!ms_status.is_ready)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized";
@@ -3979,7 +3980,14 @@ namespace tools
bool wallet_rpc_server::on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
if (!m_wallet) return not_open(er);
- res.multisig = m_wallet->multisig(&res.ready, &res.threshold, &res.total);
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ res.multisig = ms_status.multisig_is_active;
+ res.kex_is_done = ms_status.kex_is_done;
+ res.ready = ms_status.is_ready;
+ res.threshold = ms_status.threshold;
+ res.total = ms_status.total;
+
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -3992,7 +4000,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG;
er.message = "This wallet is already multisig";
@@ -4021,7 +4029,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG;
er.message = "This wallet is already multisig";
@@ -4059,14 +4067,15 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- bool ready;
- if (!m_wallet->multisig(&ready))
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig";
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized";
@@ -4100,15 +4109,15 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- bool ready;
- uint32_t threshold, total;
- if (!m_wallet->multisig(&ready, &threshold, &total))
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig";
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized";
@@ -4116,7 +4125,7 @@ namespace tools
}
CHECK_MULTISIG_ENABLED();
- if (req.info.size() < threshold - 1)
+ if (req.info.size() + 1 < ms_status.threshold)
{
er.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED;
er.message = "Needs multisig export info from more participants";
@@ -4180,9 +4189,9 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- bool ready;
- uint32_t threshold, total;
- if (!m_wallet->multisig(&ready, &threshold, &total))
+ multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig";
@@ -4190,7 +4199,7 @@ namespace tools
}
CHECK_MULTISIG_ENABLED();
- if (req.multisig_info.size() + 1 < total)
+ if (req.multisig_info.size() + 1 < ms_status.total)
{
er.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED;
er.message = "Needs multisig info from more participants";
@@ -4200,8 +4209,8 @@ namespace tools
try
{
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)
+ ms_status = m_wallet->get_multisig_status();
+ if (ms_status.is_ready)
{
res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
@@ -4224,15 +4233,15 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- bool ready;
- uint32_t threshold, total;
- if (!m_wallet->multisig(&ready, &threshold, &total))
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig";
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized";
@@ -4294,15 +4303,15 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- bool ready;
- uint32_t threshold, total;
- if (!m_wallet->multisig(&ready, &threshold, &total))
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig";
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized";
@@ -4327,7 +4336,7 @@ namespace tools
return false;
}
- if (txs.m_signers.size() < threshold)
+ if (txs.m_signers.size() < ms_status.threshold)
{
er.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED;
er.message = "Not enough signers signed this transaction.";
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index f9f534097..2173f5b6e 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -2323,12 +2323,14 @@ namespace wallet_rpc
struct response_t
{
bool multisig;
+ bool kex_is_done;
bool ready;
uint32_t threshold;
uint32_t total;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(multisig)
+ KV_SERIALIZE(kex_is_done)
KV_SERIALIZE(ready)
KV_SERIALIZE(threshold)
KV_SERIALIZE(total)