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
This commit is contained in:
+21
-10
@@ -14626,9 +14626,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)
|
||||
{
|
||||
@@ -14688,18 +14691,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;
|
||||
const epee::scope_guard wiper([&]() { 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();
|
||||
|
||||
@@ -14707,7 +14712,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");
|
||||
@@ -14716,15 +14721,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