From 24b3e9007a8ad0684edcee51df444b21a033e4ba Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 27 Mar 2016 12:35:36 +0100 Subject: Convey tx verification failure reasons to the RPC client This allows appropriate action to be taken, like displaying the reason to the user. Do just that in simplewallet, which should help a lot in determining why users fail to send. Also make it so a tx which is accepted but not relayed is seen as a success rather than a failure. --- src/rpc/core_rpc_server.cpp | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'src/rpc/core_rpc_server.cpp') diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 6b625e77b..a01d04dfe 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -355,24 +355,40 @@ namespace cryptonote cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context); tx_verification_context tvc = AUTO_VAL_INIT(tvc); - if(!m_core.handle_incoming_tx(tx_blob, tvc, false, false)) + if(!m_core.handle_incoming_tx(tx_blob, tvc, false, false) || tvc.m_verifivation_failed) { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx"); - res.status = "Failed"; - return true; - } - - if(tvc.m_verifivation_failed) - { - LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed"); + if (tvc.m_verifivation_failed) + { + LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed"); + } + else + { + LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx"); + } res.status = "Failed"; + if ((res.low_mixin = tvc.m_low_mixin)) + res.reason = "mixin too low"; + if ((res.double_spend = tvc.m_double_spend)) + res.reason = "double spend"; + if ((res.invalid_input = tvc.m_invalid_input)) + res.reason = "invalid input"; + if ((res.invalid_output = tvc.m_invalid_output)) + res.reason = "invalid output"; + if ((res.too_big = tvc.m_too_big)) + res.reason = "too big"; + if ((res.overspend = tvc.m_overspend)) + res.reason = "overspend"; + if ((res.fee_too_low = tvc.m_fee_too_low)) + res.reason = "fee too low"; return true; } if(!tvc.m_should_be_relayed) { LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed"); - res.status = "Not relayed"; + res.reason = "Not relayed"; + res.not_relayed = true; + res.status = CORE_RPC_STATUS_OK; return true; } -- cgit v1.2.3 From 8757e46b78f2778261dd7b047666b3d8ccc86ae6 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 30 Mar 2016 02:50:51 +0100 Subject: add blockhashing blob to getblocktemplate --- src/rpc/core_rpc_server.cpp | 2 ++ src/rpc/core_rpc_server_commands_defs.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src/rpc/core_rpc_server.cpp') diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 5350b6fe0..7de4ca314 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -627,8 +627,10 @@ namespace cryptonote LOG_ERROR("Failed to calculate offset for "); return false; } + blobdata hashing_blob = get_block_hashing_blob(b); res.prev_hash = string_tools::pod_to_hex(b.prev_id); res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob); + res.blockhashing_blob = string_tools::buff_to_hex_nodelimer(hashing_blob); res.status = CORE_RPC_STATUS_OK; return true; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 6d4dd1252..d2a5aec45 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -427,6 +427,7 @@ namespace cryptonote uint64_t reserved_offset; std::string prev_hash; blobdata blocktemplate_blob; + blobdata blockhashing_blob; std::string status; BEGIN_KV_SERIALIZE_MAP() @@ -435,6 +436,7 @@ namespace cryptonote KV_SERIALIZE(reserved_offset) KV_SERIALIZE(prev_hash) KV_SERIALIZE(blocktemplate_blob) + KV_SERIALIZE(blockhashing_blob) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; -- cgit v1.2.3 From 5c9dd23b1cc8d61beceaf51588bbf08936d25711 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 5 Apr 2016 19:13:24 +0100 Subject: rpc: add a do_not_relay boolean to tx submission Just to make it easier --- src/rpc/core_rpc_server.cpp | 2 +- src/rpc/core_rpc_server_commands_defs.h | 2 ++ src/wallet/wallet2.cpp | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/rpc/core_rpc_server.cpp') diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 165a24c22..988ee554a 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -383,7 +383,7 @@ namespace cryptonote return true; } - if(!tvc.m_should_be_relayed) + if(!tvc.m_should_be_relayed || req.do_not_relay) { LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed"); res.reason = "Not relayed"; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 91f5e2c90..4ef3fc17e 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -221,12 +221,14 @@ namespace cryptonote struct request { std::string tx_as_hex; + bool do_not_relay; request() {} explicit request(const transaction &); BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_as_hex) + KV_SERIALIZE(do_not_relay) END_KV_SERIALIZE_MAP() }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a9a65535f..cdd472528 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1974,6 +1974,7 @@ void wallet2::commit_tx(pending_tx& ptx) COMMAND_RPC_SEND_RAW_TX::request req; req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx)); + req.do_not_relay = false; COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp; m_daemon_rpc_mutex.lock(); bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000); -- cgit v1.2.3 From f17b2f42b28844657624e8ea41172b34f17fb2e3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 3 Apr 2016 12:51:28 +0100 Subject: rpc: add pool/blockchain and block height results to gettransactions --- src/daemon/rpc_command_executor.cpp | 16 +++++++++++++--- src/rpc/core_rpc_server.cpp | 32 ++++++++++++++++++++++++++++---- src/rpc/core_rpc_server_commands_defs.h | 29 ++++++++++++++++++++++++++--- src/simplewallet/simplewallet.cpp | 9 +++++++-- 4 files changed, 74 insertions(+), 12 deletions(-) (limited to 'src/rpc/core_rpc_server.cpp') diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 933c93ed7..ced24330d 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -575,16 +575,26 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash) { } } - if (1 == res.txs_as_hex.size()) + if (1 == res.txs.size() || 1 == res.txs_as_hex.size()) { + if (1 == res.txs.size()) + { + // only available for new style answers + if (res.txs.front().in_pool) + tools::success_msg_writer() << "Found in pool"; + else + tools::success_msg_writer() << "Found in blockchain at height " << res.txs.front().block_height; + } + // first as hex - tools::success_msg_writer() << res.txs_as_hex.front(); + const std::string &as_hex = (1 == res.txs.size()) ? res.txs.front().as_hex : res.txs_as_hex.front(); + tools::success_msg_writer() << as_hex; // then as json crypto::hash tx_hash, tx_prefix_hash; cryptonote::transaction tx; cryptonote::blobdata blob; - if (!string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), blob)) + if (!string_tools::parse_hexstr_to_binbuff(as_hex, blob)) { tools::fail_msg_writer() << "Failed to parse tx"; } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 165a24c22..f3745e627 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -240,6 +240,7 @@ namespace cryptonote // try the pool for any missing txes size_t found_in_pool = 0; + std::unordered_set pool_tx_hashes; if (!missed_txs.empty()) { std::list pool_txs; @@ -248,9 +249,11 @@ namespace cryptonote { for (std::list::const_iterator i = pool_txs.begin(); i != pool_txs.end(); ++i) { - std::list::iterator mi = std::find(missed_txs.begin(), missed_txs.end(), get_transaction_hash(*i)); + crypto::hash tx_hash = get_transaction_hash(*i); + std::list::iterator mi = std::find(missed_txs.begin(), missed_txs.end(), tx_hash); if (mi != missed_txs.end()) { + pool_tx_hashes.insert(tx_hash); missed_txs.erase(mi); txs.push_back(*i); ++found_in_pool; @@ -260,12 +263,33 @@ namespace cryptonote LOG_PRINT_L2("Found " << found_in_pool << "/" << vh.size() << " transactions in the pool"); } + std::list::const_iterator txhi = req.txs_hashes.begin(); + std::vector::const_iterator vhi = vh.begin(); BOOST_FOREACH(auto& tx, txs) { + res.txs.push_back(COMMAND_RPC_GET_TRANSACTIONS::entry()); + COMMAND_RPC_GET_TRANSACTIONS::entry &e = res.txs.back(); + + crypto::hash tx_hash = *vhi++; + e.tx_hash = *txhi++; blobdata blob = t_serializable_object_to_blob(tx); - res.txs_as_hex.push_back(string_tools::buff_to_hex_nodelimer(blob)); + e.as_hex = string_tools::buff_to_hex_nodelimer(blob); + if (req.decode_as_json) + e.as_json = obj_to_json_str(tx); + e.in_pool = pool_tx_hashes.find(tx_hash) != pool_tx_hashes.end(); + if (e.in_pool) + { + e.block_height = std::numeric_limits::max(); + } + else + { + e.block_height = m_core.get_blockchain_storage().get_db().get_tx_block_height(tx_hash); + } + + // fill up old style responses too, in case an old wallet asks + res.txs_as_hex.push_back(e.as_hex); if (req.decode_as_json) - res.txs_as_json.push_back(obj_to_json_str(tx)); + res.txs_as_json.push_back(e.as_json); } BOOST_FOREACH(const auto& miss_tx, missed_txs) @@ -273,7 +297,7 @@ namespace cryptonote res.missed_tx.push_back(string_tools::pod_to_hex(miss_tx)); } - LOG_PRINT_L2(res.txs_as_hex.size() << " transactions found, " << res.missed_tx.size() << " not found"); + LOG_PRINT_L2(res.txs.size() << " transactions found, " << res.missed_tx.size() << " not found"); res.status = CORE_RPC_STATUS_OK; return true; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 91f5e2c90..e712c27c2 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -103,18 +103,41 @@ namespace cryptonote END_KV_SERIALIZE_MAP() }; + struct entry + { + std::string tx_hash; + std::string as_hex; + std::string as_json; + bool in_pool; + uint64_t block_height; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(tx_hash) + KV_SERIALIZE(as_hex) + KV_SERIALIZE(as_json) + KV_SERIALIZE(in_pool) + KV_SERIALIZE(block_height) + END_KV_SERIALIZE_MAP() + }; struct response { - std::list txs_as_hex; //transactions blobs as hex + // older compatibility stuff + std::list txs_as_hex; //transactions blobs as hex (old compat) + std::list txs_as_json; //transactions decoded as json (old compat) + + // in both old and new std::list missed_tx; //not found transactions - std::list txs_as_json; //transactions decoded as json + + // new style + std::vector txs; std::string status; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(txs_as_hex) - KV_SERIALIZE(missed_tx) KV_SERIALIZE(txs_as_json) + KV_SERIALIZE(txs) + KV_SERIALIZE(missed_tx) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index aa571755f..30c958381 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2497,13 +2497,18 @@ bool simple_wallet::check_tx_key(const std::vector &args_) COMMAND_RPC_GET_TRANSACTIONS::response res; req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); if (!net_utils::invoke_http_json_remote_command2(m_daemon_address + "/gettransactions", req, res, m_http_client) || - res.txs_as_hex.empty()) + (res.txs.empty() && res.txs_as_hex.empty())) { fail_msg_writer() << tr("failed to get transaction from daemon"); return true; } cryptonote::blobdata tx_data; - if (!string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data)) + bool ok; + if (!res.txs.empty()) + ok = string_tools::parse_hexstr_to_binbuff(res.txs.front().as_hex, tx_data); + else + ok = string_tools::parse_hexstr_to_binbuff(res.txs_as_hex.front(), tx_data); + if (!ok) { fail_msg_writer() << tr("failed to parse transaction from daemon"); return true; -- cgit v1.2.3