Skip to content

Commit a718ad0

Browse files
committed
Get multisig working pre-FCMP++/Carrot fork
Reuse the background sync cache for multisig sync, so that upon importing multisig info, the wallet doesn't need to rescan the chain and instead can just process the background cache.
1 parent d6f2fd7 commit a718ad0

2 files changed

Lines changed: 48 additions & 34 deletions

File tree

src/fcmp_pp/tree_cache.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ template<typename C1, typename C2>
739739
bool TreeCache<C1, C2>::register_output(const OutputPair &output)
740740
{
741741
auto output_ref_hash = get_output_ref_hash(output);
742-
CHECK_AND_ASSERT_MES(m_registered_outputs.find(output_ref_hash) == m_registered_outputs.end(), false,
742+
CHECK_AND_NO_ASSERT_MES_L1(m_registered_outputs.find(output_ref_hash) == m_registered_outputs.end(), false,
743743
"output is already registered");
744744

745745
// Add to registered outputs container

src/wallet/wallet2.cpp

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,7 +2654,8 @@ void wallet2::process_new_scanned_transaction(
26542654
continue;
26552655
const cryptonote::txin_to_key &in_to_key = boost::get<cryptonote::txin_to_key>(in);
26562656
auto it = m_key_images.find(in_to_key.k_image);
2657-
if(it != m_key_images.end())
2657+
const bool key_image_known = it != m_key_images.end();
2658+
if(key_image_known)
26582659
{
26592660
transfer_details& td = m_transfers[it->second];
26602661
uint64_t amount = in_to_key.amount;
@@ -2691,7 +2692,9 @@ void wallet2::process_new_scanned_transaction(
26912692
}
26922693
}
26932694

2694-
if (!pool && (m_track_uses || (m_background_syncing && it == m_key_images.end())))
2695+
const bool check_if_possibly_spent = !pool && (m_track_uses ||
2696+
(!key_image_known && (m_background_syncing || m_multisig)));
2697+
if (check_if_possibly_spent)
26952698
{
26962699
const uint64_t amount = in_to_key.amount;
26972700
std::vector<uint64_t> offsets = cryptonote::relative_output_offsets_to_absolute(in_to_key.key_offsets);
@@ -2717,12 +2720,12 @@ void wallet2::process_new_scanned_transaction(
27172720
const bool possibly_involved_with_tx = received_an_output || recognized_owned_possibly_spent_enote;
27182721
const bool should_cache_bg_tx = possibly_involved_with_tx
27192722
&& !pool
2720-
&& m_background_syncing
2723+
&& (m_background_syncing || m_multisig)
27212724
&& !m_background_sync_data.txs.count(txid);
27222725
if (should_cache_bg_tx)
27232726
{
2724-
// we're going to re-process this receive when background sync is disabled
2725-
if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
2727+
// we're going to re-process this tx when we can generate the key images for receives
2728+
if (m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
27262729
{
27272730
size_t bgs_idx = m_background_sync_data.txs.size();
27282731
background_synced_tx_t bgs_tx = {
@@ -2733,7 +2736,7 @@ void wallet2::process_new_scanned_transaction(
27332736
.block_timestamp = ts,
27342737
.double_spend_seen = double_spend_seen
27352738
};
2736-
LOG_PRINT_L2("Adding received tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
2739+
LOG_PRINT_L2("Adding tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
27372740
m_background_sync_data.txs.insert({txid, std::move(bgs_tx)});
27382741
}
27392742
}
@@ -4605,7 +4608,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
46054608
}
46064609

46074610
m_first_refresh_done = true;
4608-
if (m_background_syncing || m_is_background_wallet)
4611+
if (m_background_syncing || m_is_background_wallet || m_multisig)
46094612
m_background_sync_data.first_refresh_done = true;
46104613

46114614
m_multisig_rescan_info = std::vector<std::vector<tools::wallet2::multisig_info>>{};
@@ -5999,6 +6002,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
59996002

60006003
create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
60016004
setup_new_blockchain();
6005+
reset_background_sync_data(m_background_sync_data);
60026006

60036007
if (!wallet_.empty())
60046008
store();
@@ -6331,6 +6335,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
63316335
this->create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt"));
63326336

63336337
this->setup_new_blockchain();
6338+
this->reset_background_sync_data(m_background_sync_data);
63346339

63356340
if (!m_wallet_file.empty())
63366341
this->store();
@@ -6560,7 +6565,7 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
65606565
store_background_keys(m_custom_background_key.get());
65616566
store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/);
65626567
}
6563-
else if (m_background_sync_type == BackgroundSyncReusePassword)
6568+
else if (m_background_sync_type == BackgroundSyncReusePassword || m_multisig)
65646569
{
65656570
reset_background_sync_data(m_background_sync_data);
65666571
}
@@ -6875,8 +6880,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
68756880

68766881
try
68776882
{
6878-
if (use_fs)
6879-
process_background_cache_on_open();
6883+
process_background_cache_on_open();
68806884
}
68816885
catch (const std::exception &e)
68826886
{
@@ -7007,6 +7011,12 @@ void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf)
70077011
//----------------------------------------------------------------------------------------------------
70087012
void wallet2::process_background_cache_on_open()
70097013
{
7014+
if (m_multisig)
7015+
{
7016+
if (!m_background_sync_data.first_refresh_done)
7017+
reset_background_sync_data(m_background_sync_data);
7018+
return;
7019+
}
70107020
if (m_wallet_file.empty())
70117021
return;
70127022
if (m_background_syncing || m_is_background_wallet)
@@ -8469,14 +8479,15 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx
84698479
for (const auto &ptx: exported_txs.m_ptx)
84708480
{
84718481
CHECK_AND_ASSERT_MES(ptx.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched selected_transfers/vin sizes");
8482+
const tools::wallet2::tx_construction_data &sd = get_construction_data(ptx);
84728483
for (size_t idx: ptx.selected_transfers)
84738484
CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8474-
CHECK_AND_ASSERT_MES(get_construction_data(ptx).selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8475-
for (size_t idx: get_construction_data(ptx).selected_transfers)
8485+
CHECK_AND_ASSERT_MES(sd.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8486+
for (size_t idx: sd.selected_transfers)
84768487
CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8477-
CHECK_AND_ASSERT_MES(get_construction_data(ptx).sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
8488+
CHECK_AND_ASSERT_MES(sd.sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
84788489
CHECK_AND_ASSERT_MES(!ptx.tx.vin.empty(), false, "Multisig tx has no inputs");
8479-
CHECK_AND_ASSERT_MES(!get_construction_data(ptx).sources.empty(), false, "Multisig tx has no sources");
8490+
CHECK_AND_ASSERT_MES(!sd.sources.empty(), false, "Multisig tx has no sources");
84808491
}
84818492

84828493
return true;
@@ -13960,7 +13971,7 @@ void wallet2::process_background_cache(const background_sync_data_t &background_
1396013971
m_processing_background_cache = false;
1396113972
});
1396213973

13963-
if (m_background_syncing || m_multisig || m_watch_only || key_on_device())
13974+
if (m_background_syncing || m_watch_only || key_on_device())
1396413975
return;
1396513976

1396613977
if (!background_sync_data.first_refresh_done)
@@ -15088,32 +15099,35 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs, bool re
1508815099
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; });
1508915100
}
1509015101

15091-
// first pass to determine where to detach the blockchain
15092-
for (size_t n = 0; n < n_outputs; ++n)
15102+
for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n)
1509315103
{
15094-
const transfer_details &td = m_transfers[n];
15095-
if (!td.m_key_image_partial)
15104+
update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15105+
}
15106+
15107+
// The background cache should have all txs saved which need to be rescanned, including potential spends. We process
15108+
// the background cache with multisig info loaded.
15109+
const background_sync_data_t background_sync_data = m_background_sync_data;
15110+
const hashchain blockchain = m_blockchain;
15111+
const TreeCacheV1 tree_cache = m_tree_cache;
15112+
process_background_cache(background_sync_data, blockchain, m_last_block_reward, tree_cache);
15113+
15114+
// Once all key images are known and we've processed the background cache, any txs present in the background
15115+
// cache are no longer useful to us. They've been processed, we can remove them.
15116+
bool all_kis_known = true;
15117+
for (const auto &td : m_transfers)
15118+
{
15119+
if (td.m_key_image_known)
1509615120
continue;
15097-
// FIXME: if we need to pop more blocks from the tree cache than the reorg depth, and the wallet has received
15098-
// outputs from before the detach height, then the wallet won't be able to correct those prior output paths.
15099-
// Some solutions:
15100-
// A) restart sync from the wallet's first received output height.
15101-
// B) re-request output paths from the daemon.
15102-
// C) multisig wallet should stop syncing upon identifying a receive.
15103-
MINFO("Multisig info importing from block height " << td.m_block_height);
15104-
auto output_tracker_cache = create_output_tracker_cache();
15105-
handle_reorg(td.m_block_height, output_tracker_cache);
15121+
all_kis_known = false;
1510615122
break;
1510715123
}
1510815124

15109-
for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n)
15125+
if (all_kis_known)
1511015126
{
15111-
update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15127+
MDEBUG("All key images are known, clearing background sync data since we don't need it anymore");
15128+
reset_background_sync_data(m_background_sync_data);
1511215129
}
1511315130

15114-
if (refresh_after_import)
15115-
refresh(false);
15116-
1511715131
return n_outputs;
1511815132
}
1511915133
//----------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)