aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/timings.cc96
-rw-r--r--src/common/timings.h10
-rw-r--r--src/cryptonote_core/tx_pool.cpp18
-rw-r--r--src/cryptonote_core/tx_pool.h11
-rw-r--r--src/gen_multisig/gen_multisig.cpp7
-rw-r--r--src/multisig/multisig_account.h13
-rw-r--r--src/ringct/rctTypes.h2
-rw-r--r--src/serialization/serialization.h44
-rw-r--r--src/simplewallet/simplewallet.cpp139
-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
16 files changed, 330 insertions, 183 deletions
diff --git a/src/common/timings.cc b/src/common/timings.cc
index 612ac2cc6..aa719fa5e 100644
--- a/src/common/timings.cc
+++ b/src/common/timings.cc
@@ -12,10 +12,11 @@ TimingsDatabase::TimingsDatabase()
{
}
-TimingsDatabase::TimingsDatabase(const std::string &filename):
+TimingsDatabase::TimingsDatabase(const std::string &filename, const bool load_previous /*=false*/):
filename(filename)
{
- load();
+ if (load_previous)
+ load();
}
TimingsDatabase::~TimingsDatabase()
@@ -73,53 +74,96 @@ bool TimingsDatabase::load()
{
i.deciles.push_back(atoi(fields[idx++].c_str()));
}
- instances.insert(std::make_pair(name, i));
+ instances.emplace_back(name, i);
}
fclose(f);
return true;
}
-bool TimingsDatabase::save()
+bool TimingsDatabase::save(const bool save_current_time /*=true*/)
{
- if (filename.empty())
+ if (filename.empty() || instances.empty())
return true;
- FILE *f = fopen(filename.c_str(), "w");
+ FILE *f = fopen(filename.c_str(), "a"); // append
if (!f)
{
MERROR("Failed to write to file " << filename << ": " << strerror(errno));
return false;
}
- for (const auto &i: instances)
+
+ if (save_current_time)
{
- fprintf(f, "%s", i.first.c_str());
- fprintf(f, "\t%lu", (unsigned long)i.second.t);
- fprintf(f, " %zu", i.second.npoints);
- fprintf(f, " %f", i.second.min);
- fprintf(f, " %f", i.second.max);
- fprintf(f, " %f", i.second.mean);
- fprintf(f, " %f", i.second.median);
- fprintf(f, " %f", i.second.stddev);
- fprintf(f, " %f", i.second.npskew);
- for (uint64_t v: i.second.deciles)
- fprintf(f, " %lu", (unsigned long)v);
+ // save current time in readable format (UTC)
+ std::time_t sys_time{std::time(nullptr)};
+ std::tm *utc_time = std::gmtime(&sys_time); //GMT is equivalent to UTC
+
+ // format: year-month-day : hour:minute:second
+ std::string current_time{};
+ if (utc_time && sys_time != (std::time_t)(-1))
+ {
+ char timeString[22]; //length = std::size("yyyy-mm-dd : hh:mm:ss") (constexpr std::size is C++17)
+ std::strftime(timeString, 22, "%F : %T", utc_time);
+ current_time += timeString;
+ }
+ else
+ {
+ current_time += "TIME_ERROR_";
+ }
+ fputc('\n', f); // add an extra line before each 'print time'
+ fprintf(f, "%s", current_time.c_str());
fputc('\n', f);
}
+
+ for (const auto &i: instances)
+ {
+ fprintf(f, "%s,", i.first.c_str());
+
+ if (i.second.npoints > 0)
+ {
+ fprintf(f, "%lu,", (unsigned long)i.second.t);
+ fprintf(f, "%zu,", i.second.npoints);
+ fprintf(f, "%f,", i.second.min);
+ fprintf(f, "%f,", i.second.max);
+ fprintf(f, "%f,", i.second.mean);
+ fprintf(f, "%f,", i.second.median);
+ fprintf(f, "%f,", i.second.stddev);
+ fprintf(f, "%f,", i.second.npskew);
+ for (uint64_t v: i.second.deciles)
+ fprintf(f, "%lu,", (unsigned long)v);
+
+ // note: only add a new line if there are points; assume that 'no points' means i.first is a message meant to be
+ // prepended to the next save operation
+ fputc('\n', f);
+ }
+ }
fclose(f);
+
+ // after saving, clear so next save does not append the same stuff over again
+ instances.clear();
+
return true;
}
-std::vector<TimingsDatabase::instance> TimingsDatabase::get(const char *name) const
+const TimingsDatabase::instance* TimingsDatabase::get_most_recent(const char *name) const
{
- std::vector<instance> ret;
- auto range = instances.equal_range(name);
- for (auto i = range.first; i != range.second; ++i)
- ret.push_back(i->second);
- std::sort(ret.begin(), ret.end(), [](const instance &e0, const instance &e1){ return e0.t < e1.t; });
- return ret;
+ time_t latest_time = 0;
+ const TimingsDatabase::instance *instance_ptr = nullptr;
+
+ for (const auto &i: instances)
+ {
+ if (i.first != name)
+ continue;
+ if (i.second.t < latest_time)
+ continue;
+
+ latest_time = i.second.t;
+ instance_ptr = &i.second;
+ }
+ return instance_ptr;
}
void TimingsDatabase::add(const char *name, const instance &i)
{
- instances.insert(std::make_pair(name, i));
+ instances.emplace_back(name, i);
}
diff --git a/src/common/timings.h b/src/common/timings.h
index fb905611f..6e7ff5659 100644
--- a/src/common/timings.h
+++ b/src/common/timings.h
@@ -2,8 +2,8 @@
#include <stdint.h>
#include <string>
+#include <utility>
#include <vector>
-#include <map>
class TimingsDatabase
{
@@ -18,17 +18,17 @@ public:
public:
TimingsDatabase();
- TimingsDatabase(const std::string &filename);
+ TimingsDatabase(const std::string &filename, const bool load_previous = false);
~TimingsDatabase();
- std::vector<instance> get(const char *name) const;
+ const instance* get_most_recent(const char *name) const;
void add(const char *name, const instance &data);
+ bool save(const bool print_current_time = true);
private:
bool load();
- bool save();
private:
std::string filename;
- std::multimap<std::string, instance> instances;
+ std::vector<std::pair<std::string, instance>> instances;
};
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index d86a9f5f9..4f0501c1d 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -246,6 +246,7 @@ namespace cryptonote
LOG_PRINT_L1("Transaction with id= "<< id << " used already spent key images");
tvc.m_verifivation_failed = true;
tvc.m_double_spend = true;
+ tvc.m_no_drop_offense = true;
return false;
}
}
@@ -434,8 +435,14 @@ namespace cryptonote
void tx_memory_pool::prune(size_t bytes)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
+
+ // Nothing to do if already empty
+ if (m_txs_by_fee_and_receive_time.empty())
+ return;
+
if (bytes == 0)
bytes = m_txpool_max_weight;
+
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain.get_db());
bool changed = false;
@@ -480,8 +487,13 @@ namespace cryptonote
reduce_txpool_weight(meta.weight);
remove_transaction_keyimages(tx, txid);
MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first);
+
+ auto it_prev = it;
+ --it_prev;
+
remove_tx_from_transient_lists(it, txid, !meta.matches(relay_category::broadcasted));
- it--;
+ it = it_prev;
+
changed = true;
}
catch (const std::exception &e)
@@ -1073,7 +1085,7 @@ namespace cryptonote
// If the total weight is too high, choose the best paying transactions
if (total_weight > max_backlog_weight)
- std::sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; });
+ std::stable_sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; });
backlog.clear();
uint64_t w = 0;
@@ -1826,7 +1838,7 @@ namespace cryptonote
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
- MERROR("Re-adding tx " << txid << " to tx pool, but it was not found in the sorted txs container");
+ MDEBUG("Re-adding tx " << txid << " to tx pool, but it was not found in the sorted txs container");
}
else
{
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 3bb96d3a8..3a111ce91 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -69,11 +69,12 @@ namespace cryptonote
{
// sort by greatest first, not least
if (a.first.first > b.first.first) return true;
- else if (a.first.first < b.first.first) return false;
- else if (a.first.second < b.first.second) return true;
- else if (a.first.second > b.first.second) return false;
- else if (a.second != b.second) return true;
- else return false;
+ if (a.first.first < b.first.first) return false;
+
+ if (a.first.second < b.first.second) return true;
+ if (a.first.second > b.first.second) return false;
+
+ return memcmp(a.second.data, b.second.data, sizeof(crypto::hash)) < 0;
}
};
diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp
index 48cf818ef..fd82c66af 100644
--- a/src/gen_multisig/gen_multisig.cpp
+++ b/src/gen_multisig/gen_multisig.cpp
@@ -121,16 +121,15 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str
}
// exchange keys until the wallets are done
- bool ready{false};
- wallets[0]->multisig(&ready);
- while (!ready)
+ multisig::multisig_account_status ms_status{wallets[0]->get_multisig_status()};
+ while (!ms_status.is_ready)
{
for (size_t n = 0; n < total; ++n)
{
kex_msgs_intermediate[n] = wallets[n]->exchange_multisig_keys(pwd_container->password(), kex_msgs_intermediate);
}
- wallets[0]->multisig(&ready);
+ ms_status = wallets[0]->get_multisig_status();
}
std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->nettype());
diff --git a/src/multisig/multisig_account.h b/src/multisig/multisig_account.h
index 0d832f243..2ea8d0133 100644
--- a/src/multisig/multisig_account.h
+++ b/src/multisig/multisig_account.h
@@ -40,6 +40,19 @@
namespace multisig
{
+ struct multisig_account_status
+ {
+ // is the multisig account active/initialized?
+ bool multisig_is_active{false};
+ // has the multisig account completed the main key exchange rounds?
+ bool kex_is_done{false};
+ // is the multisig account ready to use?
+ bool is_ready{false};
+ // multisig is: M-of-N
+ std::uint32_t threshold{0}; // M
+ std::uint32_t total{0}; // N
+ };
+
/**
* multisig account:
*
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index c168c8571..299798e17 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -374,7 +374,7 @@ namespace rct {
memset(ecdhInfo[i].amount.bytes, 0, sizeof(ecdhInfo[i].amount.bytes));
else // saving
memcpy(trunc_amount.data, ecdhInfo[i].amount.bytes, sizeof(trunc_amount));
- FIELD(trunc_amount);
+ FIELD_N("amount", trunc_amount);
if (!typename Archive<W>::is_saving()) // loading
memcpy(ecdhInfo[i].amount.bytes, trunc_amount.data, sizeof(trunc_amount));
ar.end_object();
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
index 2911aecb5..d1f97e324 100644
--- a/src/serialization/serialization.h
+++ b/src/serialization/serialization.h
@@ -123,6 +123,17 @@ inline bool do_serialize(Archive &ar, bool &v)
template <bool W, template <bool> class Archive> \
bool member_do_serialize(Archive<W> &ar) {
+/*! \macro BEGIN_SERIALIZE_FN
+ *
+ * \brief Begins the environment of the DSL as a free function
+ *
+ * Inside, instead of FIELD() and VARINT_FIELD(), use FIELD_F() and
+ * VARINT_FIELD_F(). Otherwise, this macro is similar to BEGIN_SERIALIZE().
+ */
+#define BEGIN_SERIALIZE_FN(stype) \
+ template <bool W, template <bool> class Archive> \
+ bool do_serialize(Archive<W> &ar, stype &v) {
+
/*! \macro BEGIN_SERIALIZE_OBJECT
*
* \brief begins the environment of the DSL
@@ -139,6 +150,27 @@ inline bool do_serialize(Archive &ar, bool &v)
template <bool W, template <bool> class Archive> \
bool do_serialize_object(Archive<W> &ar){
+/*! \macro BEGIN_SERIALIZE_OBJECT_FN
+ *
+ * \brief Begins the environment of the DSL as a free function in object-style
+ *
+ * Inside, instead of FIELD() and VARINT_FIELD(), use FIELD_F() and
+ * VARINT_FIELD_F(). Otherwise, this macro is similar to
+ * BEGIN_SERIALIZE_OBJECT(), as you should list only field serializations.
+ */
+#define BEGIN_SERIALIZE_OBJECT_FN(stype) \
+ template <bool W, template <bool> class Archive> \
+ bool do_serialize_object(Archive<W> &ar, stype &v); \
+ template <bool W, template <bool> class Archive> \
+ bool do_serialize(Archive<W> &ar, stype &v) { \
+ ar.begin_object(); \
+ bool r = do_serialize_object(ar, v); \
+ ar.end_object(); \
+ return r; \
+ } \
+ template <bool W, template <bool> class Archive> \
+ bool do_serialize_object(Archive<W> &ar, stype &v) { \
+
/*! \macro PREPARE_CUSTOM_VECTOR_SERIALIZATION
*/
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) \
@@ -173,6 +205,12 @@ inline bool do_serialize(Archive &ar, bool &v)
if (!r || !ar.good()) return false; \
} while(0);
+/*! \macro FIELD_F(f)
+ *
+ * \brief tags the field with the variable name and then serializes it (for use in a free function)
+ */
+#define FIELD_F(f) FIELD_N(#f, v.f)
+
/*! \macro FIELDS(f)
*
* \brief does not add a tag to the serialized value
@@ -204,6 +242,12 @@ inline bool do_serialize(Archive &ar, bool &v)
if (!ar.good()) return false; \
} while(0);
+/*! \macro VARINT_FIELD_F(f)
+ *
+ * \brief tags and serializes the varint \a f (for use in a free function)
+ */
+#define VARINT_FIELD_F(f) VARINT_FIELD_N(#f, v.f)
+
/*! \macro MAGIC_FIELD(m)
*/
#define MAGIC_FIELD(m) \
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index bff62f1a8..34681cddf 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -819,7 +819,6 @@ bool simple_wallet::print_seed(bool encrypted)
{
bool success = false;
epee::wipeable_string seed;
- bool ready, multisig;
if (m_wallet->key_on_device())
{
@@ -832,10 +831,10 @@ bool simple_wallet::print_seed(bool encrypted)
return true;
}
- multisig = m_wallet->multisig(&ready);
- if (multisig)
+ 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)
{
fail_msg_writer() << tr("wallet is multisig but not yet finalized");
return true;
@@ -844,7 +843,7 @@ bool simple_wallet::print_seed(bool encrypted)
SCOPED_WALLET_UNLOCK();
- if (!multisig && !m_wallet->is_deterministic())
+ if (!ms_status.multisig_is_active && !m_wallet->is_deterministic())
{
fail_msg_writer() << tr("wallet is non-deterministic and has no seed");
return true;
@@ -859,7 +858,7 @@ bool simple_wallet::print_seed(bool encrypted)
seed_pass = pwd_container->password();
}
- if (multisig)
+ if (ms_status.multisig_is_active)
success = m_wallet->get_multisig_seed(seed, seed_pass);
else if (m_wallet->is_deterministic())
success = m_wallet->get_seed(seed, seed_pass);
@@ -898,7 +897,7 @@ bool simple_wallet::seed_set_language(const std::vector<std::string> &args/* = s
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
fail_msg_writer() << tr("wallet is multisig and has no seed");
return true;
@@ -1044,7 +1043,7 @@ bool simple_wallet::prepare_multisig_main(const std::vector<std::string> &args,
fail_msg_writer() << tr("command not supported by HW wallet");
return false;
}
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
fail_msg_writer() << tr("This wallet is already multisig");
return false;
@@ -1091,7 +1090,7 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo
fail_msg_writer() << tr("command not supported by HW wallet");
return false;
}
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
fail_msg_writer() << tr("This wallet is already multisig");
return false;
@@ -1136,9 +1135,7 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo
auto local_args = args;
local_args.erase(local_args.begin());
std::string multisig_extra_info = m_wallet->make_multisig(orig_pwd_container->password(), local_args, threshold);
- bool ready;
- m_wallet->multisig(&ready);
- if (!ready)
+ if (!m_wallet->get_multisig_status().is_ready)
{
success_msg_writer() << tr("Another step is needed");
success_msg_writer() << multisig_extra_info;
@@ -1156,13 +1153,13 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo
return false;
}
- uint32_t total;
- if (!m_wallet->multisig(NULL, &threshold, &total))
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+ if (!ms_status.multisig_is_active)
{
fail_msg_writer() << tr("Error creating multisig: new wallet is not multisig");
return false;
}
- success_msg_writer() << std::to_string(threshold) << "/" << total << tr(" multisig address: ")
+ success_msg_writer() << std::to_string(ms_status.threshold) << "/" << ms_status.total << tr(" multisig address: ")
<< m_wallet->get_account().get_public_address_str(m_wallet->nettype());
return true;
@@ -1188,18 +1185,18 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> &
const bool force_update_use_with_caution,
const bool called_by_mms) {
CHECK_MULTISIG_ENABLED();
- bool ready;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
return false;
}
- if (!m_wallet->multisig(&ready))
+ if (!ms_status.multisig_is_active)
{
fail_msg_writer() << tr("This wallet is not multisig");
return false;
}
- if (ready)
+ if (ms_status.is_ready)
{
fail_msg_writer() << tr("This wallet is already finalized");
return false;
@@ -1215,9 +1212,7 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> &
try
{
std::string multisig_extra_info = m_wallet->exchange_multisig_keys(orig_pwd_container->password(), args, force_update_use_with_caution);
- bool ready;
- m_wallet->multisig(&ready);
- if (!ready)
+ if (!m_wallet->get_multisig_status().is_ready)
{
message_writer() << tr("Another step is needed");
message_writer() << multisig_extra_info;
@@ -1228,9 +1223,8 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> &
}
return true;
} else {
- uint32_t threshold, total;
- m_wallet->multisig(NULL, &threshold, &total);
- success_msg_writer() << tr("Multisig wallet has been successfully created. Current wallet type: ") << threshold << "/" << total;
+ const multisig::multisig_account_status ms_status_new{m_wallet->get_multisig_status()};
+ success_msg_writer() << tr("Multisig wallet has been successfully created. Current wallet type: ") << ms_status_new.threshold << "/" << ms_status_new.total;
success_msg_writer() << tr("Multisig address: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
}
@@ -1253,18 +1247,18 @@ bool simple_wallet::export_multisig(const std::vector<std::string> &args)
bool simple_wallet::export_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{
CHECK_MULTISIG_ENABLED();
- bool ready;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
return false;
}
- if (!m_wallet->multisig(&ready))
+ if (!ms_status.multisig_is_active)
{
fail_msg_writer() << tr("This wallet is not multisig");
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false;
@@ -1320,24 +1314,24 @@ bool simple_wallet::import_multisig(const std::vector<std::string> &args)
bool simple_wallet::import_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{
CHECK_MULTISIG_ENABLED();
- bool ready;
- uint32_t threshold, total;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
return false;
}
- if (!m_wallet->multisig(&ready, &threshold, &total))
+ if (!ms_status.multisig_is_active)
{
fail_msg_writer() << tr("This wallet is not multisig");
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false;
}
- if (args.size() < threshold - 1)
+ if (args.size() + 1 < ms_status.threshold)
{
PRINT_USAGE(USAGE_IMPORT_MULTISIG_INFO);
return false;
@@ -1417,18 +1411,19 @@ bool simple_wallet::sign_multisig(const std::vector<std::string> &args)
bool simple_wallet::sign_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{
CHECK_MULTISIG_ENABLED();
- bool ready;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};\
+
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
return false;
}
- if(!m_wallet->multisig(&ready))
+ if (!ms_status.multisig_is_active)
{
fail_msg_writer() << tr("This is not a multisig wallet");
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false;
@@ -1502,9 +1497,7 @@ bool simple_wallet::sign_multisig_main(const std::vector<std::string> &args, boo
if (txids.empty())
{
- uint32_t threshold;
- m_wallet->multisig(NULL, &threshold);
- uint32_t signers_needed = threshold - signers - 1;
+ uint32_t signers_needed = ms_status.threshold - signers - 1;
success_msg_writer(true) << tr("Transaction successfully signed to file ") << filename << ", "
<< signers_needed << " more signer(s) needed";
return true;
@@ -1534,19 +1527,19 @@ bool simple_wallet::submit_multisig(const std::vector<std::string> &args)
bool simple_wallet::submit_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{
CHECK_MULTISIG_ENABLED();
- bool ready;
- uint32_t threshold;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
return false;
}
- if (!m_wallet->multisig(&ready, &threshold))
+ if (!ms_status.multisig_is_active)
{
fail_msg_writer() << tr("This is not a multisig wallet");
return false;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false;
@@ -1584,10 +1577,10 @@ bool simple_wallet::submit_multisig_main(const std::vector<std::string> &args, b
return false;
}
}
- if (txs.m_signers.size() < threshold)
+ if (txs.m_signers.size() < ms_status.threshold)
{
fail_msg_writer() << (boost::format(tr("Multisig transaction signed by only %u signers, needs %u more signatures"))
- % txs.m_signers.size() % (threshold - txs.m_signers.size())).str();
+ % txs.m_signers.size() % (ms_status.threshold - txs.m_signers.size())).str();
return false;
}
@@ -1616,19 +1609,19 @@ bool simple_wallet::submit_multisig_main(const std::vector<std::string> &args, b
bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
{
CHECK_MULTISIG_ENABLED();
- bool ready;
- uint32_t threshold;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
- if (!m_wallet->multisig(&ready, &threshold))
+ if (!ms_status.multisig_is_active)
{
fail_msg_writer() << tr("This is not a multisig wallet");
return true;
}
- if (!ready)
+ if (!ms_status.is_ready)
{
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return true;
@@ -1654,10 +1647,10 @@ bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
fail_msg_writer() << tr("Failed to load multisig transaction from file");
return true;
}
- if (txs.m_signers.size() < threshold)
+ if (txs.m_signers.size() < ms_status.threshold)
{
fail_msg_writer() << (boost::format(tr("Multisig transaction signed by only %u signers, needs %u more signatures"))
- % txs.m_signers.size() % (threshold - txs.m_signers.size())).str();
+ % txs.m_signers.size() % (ms_status.threshold - txs.m_signers.size())).str();
return true;
}
@@ -3870,7 +3863,7 @@ void simple_wallet::print_seed(const epee::wipeable_string &seed)
{
success_msg_writer(true) << "\n" << boost::format(tr("NOTE: the following %s can be used to recover access to your wallet. "
"Write them down and store them somewhere safe and secure. Please do not store them in "
- "your email or on file storage services outside of your immediate control.\n")) % (m_wallet->multisig() ? tr("string") : tr("25 words"));
+ "your email or on file storage services outside of your immediate control.\n")) % (m_wallet->get_multisig_status().multisig_is_active ? tr("string") : tr("25 words"));
// don't log
int space_index = 0;
size_t len = seed.size();
@@ -4922,14 +4915,14 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
const epee::wipeable_string &msig_keys = m_wallet->decrypt<epee::wipeable_string>(std::string(multisig_keys.data(), multisig_keys.size()), key, true);
m_wallet->generate(m_wallet_file, std::move(rc.second).password(), msig_keys, create_address_file);
}
- bool ready;
- uint32_t threshold, total;
- if (!m_wallet->multisig(&ready, &threshold, &total) || !ready)
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
+ if (!ms_status.multisig_is_active || !ms_status.is_ready)
{
fail_msg_writer() << tr("failed to generate new mutlisig wallet");
return {};
}
- message_writer(console_color_white, true) << boost::format(tr("Generated new %u/%u multisig wallet: ")) % threshold % total
+ message_writer(console_color_white, true) << boost::format(tr("Generated new %u/%u multisig wallet: ")) % ms_status.threshold % ms_status.total
<< m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
catch (const std::exception& e)
@@ -4973,12 +4966,11 @@ boost::optional<epee::wipeable_string> simple_wallet::open_wallet(const boost::p
m_wallet->callback(this);
m_wallet->load(m_wallet_file, password);
std::string prefix;
- bool ready;
- uint32_t threshold, total;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (m_wallet->watch_only())
prefix = tr("Opened watch-only wallet");
- else if (m_wallet->multisig(&ready, &threshold, &total))
- prefix = (boost::format(tr("Opened %u/%u multisig wallet%s")) % threshold % total % (ready ? "" : " (not yet finalized)")).str();
+ else if (ms_status.multisig_is_active)
+ prefix = (boost::format(tr("Opened %u/%u multisig wallet%s")) % ms_status.threshold % ms_status.total % (ms_status.is_ready ? "" : " (not yet finalized)")).str();
else
prefix = tr("Opened wallet");
message_writer(console_color_white, true) <<
@@ -5096,7 +5088,7 @@ bool simple_wallet::save(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::save_watch_only(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
fail_msg_writer() << tr("wallet is multisig and cannot save a watch-only version");
return true;
@@ -6313,7 +6305,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
local_args.erase(local_args.begin());
}
- uint32_t priority = 0;
+ uint32_t priority = m_wallet->get_default_priority();
if (local_args.size() > 0 && parse_priority(local_args[0], priority))
local_args.erase(local_args.begin());
@@ -6676,7 +6668,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
// actually commit the transactions
- if (m_wallet->multisig() && called_by_mms)
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+ if (ms_status.multisig_is_active && called_by_mms)
{
std::string ciphertext = m_wallet->save_multisig_tx(ptx_vector);
if (!ciphertext.empty())
@@ -6685,7 +6678,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to MMS");
}
}
- else if (m_wallet->multisig())
+ else if (ms_status.multisig_is_active)
{
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
if (!r)
@@ -6839,7 +6832,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
}
// actually commit the transactions
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
@@ -7144,7 +7137,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
}
// actually commit the transactions
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
@@ -7379,7 +7372,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
}
// actually commit the transactions
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
@@ -7727,7 +7720,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
- if(m_wallet->multisig())
+ if(m_wallet->get_multisig_status().multisig_is_active)
{
fail_msg_writer() << tr("This is a multisig wallet, it can only sign with sign_multisig");
return true;
@@ -8260,7 +8253,7 @@ bool simple_wallet::get_reserve_proof(const std::vector<std::string> &args)
return true;
}
- if (m_wallet->watch_only() || m_wallet->multisig())
+ if (m_wallet->watch_only() || m_wallet->get_multisig_status().multisig_is_active)
{
fail_msg_writer() << tr("The reserve proof can be generated only by a full wallet");
return true;
@@ -9748,8 +9741,8 @@ bool simple_wallet::status(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::wallet_info(const std::vector<std::string> &args)
{
- bool ready;
- uint32_t threshold, total;
+ const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
+
std::string description = m_wallet->get_description();
if (description.empty())
{
@@ -9761,8 +9754,8 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
std::string type;
if (m_wallet->watch_only())
type = tr("Watch only");
- else if (m_wallet->multisig(&ready, &threshold, &total))
- type = (boost::format(tr("%u/%u multisig%s")) % threshold % total % (ready ? "" : " (not yet finalized)")).str();
+ else if (ms_status.multisig_is_active)
+ type = (boost::format(tr("%u/%u multisig%s")) % ms_status.threshold % ms_status.total % (ms_status.is_ready ? "" : " (not yet finalized)")).str();
else
type = tr("Normal");
message_writer() << tr("Type: ") << type;
@@ -9789,7 +9782,7 @@ bool simple_wallet::sign(const std::vector<std::string> &args)
fail_msg_writer() << tr("wallet is watch-only and cannot sign");
return true;
}
- if (m_wallet->multisig())
+ if (m_wallet->get_multisig_status().multisig_is_active)
{
fail_msg_writer() << tr("This wallet is multisig and cannot sign");
return true;
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)