From e05907b3e7fccf11050797c5dcf8eec81d229abe Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 20 Nov 2016 14:12:19 +0000 Subject: [PATCH 1/4] rpc: add output indices to gettransactions Someone apparently needs that to make a wallet but never asked. If you read that and that's not what you wanted, the bugtracker is at https://github.com/monero-project/monero/issues --- src/rpc/core_rpc_server.cpp | 8 ++++++++ src/rpc/core_rpc_server_commands_defs.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a02a2375b..d9fa0e383 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -388,6 +388,14 @@ namespace cryptonote res.txs_as_hex.push_back(e.as_hex); if (req.decode_as_json) res.txs_as_json.push_back(e.as_json); + + // output indices too + bool r = m_core.get_tx_outputs_gindexs(tx_hash, e.output_indices); + if (!r) + { + res.status = "Failed"; + return false; + } } BOOST_FOREACH(const auto& miss_tx, missed_txs) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 6d452f59d..efb95804c 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -162,6 +162,7 @@ namespace cryptonote std::string as_json; bool in_pool; uint64_t block_height; + std::vector output_indices; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_hash) @@ -169,6 +170,7 @@ namespace cryptonote KV_SERIALIZE(as_json) KV_SERIALIZE(in_pool) KV_SERIALIZE(block_height) + KV_SERIALIZE(output_indices) END_KV_SERIALIZE_MAP() }; From 2c0173c722af7a6dc1f30c3423d97247a4fd1ad7 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 22 Nov 2016 20:00:40 +0000 Subject: [PATCH 2/4] Add a get_outs (fully text based) version of get_outs.bin --- src/cryptonote_core/blockchain.cpp | 2 +- src/cryptonote_core/blockchain.h | 2 +- src/cryptonote_core/cryptonote_core.cpp | 2 +- src/cryptonote_core/cryptonote_core.h | 2 +- src/rpc/core_rpc_server.cpp | 38 +++++++++++++++- src/rpc/core_rpc_server.h | 4 +- src/rpc/core_rpc_server_commands_defs.h | 58 ++++++++++++++++++++----- src/wallet/wallet2.cpp | 6 +-- 8 files changed, 94 insertions(+), 20 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index ffebcd592..c2ccf3db0 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1758,7 +1758,7 @@ bool Blockchain::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::r return true; } //------------------------------------------------------------------ -bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const +bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index eb7a050b2..f9ae9d8aa 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -452,7 +452,7 @@ namespace cryptonote * * @return true */ - bool get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const; + bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const; /** * @brief gets random ringct outputs to mix with diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 9deb8863d..84a41cfbf 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -758,7 +758,7 @@ namespace cryptonote return m_blockchain_storage.get_random_outs_for_amounts(req, res); } //----------------------------------------------------------------------------------------------- - bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const + bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const { return m_blockchain_storage.get_outs(req, res); } diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 5ddab4ed4..21f84cdd4 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -471,7 +471,7 @@ namespace cryptonote * * @note see Blockchain::get_outs */ - bool get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const; + bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const; /** * diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index d9fa0e383..f31732f49 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -246,7 +246,7 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) + bool core_rpc_server::on_get_outs_bin(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) { CHECK_CORE_BUSY(); res.status = "Failed"; @@ -269,6 +269,42 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) + { + CHECK_CORE_BUSY(); + res.status = "Failed"; + + if (m_restricted) + { + if (req.outputs.size() > MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT) + { + res.status = "Too many outs requested"; + return true; + } + } + + cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::request req_bin; + req_bin.outputs = req.outputs; + cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::response res_bin; + if(!m_core.get_outs(req_bin, res_bin)) + { + return true; + } + + // convert to text + for (const auto &i: res_bin.outs) + { + res.outs.push_back(cryptonote::COMMAND_RPC_GET_OUTPUTS::outkey()); + cryptonote::COMMAND_RPC_GET_OUTPUTS::outkey &outkey = res.outs.back(); + outkey.key = epee::string_tools::pod_to_hex(i.key); + outkey.mask = epee::string_tools::pod_to_hex(i.mask); + outkey.unlocked = i.unlocked; + } + + res.status = CORE_RPC_STATUS_OK; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res) { CHECK_CORE_BUSY(); diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 2fdb790ab..b7f6cdd60 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -79,7 +79,7 @@ namespace cryptonote MAP_URI_AUTO_BIN2("/gethashes.bin", on_get_hashes, COMMAND_RPC_GET_HASHES_FAST) MAP_URI_AUTO_BIN2("/get_o_indexes.bin", on_get_indexes, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES) MAP_URI_AUTO_BIN2("/getrandom_outs.bin", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS) - MAP_URI_AUTO_BIN2("/get_outs.bin", on_get_outs, COMMAND_RPC_GET_OUTPUTS) + MAP_URI_AUTO_BIN2("/get_outs.bin", on_get_outs_bin, COMMAND_RPC_GET_OUTPUTS_BIN) MAP_URI_AUTO_BIN2("/getrandom_rctouts.bin", on_get_random_rct_outs, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS) MAP_URI_AUTO_JON2("/gettransactions", on_get_transactions, COMMAND_RPC_GET_TRANSACTIONS) MAP_URI_AUTO_JON2("/is_key_image_spent", on_is_key_image_spent, COMMAND_RPC_IS_KEY_IMAGE_SPENT) @@ -97,6 +97,7 @@ namespace cryptonote MAP_URI_AUTO_JON2_IF("/out_peers", on_out_peers, COMMAND_RPC_OUT_PEERS, !m_restricted) MAP_URI_AUTO_JON2_IF("/start_save_graph", on_start_save_graph, COMMAND_RPC_START_SAVE_GRAPH, !m_restricted) MAP_URI_AUTO_JON2_IF("/stop_save_graph", on_stop_save_graph, COMMAND_RPC_STOP_SAVE_GRAPH, !m_restricted) + MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS) BEGIN_JSON_RPC_MAP("/json_rpc") MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH) @@ -131,6 +132,7 @@ namespace cryptonote bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res); bool on_mining_status(const COMMAND_RPC_MINING_STATUS::request& req, COMMAND_RPC_MINING_STATUS::response& res); bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res); + bool on_get_outs_bin(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res); bool on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res); bool on_get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res); bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index efb95804c..e227a962d 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -293,22 +293,22 @@ namespace cryptonote }; }; //----------------------------------------------- - struct COMMAND_RPC_GET_OUTPUTS + struct get_outputs_out { - struct out - { - uint64_t amount; - uint64_t index; + uint64_t amount; + uint64_t index; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE(index) - END_KV_SERIALIZE_MAP() - }; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(amount) + KV_SERIALIZE(index) + END_KV_SERIALIZE_MAP() + }; + struct COMMAND_RPC_GET_OUTPUTS_BIN + { struct request { - std::vector outputs; + std::vector outputs; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(outputs) @@ -339,6 +339,42 @@ namespace cryptonote END_KV_SERIALIZE_MAP() }; }; + //----------------------------------------------- + struct COMMAND_RPC_GET_OUTPUTS + { + struct request + { + std::vector outputs; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(outputs) + END_KV_SERIALIZE_MAP() + }; + + struct outkey + { + std::string key; + std::string mask; + bool unlocked; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(key) + KV_SERIALIZE(mask) + KV_SERIALIZE(unlocked) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::vector outs; + std::string status; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(outs) + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + }; struct COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 15a134257..24d9272b2 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3335,8 +3335,8 @@ void wallet2::get_outs(std::vector> &outs, const std::list> &outs, const std::list Date: Tue, 22 Nov 2016 20:01:20 +0000 Subject: [PATCH 3/4] rpc: bump version after RPC changes --- src/rpc/core_rpc_server_commands_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index e227a962d..e19238c44 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -41,7 +41,7 @@ namespace cryptonote #define CORE_RPC_STATUS_BUSY "BUSY" #define CORE_RPC_STATUS_NOT_MINING "NOT MINING" -#define CORE_RPC_VERSION 4 +#define CORE_RPC_VERSION 5 struct COMMAND_RPC_GET_HEIGHT { From 1d9e22394458669e5495c9a44ae800bcc37d2a6b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 23 Nov 2016 18:55:32 +0000 Subject: [PATCH 4/4] rpc: do not include output indices for pool txes Those aren't yet in the blockchain, so will not be found (and aren't yet known, since it depends on where exactly the tx will be mined in the next block or blocks) --- src/rpc/core_rpc_server.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index f31732f49..5bf500733 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -425,12 +425,15 @@ namespace cryptonote if (req.decode_as_json) res.txs_as_json.push_back(e.as_json); - // output indices too - bool r = m_core.get_tx_outputs_gindexs(tx_hash, e.output_indices); - if (!r) + // output indices too if not in pool + if (pool_tx_hashes.find(tx_hash) == pool_tx_hashes.end()) { - res.status = "Failed"; - return false; + bool r = m_core.get_tx_outputs_gindexs(tx_hash, e.output_indices); + if (!r) + { + res.status = "Failed"; + return false; + } } }