diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 72 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 51 |
2 files changed, 105 insertions, 18 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 5350b6fe0..9fcb4373b 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<crypto::hash> pool_tx_hashes; if (!missed_txs.empty()) { std::list<transaction> pool_txs; @@ -248,9 +249,11 @@ namespace cryptonote { for (std::list<transaction>::const_iterator i = pool_txs.begin(); i != pool_txs.end(); ++i) { - std::list<crypto::hash>::iterator mi = std::find(missed_txs.begin(), missed_txs.end(), get_transaction_hash(*i)); + crypto::hash tx_hash = get_transaction_hash(*i); + std::list<crypto::hash>::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<std::string>::const_iterator txhi = req.txs_hashes.begin(); + std::vector<crypto::hash>::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<uint64_t>::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; } @@ -355,24 +379,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) + if(!tvc.m_should_be_relayed || req.do_not_relay) { 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; } @@ -627,8 +667,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..6067a28b7 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<std::string> txs_as_hex; //transactions blobs as hex + // older compatibility stuff + std::list<std::string> txs_as_hex; //transactions blobs as hex (old compat) + std::list<std::string> txs_as_json; //transactions decoded as json (old compat) + + // in both old and new std::list<std::string> missed_tx; //not found transactions - std::list<std::string> txs_as_json; //transactions decoded as json + + // new style + std::vector<entry> 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() }; @@ -221,12 +244,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() }; @@ -234,9 +259,27 @@ namespace cryptonote struct response { std::string status; + std::string reason; + bool not_relayed; + bool low_mixin; + bool double_spend; + bool invalid_input; + bool invalid_output; + bool too_big; + bool overspend; + bool fee_too_low; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) + KV_SERIALIZE(reason) + KV_SERIALIZE(not_relayed) + KV_SERIALIZE(low_mixin) + KV_SERIALIZE(double_spend) + KV_SERIALIZE(invalid_input) + KV_SERIALIZE(invalid_output) + KV_SERIALIZE(too_big) + KV_SERIALIZE(overspend) + KV_SERIALIZE(fee_too_low) END_KV_SERIALIZE_MAP() }; }; @@ -427,6 +470,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 +479,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() }; |