Merge pull request #7852
8d94d08
replace 'multisig()' with 'get_multisig_status()' using multisig_account_status and including '.kex_is_done' member (koe)
This commit is contained in:
commit
3a47cdad13
|
@ -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());
|
||||||
|
|
|
@ -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:
|
||||||
*
|
*
|
||||||
|
|
|
@ -819,7 +819,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())
|
||||||
{
|
{
|
||||||
|
@ -832,10 +831,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;
|
||||||
|
@ -844,7 +843,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;
|
||||||
|
@ -859,7 +858,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);
|
||||||
|
@ -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");
|
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;
|
||||||
|
@ -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");
|
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;
|
||||||
|
@ -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");
|
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;
|
||||||
|
@ -1136,9 +1135,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;
|
||||||
|
@ -1156,13 +1153,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;
|
||||||
|
@ -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 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;
|
||||||
|
@ -1215,9 +1212,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;
|
||||||
|
@ -1228,9 +1223,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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
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;
|
||||||
|
@ -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)
|
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;
|
||||||
|
@ -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)
|
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;
|
||||||
|
@ -1502,9 +1497,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;
|
||||||
|
@ -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)
|
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;
|
||||||
|
@ -1584,10 +1577,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
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;
|
||||||
|
@ -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");
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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. "
|
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();
|
||||||
|
@ -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);
|
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)
|
||||||
|
@ -4973,12 +4966,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) <<
|
||||||
|
@ -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>()*/)
|
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;
|
||||||
|
@ -6676,7 +6668,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())
|
||||||
|
@ -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");
|
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)
|
||||||
|
@ -6839,7 +6832,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");
|
||||||
|
@ -7144,7 +7137,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");
|
||||||
|
@ -7379,7 +7372,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");
|
||||||
|
@ -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");
|
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;
|
||||||
|
@ -8260,7 +8253,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;
|
||||||
|
@ -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 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())
|
||||||
{
|
{
|
||||||
|
@ -9761,8 +9754,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;
|
||||||
|
@ -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");
|
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;
|
||||||
|
|
|
@ -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"
|
||||||
|
@ -87,12 +88,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,12 +107,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1297,7 +1300,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;
|
||||||
}
|
}
|
||||||
|
@ -1318,7 +1327,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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2053,8 +2062,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 {};
|
||||||
|
|
|
@ -322,9 +322,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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase) 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;
|
||||||
|
@ -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(),
|
THROW_WALLET_EXCEPTION_IF(num_expected_ms_keys != keys.m_multisig_keys.size(),
|
||||||
error::wallet_internal_error, "Unexpected number of private multisig keys")
|
error::wallet_internal_error, "Unexpected number of private multisig 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;
|
||||||
|
@ -5617,8 +5617,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;
|
||||||
|
@ -5745,20 +5745,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
|
||||||
|
@ -14302,9 +14312,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();
|
||||||
|
|
|
@ -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"
|
||||||
|
@ -1059,7 +1060,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()) const;
|
bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string()) const;
|
||||||
|
|
|
@ -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)
|
||||||
|
@ -1024,7 +1024,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())
|
||||||
|
@ -2066,10 +2066,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";
|
||||||
|
@ -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)
|
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;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -3992,7 +4000,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";
|
||||||
|
@ -4021,7 +4029,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";
|
||||||
|
@ -4059,14 +4067,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";
|
||||||
|
@ -4100,15 +4109,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";
|
||||||
|
@ -4116,7 +4125,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";
|
||||||
|
@ -4180,9 +4189,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";
|
||||||
|
@ -4190,7 +4199,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";
|
||||||
|
@ -4200,8 +4209,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());
|
||||||
}
|
}
|
||||||
|
@ -4224,15 +4233,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";
|
||||||
|
@ -4294,15 +4303,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";
|
||||||
|
@ -4327,7 +4336,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.";
|
||||||
|
|
|
@ -2323,12 +2323,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)
|
||||||
|
|
|
@ -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("");
|
||||||
|
|
||||||
|
@ -227,9 +227,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue