From 6853d903ce99e099942b50bbcd5d3c54f03c0a51 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 5 Jul 2019 19:45:57 +0200 Subject: [PATCH] added command for analysing tx outputs --- src/currency_core/blockchain_storage.cpp | 76 +++++++++++++++++++++++- src/currency_core/blockchain_storage.h | 1 + src/daemon/daemon_commands_handler.h | 23 +++++++ 3 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 03d989af..e7012315 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -3406,8 +3406,7 @@ uint64_t blockchain_storage::tx_fee_median_for_height(uint64_t h)const //------------------------------------------------------------------ bool blockchain_storage::validate_all_aliases_for_new_median_mode() { - - LOG_PRINT_L0("Started reinitialization of median fee..."); + LOG_PRINT_L0("Started reinitialization of median fee..."); math_helper::once_a_time_seconds<10> log_idle; uint64_t sz = m_db_blocks.size(); for (uint64_t i = 0; i != sz; i++) @@ -3446,6 +3445,79 @@ bool blockchain_storage::validate_all_aliases_for_new_median_mode() return true; } //------------------------------------------------------------------ +bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const +{ + CRITICAL_REGION_LOCAL(m_read_lock); + auto tx_ptr = m_db_transactions.find(tx_id); + + if (!tx_ptr) + { + LOG_PRINT_RED_L0("Tx " << tx_id << " not found"); + return true; + } + + //amount -> index -> [{tx_id, rind_count}] + std::map > > > usage_stat; + + CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() == tx_ptr->m_global_output_indexes.size(), false, "Internal error: output size missmatch"); + for (uint64_t i = 0; i!= tx_ptr->tx.vout.size();i++) + { + if (tx_ptr->tx.vout[i].target.type() != typeid(currency::txout_to_key)) + continue; + + usage_stat[tx_ptr->tx.vout[i].amount][tx_ptr->m_global_output_indexes[i]]; + + } + + LOG_PRINT_L0("Lookup in all transactions...."); + for (uint64_t i = 0; i != m_db_blocks.size(); i++) + { + auto block_ptr = m_db_blocks[i]; + for (auto block_tx_id : block_ptr->bl.tx_hashes) + { + auto block_tx_ptr = m_db_transactions.find(block_tx_id); + for (auto txi_in : block_tx_ptr->tx.vin) + { + if(txi_in.type() != typeid(currency::txin_to_key)) + continue; + currency::txin_to_key& txi_in_tokey = boost::get(txi_in); + uint64_t amount = txi_in_tokey.amount; + auto amount_it = usage_stat.find(amount); + if(amount_it == usage_stat.end()) + continue; + + for (txout_v& off : txi_in_tokey.key_offsets) + { + if(off.type() != typeid(uint64_t)) + continue; + uint64_t index = boost::get(off); + auto index_it = amount_it->second.find(index); + if(index_it == amount_it->second.end()) + continue; + index_it->second.push_back(std::pair(block_tx_id, txi_in_tokey.key_offsets.size())); + } + } + } + } + + std::stringstream ss; + for (auto& amount : usage_stat) + { + for (auto& index : amount.second) + { + ss << "[" << print_money(amount.first) << ":" << index.first << "]" << ENDL ; + for (auto& list_entry : index.second) + { + ss << " " << list_entry.first << ": " << list_entry.second << ENDL; + } + } + } + + LOG_PRINT_L0("Results: " << ENDL << ss.str()); + + return true; +} +//------------------------------------------------------------------ bool blockchain_storage::have_tx_keyimges_as_spent(const transaction &tx) const { // check all tx's inputs for being already spent diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 580afe81..db65c420 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -429,6 +429,7 @@ namespace currency void inspect_blocks_index() const; bool rebuild_tx_fee_medians(); bool validate_all_aliases_for_new_median_mode(); + bool print_tx_outputs_lookup(const crypto::hash& tx_id) const; private: //-------------- DB containers -------------- diff --git a/src/daemon/daemon_commands_handler.h b/src/daemon/daemon_commands_handler.h index e5f7fcc2..39cb39f6 100644 --- a/src/daemon/daemon_commands_handler.h +++ b/src/daemon/daemon_commands_handler.h @@ -67,6 +67,8 @@ public: m_cmd_binder.set_handler("print_deadlock_guard", boost::bind(&daemon_commands_handler::print_deadlock_guard, this, _1), "Print all threads which is blocked or involved in mutex ownership"); m_cmd_binder.set_handler("print_block_from_hex_blob", boost::bind(&daemon_commands_handler::print_block_from_hex_blob, this, _1), "Unserialize block from hex binary data to json-like representation"); m_cmd_binder.set_handler("print_tx_from_hex_blob", boost::bind(&daemon_commands_handler::print_tx_from_hex_blob, this, _1), "Unserialize transaction from hex binary data to json-like representation"); + m_cmd_binder.set_handler("print_tx_outputs_usage", boost::bind(&daemon_commands_handler::print_tx_outputs_usage, this, _1), "Analyse if tx outputs for involved in subsequent transactions"); + } bool start_handling() @@ -674,6 +676,27 @@ private: LOG_PRINT_GREEN(ss.str(), LOG_LEVEL_0); return true; } + //-------------------------------------------------------------------------------- + bool print_tx_outputs_usage(const std::vector& args) + { + if (args.empty()) + { + std::cout << "expected: print_tx " << std::endl; + return true; + } + + const std::string& str_hash = args.front(); + crypto::hash tx_hash; + if (!parse_hash256(str_hash, tx_hash)) + { + return true; + } + + m_srv.get_payload_object().get_core().get_blockchain_storage().print_tx_outputs_lookup(tx_hash); + return true; + } + + //-------------------------------------------------------------------------------- bool print_pool(const std::vector& args) {