mirror of
https://codeberg.org/anoncontributorxmr/monero.git
synced 2024-11-26 17:32:33 +00:00
wallet: guard against partly initialized multisig wallet
This commit is contained in:
parent
66e34e85b1
commit
265290388b
6 changed files with 82 additions and 19 deletions
|
@ -849,11 +849,17 @@ bool simple_wallet::make_multisig(const std::vector<std::string> &args)
|
||||||
|
|
||||||
bool simple_wallet::finalize_multisig(const std::vector<std::string> &args)
|
bool simple_wallet::finalize_multisig(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
if (!m_wallet->multisig())
|
bool ready;
|
||||||
|
if (!m_wallet->multisig(&ready))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("This wallet is not multisig");
|
fail_msg_writer() << tr("This wallet is not multisig");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (ready)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("This wallet is already finalized");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const auto orig_pwd_container = get_and_verify_password();
|
const auto orig_pwd_container = get_and_verify_password();
|
||||||
if(orig_pwd_container == boost::none)
|
if(orig_pwd_container == boost::none)
|
||||||
|
@ -887,11 +893,17 @@ bool simple_wallet::finalize_multisig(const std::vector<std::string> &args)
|
||||||
|
|
||||||
bool simple_wallet::export_multisig(const std::vector<std::string> &args)
|
bool simple_wallet::export_multisig(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
if (!m_wallet->multisig())
|
bool ready;
|
||||||
|
if (!m_wallet->multisig(&ready))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("This wallet is not multisig");
|
fail_msg_writer() << tr("This wallet is not multisig");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!ready)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("usage: export_multisig_info <filename>");
|
fail_msg_writer() << tr("usage: export_multisig_info <filename>");
|
||||||
|
@ -937,12 +949,18 @@ bool simple_wallet::export_multisig(const std::vector<std::string> &args)
|
||||||
|
|
||||||
bool simple_wallet::import_multisig(const std::vector<std::string> &args)
|
bool simple_wallet::import_multisig(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
|
bool ready;
|
||||||
uint32_t threshold, total;
|
uint32_t threshold, total;
|
||||||
if (!m_wallet->multisig(&threshold, &total))
|
if (!m_wallet->multisig(&ready, &threshold, &total))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("This wallet is not multisig");
|
fail_msg_writer() << tr("This wallet is not multisig");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!ready)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (args.size() < threshold - 1)
|
if (args.size() < threshold - 1)
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("usage: import_multisig_info <filename1> [<filename2>...] - one for each other participant");
|
fail_msg_writer() << tr("usage: import_multisig_info <filename1> [<filename2>...] - one for each other participant");
|
||||||
|
@ -1065,11 +1083,17 @@ bool simple_wallet::accept_loaded_tx(const tools::wallet2::multisig_tx_set &txs)
|
||||||
|
|
||||||
bool simple_wallet::sign_multisig(const std::vector<std::string> &args)
|
bool simple_wallet::sign_multisig(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
if(!m_wallet->multisig())
|
bool ready;
|
||||||
|
if(!m_wallet->multisig(&ready))
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("usage: sign_multisig <filename>");
|
fail_msg_writer() << tr("usage: sign_multisig <filename>");
|
||||||
|
@ -1103,7 +1127,7 @@ bool simple_wallet::sign_multisig(const std::vector<std::string> &args)
|
||||||
if (txids.empty())
|
if (txids.empty())
|
||||||
{
|
{
|
||||||
uint32_t threshold;
|
uint32_t threshold;
|
||||||
m_wallet->multisig(&threshold);
|
m_wallet->multisig(NULL, &threshold);
|
||||||
uint32_t signers_needed = threshold - signers - 1;
|
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";
|
||||||
|
@ -1126,12 +1150,18 @@ bool simple_wallet::sign_multisig(const std::vector<std::string> &args)
|
||||||
|
|
||||||
bool simple_wallet::submit_multisig(const std::vector<std::string> &args)
|
bool simple_wallet::submit_multisig(const std::vector<std::string> &args)
|
||||||
{
|
{
|
||||||
|
bool ready;
|
||||||
uint32_t threshold;
|
uint32_t threshold;
|
||||||
if (!m_wallet->multisig(&threshold))
|
if (!m_wallet->multisig(&ready, &threshold))
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << tr("This multisig wallet is not yet finalized");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
{
|
{
|
||||||
fail_msg_writer() << tr("usage: submit_multisig <filename>");
|
fail_msg_writer() << tr("usage: submit_multisig <filename>");
|
||||||
|
@ -2717,11 +2747,12 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
|
bool ready;
|
||||||
uint32_t threshold, total;
|
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(&threshold, &total))
|
else if (m_wallet->multisig(&ready, &threshold, &total))
|
||||||
prefix = (boost::format(tr("Opened %u/%u multisig wallet")) % threshold % total).str();
|
prefix = (boost::format(tr("Opened %u/%u multisig wallet%s")) % threshold % total % (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) <<
|
||||||
|
|
|
@ -3039,7 +3039,7 @@ bool wallet2::verify_extra_multisig_info(const std::string &data, std::unordered
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wallet2::multisig(uint32_t *threshold, uint32_t *total) const
|
bool wallet2::multisig(bool *ready, uint32_t *threshold, uint32_t *total) const
|
||||||
{
|
{
|
||||||
if (!m_multisig)
|
if (!m_multisig)
|
||||||
return false;
|
return false;
|
||||||
|
@ -3047,6 +3047,8 @@ bool wallet2::multisig(uint32_t *threshold, uint32_t *total) const
|
||||||
*threshold = m_multisig_threshold;
|
*threshold = m_multisig_threshold;
|
||||||
if (total)
|
if (total)
|
||||||
*total = m_multisig_signers.size();
|
*total = m_multisig_signers.size();
|
||||||
|
if (ready)
|
||||||
|
*ready = !(get_account().get_keys().m_account_address.m_spend_public_key == rct::rct2pk(rct::identity()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -598,7 +598,7 @@ namespace tools
|
||||||
bool testnet() const { return m_testnet; }
|
bool testnet() const { return m_testnet; }
|
||||||
bool restricted() const { return m_restricted; }
|
bool restricted() const { return m_restricted; }
|
||||||
bool watch_only() const { return m_watch_only; }
|
bool watch_only() const { return m_watch_only; }
|
||||||
bool multisig(uint32_t *threshold = NULL, uint32_t *total = NULL) const;
|
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
|
||||||
bool has_multisig_partial_key_images() const;
|
bool has_multisig_partial_key_images() const;
|
||||||
|
|
||||||
// locked & unlocked balance of given or current subaddress account
|
// locked & unlocked balance of given or current subaddress account
|
||||||
|
|
|
@ -2342,7 +2342,7 @@ 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)
|
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)
|
||||||
{
|
{
|
||||||
if (!m_wallet) return not_open(er);
|
if (!m_wallet) return not_open(er);
|
||||||
res.multisig = m_wallet->multisig(&res.threshold, &res.total);
|
res.multisig = m_wallet->multisig(&res.ready, &res.threshold, &res.total);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -2468,12 +2468,19 @@ namespace tools
|
||||||
er.message = "Command unavailable in restricted mode.";
|
er.message = "Command unavailable in restricted mode.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_wallet->multisig())
|
bool ready;
|
||||||
|
if (!m_wallet->multisig(&ready))
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
|
||||||
|
er.message = "This wallet is multisig, but not yet finalized";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<tools::wallet2::multisig_info> info;
|
std::vector<tools::wallet2::multisig_info> info;
|
||||||
try
|
try
|
||||||
|
@ -2514,13 +2521,20 @@ namespace tools
|
||||||
er.message = "Command unavailable in restricted mode.";
|
er.message = "Command unavailable in restricted mode.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool ready;
|
||||||
uint32_t threshold, total;
|
uint32_t threshold, total;
|
||||||
if (!m_wallet->multisig(&threshold, &total))
|
if (!m_wallet->multisig(&ready, &threshold, &total))
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG;
|
||||||
|
er.message = "This wallet is multisig, but not yet finalized";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (req.info.size() < threshold - 1)
|
if (req.info.size() < threshold - 1)
|
||||||
{
|
{
|
||||||
|
@ -2607,13 +2621,20 @@ namespace tools
|
||||||
er.message = "Command unavailable in restricted mode.";
|
er.message = "Command unavailable in restricted mode.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool ready;
|
||||||
uint32_t threshold, total;
|
uint32_t threshold, total;
|
||||||
if (!m_wallet->multisig(&threshold, &total))
|
if (!m_wallet->multisig(&ready, &threshold, &total))
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG;
|
||||||
|
er.message = "This wallet is multisig, and already finalized";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (req.multisig_info.size() < threshold - 1)
|
if (req.multisig_info.size() < threshold - 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1499,11 +1499,13 @@ namespace wallet_rpc
|
||||||
struct response
|
struct response
|
||||||
{
|
{
|
||||||
bool multisig;
|
bool multisig;
|
||||||
|
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(ready)
|
||||||
KV_SERIALIZE(threshold)
|
KV_SERIALIZE(threshold)
|
||||||
KV_SERIALIZE(total)
|
KV_SERIALIZE(total)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
|
|
|
@ -94,11 +94,14 @@ static void make_M_2_wallet(tools::wallet2 &wallet0, tools::wallet2 &wallet1, un
|
||||||
|
|
||||||
ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet1.get_account().get_public_address_str(true));
|
ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet1.get_account().get_public_address_str(true));
|
||||||
|
|
||||||
|
bool ready;
|
||||||
uint32_t threshold, total;
|
uint32_t threshold, total;
|
||||||
ASSERT_TRUE(wallet0.multisig(&threshold, &total));
|
ASSERT_TRUE(wallet0.multisig(&ready, &threshold, &total));
|
||||||
|
ASSERT_TRUE(ready);
|
||||||
ASSERT_TRUE(threshold == M);
|
ASSERT_TRUE(threshold == M);
|
||||||
ASSERT_TRUE(total == 2);
|
ASSERT_TRUE(total == 2);
|
||||||
ASSERT_TRUE(wallet1.multisig(&threshold, &total));
|
ASSERT_TRUE(wallet1.multisig(&ready, &threshold, &total));
|
||||||
|
ASSERT_TRUE(ready);
|
||||||
ASSERT_TRUE(threshold == M);
|
ASSERT_TRUE(threshold == M);
|
||||||
ASSERT_TRUE(total == 2);
|
ASSERT_TRUE(total == 2);
|
||||||
}
|
}
|
||||||
|
@ -149,14 +152,18 @@ static void make_M_3_wallet(tools::wallet2 &wallet0, tools::wallet2 &wallet1, to
|
||||||
ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet1.get_account().get_public_address_str(true));
|
ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet1.get_account().get_public_address_str(true));
|
||||||
ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet2.get_account().get_public_address_str(true));
|
ASSERT_TRUE(wallet0.get_account().get_public_address_str(true) == wallet2.get_account().get_public_address_str(true));
|
||||||
|
|
||||||
|
bool ready;
|
||||||
uint32_t threshold, total;
|
uint32_t threshold, total;
|
||||||
ASSERT_TRUE(wallet0.multisig(&threshold, &total));
|
ASSERT_TRUE(wallet0.multisig(&ready, &threshold, &total));
|
||||||
|
ASSERT_TRUE(ready);
|
||||||
ASSERT_TRUE(threshold == M);
|
ASSERT_TRUE(threshold == M);
|
||||||
ASSERT_TRUE(total == 3);
|
ASSERT_TRUE(total == 3);
|
||||||
ASSERT_TRUE(wallet1.multisig(&threshold, &total));
|
ASSERT_TRUE(wallet1.multisig(&ready, &threshold, &total));
|
||||||
|
ASSERT_TRUE(ready);
|
||||||
ASSERT_TRUE(threshold == M);
|
ASSERT_TRUE(threshold == M);
|
||||||
ASSERT_TRUE(total == 3);
|
ASSERT_TRUE(total == 3);
|
||||||
ASSERT_TRUE(wallet2.multisig(&threshold, &total));
|
ASSERT_TRUE(wallet2.multisig(&ready, &threshold, &total));
|
||||||
|
ASSERT_TRUE(ready);
|
||||||
ASSERT_TRUE(threshold == M);
|
ASSERT_TRUE(threshold == M);
|
||||||
ASSERT_TRUE(total == 3);
|
ASSERT_TRUE(total == 3);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue