replace 'multisig()' with 'get_multisig_status()' using multisig_account_status and including '.kex_is_done' member

This commit is contained in:
koe 2021-08-11 07:35:43 -05:00
parent c5d10a4ac4
commit 8d94d08816
11 changed files with 197 additions and 154 deletions

View file

@ -121,16 +121,15 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str
} }
// exchange keys until the wallets are done // exchange keys until the wallets are done
bool ready{false}; multisig::multisig_account_status ms_status{wallets[0]->get_multisig_status()};
wallets[0]->multisig(&ready); while (!ms_status.is_ready)
while (!ready)
{ {
for (size_t n = 0; n < total; ++n) for (size_t n = 0; n < total; ++n)
{ {
kex_msgs_intermediate[n] = wallets[n]->exchange_multisig_keys(pwd_container->password(), kex_msgs_intermediate); 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()); std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->nettype());

View file

@ -40,6 +40,19 @@
namespace multisig 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: * multisig account:
* *

View file

@ -786,7 +786,6 @@ bool simple_wallet::print_seed(bool encrypted)
{ {
bool success = false; bool success = false;
epee::wipeable_string seed; epee::wipeable_string seed;
bool ready, multisig;
if (m_wallet->key_on_device()) if (m_wallet->key_on_device())
{ {
@ -799,10 +798,10 @@ bool simple_wallet::print_seed(bool encrypted)
return true; return true;
} }
multisig = m_wallet->multisig(&ready); const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (multisig) if (ms_status.multisig_is_active)
{ {
if (!ready) if (!ms_status.is_ready)
{ {
fail_msg_writer() << tr("wallet is multisig but not yet finalized"); fail_msg_writer() << tr("wallet is multisig but not yet finalized");
return true; return true;
@ -811,7 +810,7 @@ bool simple_wallet::print_seed(bool encrypted)
SCOPED_WALLET_UNLOCK(); 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"); fail_msg_writer() << tr("wallet is non-deterministic and has no seed");
return true; return true;
@ -826,7 +825,7 @@ bool simple_wallet::print_seed(bool encrypted)
seed_pass = pwd_container->password(); seed_pass = pwd_container->password();
} }
if (multisig) if (ms_status.multisig_is_active)
success = m_wallet->get_multisig_seed(seed, seed_pass); success = m_wallet->get_multisig_seed(seed, seed_pass);
else if (m_wallet->is_deterministic()) else if (m_wallet->is_deterministic())
success = m_wallet->get_seed(seed, seed_pass); success = m_wallet->get_seed(seed, seed_pass);
@ -865,7 +864,7 @@ bool simple_wallet::seed_set_language(const std::vector<std::string> &args/* = s
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return true; 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"); fail_msg_writer() << tr("wallet is multisig and has no seed");
return true; return true;
@ -1011,7 +1010,7 @@ bool simple_wallet::prepare_multisig_main(const std::vector<std::string> &args,
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return false; return false;
} }
if (m_wallet->multisig()) if (m_wallet->get_multisig_status().multisig_is_active)
{ {
fail_msg_writer() << tr("This wallet is already multisig"); fail_msg_writer() << tr("This wallet is already multisig");
return false; return false;
@ -1058,7 +1057,7 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return false; return false;
} }
if (m_wallet->multisig()) if (m_wallet->get_multisig_status().multisig_is_active)
{ {
fail_msg_writer() << tr("This wallet is already multisig"); fail_msg_writer() << tr("This wallet is already multisig");
return false; return false;
@ -1103,9 +1102,7 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo
auto local_args = args; auto local_args = args;
local_args.erase(local_args.begin()); local_args.erase(local_args.begin());
std::string multisig_extra_info = m_wallet->make_multisig(orig_pwd_container->password(), local_args, threshold); std::string multisig_extra_info = m_wallet->make_multisig(orig_pwd_container->password(), local_args, threshold);
bool ready; if (!m_wallet->get_multisig_status().is_ready)
m_wallet->multisig(&ready);
if (!ready)
{ {
success_msg_writer() << tr("Another step is needed"); success_msg_writer() << tr("Another step is needed");
success_msg_writer() << multisig_extra_info; success_msg_writer() << multisig_extra_info;
@ -1123,13 +1120,13 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo
return false; return false;
} }
uint32_t total; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (!m_wallet->multisig(NULL, &threshold, &total)) if (!ms_status.multisig_is_active)
{ {
fail_msg_writer() << tr("Error creating multisig: new wallet is not multisig"); fail_msg_writer() << tr("Error creating multisig: new wallet is not multisig");
return false; 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()); << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
return true; return true;
@ -1155,18 +1152,18 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> &
const bool force_update_use_with_caution, const bool force_update_use_with_caution,
const bool called_by_mms) { const bool called_by_mms) {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (m_wallet->key_on_device()) if (m_wallet->key_on_device())
{ {
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return false; return false;
} }
if (!m_wallet->multisig(&ready)) if (!ms_status.multisig_is_active)
{ {
fail_msg_writer() << tr("This wallet is not multisig"); fail_msg_writer() << tr("This wallet is not multisig");
return false; return false;
} }
if (ready) if (ms_status.is_ready)
{ {
fail_msg_writer() << tr("This wallet is already finalized"); fail_msg_writer() << tr("This wallet is already finalized");
return false; return false;
@ -1182,9 +1179,7 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> &
try try
{ {
std::string multisig_extra_info = m_wallet->exchange_multisig_keys(orig_pwd_container->password(), args, force_update_use_with_caution); std::string multisig_extra_info = m_wallet->exchange_multisig_keys(orig_pwd_container->password(), args, force_update_use_with_caution);
bool ready; if (!m_wallet->get_multisig_status().is_ready)
m_wallet->multisig(&ready);
if (!ready)
{ {
message_writer() << tr("Another step is needed"); message_writer() << tr("Another step is needed");
message_writer() << multisig_extra_info; message_writer() << multisig_extra_info;
@ -1195,9 +1190,8 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> &
} }
return true; return true;
} else { } else {
uint32_t threshold, total; const multisig::multisig_account_status ms_status_new{m_wallet->get_multisig_status()};
m_wallet->multisig(NULL, &threshold, &total); 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 wallet has been successfully created. Current wallet type: ") << threshold << "/" << total;
success_msg_writer() << tr("Multisig address: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); success_msg_writer() << tr("Multisig address: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
} }
} }
@ -1220,18 +1214,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) bool simple_wallet::export_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (m_wallet->key_on_device()) if (m_wallet->key_on_device())
{ {
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return false; return false;
} }
if (!m_wallet->multisig(&ready)) if (!ms_status.multisig_is_active)
{ {
fail_msg_writer() << tr("This wallet is not multisig"); fail_msg_writer() << tr("This wallet is not multisig");
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
fail_msg_writer() << tr("This multisig wallet is not yet finalized"); fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false; return false;
@ -1287,24 +1281,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) bool simple_wallet::import_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
if (m_wallet->key_on_device()) if (m_wallet->key_on_device())
{ {
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return false; return false;
} }
if (!m_wallet->multisig(&ready, &threshold, &total)) if (!ms_status.multisig_is_active)
{ {
fail_msg_writer() << tr("This wallet is not multisig"); fail_msg_writer() << tr("This wallet is not multisig");
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
fail_msg_writer() << tr("This multisig wallet is not yet finalized"); fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false; return false;
} }
if (args.size() < threshold - 1) if (args.size() + 1 < ms_status.threshold)
{ {
PRINT_USAGE(USAGE_IMPORT_MULTISIG_INFO); PRINT_USAGE(USAGE_IMPORT_MULTISIG_INFO);
return false; return false;
@ -1384,18 +1378,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) bool simple_wallet::sign_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};\
if (m_wallet->key_on_device()) if (m_wallet->key_on_device())
{ {
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return false; return false;
} }
if(!m_wallet->multisig(&ready)) if (!ms_status.multisig_is_active)
{ {
fail_msg_writer() << tr("This is not a multisig wallet"); fail_msg_writer() << tr("This is not a multisig wallet");
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
fail_msg_writer() << tr("This multisig wallet is not yet finalized"); fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false; return false;
@ -1469,9 +1464,7 @@ bool simple_wallet::sign_multisig_main(const std::vector<std::string> &args, boo
if (txids.empty()) if (txids.empty())
{ {
uint32_t threshold; uint32_t signers_needed = ms_status.threshold - signers - 1;
m_wallet->multisig(NULL, &threshold);
uint32_t signers_needed = threshold - signers - 1;
success_msg_writer(true) << tr("Transaction successfully signed to file ") << filename << ", " success_msg_writer(true) << tr("Transaction successfully signed to file ") << filename << ", "
<< signers_needed << " more signer(s) needed"; << signers_needed << " more signer(s) needed";
return true; return true;
@ -1501,19 +1494,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) bool simple_wallet::submit_multisig_main(const std::vector<std::string> &args, bool called_by_mms)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold;
if (m_wallet->key_on_device()) if (m_wallet->key_on_device())
{ {
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return false; return false;
} }
if (!m_wallet->multisig(&ready, &threshold)) if (!ms_status.multisig_is_active)
{ {
fail_msg_writer() << tr("This is not a multisig wallet"); fail_msg_writer() << tr("This is not a multisig wallet");
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
fail_msg_writer() << tr("This multisig wallet is not yet finalized"); fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return false; return false;
@ -1551,10 +1544,10 @@ bool simple_wallet::submit_multisig_main(const std::vector<std::string> &args, b
return false; 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")) 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; return false;
} }
@ -1583,19 +1576,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) bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold;
if (m_wallet->key_on_device()) if (m_wallet->key_on_device())
{ {
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return true; return true;
} }
if (!m_wallet->multisig(&ready, &threshold)) if (!ms_status.multisig_is_active)
{ {
fail_msg_writer() << tr("This is not a multisig wallet"); fail_msg_writer() << tr("This is not a multisig wallet");
return true; return true;
} }
if (!ready) if (!ms_status.is_ready)
{ {
fail_msg_writer() << tr("This multisig wallet is not yet finalized"); fail_msg_writer() << tr("This multisig wallet is not yet finalized");
return true; return true;
@ -1621,10 +1614,10 @@ bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
fail_msg_writer() << tr("Failed to load multisig transaction from file"); fail_msg_writer() << tr("Failed to load multisig transaction from file");
return true; 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")) 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; return true;
} }
@ -4053,7 +4046,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. " 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 " "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 // don't log
int space_index = 0; int space_index = 0;
size_t len = seed.size(); size_t len = seed.size();
@ -5115,14 +5108,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); 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); m_wallet->generate(m_wallet_file, std::move(rc.second).password(), msig_keys, create_address_file);
} }
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
if (!m_wallet->multisig(&ready, &threshold, &total) || !ready) if (!ms_status.multisig_is_active || !ms_status.is_ready)
{ {
fail_msg_writer() << tr("failed to generate new mutlisig wallet"); fail_msg_writer() << tr("failed to generate new mutlisig wallet");
return {}; 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()); << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -5166,12 +5159,11 @@ boost::optional<epee::wipeable_string> simple_wallet::open_wallet(const boost::p
m_wallet->callback(this); m_wallet->callback(this);
m_wallet->load(m_wallet_file, password); m_wallet->load(m_wallet_file, password);
std::string prefix; std::string prefix;
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
if (m_wallet->watch_only()) if (m_wallet->watch_only())
prefix = tr("Opened watch-only wallet"); prefix = tr("Opened watch-only wallet");
else if (m_wallet->multisig(&ready, &threshold, &total)) else if (ms_status.multisig_is_active)
prefix = (boost::format(tr("Opened %u/%u multisig wallet%s")) % threshold % total % (ready ? "" : " (not yet finalized)")).str(); 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 else
prefix = tr("Opened wallet"); prefix = tr("Opened wallet");
message_writer(console_color_white, true) << message_writer(console_color_white, true) <<
@ -5290,7 +5282,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>()*/) 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"); fail_msg_writer() << tr("wallet is multisig and cannot save a watch-only version");
return true; return true;
@ -6906,7 +6898,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
} }
// actually commit the transactions // 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); std::string ciphertext = m_wallet->save_multisig_tx(ptx_vector);
if (!ciphertext.empty()) if (!ciphertext.empty())
@ -6915,7 +6908,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"); 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"); bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
if (!r) if (!r)
@ -7069,7 +7062,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
} }
// actually commit the transactions // actually commit the transactions
if (m_wallet->multisig()) if (m_wallet->get_multisig_status().multisig_is_active)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
@ -7374,7 +7367,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
} }
// actually commit the transactions // actually commit the transactions
if (m_wallet->multisig()) if (m_wallet->get_multisig_status().multisig_is_active)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
@ -7609,7 +7602,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
} }
// actually commit the transactions // actually commit the transactions
if (m_wallet->multisig()) if (m_wallet->get_multisig_status().multisig_is_active)
{ {
CHECK_MULTISIG_ENABLED(); CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
@ -7957,7 +7950,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
fail_msg_writer() << tr("command not supported by HW wallet"); fail_msg_writer() << tr("command not supported by HW wallet");
return true; 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"); fail_msg_writer() << tr("This is a multisig wallet, it can only sign with sign_multisig");
return true; return true;
@ -8490,7 +8483,7 @@ bool simple_wallet::get_reserve_proof(const std::vector<std::string> &args)
return true; 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"); fail_msg_writer() << tr("The reserve proof can be generated only by a full wallet");
return true; return true;
@ -10051,8 +10044,8 @@ bool simple_wallet::status(const std::vector<std::string> &args)
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
bool simple_wallet::wallet_info(const std::vector<std::string> &args) bool simple_wallet::wallet_info(const std::vector<std::string> &args)
{ {
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
std::string description = m_wallet->get_description(); std::string description = m_wallet->get_description();
if (description.empty()) if (description.empty())
{ {
@ -10064,8 +10057,8 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
std::string type; std::string type;
if (m_wallet->watch_only()) if (m_wallet->watch_only())
type = tr("Watch only"); type = tr("Watch only");
else if (m_wallet->multisig(&ready, &threshold, &total)) else if (ms_status.multisig_is_active)
type = (boost::format(tr("%u/%u multisig%s")) % threshold % total % (ready ? "" : " (not yet finalized)")).str(); type = (boost::format(tr("%u/%u multisig%s")) % ms_status.threshold % ms_status.total % (ms_status.is_ready ? "" : " (not yet finalized)")).str();
else else
type = tr("Normal"); type = tr("Normal");
message_writer() << tr("Type: ") << type; message_writer() << tr("Type: ") << type;
@ -10092,7 +10085,7 @@ bool simple_wallet::sign(const std::vector<std::string> &args)
fail_msg_writer() << tr("wallet is watch-only and cannot sign"); fail_msg_writer() << tr("wallet is watch-only and cannot sign");
return true; 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"); fail_msg_writer() << tr("This wallet is multisig and cannot sign");
return true; return true;

View file

@ -38,6 +38,7 @@
#include "subaddress_account.h" #include "subaddress_account.h"
#include "common_defines.h" #include "common_defines.h"
#include "common/util.h" #include "common/util.h"
#include "multisig/multisig_account.h"
#include "mnemonics/electrum-words.h" #include "mnemonics/electrum-words.h"
#include "mnemonics/english.h" #include "mnemonics/english.h"
@ -84,12 +85,13 @@ namespace {
throw runtime_error("Wallet is not initialized yet"); throw runtime_error("Wallet is not initialized yet");
} }
bool ready; const multisig::multisig_account_status ms_status{wallet->get_multisig_status()};
if (!wallet->multisig(&ready)) {
if (!ms_status.multisig_is_active) {
throw runtime_error("Wallet is not multisig"); throw runtime_error("Wallet is not multisig");
} }
if (!ready) { if (!ms_status.is_ready) {
throw runtime_error("Multisig wallet is not finalized yet"); throw runtime_error("Multisig wallet is not finalized yet");
} }
} }
@ -102,12 +104,13 @@ namespace {
throw runtime_error("Wallet is not initialized yet"); throw runtime_error("Wallet is not initialized yet");
} }
bool ready; const multisig::multisig_account_status ms_status{wallet->get_multisig_status()};
if (!wallet->multisig(&ready)) {
if (!ms_status.multisig_is_active) {
throw runtime_error("Wallet is not multisig"); throw runtime_error("Wallet is not multisig");
} }
if (ready) { if (ms_status.is_ready) {
throw runtime_error("Multisig wallet is already finalized"); throw runtime_error("Multisig wallet is already finalized");
} }
} }
@ -1362,7 +1365,13 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex
MultisigState WalletImpl::multisig() const { MultisigState WalletImpl::multisig() const {
MultisigState state; 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; return state;
} }
@ -1383,7 +1392,7 @@ string WalletImpl::makeMultisig(const vector<string>& info, const uint32_t thres
try { try {
clearStatus(); clearStatus();
if (m_wallet->multisig()) { if (m_wallet->get_multisig_status().multisig_is_active) {
throw runtime_error("Wallet is already multisig"); throw runtime_error("Wallet is already multisig");
} }
@ -2118,8 +2127,8 @@ std::string WalletImpl::signMultisigParticipant(const std::string &message) cons
{ {
clearStatus(); clearStatus();
bool ready = false; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (!m_wallet->multisig(&ready) || !ready) { if (!ms_status.multisig_is_active || !ms_status.is_ready) {
m_status = Status_Error; m_status = Status_Error;
m_errorString = tr("The wallet must be in multisig ready state"); m_errorString = tr("The wallet must be in multisig ready state");
return {}; return {};

View file

@ -321,9 +321,10 @@ struct SubaddressAccount
}; };
struct MultisigState { 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 isMultisig;
bool kexIsDone;
bool isReady; bool isReady;
uint32_t threshold; uint32_t threshold;
uint32_t total; uint32_t total;

View file

@ -245,18 +245,23 @@ namespace mms
crypto::secret_key view_secret_key; crypto::secret_key view_secret_key;
bool multisig; bool multisig;
bool multisig_is_ready; bool multisig_is_ready;
bool multisig_kex_is_done;
bool has_multisig_partial_key_images; bool has_multisig_partial_key_images;
uint32_t multisig_rounds_passed; uint32_t multisig_rounds_passed;
size_t num_transfer_details; size_t num_transfer_details;
std::string mms_file; std::string mms_file;
BEGIN_SERIALIZE_OBJECT() BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0) VERSION_FIELD(1)
FIELD(address) FIELD(address)
VARINT_FIELD(nettype) VARINT_FIELD(nettype)
FIELD(view_secret_key) FIELD(view_secret_key)
FIELD(multisig) FIELD(multisig)
FIELD(multisig_is_ready) 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) FIELD(has_multisig_partial_key_images)
VARINT_FIELD(multisig_rounds_passed) VARINT_FIELD(multisig_rounds_passed)
VARINT_FIELD(num_transfer_details) VARINT_FIELD(num_transfer_details)

View file

@ -1412,14 +1412,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, bool raw) const bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase, bool raw) const
{ {
bool ready; const multisig::multisig_account_status ms_status{get_multisig_status()};
uint32_t threshold, total;
if (!multisig(&ready, &threshold, &total)) if (!ms_status.multisig_is_active)
{ {
std::cout << "This is not a multisig wallet" << std::endl; std::cout << "This is not a multisig wallet" << std::endl;
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
std::cout << "This multisig wallet is not yet finalized" << std::endl; std::cout << "This multisig wallet is not yet finalized" << std::endl;
return false; return false;
@ -1434,8 +1434,8 @@ bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeabl
crypto::public_key pkey; crypto::public_key pkey;
const account_keys &keys = get_account().get_keys(); const account_keys &keys = get_account().get_keys();
epee::wipeable_string data; epee::wipeable_string data;
data.append((const char*)&threshold, sizeof(uint32_t)); data.append((const char*)&ms_status.threshold, sizeof(uint32_t));
data.append((const char*)&total, sizeof(uint32_t)); data.append((const char*)&ms_status.total, sizeof(uint32_t));
skey = keys.m_spend_secret_key; skey = keys.m_spend_secret_key;
data.append((const char*)&skey, sizeof(skey)); data.append((const char*)&skey, sizeof(skey));
pkey = keys.m_account_address.m_spend_public_key; pkey = keys.m_account_address.m_spend_public_key;
@ -5135,8 +5135,8 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
const std::vector<std::string> &kex_messages, const std::vector<std::string> &kex_messages,
const bool force_update_use_with_caution /*= false*/) const bool force_update_use_with_caution /*= false*/)
{ {
bool ready{false}; const multisig::multisig_account_status ms_status{get_multisig_status()};
CHECK_AND_ASSERT_THROW_MES(multisig(&ready), "The wallet is not multisig"); CHECK_AND_ASSERT_THROW_MES(ms_status.multisig_is_active, "The wallet is not multisig");
// decrypt account keys // decrypt account keys
epee::misc_utils::auto_scope_leave_caller keys_reencryptor; epee::misc_utils::auto_scope_leave_caller keys_reencryptor;
@ -5263,20 +5263,30 @@ std::string wallet2::get_multisig_first_kex_msg() const
return multisig_account.get_next_kex_round_msg(); 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) multisig::multisig_account_status ret;
return false;
if (threshold) if (m_multisig)
*threshold = m_multisig_threshold;
if (total)
*total = m_multisig_signers.size();
if (ready)
{ {
*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)); (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 bool wallet2::has_multisig_partial_key_images() const
@ -14332,9 +14342,13 @@ void wallet2::generate_genesis(cryptonote::block& b) const {
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
mms::multisig_wallet_state wallet2::get_multisig_wallet_state() 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; mms::multisig_wallet_state state;
state.nettype = m_nettype; 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.has_multisig_partial_key_images = has_multisig_partial_key_images();
state.multisig_rounds_passed = m_multisig_rounds_passed; state.multisig_rounds_passed = m_multisig_rounds_passed;
state.num_transfer_details = m_transfers.size(); state.num_transfer_details = m_transfers.size();

View file

@ -57,6 +57,7 @@
#include "common/util.h" #include "common/util.h"
#include "crypto/chacha.h" #include "crypto/chacha.h"
#include "crypto/hash.h" #include "crypto/hash.h"
#include "multisig/multisig_account.h"
#include "ringct/rctTypes.h" #include "ringct/rctTypes.h"
#include "ringct/rctOps.h" #include "ringct/rctOps.h"
#include "checkpoints/checkpoints.h" #include "checkpoints/checkpoints.h"
@ -1031,7 +1032,7 @@ private:
cryptonote::network_type nettype() const { return m_nettype; } cryptonote::network_type nettype() const { return m_nettype; }
bool watch_only() const { return m_watch_only; } 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_multisig_partial_key_images() const;
bool has_unknown_key_images() const; bool has_unknown_key_images() const;
bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const; bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const;

View file

@ -65,7 +65,7 @@ using namespace epee;
#define CHECK_MULTISIG_ENABLED() \ #define CHECK_MULTISIG_ENABLED() \
do \ 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.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"; \ 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.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.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, 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; 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) if (req.all_accounts)
@ -1018,7 +1018,7 @@ namespace tools
fill(spent_key_images, key_image_list); 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)); multisig_txset = epee::string_tools::buff_to_hex_nodelimer(m_wallet->save_multisig_tx(ptx_vector));
if (multisig_txset.empty()) if (multisig_txset.empty())
@ -2060,10 +2060,11 @@ namespace tools
if (req.key_type.compare("mnemonic") == 0) if (req.key_type.compare("mnemonic") == 0)
{ {
epee::wipeable_string seed; epee::wipeable_string seed;
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (m_wallet->multisig(&ready))
if (ms_status.multisig_is_active)
{ {
if (!ready) if (!ms_status.is_ready)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized"; er.message = "This wallet is multisig, but not yet finalized";
@ -3942,7 +3943,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) 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); 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; return true;
} }
//------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------
@ -3955,7 +3963,7 @@ namespace tools
er.message = "Command unavailable in restricted mode."; er.message = "Command unavailable in restricted mode.";
return false; return false;
} }
if (m_wallet->multisig()) if (m_wallet->get_multisig_status().multisig_is_active)
{ {
er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG;
er.message = "This wallet is already multisig"; er.message = "This wallet is already multisig";
@ -3984,7 +3992,7 @@ namespace tools
er.message = "Command unavailable in restricted mode."; er.message = "Command unavailable in restricted mode.";
return false; return false;
} }
if (m_wallet->multisig()) if (m_wallet->get_multisig_status().multisig_is_active)
{ {
er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG;
er.message = "This wallet is already multisig"; er.message = "This wallet is already multisig";
@ -4022,14 +4030,15 @@ namespace tools
er.message = "Command unavailable in restricted mode."; er.message = "Command unavailable in restricted mode.";
return false; return false;
} }
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
if (!m_wallet->multisig(&ready))
if (!ms_status.multisig_is_active)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig"; er.message = "This wallet is not multisig";
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized"; er.message = "This wallet is multisig, but not yet finalized";
@ -4063,15 +4072,15 @@ namespace tools
er.message = "Command unavailable in restricted mode."; er.message = "Command unavailable in restricted mode.";
return false; return false;
} }
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
if (!m_wallet->multisig(&ready, &threshold, &total)) if (!ms_status.multisig_is_active)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig"; er.message = "This wallet is not multisig";
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized"; er.message = "This wallet is multisig, but not yet finalized";
@ -4079,7 +4088,7 @@ namespace tools
} }
CHECK_MULTISIG_ENABLED(); 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.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED;
er.message = "Needs multisig export info from more participants"; er.message = "Needs multisig export info from more participants";
@ -4143,9 +4152,9 @@ namespace tools
er.message = "Command unavailable in restricted mode."; er.message = "Command unavailable in restricted mode.";
return false; return false;
} }
bool ready; multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
if (!m_wallet->multisig(&ready, &threshold, &total)) if (!ms_status.multisig_is_active)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig"; er.message = "This wallet is not multisig";
@ -4153,7 +4162,7 @@ namespace tools
} }
CHECK_MULTISIG_ENABLED(); 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.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED;
er.message = "Needs multisig info from more participants"; er.message = "Needs multisig info from more participants";
@ -4163,8 +4172,8 @@ namespace tools
try try
{ {
res.multisig_info = m_wallet->exchange_multisig_keys(req.password, req.multisig_info, req.force_update_use_with_caution); res.multisig_info = m_wallet->exchange_multisig_keys(req.password, req.multisig_info, req.force_update_use_with_caution);
m_wallet->multisig(&ready); ms_status = m_wallet->get_multisig_status();
if (ready) if (ms_status.is_ready)
{ {
res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype());
} }
@ -4187,15 +4196,15 @@ namespace tools
er.message = "Command unavailable in restricted mode."; er.message = "Command unavailable in restricted mode.";
return false; return false;
} }
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
if (!m_wallet->multisig(&ready, &threshold, &total)) if (!ms_status.multisig_is_active)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig"; er.message = "This wallet is not multisig";
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized"; er.message = "This wallet is multisig, but not yet finalized";
@ -4257,15 +4266,15 @@ namespace tools
er.message = "Command unavailable in restricted mode."; er.message = "Command unavailable in restricted mode.";
return false; return false;
} }
bool ready; const multisig::multisig_account_status ms_status{m_wallet->get_multisig_status()};
uint32_t threshold, total;
if (!m_wallet->multisig(&ready, &threshold, &total)) if (!ms_status.multisig_is_active)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is not multisig"; er.message = "This wallet is not multisig";
return false; return false;
} }
if (!ready) if (!ms_status.is_ready)
{ {
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
er.message = "This wallet is multisig, but not yet finalized"; er.message = "This wallet is multisig, but not yet finalized";
@ -4290,7 +4299,7 @@ namespace tools
return false; 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.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED;
er.message = "Not enough signers signed this transaction."; er.message = "Not enough signers signed this transaction.";

View file

@ -2402,12 +2402,14 @@ namespace wallet_rpc
struct response_t struct response_t
{ {
bool multisig; bool multisig;
bool kex_is_done;
bool ready; bool ready;
uint32_t threshold; uint32_t threshold;
uint32_t total; uint32_t total;
BEGIN_KV_SERIALIZE_MAP() BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(multisig) KV_SERIALIZE(multisig)
KV_SERIALIZE(kex_is_done)
KV_SERIALIZE(ready) KV_SERIALIZE(ready)
KV_SERIALIZE(threshold) KV_SERIALIZE(threshold)
KV_SERIALIZE(total) KV_SERIALIZE(total)

View file

@ -159,12 +159,12 @@ static void check_results(const std::vector<std::string> &intermediate_infos,
for (size_t i = 0; i < wallets.size(); ++i) for (size_t i = 0; i < wallets.size(); ++i)
{ {
EXPECT_TRUE(!intermediate_infos[i].empty()); EXPECT_TRUE(!intermediate_infos[i].empty());
bool ready; const multisig::multisig_account_status ms_status{wallets[i].get_multisig_status()};
uint32_t threshold, total; EXPECT_TRUE(ms_status.multisig_is_active);
EXPECT_TRUE(wallets[i].multisig(&ready, &threshold, &total)); EXPECT_TRUE(ms_status.kex_is_done);
EXPECT_TRUE(ready); EXPECT_TRUE(ms_status.is_ready);
EXPECT_TRUE(threshold == M); EXPECT_TRUE(ms_status.threshold == M);
EXPECT_TRUE(total == wallets.size()); EXPECT_TRUE(ms_status.total == wallets.size());
wallets[i].decrypt_keys(""); wallets[i].decrypt_keys("");
@ -226,10 +226,8 @@ static void make_wallets(const unsigned int M, const unsigned int N, const bool
} }
// wallets should not be multisig yet // wallets should not be multisig yet
for (const auto &wallet: wallets) for (const auto& wallet: wallets)
{ ASSERT_FALSE(wallet.get_multisig_status().multisig_is_active);
ASSERT_FALSE(wallet.multisig());
}
// make wallets multisig, get second round kex messages (if appropriate) // make wallets multisig, get second round kex messages (if appropriate)
std::vector<std::string> intermediate_infos(wallets.size()); std::vector<std::string> intermediate_infos(wallets.size());
@ -242,16 +240,15 @@ static void make_wallets(const unsigned int M, const unsigned int N, const bool
++rounds_complete; ++rounds_complete;
// perform kex rounds until kex is complete // perform kex rounds until kex is complete
bool ready; multisig::multisig_account_status ms_status{wallets[0].get_multisig_status()};
wallets[0].multisig(&ready); while (!ms_status.is_ready)
while (!ready)
{ {
if (force_update) if (force_update)
intermediate_infos = exchange_round_force_update(wallets, intermediate_infos, rounds_complete + 1); intermediate_infos = exchange_round_force_update(wallets, intermediate_infos, rounds_complete + 1);
else else
intermediate_infos = exchange_round(wallets, intermediate_infos); intermediate_infos = exchange_round(wallets, intermediate_infos);
wallets[0].multisig(&ready); ms_status = wallets[0].get_multisig_status();
++rounds_complete; ++rounds_complete;
} }