mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 07:31:35 +02:00
wallet2: keep multisig import state consistent across failed refreshes
(cherry picked from commit b2cd62754bfb837bad2a49ea5b3808f35bb6a16c)
This commit is contained in:
+21
-10
@@ -15419,9 +15419,12 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs, bool re
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
|
||||
|
||||
if (!m_multisig_rescan_k.empty() && !m_multisig_rescan_info.empty())
|
||||
// consume pending rescan state from a prior import if refreshing
|
||||
if (refresh_after_import && !m_multisig_rescan_k.empty() && !m_multisig_rescan_info.empty())
|
||||
refresh(false);
|
||||
|
||||
// parse and validate locally so failures preserve any pending rescan state
|
||||
std::vector<std::vector<tools::wallet2::multisig_info>> info;
|
||||
std::unordered_set<crypto::public_key> seen;
|
||||
for (cryptonote::blobdata &data: blobs)
|
||||
{
|
||||
@@ -15487,18 +15490,20 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs, bool re
|
||||
}
|
||||
|
||||
MINFO(boost::format("%u outputs found") % boost::lexical_cast<std::string>(i.size()));
|
||||
m_multisig_rescan_info.push_back(std::move(i));
|
||||
info.push_back(std::move(i));
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(m_multisig_rescan_info.size() + 1 <= m_multisig_signers.size() && m_multisig_rescan_info.size() + 1 >= m_multisig_threshold, "Wrong number of multisig sources");
|
||||
CHECK_AND_ASSERT_THROW_MES(info.size() + 1 <= m_multisig_signers.size() && info.size() + 1 >= m_multisig_threshold, "Wrong number of multisig sources");
|
||||
|
||||
m_multisig_rescan_k.reserve(m_transfers.size());
|
||||
std::vector<std::vector<rct::key>> k;
|
||||
auto wiper = epee::misc_utils::create_scope_leave_handler([&](){for (auto &v: k) memwipe(v.data(), v.size() * sizeof(v[0]));});
|
||||
k.reserve(m_transfers.size());
|
||||
for (const auto &td: m_transfers)
|
||||
m_multisig_rescan_k.push_back(td.m_multisig_k);
|
||||
k.push_back(td.m_multisig_k);
|
||||
|
||||
// how many outputs we're going to update
|
||||
size_t n_outputs = m_transfers.size();
|
||||
for (const auto &pi: m_multisig_rescan_info)
|
||||
for (const auto &pi: info)
|
||||
if (pi.size() < n_outputs)
|
||||
n_outputs = pi.size();
|
||||
|
||||
@@ -15506,7 +15511,7 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs, bool re
|
||||
return 0;
|
||||
|
||||
// check signers are consistent
|
||||
for (const auto &pi: m_multisig_rescan_info)
|
||||
for (const auto &pi: info)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(std::find(m_multisig_signers.begin(), m_multisig_signers.end(), pi[0].m_signer) != m_multisig_signers.end(),
|
||||
"Signer is not a member of this multisig wallet");
|
||||
@@ -15515,15 +15520,21 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs, bool re
|
||||
}
|
||||
|
||||
// trim data we don't have info for from all participants
|
||||
for (auto &pi: m_multisig_rescan_info)
|
||||
for (auto &pi: info)
|
||||
pi.resize(n_outputs);
|
||||
|
||||
// sort by signer
|
||||
if (!m_multisig_rescan_info.empty() && !m_multisig_rescan_info.front().empty())
|
||||
if (!info.empty() && !info.front().empty())
|
||||
{
|
||||
std::sort(m_multisig_rescan_info.begin(), m_multisig_rescan_info.end(), [](const std::vector<tools::wallet2::multisig_info> &i0, const std::vector<tools::wallet2::multisig_info> &i1){ return memcmp(&i0[0].m_signer, &i1[0].m_signer, sizeof(i0[0].m_signer)) < 0; });
|
||||
std::sort(info.begin(), info.end(), [](const std::vector<tools::wallet2::multisig_info> &i0, const std::vector<tools::wallet2::multisig_info> &i1){ return memcmp(&i0[0].m_signer, &i1[0].m_signer, sizeof(i0[0].m_signer)) < 0; });
|
||||
}
|
||||
|
||||
// wipe prior pending rescan state and install its replacement only after full validation
|
||||
for (auto &v: m_multisig_rescan_k)
|
||||
memwipe(v.data(), v.size() * sizeof(v[0]));
|
||||
m_multisig_rescan_info = std::move(info);
|
||||
m_multisig_rescan_k = std::move(k);
|
||||
|
||||
// first pass to determine where to detach the blockchain
|
||||
for (size_t n = 0; n < n_outputs; ++n)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user