mirror of
https://github.com/monero-project/monero.git
synced 2026-01-18 23:55:47 -08:00
Adding support for hidden (anonymity) txpool
This commit is contained in:
@@ -115,8 +115,10 @@ namespace cryptonote
|
||||
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
|
||||
bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version)
|
||||
{
|
||||
const bool kept_by_block = (tx_relay == relay_method::block);
|
||||
|
||||
// this should already be called with that lock, but let's make it explicit for clarity
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
|
||||
@@ -227,7 +229,7 @@ namespace cryptonote
|
||||
|
||||
crypto::hash max_used_block_id = null_hash;
|
||||
uint64_t max_used_block_height = 0;
|
||||
cryptonote::txpool_tx_meta_t meta;
|
||||
cryptonote::txpool_tx_meta_t meta{};
|
||||
bool ch_inp_res = check_tx_inputs([&tx]()->cryptonote::transaction&{ return tx; }, id, max_used_block_height, max_used_block_id, tvc, kept_by_block);
|
||||
if(!ch_inp_res)
|
||||
{
|
||||
@@ -241,11 +243,10 @@ namespace cryptonote
|
||||
meta.max_used_block_height = 0;
|
||||
meta.last_failed_height = 0;
|
||||
meta.last_failed_id = null_hash;
|
||||
meta.kept_by_block = kept_by_block;
|
||||
meta.receive_time = receive_time;
|
||||
meta.last_relayed_time = time(NULL);
|
||||
meta.relayed = relayed;
|
||||
meta.do_not_relay = do_not_relay;
|
||||
meta.set_relay_method(tx_relay);
|
||||
meta.double_spend_seen = have_tx_keyimges_as_spent(tx);
|
||||
meta.pruned = tx.pruned;
|
||||
meta.bf_padding = 0;
|
||||
@@ -256,9 +257,10 @@ namespace cryptonote
|
||||
m_parsed_tx_cache.insert(std::make_pair(id, tx));
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
LockedTXN lock(m_blockchain);
|
||||
m_blockchain.add_txpool_tx(id, blob, meta);
|
||||
if (!insert_key_images(tx, id, kept_by_block))
|
||||
if (!insert_key_images(tx, id, tx_relay))
|
||||
return false;
|
||||
|
||||
m_blockchain.add_txpool_tx(id, blob, meta);
|
||||
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id);
|
||||
lock.commit();
|
||||
}
|
||||
@@ -280,7 +282,6 @@ namespace cryptonote
|
||||
{
|
||||
//update transactions container
|
||||
meta.weight = tx_weight;
|
||||
meta.kept_by_block = kept_by_block;
|
||||
meta.fee = fee;
|
||||
meta.max_used_block_id = max_used_block_id;
|
||||
meta.max_used_block_height = max_used_block_height;
|
||||
@@ -289,7 +290,7 @@ namespace cryptonote
|
||||
meta.receive_time = receive_time;
|
||||
meta.last_relayed_time = time(NULL);
|
||||
meta.relayed = relayed;
|
||||
meta.do_not_relay = do_not_relay;
|
||||
meta.set_relay_method(tx_relay);
|
||||
meta.double_spend_seen = false;
|
||||
meta.pruned = tx.pruned;
|
||||
meta.bf_padding = 0;
|
||||
@@ -302,9 +303,10 @@ namespace cryptonote
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
LockedTXN lock(m_blockchain);
|
||||
m_blockchain.remove_txpool_tx(id);
|
||||
m_blockchain.add_txpool_tx(id, blob, meta);
|
||||
if (!insert_key_images(tx, id, kept_by_block))
|
||||
if (!insert_key_images(tx, id, tx_relay))
|
||||
return false;
|
||||
|
||||
m_blockchain.add_txpool_tx(id, blob, meta);
|
||||
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id);
|
||||
lock.commit();
|
||||
}
|
||||
@@ -315,7 +317,7 @@ namespace cryptonote
|
||||
}
|
||||
tvc.m_added_to_pool = true;
|
||||
|
||||
if(meta.fee > 0 && !do_not_relay)
|
||||
if(meta.fee > 0 && tx_relay != relay_method::none)
|
||||
tvc.m_should_be_relayed = true;
|
||||
}
|
||||
|
||||
@@ -331,7 +333,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::add_tx(transaction &tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay, uint8_t version)
|
||||
bool tx_memory_pool::add_tx(transaction &tx, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version)
|
||||
{
|
||||
crypto::hash h = null_hash;
|
||||
size_t blob_size = 0;
|
||||
@@ -339,7 +341,7 @@ namespace cryptonote
|
||||
t_serializable_object_to_blob(tx, bl);
|
||||
if (bl.size() == 0 || !get_transaction_hash(tx, h))
|
||||
return false;
|
||||
return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, keeped_by_block, relayed, do_not_relay, version);
|
||||
return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, tx_relay, relayed, version);
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
size_t tx_memory_pool::get_txpool_weight() const
|
||||
@@ -375,7 +377,7 @@ namespace cryptonote
|
||||
txpool_tx_meta_t meta;
|
||||
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
|
||||
{
|
||||
MERROR("Failed to find tx in txpool");
|
||||
MERROR("Failed to find tx_meta in txpool");
|
||||
return;
|
||||
}
|
||||
// don't prune the kept_by_block ones, they're likely added because we're adding a block with those
|
||||
@@ -384,7 +386,7 @@ namespace cryptonote
|
||||
--it;
|
||||
continue;
|
||||
}
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid, relay_category::all);
|
||||
cryptonote::transaction_prefix tx;
|
||||
if (!parse_and_validate_tx_prefix_from_blob(txblob, tx))
|
||||
{
|
||||
@@ -413,17 +415,38 @@ namespace cryptonote
|
||||
MINFO("Pool weight after pruning is larger than limit: " << m_txpool_weight << "/" << bytes);
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block)
|
||||
bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, relay_method tx_relay)
|
||||
{
|
||||
for(const auto& in: tx.vin)
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, txin, false);
|
||||
std::unordered_set<crypto::hash>& kei_image_set = m_spent_key_images[txin.k_image];
|
||||
CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block
|
||||
<< ", kei_image_set.size()=" << kei_image_set.size() << ENDL << "txin.k_image=" << txin.k_image << ENDL
|
||||
<< "tx_id=" << id );
|
||||
auto ins_res = kei_image_set.insert(id);
|
||||
CHECK_AND_ASSERT_MES(ins_res.second, false, "internal error: try to insert duplicate iterator in key_image set");
|
||||
|
||||
/* If any existing key-image in the set is publicly visible AND this is
|
||||
not forcibly "kept_by_block", then fail (duplicate key image). If all
|
||||
existing key images are supposed to be hidden, we silently allow so
|
||||
that the node doesn't leak knowledge of a local/stem tx. */
|
||||
bool visible = false;
|
||||
if (tx_relay != relay_method::block)
|
||||
{
|
||||
for (const crypto::hash& other_id : kei_image_set)
|
||||
visible |= m_blockchain.txpool_tx_matches_category(other_id, relay_category::legacy);
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(!visible, false, "internal error: tx_relay=" << unsigned(tx_relay)
|
||||
<< ", kei_image_set.size()=" << kei_image_set.size() << ENDL << "txin.k_image=" << txin.k_image << ENDL
|
||||
<< "tx_id=" << id);
|
||||
|
||||
/* If adding a tx (hash) that already exists, fail only if the tx has
|
||||
been publicly "broadcast" previously. This way, when a private tx is
|
||||
received for the first time from a remote node, "this" node will
|
||||
respond as-if it were seen for the first time. LMDB does the
|
||||
"hard-check" on key-images, so the effect is overwriting the existing
|
||||
tx_pool metadata and "first seen" time. */
|
||||
const bool new_or_previously_private =
|
||||
kei_image_set.insert(id).second ||
|
||||
!m_blockchain.txpool_tx_matches_category(id, relay_category::legacy);
|
||||
CHECK_AND_ASSERT_MES(new_or_previously_private, false, "internal error: try to insert duplicate iterator in key_image set");
|
||||
}
|
||||
++m_cookie;
|
||||
return true;
|
||||
@@ -475,10 +498,10 @@ namespace cryptonote
|
||||
txpool_tx_meta_t meta;
|
||||
if (!m_blockchain.get_txpool_tx_meta(id, meta))
|
||||
{
|
||||
MERROR("Failed to find tx in txpool");
|
||||
MERROR("Failed to find tx_meta in txpool");
|
||||
return false;
|
||||
}
|
||||
txblob = m_blockchain.get_txpool_tx_blob(id);
|
||||
txblob = m_blockchain.get_txpool_tx_blob(id, relay_category::all);
|
||||
auto ci = m_parsed_tx_cache.find(id);
|
||||
if (ci != m_parsed_tx_cache.end())
|
||||
{
|
||||
@@ -533,7 +556,7 @@ namespace cryptonote
|
||||
MERROR("Failed to find tx in txpool");
|
||||
return false;
|
||||
}
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid, relay_category::all);
|
||||
auto ci = m_parsed_tx_cache.find(txid);
|
||||
if (ci != m_parsed_tx_cache.end())
|
||||
{
|
||||
@@ -611,7 +634,7 @@ namespace cryptonote
|
||||
remove.push_back(std::make_pair(txid, meta.weight));
|
||||
}
|
||||
return true;
|
||||
}, false);
|
||||
}, false, relay_category::all);
|
||||
|
||||
if (!remove.empty())
|
||||
{
|
||||
@@ -621,7 +644,7 @@ namespace cryptonote
|
||||
const crypto::hash &txid = entry.first;
|
||||
try
|
||||
{
|
||||
cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid);
|
||||
cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid, relay_category::all);
|
||||
cryptonote::transaction_prefix tx;
|
||||
if (!parse_and_validate_tx_prefix_from_blob(bd, tx))
|
||||
{
|
||||
@@ -649,7 +672,7 @@ namespace cryptonote
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
//TODO: investigate whether boolean return is appropriate
|
||||
bool tx_memory_pool::get_relayable_transactions(std::vector<std::pair<crypto::hash, cryptonote::blobdata>> &txs) const
|
||||
bool tx_memory_pool::get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>> &txs) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
@@ -667,8 +690,7 @@ namespace cryptonote
|
||||
{
|
||||
try
|
||||
{
|
||||
cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid);
|
||||
txs.push_back(std::make_pair(txid, bd));
|
||||
txs.emplace_back(txid, m_blockchain.get_txpool_tx_blob(txid, relay_category::all), meta.get_relay_method());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -678,26 +700,27 @@ namespace cryptonote
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, false);
|
||||
}, false, relay_category::relayable);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
void tx_memory_pool::set_relayed(const std::vector<std::pair<crypto::hash, cryptonote::blobdata>> &txs)
|
||||
void tx_memory_pool::set_relayed(const epee::span<const crypto::hash> hashes, const relay_method method)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
const time_t now = time(NULL);
|
||||
LockedTXN lock(m_blockchain);
|
||||
for (auto it = txs.begin(); it != txs.end(); ++it)
|
||||
for (const auto& hash : hashes)
|
||||
{
|
||||
try
|
||||
{
|
||||
txpool_tx_meta_t meta;
|
||||
if (m_blockchain.get_txpool_tx_meta(it->first, meta))
|
||||
if (m_blockchain.get_txpool_tx_meta(hash, meta))
|
||||
{
|
||||
meta.relayed = true;
|
||||
meta.last_relayed_time = now;
|
||||
m_blockchain.update_txpool_tx(it->first, meta);
|
||||
meta.set_relay_method(method);
|
||||
m_blockchain.update_txpool_tx(hash, meta);
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
@@ -709,18 +732,19 @@ namespace cryptonote
|
||||
lock.commit();
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
size_t tx_memory_pool::get_transactions_count(bool include_unrelayed_txes) const
|
||||
size_t tx_memory_pool::get_transactions_count(bool include_sensitive) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
return m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
|
||||
return m_blockchain.get_txpool_tx_count(include_sensitive);
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
void tx_memory_pool::get_transactions(std::vector<transaction>& txs, bool include_unrelayed_txes) const
|
||||
void tx_memory_pool::get_transactions(std::vector<transaction>& txs, bool include_sensitive) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
|
||||
const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted;
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count(include_sensitive));
|
||||
m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
transaction tx;
|
||||
if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(*bd, tx) : parse_and_validate_tx_from_blob(*bd, tx)))
|
||||
@@ -732,39 +756,42 @@ namespace cryptonote
|
||||
tx.set_hash(txid);
|
||||
txs.push_back(std::move(tx));
|
||||
return true;
|
||||
}, true, include_unrelayed_txes);
|
||||
}, true, category);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void tx_memory_pool::get_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes) const
|
||||
void tx_memory_pool::get_transaction_hashes(std::vector<crypto::hash>& txs, bool include_sensitive) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
|
||||
const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted;
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count(include_sensitive));
|
||||
m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
txs.push_back(txid);
|
||||
return true;
|
||||
}, false, include_unrelayed_txes);
|
||||
}, false, category);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void tx_memory_pool::get_transaction_backlog(std::vector<tx_backlog_entry>& backlog, bool include_unrelayed_txes) const
|
||||
void tx_memory_pool::get_transaction_backlog(std::vector<tx_backlog_entry>& backlog, bool include_sensitive) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
const uint64_t now = time(NULL);
|
||||
backlog.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
|
||||
const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted;
|
||||
backlog.reserve(m_blockchain.get_txpool_tx_count(include_sensitive));
|
||||
m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
backlog.push_back({meta.weight, meta.fee, meta.receive_time - now});
|
||||
return true;
|
||||
}, false, include_unrelayed_txes);
|
||||
}, false, category);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void tx_memory_pool::get_transaction_stats(struct txpool_stats& stats, bool include_unrelayed_txes) const
|
||||
void tx_memory_pool::get_transaction_stats(struct txpool_stats& stats, bool include_sensitive) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
const uint64_t now = time(NULL);
|
||||
const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted;
|
||||
std::map<uint64_t, txpool_histo> agebytes;
|
||||
stats.txs_total = m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
|
||||
stats.txs_total = m_blockchain.get_txpool_tx_count(include_sensitive);
|
||||
std::vector<uint32_t> weights;
|
||||
weights.reserve(stats.txs_total);
|
||||
m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
@@ -789,7 +816,8 @@ namespace cryptonote
|
||||
if (meta.double_spend_seen)
|
||||
++stats.num_double_spends;
|
||||
return true;
|
||||
}, false, include_unrelayed_txes);
|
||||
}, false, category);
|
||||
|
||||
stats.bytes_med = epee::misc_utils::median(weights);
|
||||
if (stats.txs_total > 1)
|
||||
{
|
||||
@@ -847,8 +875,10 @@ namespace cryptonote
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
tx_infos.reserve(m_blockchain.get_txpool_tx_count());
|
||||
key_image_infos.reserve(m_blockchain.get_txpool_tx_count());
|
||||
const relay_category category = include_sensitive_data ? relay_category::all : relay_category::broadcasted;
|
||||
const size_t count = m_blockchain.get_txpool_tx_count(include_sensitive_data);
|
||||
tx_infos.reserve(count);
|
||||
key_image_infos.reserve(count);
|
||||
m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
tx_info txi;
|
||||
txi.id_hash = epee::string_tools::pod_to_hex(txid);
|
||||
@@ -879,7 +909,7 @@ namespace cryptonote
|
||||
txi.double_spend_seen = meta.double_spend_seen;
|
||||
tx_infos.push_back(std::move(txi));
|
||||
return true;
|
||||
}, true, include_sensitive_data);
|
||||
}, true, category);
|
||||
|
||||
txpool_tx_meta_t meta;
|
||||
for (const key_images_container::value_type& kee : m_spent_key_images) {
|
||||
@@ -889,30 +919,13 @@ namespace cryptonote
|
||||
ki.id_hash = epee::string_tools::pod_to_hex(k_image);
|
||||
for (const crypto::hash& tx_id_hash : kei_image_set)
|
||||
{
|
||||
if (!include_sensitive_data)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!m_blockchain.get_txpool_tx_meta(tx_id_hash, meta))
|
||||
{
|
||||
MERROR("Failed to get tx meta from txpool");
|
||||
return false;
|
||||
}
|
||||
if (!meta.relayed)
|
||||
// Do not include that transaction if in restricted mode and it's not relayed
|
||||
continue;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
MERROR("Failed to get tx meta from txpool: " << e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash));
|
||||
if (m_blockchain.txpool_tx_matches_category(tx_id_hash, category))
|
||||
ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash));
|
||||
}
|
||||
|
||||
// Only return key images for which we have at least one tx that we can show for them
|
||||
if (!ki.txs_hashes.empty())
|
||||
key_image_infos.push_back(ki);
|
||||
key_image_infos.push_back(std::move(ki));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -948,18 +961,19 @@ namespace cryptonote
|
||||
txi.double_spend_seen = meta.double_spend_seen;
|
||||
tx_infos.push_back(txi);
|
||||
return true;
|
||||
}, true, false);
|
||||
}, true, relay_category::broadcasted);
|
||||
|
||||
for (const key_images_container::value_type& kee : m_spent_key_images) {
|
||||
std::vector<crypto::hash> tx_hashes;
|
||||
const std::unordered_set<crypto::hash>& kei_image_set = kee.second;
|
||||
for (const crypto::hash& tx_id_hash : kei_image_set)
|
||||
{
|
||||
tx_hashes.push_back(tx_id_hash);
|
||||
if (m_blockchain.txpool_tx_matches_category(tx_id_hash, relay_category::broadcasted))
|
||||
tx_hashes.push_back(tx_id_hash);
|
||||
}
|
||||
|
||||
const crypto::key_image& k_image = kee.first;
|
||||
key_image_infos[k_image] = std::move(tx_hashes);
|
||||
if (!tx_hashes.empty())
|
||||
key_image_infos[kee.first] = std::move(tx_hashes);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -973,19 +987,26 @@ namespace cryptonote
|
||||
|
||||
for (const auto& image : key_images)
|
||||
{
|
||||
spent.push_back(m_spent_key_images.find(image) == m_spent_key_images.end() ? false : true);
|
||||
bool is_spent = false;
|
||||
const auto found = m_spent_key_images.find(image);
|
||||
if (found != m_spent_key_images.end())
|
||||
{
|
||||
for (const crypto::hash& tx_hash : found->second)
|
||||
is_spent |= m_blockchain.txpool_tx_matches_category(tx_hash, relay_category::broadcasted);
|
||||
}
|
||||
spent.push_back(is_spent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::get_transaction(const crypto::hash& id, cryptonote::blobdata& txblob) const
|
||||
bool tx_memory_pool::get_transaction(const crypto::hash& id, cryptonote::blobdata& txblob, relay_category tx_category) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
try
|
||||
{
|
||||
return m_blockchain.get_txpool_tx_blob(id, txblob);
|
||||
return m_blockchain.get_txpool_tx_blob(id, txblob, tx_category);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -1009,11 +1030,11 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::have_tx(const crypto::hash &id) const
|
||||
bool tx_memory_pool::have_tx(const crypto::hash &id, relay_category tx_category) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
return m_blockchain.get_db().txpool_has_tx(id);
|
||||
return m_blockchain.get_db().txpool_has_tx(id, tx_category);
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::have_tx_keyimges_as_spent(const transaction& tx) const
|
||||
@@ -1032,7 +1053,14 @@ namespace cryptonote
|
||||
bool tx_memory_pool::have_tx_keyimg_as_spent(const crypto::key_image& key_im) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
return m_spent_key_images.end() != m_spent_key_images.find(key_im);
|
||||
bool spent = false;
|
||||
const auto found = m_spent_key_images.find(key_im);
|
||||
if (found != m_spent_key_images.end())
|
||||
{
|
||||
for (const crypto::hash& tx_hash : found->second)
|
||||
spent |= m_blockchain.txpool_tx_matches_category(tx_hash, relay_category::broadcasted);
|
||||
}
|
||||
return spent;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
void tx_memory_pool::lock() const
|
||||
@@ -1217,13 +1245,14 @@ namespace cryptonote
|
||||
<< "weight: " << meta.weight << std::endl
|
||||
<< "fee: " << print_money(meta.fee) << std::endl
|
||||
<< "kept_by_block: " << (meta.kept_by_block ? 'T' : 'F') << std::endl
|
||||
<< "is_local" << (meta.is_local ? 'T' : 'F') << std::endl
|
||||
<< "double_spend_seen: " << (meta.double_spend_seen ? 'T' : 'F') << std::endl
|
||||
<< "max_used_block_height: " << meta.max_used_block_height << std::endl
|
||||
<< "max_used_block_id: " << meta.max_used_block_id << std::endl
|
||||
<< "last_failed_height: " << meta.last_failed_height << std::endl
|
||||
<< "last_failed_id: " << meta.last_failed_id << std::endl;
|
||||
return true;
|
||||
}, !short_format);
|
||||
}, !short_format, relay_category::all);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@@ -1255,7 +1284,7 @@ namespace cryptonote
|
||||
for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
|
||||
{
|
||||
txpool_tx_meta_t meta;
|
||||
if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
|
||||
if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta) && !meta.matches(relay_category::legacy))
|
||||
{
|
||||
MERROR(" failed to find tx meta");
|
||||
continue;
|
||||
@@ -1304,7 +1333,9 @@ namespace cryptonote
|
||||
}
|
||||
}
|
||||
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second);
|
||||
// "local" and "stem" txes are filtered above
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second, relay_category::all);
|
||||
|
||||
cryptonote::transaction tx;
|
||||
|
||||
// Skip transactions that are not ready to be
|
||||
@@ -1379,7 +1410,7 @@ namespace cryptonote
|
||||
remove.insert(txid);
|
||||
}
|
||||
return true;
|
||||
}, false);
|
||||
}, false, relay_category::all);
|
||||
|
||||
size_t n_removed = 0;
|
||||
if (!remove.empty())
|
||||
@@ -1389,7 +1420,7 @@ namespace cryptonote
|
||||
{
|
||||
try
|
||||
{
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
|
||||
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid, relay_category::all);
|
||||
cryptonote::transaction tx;
|
||||
if (!parse_and_validate_tx_from_blob(txblob, tx)) // remove pruned ones on startup, they're meant to be temporary
|
||||
{
|
||||
@@ -1450,7 +1481,7 @@ namespace cryptonote
|
||||
remove.push_back(txid);
|
||||
return true;
|
||||
}
|
||||
if (!insert_key_images(tx, txid, meta.kept_by_block))
|
||||
if (!insert_key_images(tx, txid, meta.get_relay_method()))
|
||||
{
|
||||
MFATAL("Failed to insert key images from txpool tx");
|
||||
return false;
|
||||
@@ -1458,7 +1489,7 @@ namespace cryptonote
|
||||
m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.weight, meta.receive_time), txid);
|
||||
m_txpool_weight += meta.weight;
|
||||
return true;
|
||||
}, true);
|
||||
}, true, relay_category::all);
|
||||
if (!r)
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user