diff --git a/src/carrot_impl/account.cpp b/src/carrot_impl/account.cpp index 19c349493..866f8a1a3 100644 --- a/src/carrot_impl/account.cpp +++ b/src/carrot_impl/account.cpp @@ -308,12 +308,18 @@ crypto::secret_key carrot_and_legacy_account::generate( } //---------------------------------------------------------------------------------------------------------------------- void carrot_and_legacy_account::set_carrot_keys() -{ +{ + // top level keys m_keys.s_master = m_keys.m_spend_secret_key; make_carrot_provespend_key(m_keys.s_master, m_keys.k_prove_spend); make_carrot_viewbalance_secret(m_keys.s_master, m_keys.s_view_balance); + + // view balance keys + make_carrot_viewincoming_key(m_keys.s_view_balance, m_keys.k_view_incoming); make_carrot_generateimage_key(m_keys.s_view_balance, m_keys.k_generate_image); make_carrot_generateaddress_secret(m_keys.s_view_balance, m_keys.s_generate_address); + + // carrot account address make_carrot_spend_pubkey(m_keys.k_generate_image, m_keys.k_prove_spend, m_keys.m_carrot_account_address.m_spend_public_key); k_view_incoming_dev.view_key_scalar_mult_ed25519( m_keys.m_carrot_account_address.m_spend_public_key, diff --git a/src/carrot_impl/account.h b/src/carrot_impl/account.h index 525216263..9431be26c 100644 --- a/src/carrot_impl/account.h +++ b/src/carrot_impl/account.h @@ -53,7 +53,7 @@ namespace carrot std::unordered_map subaddress_map; AddressDeriveType default_derive_type; - carrot_and_legacy_account(): k_view_incoming_dev(get_keys().m_view_secret_key), + carrot_and_legacy_account(): k_view_incoming_dev(get_keys().k_view_incoming), s_view_balance_dev(get_keys().s_view_balance), s_generate_address_dev(get_keys().s_generate_address) {} diff --git a/src/carrot_impl/format_utils.cpp b/src/carrot_impl/format_utils.cpp index 5b8183360..c3c97aa4d 100644 --- a/src/carrot_impl/format_utils.cpp +++ b/src/carrot_impl/format_utils.cpp @@ -59,10 +59,10 @@ static void store_carrot_ephemeral_pubkeys_to_extra(const EnoteContainer &enotes if (nouts == 0) return; - const bool use_shared_ephemeral_pubkey = nouts == 2 && 0 == memcmp( + const bool use_shared_ephemeral_pubkey = nouts == 1 || (nouts == 2 && 0 == memcmp( &enotes.front().enote_ephemeral_pubkey, &enotes.back().enote_ephemeral_pubkey, - sizeof(mx25519_pubkey)); + sizeof(mx25519_pubkey))); bool success = true; if (use_shared_ephemeral_pubkey) { diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h index e1e460dc0..44fd507f1 100644 --- a/src/cryptonote_basic/account.h +++ b/src/cryptonote_basic/account.h @@ -57,6 +57,7 @@ namespace cryptonote crypto::secret_key s_master; crypto::secret_key k_prove_spend; crypto::secret_key s_view_balance; + crypto::secret_key k_view_incoming; crypto::secret_key k_generate_image; crypto::secret_key s_generate_address; diff --git a/src/wallet/scanning_tools.cpp b/src/wallet/scanning_tools.cpp index 063b3bfcd..a79ab1a60 100644 --- a/src/wallet/scanning_tools.cpp +++ b/src/wallet/scanning_tools.cpp @@ -727,7 +727,7 @@ void view_incoming_scan_transaction( //! @TODO: HW device const bool is_carrot = carrot::is_carrot_transaction_v1(tx); carrot::view_incoming_key_ram_borrowed_device k_view_dev( - is_carrot ? acc.s_view_balance : acc.m_view_secret_key + is_carrot ? acc.k_view_incoming : acc.m_view_secret_key ); // do view-incoming scan for each output enotes @@ -775,7 +775,7 @@ void view_incoming_scan_transaction( const bool is_carrot = carrot::is_carrot_transaction_v1(tx); perform_ecdh_derivations(epee::to_span(main_tx_ephemeral_pubkeys), epee::to_span(additional_tx_ephemeral_pubkeys), - is_carrot ? acc.s_view_balance : acc.m_view_secret_key, + is_carrot ? acc.k_view_incoming : acc.m_view_secret_key, acc.get_device(), is_carrot, main_derivations, @@ -799,8 +799,13 @@ std::vector> view_incoming_scan_t //const std::unordered_map &subaddress_map, tools::keystore &subaddress_keystore) { - std::vector> res(tx.vout.size()); - view_incoming_scan_transaction(tx, acc, subaddress_keystore, epee::to_mut_span(res)); + const auto n_outputs = tx.vout.size(); + std::vector> res(n_outputs); + if (n_outputs > 0) + { + view_incoming_scan_transaction(tx, acc, subaddress_keystore, epee::to_mut_span(res)); + } + return res; } //------------------------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 4b7376dcb..f51a78a40 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3480,12 +3480,19 @@ void wallet2::process_parsed_blocks(const uint64_t start_height, const std::vect auto tx_scan_job = [this, &enote_scan_infos, &output_key_images, &password_failure, &keystore] (const cryptonote::transaction &tx, size_t tx_output_idx) { + if (tx.vout.empty()) + { + MWARNING("Skipping tx without any outputs: " << get_transaction_hash(tx) << ", height: " << m_blockchain.size()); + return; + } + const size_t output_span_end = tx_output_idx + tx.vout.size(); if (output_span_end > enote_scan_infos.size() || output_span_end > output_key_images.size()) { LOG_ERROR("BUG: tx scan worker output index out of bounds, skipping..."); return; } + wallet::view_incoming_scan_transaction(tx, this->m_account.get_keys(), keystore, @@ -3505,31 +3512,44 @@ void wallet2::process_parsed_blocks(const uint64_t start_height, const std::vect size_t i = 0; size_t tx_output_idx = 0; while (i < blocks.size()) { - tools::threadpool::waiter scan_blocks_waiter(tpool); - for (size_t j = 0; j < 10; ++j) + const parsed_block &par_blk = parsed_blocks.at(i); + const std::uint64_t height = start_height + i; + const bool skip_scan_for_this_block = should_skip_block(par_blk.block, height); + if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase) + tx_scan_job(par_blk.block.miner_tx, tx_output_idx); + tx_output_idx += par_blk.block.miner_tx.vout.size(); + if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase) + tx_scan_job(par_blk.block.protocol_tx, tx_output_idx); + tx_output_idx += par_blk.block.protocol_tx.vout.size(); + for (const cryptonote::transaction &tx : par_blk.txes) { - const parsed_block &par_blk = parsed_blocks.at(i); - const std::uint64_t height = start_height + i; - const bool skip_scan_for_this_block = should_skip_block(par_blk.block, height); - if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase) - tpool.submit(&scan_blocks_waiter, std::bind(tx_scan_job, std::cref(par_blk.block.miner_tx), tx_output_idx)); - tx_output_idx += par_blk.block.miner_tx.vout.size(); - if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase) - tpool.submit(&scan_blocks_waiter, std::bind(tx_scan_job, std::cref(par_blk.block.protocol_tx), tx_output_idx)); - tx_output_idx += par_blk.block.protocol_tx.vout.size(); - for (const cryptonote::transaction &tx : par_blk.txes) - { - if (!skip_scan_for_this_block) - tpool.submit(&scan_blocks_waiter, std::bind(tx_scan_job, std::cref(tx), tx_output_idx)); - tx_output_idx += tx.vout.size(); - } - if (++i >= blocks.size()) break; - } - if (!scan_blocks_waiter.wait()) - { - THROW_WALLET_EXCEPTION_IF(password_failure, error::password_needed); - THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Unrecognized exception in enote scanning threadpool"); + if (!skip_scan_for_this_block) + tx_scan_job(tx, tx_output_idx); + tx_output_idx += tx.vout.size(); } + // tools::threadpool::waiter scan_blocks_waiter(tpool); + // for (size_t j = 0; j < 10; ++j) + // { + // if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase) + // tpool.submit(&scan_blocks_waiter, std::bind(tx_scan_job, std::cref(par_blk.block.miner_tx), tx_output_idx)); + // tx_output_idx += par_blk.block.miner_tx.vout.size(); + // if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase) + // tpool.submit(&scan_blocks_waiter, std::bind(tx_scan_job, std::cref(par_blk.block.protocol_tx), tx_output_idx)); + // tx_output_idx += par_blk.block.protocol_tx.vout.size(); + // for (const cryptonote::transaction &tx : par_blk.txes) + // { + // if (!skip_scan_for_this_block) + // tpool.submit(&scan_blocks_waiter, std::bind(tx_scan_job, std::cref(tx), tx_output_idx)); + // tx_output_idx += tx.vout.size(); + // } + // if (++i >= blocks.size()) break; + // } + // if (!scan_blocks_waiter.wait()) + // { + // THROW_WALLET_EXCEPTION_IF(password_failure, error::password_needed); + // THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Unrecognized exception in enote scanning threadpool"); + // } + i++; } // Start processing blockchain entries with scanned outputs