Skip to content

Commit 6f06684

Browse files
committed
Merge pull request #9911
5550c0a fix: multisig stale data after failed refresh (SNeedlewoods)
2 parents 933b1c3 + 5550c0a commit 6f06684

File tree

2 files changed

+29
-38
lines changed

2 files changed

+29
-38
lines changed

src/wallet/wallet2.cpp

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,8 +1187,6 @@ void wallet_device_callback::on_progress(const hw::device_progress& event)
11871187

11881188
wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory):
11891189
m_http_client(http_client_factory->create()),
1190-
m_multisig_rescan_info(NULL),
1191-
m_multisig_rescan_k(NULL),
11921190
m_upper_transaction_weight_limit(0),
11931191
m_run(true),
11941192
m_callback(0),
@@ -2186,7 +2184,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
21862184
THROW_WALLET_EXCEPTION_IF(i >= tx.vout.size(), error::wallet_internal_error, "Invalid vout index");
21872185

21882186
// if keys are encrypted, ask for password
2189-
if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only && !m_multisig_rescan_k && !m_background_syncing)
2187+
if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only && m_multisig_rescan_k.empty() && !m_background_syncing)
21902188
{
21912189
static critical_section password_lock;
21922190
CRITICAL_REGION_LOCAL(password_lock);
@@ -2550,10 +2548,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
25502548
(*output_tracker_cache)[std::make_pair(tx.vout[o].amount, td.m_global_output_index)] = m_transfers.size() - 1;
25512549
if (m_multisig)
25522550
{
2553-
THROW_WALLET_EXCEPTION_IF(!m_multisig_rescan_k && m_multisig_rescan_info,
2551+
THROW_WALLET_EXCEPTION_IF(m_multisig_rescan_k.empty() && !m_multisig_rescan_info.empty(),
25542552
error::wallet_internal_error, "NULL m_multisig_rescan_k");
2555-
if (m_multisig_rescan_info && m_multisig_rescan_info->front().size() >= m_transfers.size())
2556-
update_multisig_rescan_info(*m_multisig_rescan_k, *m_multisig_rescan_info, m_transfers.size() - 1);
2553+
if (!m_multisig_rescan_info.empty() && m_multisig_rescan_info.front().size() >= m_transfers.size())
2554+
update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, m_transfers.size() - 1);
25572555
}
25582556
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
25592557
if (!ignore_callbacks && 0 != m_callback)
@@ -2625,10 +2623,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
26252623
(*output_tracker_cache)[std::make_pair(tx.vout[o].amount, td.m_global_output_index)] = kit->second;
26262624
if (m_multisig)
26272625
{
2628-
THROW_WALLET_EXCEPTION_IF(!m_multisig_rescan_k && m_multisig_rescan_info,
2626+
THROW_WALLET_EXCEPTION_IF(m_multisig_rescan_k.empty() && !m_multisig_rescan_info.empty(),
26292627
error::wallet_internal_error, "NULL m_multisig_rescan_k");
2630-
if (m_multisig_rescan_info && m_multisig_rescan_info->front().size() >= m_transfers.size())
2631-
update_multisig_rescan_info(*m_multisig_rescan_k, *m_multisig_rescan_info, m_transfers.size() - 1);
2628+
if (!m_multisig_rescan_info.empty() && m_multisig_rescan_info.front().size() >= m_transfers.size())
2629+
update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, m_transfers.size() - 1);
26322630
}
26332631
THROW_WALLET_EXCEPTION_IF(td.get_public_key() != tx_scan_info[o].in_ephemeral.pub, error::wallet_internal_error, "Inconsistent public keys");
26342632
THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status");
@@ -4261,6 +4259,12 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
42614259
if (m_background_syncing || m_is_background_wallet)
42624260
m_background_sync_data.first_refresh_done = true;
42634261

4262+
m_multisig_rescan_info = std::vector<std::vector<tools::wallet2::multisig_info>>{};
4263+
for (auto &v: m_multisig_rescan_k)
4264+
memwipe(v.data(), v.size() * sizeof(v[0]));
4265+
4266+
m_multisig_rescan_k = std::vector<std::vector<rct::key>>{};
4267+
42644268
LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all(false)) << ", unlocked: " << print_money(unlocked_balance_all(false)));
42654269
}
42664270
//----------------------------------------------------------------------------------------------------
@@ -15387,7 +15391,9 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
1538715391
{
1538815392
CHECK_AND_ASSERT_THROW_MES(m_multisig, "Wallet is not multisig");
1538915393

15390-
std::vector<std::vector<tools::wallet2::multisig_info>> info;
15394+
if (!m_multisig_rescan_k.empty() && !m_multisig_rescan_info.empty())
15395+
refresh(false);
15396+
1539115397
std::unordered_set<crypto::public_key> seen;
1539215398
for (cryptonote::blobdata &data: blobs)
1539315399
{
@@ -15453,28 +15459,26 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
1545315459
}
1545415460

1545515461
MINFO(boost::format("%u outputs found") % boost::lexical_cast<std::string>(i.size()));
15456-
info.push_back(std::move(i));
15462+
m_multisig_rescan_info.push_back(std::move(i));
1545715463
}
1545815464

15459-
CHECK_AND_ASSERT_THROW_MES(info.size() + 1 <= m_multisig_signers.size() && info.size() + 1 >= m_multisig_threshold, "Wrong number of multisig sources");
15465+
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");
1546015466

15461-
std::vector<std::vector<rct::key>> k;
15462-
auto wiper = epee::misc_utils::create_scope_leave_handler([&](){for (auto &v: k) memwipe(v.data(), v.size() * sizeof(v[0]));});
15463-
k.reserve(m_transfers.size());
15467+
m_multisig_rescan_k.reserve(m_transfers.size());
1546415468
for (const auto &td: m_transfers)
15465-
k.push_back(td.m_multisig_k);
15469+
m_multisig_rescan_k.push_back(td.m_multisig_k);
1546615470

1546715471
// how many outputs we're going to update
1546815472
size_t n_outputs = m_transfers.size();
15469-
for (const auto &pi: info)
15473+
for (const auto &pi: m_multisig_rescan_info)
1547015474
if (pi.size() < n_outputs)
1547115475
n_outputs = pi.size();
1547215476

1547315477
if (n_outputs == 0)
1547415478
return 0;
1547515479

1547615480
// check signers are consistent
15477-
for (const auto &pi: info)
15481+
for (const auto &pi: m_multisig_rescan_info)
1547815482
{
1547915483
CHECK_AND_ASSERT_THROW_MES(std::find(m_multisig_signers.begin(), m_multisig_signers.end(), pi[0].m_signer) != m_multisig_signers.end(),
1548015484
"Signer is not a member of this multisig wallet");
@@ -15483,13 +15487,13 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
1548315487
}
1548415488

1548515489
// trim data we don't have info for from all participants
15486-
for (auto &pi: info)
15490+
for (auto &pi: m_multisig_rescan_info)
1548715491
pi.resize(n_outputs);
1548815492

1548915493
// sort by signer
15490-
if (!info.empty() && !info.front().empty())
15494+
if (!m_multisig_rescan_info.empty() && !m_multisig_rescan_info.front().empty())
1549115495
{
15492-
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; });
15496+
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; });
1549315497
}
1549415498

1549515499
// first pass to determine where to detach the blockchain
@@ -15505,24 +15509,11 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
1550515509

1550615510
for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n)
1550715511
{
15508-
update_multisig_rescan_info(k, info, n);
15512+
update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
1550915513
}
1551015514

15511-
m_multisig_rescan_k = &k;
15512-
m_multisig_rescan_info = &info;
15513-
try
15514-
{
1551515515

15516-
refresh(false);
15517-
}
15518-
catch (...)
15519-
{
15520-
m_multisig_rescan_info = NULL;
15521-
m_multisig_rescan_k = NULL;
15522-
throw;
15523-
}
15524-
m_multisig_rescan_info = NULL;
15525-
m_multisig_rescan_k = NULL;
15516+
refresh(false);
1552615517

1552715518
return n_outputs;
1552815519
}

src/wallet/wallet2.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,8 +1981,8 @@ namespace tools
19811981
std::vector<tools::wallet2::address_book_row> m_address_book;
19821982
std::pair<serializable_map<std::string, std::string>, std::vector<std::string>> m_account_tags;
19831983
uint64_t m_upper_transaction_weight_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
1984-
const std::vector<std::vector<tools::wallet2::multisig_info>> *m_multisig_rescan_info;
1985-
const std::vector<std::vector<rct::key>> *m_multisig_rescan_k;
1984+
std::vector<std::vector<tools::wallet2::multisig_info>> m_multisig_rescan_info;
1985+
std::vector<std::vector<rct::key>> m_multisig_rescan_k;
19861986
serializable_unordered_map<crypto::public_key, crypto::key_image> m_cold_key_images;
19871987

19881988
std::atomic<bool> m_run;

0 commit comments

Comments
 (0)