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
This commit is contained in:
woodser
2021-08-17 08:16:39 -04:00
parent a8690e21db
commit 21ac40a287
4 changed files with 98 additions and 21 deletions
+54 -2
View File
@@ -159,7 +159,31 @@ namespace monero {
// return root
return root;
}
std::shared_ptr<monero_block_header> monero_block_header::copy(const std::shared_ptr<monero_block_header>& src, const std::shared_ptr<monero_block_header>& 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<monero_block_header>& self, const std::shared_ptr<monero_block_header>& 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> monero_block::copy(const std::shared_ptr<monero_block>& src, const std::shared_ptr<monero_block>& tgt) const {
if (this != src.get()) throw std::runtime_error("this block != src");
monero_block_header::copy(std::static_pointer_cast<monero_block_header>(src), std::static_pointer_cast<monero_block_header>(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<monero_tx>());
tgt->m_miner_tx.get()->m_block = tgt;
}
if (!src->m_txs.empty()) {
bool use_wallet_types = std::dynamic_pointer_cast<monero_tx_wallet>(src->m_txs[0]) != 0;
tgt->m_txs = std::vector<std::shared_ptr<monero_tx>>();
for (const auto& tx : src->m_txs) {
if (use_wallet_types) {
std::shared_ptr<monero_tx_wallet> tx_wallet = std::static_pointer_cast<monero_tx_wallet>(tx);
std::shared_ptr<monero_tx_wallet> tx_copy = tx_wallet->copy(tx_wallet, std::make_shared<monero_tx_wallet>());
tx_copy->m_block = tgt;
tgt->m_txs.push_back(tx_copy);
} else {
std::shared_ptr<monero_tx> tx_copy = tx->copy(tx, std::make_shared<monero_tx>());
tx_copy->m_block = tgt;
tgt->m_txs.push_back(tx_copy);
}
}
}
if (!src->m_tx_hashes.empty()) tgt->m_tx_hashes = std::vector<std::string>(src->m_tx_hashes);
return tgt;
}
void monero_block::merge(const std::shared_ptr<monero_block_header>& self, const std::shared_ptr<monero_block_header>& other) {
merge(std::static_pointer_cast<monero_block>(self), std::static_pointer_cast<monero_block>(other));
}
+2
View File
@@ -145,6 +145,7 @@ namespace monero {
boost::optional<std::string> m_pow_hash;
rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const;
std::shared_ptr<monero_block_header> copy(const std::shared_ptr<monero_block_header>& src, const std::shared_ptr<monero_block_header>& tgt) const;
virtual void merge(const std::shared_ptr<monero_block_header>& self, const std::shared_ptr<monero_block_header>& other);
};
@@ -158,6 +159,7 @@ namespace monero {
std::vector<std::string> m_tx_hashes;
rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const;
std::shared_ptr<monero_block> copy(const std::shared_ptr<monero_block>& src, const std::shared_ptr<monero_block>& tgt) const;
void merge(const std::shared_ptr<monero_block_header>& self, const std::shared_ptr<monero_block_header>& other);
void merge(const std::shared_ptr<monero_block>& self, const std::shared_ptr<monero_block>& other);
};
+23 -9
View File
@@ -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<std::shared_ptr<monero_tx_wallet>> 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<std::string> 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<monero_tx_wallet>& 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<monero_output_wallet> output = std::make_shared<monero_output_wallet>();
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<monero_output_wallet> input = std::make_shared<monero_output_wallet>();
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<monero_tx_wallet> tx_notify = std::make_shared<monero_tx_wallet>();
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<monero_block> block_notify = std::make_shared<monero_block>();
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
+19 -10
View File
@@ -208,13 +208,11 @@ namespace monero {
}
std::shared_ptr<monero_tx_wallet> monero_tx_wallet::copy(const std::shared_ptr<monero_tx>& src, const std::shared_ptr<monero_tx>& tgt) const {
MTRACE("monero_tx_wallet::copy(const std::shared_ptr<monero_tx>& src, const std::shared_ptr<monero_tx>& tgt)");
return monero_tx_wallet::copy(std::static_pointer_cast<monero_tx_wallet>(src), std::static_pointer_cast<monero_tx_wallet>(tgt));
};
std::shared_ptr<monero_tx_wallet> monero_tx_wallet::copy(const std::shared_ptr<monero_tx_wallet>& src, const std::shared_ptr<monero_tx_wallet>& tgt) const {
MTRACE("monero_tx_wallet::copy(const std::shared_ptr<monero_tx_wallet>& src, const std::shared_ptr<monero_tx_wallet>& 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<monero_tx>(src), std::static_pointer_cast<monero_tx>(tgt));
@@ -437,7 +435,6 @@ namespace monero {
};
std::shared_ptr<monero_tx_query> monero_tx_query::copy(const std::shared_ptr<monero_tx_query>& src, const std::shared_ptr<monero_tx_query>& tgt) const {
MTRACE("monero_tx_query::copy(const std::shared_ptr<monero_tx_query>& src, const std::shared_ptr<monero_tx_query>& 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> monero_destination::copy(const std::shared_ptr<monero_destination>& src, const std::shared_ptr<monero_destination>& tgt) const {
MTRACE("monero_destination::copy(const std::shared_ptr<monero_destination>& src, const std::shared_ptr<monero_destination>& 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> monero_incoming_transfer::copy(const std::shared_ptr<monero_incoming_transfer>& src, const std::shared_ptr<monero_incoming_transfer>& 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<monero_transfer>(src), std::static_pointer_cast<monero_transfer>(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<bool> monero_incoming_transfer::is_incoming() const { return true; }
@@ -752,8 +752,17 @@ namespace monero {
};
std::shared_ptr<monero_outgoing_transfer> monero_outgoing_transfer::copy(const std::shared_ptr<monero_outgoing_transfer>& src, const std::shared_ptr<monero_outgoing_transfer>& 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<monero_transfer>(src), std::static_pointer_cast<monero_transfer>(tgt));
if (!src->m_subaddress_indices.empty()) tgt->m_subaddress_indices = std::vector<uint32_t>(src->m_subaddress_indices);
if (!src->m_addresses.empty()) tgt->m_addresses = std::vector<std::string>(src->m_addresses);
if (!src->m_destinations.empty()) {
tgt->m_destinations = std::vector<std::shared_ptr<monero_destination>>();
for (const std::shared_ptr<monero_destination>& destination : src->m_destinations) {
tgt->m_destinations.push_back(destination->copy(destination, std::make_shared<monero_destination>()));
}
}
return tgt;
};
boost::optional<bool> monero_outgoing_transfer::is_incoming() const { return false; }