Skip to content

Commit

Permalink
improve performance and reliability of notifications
Browse files Browse the repository at this point in the history
only monitor recent blocks for notifications
create dummy input and tx for notification
implement copy() for monero_block_header, monero_block, in/out transfers
  • Loading branch information
woodser committed Aug 17, 2021
1 parent a8690e2 commit 21ac40a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 21 deletions.
56 changes: 54 additions & 2 deletions src/daemon/monero_daemon_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
Expand Down
2 changes: 2 additions & 0 deletions src/daemon/monero_daemon_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand All @@ -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);
};
Expand Down
32 changes: 23 additions & 9 deletions src/wallet/monero_wallet_full.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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
Expand Down
29 changes: 19 additions & 10 deletions src/wallet/monero_wallet_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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; }
Expand Down Expand Up @@ -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; }
Expand Down

0 comments on commit 21ac40a

Please sign in to comment.