Check if key images already in mempool

Partially solves issue:
https://github.com/moneroexamples/openmonero/issues/48

It checks if a tx that you are submitting contains key images
that are present in mempool, and print outs an appropiate
error message.

Ideally, differnt outputs should be used by the frontend in this case.
But for now, we have to just wait till our past txs get confirmed and disappear from the mempool.
pull/88/head
moneroexamples 6 years ago
parent a3e5b40c29
commit d7d2cc5a40

@ -895,6 +895,56 @@ CurrentBlockchainStatus::find_tx_in_mempool(
return false;
}
bool
CurrentBlockchainStatus::find_key_images_in_mempool(std::vector<txin_v> const& vin)
{
mempool_txs_t mempool_tx_cpy;
{
// make local copy of the mempool, so that we dont lock it for
// long, as this function can take longer to execute
std::lock_guard<std::mutex> lck (searching_threads_map_mtx);
mempool_tx_cpy = mempool_txs;
}
// perform exhostive search to check if any key image in vin vector
// is in the mempool. This is used to check if a tx generated by the frontend
// is using any key images that area already in the mempool.
for (auto const& kin: vin)
{
if(kin.type() != typeid(txin_to_key))
continue;
// get tx input key
const txin_to_key& tx_in_to_key
= boost::get<cryptonote::txin_to_key>(kin);
for (auto const& mtx: mempool_tx_cpy)
{
const transaction &m_tx = mtx.second;
vector<txin_to_key> input_key_imgs = xmreg::get_key_images(m_tx);
for (auto const& mki: input_key_imgs)
{
// if a matching key image found in the mempool
if (mki.k_image == tx_in_to_key.k_image)
return true;
}
}
}
return false;
}
bool
CurrentBlockchainStatus::find_key_images_in_mempool(transaction const& tx)
{
return find_key_images_in_mempool(tx.vin);
}
bool
CurrentBlockchainStatus::get_tx(crypto::hash const& tx_hash, transaction& tx)
{

@ -198,6 +198,12 @@ struct CurrentBlockchainStatus
find_tx_in_mempool(crypto::hash const& tx_hash,
transaction& tx);
static bool
find_key_images_in_mempool(std::vector<txin_v> const& vin);
static bool
find_key_images_in_mempool(transaction const& tx);
static bool
get_tx(crypto::hash const& tx_hash, transaction& tx);

@ -821,17 +821,56 @@ YourMoneroRequests::submit_raw_tx(const shared_ptr< Session > session, const Byt
string error_msg;
// before we submit the tx into the deamon, we are going to do a few checks.
// first, we parse the hexbuffer submmited by the frontend into binary buffer block
// second, we are going to check if we can construct valid transaction object
// fromt that binary buffer.
// third, we are going to check if any key image in this tx is in any of the txs
// in the mempool. This allows us to make a clear comment that the tx
// uses outputs just spend. This happens we a users submits few txs, one after another
// before previous txs get included in a block and are still present in the mempool.
std::string tx_blob;
if(!epee::string_tools::parse_hexstr_to_binbuff(raw_tx_blob, tx_blob))
{
j_response["status"] = "error";
j_response["error"] = "Tx faild parse_hexstr_to_binbuff";
session_close(session, j_response.dump());
return;
}
transaction tx_to_be_submitted;
if (!parse_and_validate_tx_from_blob(tx_blob, tx_to_be_submitted))
{
j_response["status"] = "error";
j_response["error"] = "Tx faild parse_and_validate_tx_from_blob";
session_close(session, j_response.dump());
return;
}
if (CurrentBlockchainStatus::find_key_images_in_mempool(tx_to_be_submitted))
{
j_response["status"] = "error";
j_response["error"] = "Tx uses your outputs that area already in the mempool. "
"Please wait till your previous tx(s) get mined";
session_close(session, j_response.dump());
return;
}
if (!CurrentBlockchainStatus::commit_tx(
raw_tx_blob, error_msg,
CurrentBlockchainStatus::do_not_relay))
{
j_response["status"] = "error";
j_response["error"] = error_msg;
session_close(session, j_response.dump());
return;
}
else
{
j_response["status"] = "success";
}
j_response["status"] = "success";
string response_body = j_response.dump();

Loading…
Cancel
Save