@@ -2645,7 +2645,8 @@ void wallet2::process_new_scanned_transaction(
26452645 continue;
26462646 const cryptonote::txin_to_key &in_to_key = boost::get<cryptonote::txin_to_key>(in);
26472647 auto it = m_key_images.find(in_to_key.k_image);
2648- if(it != m_key_images.end())
2648+ const bool key_image_known = it != m_key_images.end();
2649+ if(key_image_known)
26492650 {
26502651 transfer_details& td = m_transfers[it->second];
26512652 uint64_t amount = in_to_key.amount;
@@ -2682,7 +2683,9 @@ void wallet2::process_new_scanned_transaction(
26822683 }
26832684 }
26842685
2685- if (!pool && (m_track_uses || (m_background_syncing && it == m_key_images.end())))
2686+ const bool check_if_possibly_spent = !pool && (m_track_uses ||
2687+ (!key_image_known && (m_background_syncing || m_multisig)));
2688+ if (check_if_possibly_spent)
26862689 {
26872690 const uint64_t amount = in_to_key.amount;
26882691 std::vector<uint64_t> offsets = cryptonote::relative_output_offsets_to_absolute(in_to_key.key_offsets);
@@ -2708,12 +2711,12 @@ void wallet2::process_new_scanned_transaction(
27082711 const bool possibly_involved_with_tx = received_an_output || recognized_owned_possibly_spent_enote;
27092712 const bool should_cache_bg_tx = possibly_involved_with_tx
27102713 && !pool
2711- && m_background_syncing
2714+ && ( m_background_syncing || m_multisig)
27122715 && !m_background_sync_data.txs.count(txid);
27132716 if (should_cache_bg_tx)
27142717 {
2715- // we're going to re-process this receive when background sync is disabled
2716- if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
2718+ // we're going to re-process this tx when we can generate the key images for receives
2719+ if (m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end())
27172720 {
27182721 size_t bgs_idx = m_background_sync_data.txs.size();
27192722 background_synced_tx_t bgs_tx = {
@@ -2724,7 +2727,7 @@ void wallet2::process_new_scanned_transaction(
27242727 .block_timestamp = ts,
27252728 .double_spend_seen = double_spend_seen
27262729 };
2727- LOG_PRINT_L2("Adding received tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
2730+ LOG_PRINT_L2("Adding tx " << txid << " to background sync data (idx=" << bgs_idx << ")");
27282731 m_background_sync_data.txs.insert({txid, std::move(bgs_tx)});
27292732 }
27302733 }
@@ -4546,7 +4549,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
45464549 }
45474550
45484551 m_first_refresh_done = true;
4549- if (m_background_syncing || m_is_background_wallet)
4552+ if (m_background_syncing || m_is_background_wallet || m_multisig )
45504553 m_background_sync_data.first_refresh_done = true;
45514554
45524555 m_multisig_rescan_info = std::vector<std::vector<tools::wallet2::multisig_info>>{};
@@ -5939,6 +5942,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
59395942
59405943 create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
59415944 setup_new_blockchain();
5945+ reset_background_sync_data(m_background_sync_data);
59425946
59435947 if (!wallet_.empty())
59445948 store();
@@ -6271,6 +6275,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
62716275 this->create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt"));
62726276
62736277 this->setup_new_blockchain();
6278+ this->reset_background_sync_data(m_background_sync_data);
62746279
62756280 if (!m_wallet_file.empty())
62766281 this->store();
@@ -6500,7 +6505,7 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
65006505 store_background_keys(m_custom_background_key.get());
65016506 store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/);
65026507 }
6503- else if (m_background_sync_type == BackgroundSyncReusePassword)
6508+ else if (m_background_sync_type == BackgroundSyncReusePassword || m_multisig )
65046509 {
65056510 reset_background_sync_data(m_background_sync_data);
65066511 }
@@ -6842,8 +6847,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
68426847
68436848 try
68446849 {
6845- if (use_fs)
6846- process_background_cache_on_open();
6850+ process_background_cache_on_open();
68476851 }
68486852 catch (const std::exception &e)
68496853 {
@@ -6974,6 +6978,12 @@ void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf)
69746978//----------------------------------------------------------------------------------------------------
69756979void wallet2::process_background_cache_on_open()
69766980{
6981+ if (m_multisig)
6982+ {
6983+ if (!m_background_sync_data.first_refresh_done)
6984+ reset_background_sync_data(m_background_sync_data);
6985+ return;
6986+ }
69776987 if (m_wallet_file.empty())
69786988 return;
69796989 if (m_background_syncing || m_is_background_wallet)
@@ -8435,13 +8445,11 @@ bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx
84358445 // sanity checks
84368446 for (const auto &ptx: exported_txs.m_ptx)
84378447 {
8438- CHECK_AND_ASSERT_MES(ptx.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched selected_transfers/vin sizes");
8439- for (size_t idx: ptx.selected_transfers)
8440- CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8441- CHECK_AND_ASSERT_MES(get_construction_data(ptx).selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8442- for (size_t idx: get_construction_data(ptx).selected_transfers)
8448+ const tools::wallet2::tx_construction_data &sd = get_construction_data(ptx);
8449+ CHECK_AND_ASSERT_MES(sd.selected_transfers.size() == ptx.tx.vin.size(), false, "Mismatched cd selected_transfers/vin sizes");
8450+ for (size_t idx: sd.selected_transfers)
84438451 CHECK_AND_ASSERT_MES(idx < m_transfers.size(), false, "Transfer index out of range");
8444- CHECK_AND_ASSERT_MES(get_construction_data(ptx) .sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
8452+ CHECK_AND_ASSERT_MES(sd .sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
84458453 }
84468454
84478455 return true;
@@ -13983,7 +13991,7 @@ void wallet2::process_background_cache(const background_sync_data_t &background_
1398313991 m_processing_background_cache = false;
1398413992 });
1398513993
13986- if (m_background_syncing || m_multisig || m_watch_only || key_on_device())
13994+ if (m_background_syncing || m_watch_only || key_on_device())
1398713995 return;
1398813996
1398913997 if (!background_sync_data.first_refresh_done)
@@ -15032,32 +15040,35 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
1503215040 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; });
1503315041 }
1503415042
15035- // first pass to determine where to detach the blockchain
15036- for (size_t n = 0; n < n_outputs; ++n)
15043+ for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n)
1503715044 {
15038- const transfer_details &td = m_transfers[n];
15039- if (!td.m_key_image_partial)
15045+ update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15046+ }
15047+
15048+ // The background cache should have all txs saved which need to be rescanned, including potential spends. We process
15049+ // the background cache with multisig info loaded.
15050+ const background_sync_data_t background_sync_data = m_background_sync_data;
15051+ const hashchain blockchain = m_blockchain;
15052+ const TreeCacheV1 tree_cache = m_tree_cache;
15053+ process_background_cache(background_sync_data, blockchain, m_last_block_reward, tree_cache);
15054+
15055+ // Once all key images are known and we've processed the background cache, any txs present in the background
15056+ // cache are no longer useful to us. They've been processed, we can remove them.
15057+ bool all_kis_known = true;
15058+ for (const auto &td : m_transfers)
15059+ {
15060+ if (td.m_key_image_known)
1504015061 continue;
15041- // FIXME: if we need to pop more blocks from the tree cache than the reorg depth, and the wallet has received
15042- // outputs from before the detach height, then the wallet won't be able to correct those prior output paths.
15043- // Some solutions:
15044- // A) restart sync from the wallet's first received output height.
15045- // B) re-request output paths from the daemon.
15046- // C) multisig wallet should stop syncing upon identifying a receive.
15047- MINFO("Multisig info importing from block height " << td.m_block_height);
15048- auto output_tracker_cache = create_output_tracker_cache();
15049- handle_reorg(td.m_block_height, output_tracker_cache);
15062+ all_kis_known = false;
1505015063 break;
1505115064 }
1505215065
15053- for (size_t n = 0; n < n_outputs && n < m_transfers.size(); ++n )
15066+ if (all_kis_known )
1505415067 {
15055- update_multisig_rescan_info(m_multisig_rescan_k, m_multisig_rescan_info, n);
15068+ MDEBUG("All key images are known, clearing background sync data since we don't need it anymore");
15069+ reset_background_sync_data(m_background_sync_data);
1505615070 }
1505715071
15058-
15059- refresh(false);
15060-
1506115072 return n_outputs;
1506215073}
1506315074//----------------------------------------------------------------------------------------------------
0 commit comments