Add a is_key_image_spent daemon command and RPC call

pull/95/head
moneromooo-monero 9 years ago
parent 35abef1b92
commit 83bbea4c7f
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3

@ -515,6 +515,21 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::is_key_image_spent(const crypto::key_image &key_image)
{
return m_blockchain_storage.have_tx_keyimg_as_spent(key_image);
}
//-----------------------------------------------------------------------------------------------
bool core::are_key_images_spent(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent)
{
spent.clear();
BOOST_FOREACH(auto& ki, key_im)
{
spent.push_back(m_blockchain_storage.have_tx_keyimg_as_spent(ki));
}
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_inputs_keyimages_diff(const transaction& tx)
{
std::unordered_set<crypto::key_image> ki;

@ -145,6 +145,9 @@ namespace cryptonote
void stop();
bool is_key_image_spent(const crypto::key_image& key_im);
bool are_key_images_spent(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent);
private:
bool add_new_tx(const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block);
bool add_new_tx(const transaction& tx, tx_verification_context& tvc, bool keeped_by_block);
@ -157,8 +160,6 @@ namespace cryptonote
bool check_tx_semantic(const transaction& tx, bool keeped_by_block);
//check if tx already in memory pool or in main blockchain
bool is_key_image_spent(const crypto::key_image& key_im);
bool check_tx_ring_signature(const txin_to_key& tx, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig);
bool is_tx_spendtime_unlocked(uint64_t unlock_time);
bool update_miner_block_template();

@ -180,6 +180,26 @@ bool t_command_parser_executor::print_transaction(const std::vector<std::string>
return true;
}
bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string>& args)
{
if (args.empty())
{
std::cout << "expected: is_key_image_spent <key_image>" << std::endl;
return true;
}
const std::string& str = args.front();
crypto::key_image ki;
crypto::hash hash;
if (parse_hash256(str, hash))
{
memcpy(&ki, &hash, sizeof(ki));
m_executor.is_key_image_spent(ki);
}
return true;
}
bool t_command_parser_executor::print_transaction_pool_long(const std::vector<std::string>& args)
{
if (!args.empty()) return false;

@ -75,6 +75,8 @@ public:
bool print_transaction(const std::vector<std::string>& args);
bool is_key_image_spent(const std::vector<std::string>& args);
bool print_transaction_pool_long(const std::vector<std::string>& args);
bool print_transaction_pool_short(const std::vector<std::string>& args);

@ -84,6 +84,11 @@ t_command_server::t_command_server(
, std::bind(&t_command_parser_executor::print_transaction, &m_parser, p::_1)
, "Print transaction, print_tx <transaction_hash>"
);
m_command_lookup.set_handler(
"is_key_image_spent"
, std::bind(&t_command_parser_executor::is_key_image_spent, &m_parser, p::_1)
, "Prints whether a given key image is in the spent key images set, is_key_image_spent <key_image>"
);
m_command_lookup.set_handler(
"start_mining"
, std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1)

@ -520,6 +520,42 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash) {
return true;
}
bool t_rpc_command_executor::is_key_image_spent(const crypto::key_image &ki) {
cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::request req;
cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::response res;
std::string fail_message = "Problem checkking key image";
req.key_images.push_back(epee::string_tools::pod_to_hex(ki));
if (m_is_rpc)
{
if (!m_rpc_client->rpc_request(req, res, "/is_key_image_spent", fail_message.c_str()))
{
return true;
}
}
else
{
if (!m_rpc_server->on_is_key_image_spent(req, res))
{
tools::fail_msg_writer() << fail_message.c_str();
return true;
}
}
if (1 == res.spent_status.size())
{
// first as hex
tools::success_msg_writer() << ki << ": " << (res.spent_status.front() ? "spent" : "unspent");
}
else
{
tools::fail_msg_writer() << "key image status could not be determined" << std::endl;
}
return true;
}
bool t_rpc_command_executor::print_transaction_pool_long() {
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;

@ -87,6 +87,8 @@ public:
bool print_transaction(crypto::hash transaction_hash);
bool is_key_image_spent(const crypto::key_image &ki);
bool print_transaction_pool_long();
bool print_transaction_pool_short();

@ -241,6 +241,35 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request& req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response& res)
{
CHECK_CORE_BUSY();
std::vector<crypto::key_image> key_images;
BOOST_FOREACH(const auto& ki_hex_str, req.key_images)
{
blobdata b;
if(!string_tools::parse_hexstr_to_binbuff(ki_hex_str, b))
{
res.status = "Failed to parse hex representation of key image";
return true;
}
if(b.size() != sizeof(crypto::key_image))
{
res.status = "Failed, size of data mismatch";
}
key_images.push_back(*reinterpret_cast<const crypto::key_image*>(b.data()));
}
bool r = m_core.are_key_images_spent(key_images, res.spent_status);
if(!r)
{
res.status = "Failed";
return true;
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res)
{
CHECK_CORE_READY();

@ -77,6 +77,7 @@ namespace cryptonote
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_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)
MAP_URI_AUTO_JON2("/sendrawtransaction", on_send_raw_tx, COMMAND_RPC_SEND_RAW_TX)
MAP_URI_AUTO_JON2("/start_mining", on_start_mining, COMMAND_RPC_START_MINING)
MAP_URI_AUTO_JON2("/stop_mining", on_stop_mining, COMMAND_RPC_STOP_MINING)
@ -108,6 +109,7 @@ namespace cryptonote
bool on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res);
bool on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res);
bool on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res);
bool on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request& req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response& res);
bool on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res);
bool on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res);
bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res);

@ -116,6 +116,31 @@ namespace cryptonote
};
};
//-----------------------------------------------
struct COMMAND_RPC_IS_KEY_IMAGE_SPENT
{
struct request
{
std::vector<std::string> key_images;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(key_images)
END_KV_SERIALIZE_MAP()
};
struct response
{
std::vector<bool> spent_status;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(spent_status)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
};
//-----------------------------------------------
struct COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES
{

Loading…
Cancel
Save