From 21ac40a287381664795ffe5873c09f165690323d Mon Sep 17 00:00:00 2001 From: woodser Date: Tue, 17 Aug 2021 08:16:39 -0400 Subject: [PATCH] improve performance and reliability of notifications only monitor recent blocks for notifications create dummy input and tx for notification implement copy() for monero_block_header, monero_block, in/out transfers --- src/daemon/monero_daemon_model.cpp | 56 ++++++++++++++++++++++++++++-- src/daemon/monero_daemon_model.h | 2 ++ src/wallet/monero_wallet_full.cpp | 32 ++++++++++++----- src/wallet/monero_wallet_model.cpp | 29 ++++++++++------ 4 files changed, 98 insertions(+), 21 deletions(-) diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index 47aac08..5a8e753 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -159,7 +159,31 @@ namespace monero { // return root return root; } - + + std::shared_ptr monero_block_header::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { + if (this != src.get()) throw std::runtime_error("this block header != src"); + tgt->m_hash = src->m_hash; + tgt->m_height = src->m_height; + tgt->m_timestamp = src->m_timestamp; + tgt->m_size = src->m_size; + tgt->m_weight = src->m_weight; + tgt->m_long_term_weight = src->m_long_term_weight; + tgt->m_depth = src->m_depth; + tgt->m_difficulty = src->m_difficulty; + tgt->m_cumulative_difficulty = src->m_cumulative_difficulty; + tgt->m_major_version = src->m_major_version; + tgt->m_minor_version = src->m_minor_version; + tgt->m_nonce = src->m_nonce; + tgt->m_miner_tx_hash = src->m_miner_tx_hash; + tgt->m_num_txs = src->m_num_txs; + tgt->m_orphan_status = src->m_orphan_status; + tgt->m_prev_hash = src->m_prev_hash; + tgt->m_reward = src->m_reward; + tgt->m_pow_hash = src->m_pow_hash; + tgt->m_hash = src->m_hash; + return tgt; + } + void monero_block_header::merge(const std::shared_ptr& self, const std::shared_ptr& other) { if (this != self.get()) throw std::runtime_error("this != self"); if (self == other) return; @@ -204,7 +228,35 @@ namespace monero { // return root return root; } - + + std::shared_ptr monero_block::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { + if (this != src.get()) throw std::runtime_error("this block != src"); + monero_block_header::copy(std::static_pointer_cast(src), std::static_pointer_cast(tgt)); + tgt->m_hex = src->m_hex; + if (src->m_miner_tx) { + tgt->m_miner_tx = src->m_miner_tx.get()->copy(src->m_miner_tx.get(), std::make_shared()); + tgt->m_miner_tx.get()->m_block = tgt; + } + if (!src->m_txs.empty()) { + bool use_wallet_types = std::dynamic_pointer_cast(src->m_txs[0]) != 0; + tgt->m_txs = std::vector>(); + for (const auto& tx : src->m_txs) { + if (use_wallet_types) { + std::shared_ptr tx_wallet = std::static_pointer_cast(tx); + std::shared_ptr tx_copy = tx_wallet->copy(tx_wallet, std::make_shared()); + tx_copy->m_block = tgt; + tgt->m_txs.push_back(tx_copy); + } else { + std::shared_ptr tx_copy = tx->copy(tx, std::make_shared()); + tx_copy->m_block = tgt; + tgt->m_txs.push_back(tx_copy); + } + } + } + if (!src->m_tx_hashes.empty()) tgt->m_tx_hashes = std::vector(src->m_tx_hashes); + return tgt; + } + void monero_block::merge(const std::shared_ptr& self, const std::shared_ptr& other) { merge(std::static_pointer_cast(self), std::static_pointer_cast(other)); } diff --git a/src/daemon/monero_daemon_model.h b/src/daemon/monero_daemon_model.h index 8bbd2a5..25c1974 100644 --- a/src/daemon/monero_daemon_model.h +++ b/src/daemon/monero_daemon_model.h @@ -145,6 +145,7 @@ namespace monero { boost::optional m_pow_hash; rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; + std::shared_ptr copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const; virtual void merge(const std::shared_ptr& self, const std::shared_ptr& other); }; @@ -158,6 +159,7 @@ namespace monero { std::vector m_tx_hashes; rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; + std::shared_ptr copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const; void merge(const std::shared_ptr& self, const std::shared_ptr& other); void merge(const std::shared_ptr& self, const std::shared_ptr& other); }; diff --git a/src/wallet/monero_wallet_full.cpp b/src/wallet/monero_wallet_full.cpp index c54e819..cb4c33f 100644 --- a/src/wallet/monero_wallet_full.cpp +++ b/src/wallet/monero_wallet_full.cpp @@ -937,6 +937,7 @@ namespace monero { monero_tx_query query = monero_tx_query(); query.m_is_locked = true; query.m_is_confirmed = true; + query.m_min_height = m_wallet.get_height() - 70; // only monitor recent txs std::vector> locked_txs = m_wallet.get_txs(query); // collect hashes of txs no longer locked @@ -957,7 +958,6 @@ namespace monero { if (!tx_hashes_no_longer_locked.empty()) { query.m_hashes = tx_hashes_no_longer_locked; query.m_is_locked = false; - query.m_is_confirmed = true; query.m_include_outputs = true; std::vector missing_tx_hashes; txs_no_longer_locked = m_wallet.get_txs(query, missing_tx_hashes); @@ -977,15 +977,29 @@ namespace monero { void notify_outputs(const std::shared_ptr& tx) { - // notify spent outputs // TODO: this provides one input with outgoing amount like monero-wallet-rpc client, use real inputs instead + // notify spent outputs if (tx->m_outgoing_transfer != boost::none) { - std::shared_ptr output = std::make_shared(); - tx->m_inputs.push_back(output); // TODO: should copy tx and block before modifying - output->m_tx = tx; - output->m_amount = tx->m_outgoing_transfer.get()->m_amount.get() + tx->m_fee.get(); - output->m_account_index = tx->m_outgoing_transfer.get()->m_account_index; - if (tx->m_outgoing_transfer.get()->m_subaddress_indices.size() == 1) output->m_subaddress_index = tx->m_outgoing_transfer.get()->m_subaddress_indices[0]; // initialize if transfer sourced from single subaddress - for (monero_wallet_listener* listener : m_wallet.get_listeners()) listener->on_output_spent(*output); + + // build dummy input for notification // TODO: this provides one input with outgoing amount like monero-wallet-rpc client, use real inputs instead + std::shared_ptr input = std::make_shared(); + input->m_amount = tx->m_outgoing_transfer.get()->m_amount.get() + tx->m_fee.get(); + input->m_account_index = tx->m_outgoing_transfer.get()->m_account_index; + if (tx->m_outgoing_transfer.get()->m_subaddress_indices.size() == 1) input->m_subaddress_index = tx->m_outgoing_transfer.get()->m_subaddress_indices[0]; // initialize if transfer sourced from single subaddress + std::shared_ptr tx_notify = std::make_shared(); + input->m_tx = tx_notify; + tx_notify->m_inputs.push_back(input); + tx_notify->m_hash = tx->m_hash; + tx_notify->m_is_locked = tx->m_is_locked; + tx_notify->m_unlock_height = tx->m_unlock_height; + if (tx->m_block != boost::none) { + std::shared_ptr block_notify = std::make_shared(); + tx_notify->m_block = block_notify; + block_notify->m_height = tx->get_height(); + block_notify->m_txs.push_back(tx_notify); + } + + // notify listeners + for (monero_wallet_listener* listener : m_wallet.get_listeners()) listener->on_output_spent(*input); } // notify received outputs diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 5dc32e1..58b3801 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -208,13 +208,11 @@ namespace monero { } std::shared_ptr monero_tx_wallet::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { - MTRACE("monero_tx_wallet::copy(const std::shared_ptr& src, const std::shared_ptr& tgt)"); return monero_tx_wallet::copy(std::static_pointer_cast(src), std::static_pointer_cast(tgt)); }; std::shared_ptr monero_tx_wallet::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { - MTRACE("monero_tx_wallet::copy(const std::shared_ptr& src, const std::shared_ptr& tgt)"); - if (this != src.get()) throw std::runtime_error("this != src"); + if (this != src.get()) throw std::runtime_error("this tx != src"); // copy base class monero_tx::copy(std::static_pointer_cast(src), std::static_pointer_cast(tgt)); @@ -437,7 +435,6 @@ namespace monero { }; std::shared_ptr monero_tx_query::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { - MTRACE("monero_tx_query::copy(const std::shared_ptr& src, const std::shared_ptr& tgt)"); if (this != src.get()) throw std::runtime_error("this != src"); // copy base class @@ -579,8 +576,7 @@ namespace monero { } std::shared_ptr monero_destination::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { - MTRACE("monero_destination::copy(const std::shared_ptr& src, const std::shared_ptr& tgt)"); - if (this != src.get()) throw std::runtime_error("this != src"); + if (this != src.get()) throw std::runtime_error("this destination!= src"); tgt->m_address = src->m_address; tgt->m_amount = src->m_amount; return tgt; @@ -713,8 +709,12 @@ namespace monero { } std::shared_ptr monero_incoming_transfer::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { - std::cout << "monero_incoming_transfer::copy()" << std::endl; - throw std::runtime_error("monero_incoming_transfer::copy(inTransfer) not implemented"); + if (this != src.get()) throw std::runtime_error("this incoming transfer != src"); + monero_transfer::copy(std::static_pointer_cast(src), std::static_pointer_cast(tgt)); + tgt->m_subaddress_index = src->m_subaddress_index; + tgt->m_address = src->m_address; + tgt->m_num_suggested_confirmations = src->m_num_suggested_confirmations; + return tgt; }; boost::optional monero_incoming_transfer::is_incoming() const { return true; } @@ -752,8 +752,17 @@ namespace monero { }; std::shared_ptr monero_outgoing_transfer::copy(const std::shared_ptr& src, const std::shared_ptr& tgt) const { - std::cout << "monero_outgoing_transfer::copy()" << std::endl; - throw std::runtime_error("monero_outgoing_transfer::copy(out_transfer) not implemented"); + if (this != src.get()) throw std::runtime_error("this outgoing transfer != src"); + monero_transfer::copy(std::static_pointer_cast(src), std::static_pointer_cast(tgt)); + if (!src->m_subaddress_indices.empty()) tgt->m_subaddress_indices = std::vector(src->m_subaddress_indices); + if (!src->m_addresses.empty()) tgt->m_addresses = std::vector(src->m_addresses); + if (!src->m_destinations.empty()) { + tgt->m_destinations = std::vector>(); + for (const std::shared_ptr& destination : src->m_destinations) { + tgt->m_destinations.push_back(destination->copy(destination, std::make_shared())); + } + } + return tgt; }; boost::optional monero_outgoing_transfer::is_incoming() const { return false; }