Electroneum
cryptonote::tx_memory_pool Class Reference

Transaction pool, handles transactions which are not part of a block. More...

#include <tx_pool.h>

Inheritance diagram for cryptonote::tx_memory_pool:
Collaboration diagram for cryptonote::tx_memory_pool:

Classes

struct  tx_details
 information about a single transaction More...
 

Public Member Functions

 tx_memory_pool (Blockchain &bchs)
 Constructor. More...
 
bool add_tx (transaction &tx, 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 add_tx (transaction &tx, tx_verification_context &tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
 add a transaction to the transaction pool More...
 
bool take_tx (const crypto::hash &id, transaction &tx, cryptonote::blobdata &txblob, size_t &tx_weight, uint64_t &fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen, bool &nonexistent_utxo_seen)
 takes a transaction with the given hash from the pool More...
 
bool have_tx (const crypto::hash &id) const
 checks if the pool has a transaction with the given hash More...
 
bool on_blockchain_inc (uint64_t new_block_height, const crypto::hash &top_block_id)
 action to take when notified of a block added to the blockchain More...
 
bool on_blockchain_dec (uint64_t new_block_height, const crypto::hash &top_block_id)
 action to take when notified of a block removed from the blockchain More...
 
void on_idle ()
 action to take periodically More...
 
void lock () const
 locks the transaction pool More...
 
void unlock () const
 unlocks the transaction pool More...
 
bool init (size_t max_txpool_weight=0)
 loads pool state (if any) from disk, and initializes pool More...
 
bool deinit ()
 attempts to save the transaction pool state to disk More...
 
bool fill_block_template (block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, uint8_t version)
 Chooses transactions for a block to include. More...
 
void get_transactions (std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
 get a list of all transactions in the pool More...
 
void get_transaction_hashes (std::vector< crypto::hash > &txs, bool include_unrelayed_txes=true) const
 get a list of all transaction hashes in the pool More...
 
void get_transaction_backlog (std::vector< tx_backlog_entry > &backlog, bool include_unrelayed_txes=true) const
 get (weight, fee, receive time) for all transaction in the pool More...
 
void get_transaction_stats (struct txpool_stats &stats, bool include_unrelayed_txes=true) const
 get a summary statistics of all transaction hashes in the pool More...
 
bool utxo_spent_in_pool (const txin_to_key_public &in) const
 get a summary statistics of all transaction hashes in the pool More...
 
bool get_transactions_and_spent_keys_info (std::vector< tx_info > &tx_infos, std::vector< spent_key_image_info > &key_image_infos, bool include_sensitive_data=true) const
 get information about all transactions and key images in the pool More...
 
bool get_pool_for_rpc (std::vector< cryptonote::rpc::tx_in_pool > &tx_infos, cryptonote::rpc::key_images_with_tx_hashes &key_image_infos) const
 get information about all transactions and key images in the pool More...
 
bool check_for_key_images (const std::vector< crypto::key_image > &key_images, std::vector< bool > spent) const
 check for presence of key images in the pool More...
 
bool get_transaction (const crypto::hash &h, cryptonote::blobdata &txblob) const
 get a specific transaction from the pool More...
 
bool get_relayable_transactions (std::vector< std::pair< crypto::hash, cryptonote::blobdata >> &txs) const
 get a list of all relayable transactions and their hashes More...
 
void set_relayed (const std::vector< std::pair< crypto::hash, cryptonote::blobdata >> &txs)
 tell the pool that certain transactions were just relayed More...
 
size_t get_transactions_count (bool include_unrelayed_txes=true) const
 get the total number of transactions in the pool More...
 
std::string print_pool (bool short_format) const
 get a string containing human-readable pool information More...
 
size_t validate (uint8_t version)
 remove transactions from the pool which are no longer valid More...
 
uint64_t cookie () const
 return the cookie More...
 
size_t get_txpool_weight () const
 get the cumulative txpool weight in bytes More...
 
void set_txpool_max_weight (size_t bytes)
 set the max cumulative txpool weight in bytes More...
 

Detailed Description

Transaction pool, handles transactions which are not part of a block.

This class handles all transactions which have been received, but not as part of a block.

This handling includes: storing the transactions organizing the transactions by fee per weight unit taking/giving transactions to and from various other components saving the transactions to disk on shutdown helping create a new block template by choosing transactions for it

Definition at line 94 of file tx_pool.h.

Constructor & Destructor Documentation

◆ tx_memory_pool()

cryptonote::tx_memory_pool::tx_memory_pool ( Blockchain bchs)

Constructor.

Parameters
bchsa Blockchain class instance, for getting chain info

Definition at line 117 of file tx_pool.cpp.

117  : m_blockchain(bchs), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_cookie(0)
118  {
119 
120  }
#define DEFAULT_TXPOOL_MAX_WEIGHT

Member Function Documentation

◆ add_tx() [1/2]

bool cryptonote::tx_memory_pool::add_tx ( transaction tx,
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 
)

Parameters
idthe transaction's hash
tx_weightthe transaction's weight

Definition at line 122 of file tx_pool.cpp.

123  {
124  // this should already be called with that lock, but let's make it explicit for clarity
125  CRITICAL_REGION_LOCAL(m_transactions_lock);
126 
128  if (tx.version == 0)
129  {
130  // v0 never accepted
131  LOG_PRINT_L1("transaction version 0 is invalid");
132  tvc.m_verification_failed = true;
133  return false;
134  }
135 
136  // we do not accept transactions that timed out before, unless they're
137  // kept_by_block
138  if (!kept_by_block && m_timed_out_transactions.find(id) != m_timed_out_transactions.end())
139  {
140  // not clear if we should set that, since verifivation (sic) did not fail before, since
141  // the tx was accepted before timing out.
142  tvc.m_verification_failed = true;
143  return false;
144  }
145 
147  {
148  tvc.m_verification_failed = true;
149  tvc.m_invalid_input = true;
150  return false;
151  }
152 
153  if(!check_outs_valid(tx))
154  {
155  tvc.m_verification_failed = true;
156  tvc.m_invalid_output = true;
157  return false;
158  }
159 
160  // fee per kilobyte, size rounded up.
161  uint64_t fee = 0;
162 
163  uint64_t inputs_amount = 0;
164  if(!get_inputs_etn_amount(tx, inputs_amount))
165  {
166  tvc.m_verification_failed = true;
167  return false;
168  }
169 
170  uint64_t outputs_amount = get_outs_etn_amount(tx);
171  fee = inputs_amount - outputs_amount;
172 
173  if(tx.version == 3 && m_blockchain.get_current_blockchain_height() > (m_blockchain.get_nettype() == MAINNET ? 1811310 : 1455270)) {
174  if(outputs_amount != inputs_amount)
175  {
176  LOG_PRINT_L1("transaction fee isnt zero: outputs_amount != inputs_amount, rejecting.");
177  tvc.m_verification_failed = true;
178  return false;
179  }
180 
181  if(fee != 0){
182  LOG_PRINT_L1("We are migrating to aurelius and this transaction should have zero fee and it doesn't, rejecting.");
183  tvc.m_verification_failed = true;
184  return false;
185  }
186  }else{
187 
188  if(outputs_amount > inputs_amount)
189  {
190  LOG_PRINT_L1("transaction use more ETN than it has: use " << print_etn(outputs_amount) << ", have " << print_etn(inputs_amount));
191  tvc.m_verification_failed = true;
192  tvc.m_overspend = true;
193  return false;
194  }
195  else if(tx.version != 2 && outputs_amount == inputs_amount)
196  {
197 
198  // v1 & v2 tx ins/outs semantics are checked in the same way regardless of our chains height or the network height
199  if(tx.version == 1) {
200  LOG_PRINT_L1("v1 transaction fee is zero: outputs_amount == inputs_amount, rejecting.");
201  tvc.m_verification_failed = true;
202  tvc.m_fee_too_low = true;
203  return false;
204  }
205 
206  // for v3 these are fee paying before the final fork, but feeless afterwards.
207  // the only way of splitting the two up is by checking the destination, because after the final hard fork,
208  // transactions can only go to the bridge (consensus rule elsewhere)
209  if(tx.version == 3){
210  //check to see if all outputs are to the bridge address. if so, waive fee, otherwise if feeless return false
211  std::string portal_address_viewkey_hex_str;
212  std::string portal_address_spendkey_hex_str;
213  if(m_blockchain.get_nettype() == MAINNET){
214  portal_address_viewkey_hex_str = "2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375";
215  portal_address_spendkey_hex_str = "8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137";
216  }else{
217  portal_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
218  portal_address_spendkey_hex_str = "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3"; //
219  }
220  bool is_sc_migration = true;
221  for (auto output: tx.vout){
222  const auto out = boost::get<txout_to_key_public>(output.target);
223  std::string out_spendkey_str = epee::string_tools::pod_to_hex(out.address.m_spend_public_key.data);
224  std::string out_viewkey_str = epee::string_tools::pod_to_hex(out.address.m_view_public_key.data);
225 
226  // If we found an output not going to the bridge, the tx is certainly pre the final hard fork.
227  // so check tx ins/outs semantics here and error/break loop as needed.
228  if(out_spendkey_str != portal_address_spendkey_hex_str || out_viewkey_str != portal_address_viewkey_hex_str){
229  is_sc_migration = false;
230  if(inputs_amount <= outputs_amount){
231  LOG_PRINT_L1("pre smartchain migration version 3 tx with wrong amounts: ins " << print_etn(inputs_amount) << ", outs " << print_etn(outputs_amount) << ", rejected for tx id= "
232  << get_transaction_hash(tx));
233  return false;
234  }else {
235  break; // we only need to check the overall tx once
236  }
237  }
238  }
239 
240  if (is_sc_migration == true && inputs_amount != outputs_amount){
241  LOG_PRINT_L1("version 3 smartchain migration tx should be feeless but has wrong amounts: ins " << print_etn(inputs_amount) << ", outs " << print_etn(outputs_amount) << ", rejected for tx id= "
242  << get_transaction_hash(tx));
243  return false;
244  }
245  }
246  }
247 
248  if(tx.version == 2 && fee != 0) //Assure 0 fee tx v2 (migration tx)
249  {
250  LOG_PRINT_L1("transaction v2 fee is greater than zero, rejecting.");
251  tvc.m_verification_failed = true;
252  return false;
253  }
254 
255  if (tx.version != 2 && !kept_by_block && !m_blockchain.check_fee(tx_weight, fee))
256  {
257  tvc.m_verification_failed = true;
258  tvc.m_fee_too_low = true;
259  return false;
260  }
261  }
262 
263  size_t tx_weight_limit = get_transaction_weight_limit(version);
264  if ((!kept_by_block || version >= HF_VERSION_PER_BYTE_FEE) && tx_weight > tx_weight_limit)
265  {
266  LOG_PRINT_L1("transaction is too heavy: " << tx_weight << " bytes, maximum weight: " << tx_weight_limit);
267  tvc.m_verification_failed = true;
268  tvc.m_too_big = true;
269  return false;
270  }
271 
272  // if the transaction came from a block popped from the chain,
273  // don't check if we have its key images as spent.
274  // TODO: Investigate why not?
275  if(!kept_by_block)
276  {
277  if(tx.version <= 2) {
278  if (key_images_already_spent(tx)) {
279  mark_double_spend_or_nonexistent_utxo(tx);
280  LOG_PRINT_L1("Transaction with id= " << id << " used already spent key images");
281  tvc.m_verification_failed = true;
282  tvc.m_double_spend = true;
283  return false;
284  }
285  }
286  if(tx.version > 2) {
287  if (utxo_nonexistent(tx)) {
288  mark_double_spend_or_nonexistent_utxo(tx);
289  LOG_PRINT_L1("Transaction with id= " << id << " used nonexistent utxos");
290  tvc.m_verification_failed = true;
291  tvc.m_utxo_nonexistent = true;
292  return false;
293  }
294  }
295  }
296 
297  if (!m_blockchain.check_tx_outputs(tx, tvc))
298  {
299  LOG_PRINT_L1("Transaction with id= "<< id << " has at least one invalid output");
300  tvc.m_verification_failed = true;
301  tvc.m_invalid_output = true;
302  return false;
303  }
304 
305  // assume failure during verification steps until success is certain
306  tvc.m_verification_failed = true;
307 
308  time_t receive_time = time(nullptr);
309 
310  crypto::hash max_used_block_id = null_hash;
311  uint64_t max_used_block_height = 0;
313 
314  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);
315 
316  if(tx.version == 3 && m_blockchain.get_current_blockchain_height() > (m_blockchain.get_nettype() == MAINNET ? 1811310 : 1455270)) {
317 
318  //testing
319  //std::string hex_hash = "b166158ee98c5b01252ef6180a1d1ec5f8eced68c947e1a0f2444cf3b9730371";
320  //crypto::hash testing_tx_hash;
321  //epee::string_tools::hex_to_pod(hex_hash, testing_tx_hash);
322  //transaction testing_tx;
323  //m_blockchain.get_db().get_tx(testing_tx_hash, testing_tx);
324 
325  // Block all transactions that don't have valid migration information in the tx extra
326  std::vector<tx_extra_field> tx_extra_fields;
327  //parse_tx_extra(tx.extra, tx_extra_fields);
328  parse_tx_extra(tx.extra, tx_extra_fields);
329  cryptonote::tx_extra_bridge_source_address bridge_source_address;
330  cryptonote::tx_extra_bridge_smartchain_address bridge_smartchain_address;
331  find_tx_extra_field_by_type(tx_extra_fields, bridge_source_address);
332  find_tx_extra_field_by_type(tx_extra_fields, bridge_smartchain_address);
333 
334  address_parse_info parse_info_dummy;
335  if(!cryptonote::get_account_address_from_str(parse_info_dummy, m_blockchain.get_nettype(), bridge_source_address.data)){
336  tvc.m_verification_failed = true;
337  tvc.m_bad_bridge_source_address = true;
338  }
339 
340  // The regular expression pattern for a valid Ethereum address
341  bool valid_smartchain_address = true;
342  std::string string_smartchain_address = bridge_smartchain_address.data;
343  //string_smartchain_address = "0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d";
344  std::regex pattern("^(0x|0X)[a-fA-F0-9]{40}$");
345  if(!std::regex_match(string_smartchain_address, pattern))
346  valid_smartchain_address = false;
347 
348 
349  bool isMixedCase = std::any_of(string_smartchain_address.begin(), string_smartchain_address.end(), [](char c) {
350  return std::isupper(c);
351  }) && std::any_of(string_smartchain_address.begin(), string_smartchain_address.end(), [](char c) {
352  return std::islower(c);
353  });
354 
355  if(isMixedCase && valid_smartchain_address != false){ // if it's mixed case, we have to do extra checks
356  // Convert the address to lowercase for hashing
357  std::string lower_address = string_smartchain_address.substr(2);
358  std::transform(lower_address.begin(), lower_address.end(), lower_address.begin(), ::tolower);
359 
360  unsigned char hashed_lower[32];
361  keccak(reinterpret_cast<const uint8_t *>(lower_address.data()), 40, hashed_lower, 32);
362  std::string address_hash = epee::string_tools::pod_to_hex(hashed_lower); // should be 0x12ed7467c3852e6b2Bd3C22AF694be8DF7637B10.
363 
365  for (size_t i = 0; i < lower_address.length(); i++) {
366  if (std::isdigit(lower_address[i])) {
367  hash += lower_address[i];
368  }
369  else if (address_hash[i] >= '8') {
370  hash += std::toupper(lower_address[i]);
371  }
372  else {
373  hash += lower_address[i];
374  }
375  }
376  std::string checksum = hash.substr(0, 8);
377  for (size_t i = 2; i < checksum.length() + 2; i++) {
378  if (std::islower(string_smartchain_address[i]) && checksum[i - 2] < 'a') {
379  valid_smartchain_address = false;
380  }
381  else if (std::isupper(string_smartchain_address[i]) && checksum[i - 2] < 'A') {
382  char lower_char = std::tolower(string_smartchain_address[i]);
383  if (checksum[i - 2] != lower_char) {
384  valid_smartchain_address = false;
385  }
386  }
387  else if (checksum[i - 2] != string_smartchain_address[i]) {
388  valid_smartchain_address = false;
389  }
390  }
391 
392  } //end of is mixed case
393 
394  if(!valid_smartchain_address){
395  tvc.m_verification_failed = true;
396  tvc.m_bad_bridge_smartchain_address = true;
397  return false;
398  }
399  //BLOCK ALL TX NOT GOING TO THE PORTAL ADDRESS
400  std::string portal_address_viewkey_hex_str;
401  std::string portal_address_spendkey_hex_str;
402  if(m_blockchain.get_nettype() == MAINNET){
403  portal_address_viewkey_hex_str = "2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375";
404  portal_address_spendkey_hex_str = "8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137";
405  }else{
406  portal_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
407  portal_address_spendkey_hex_str = "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3"; //
408  }
409 
410  for (auto output: tx.vout){
411  const auto out = boost::get<txout_to_key_public>(output.target);
412  std::string out_spendkey_str = epee::string_tools::pod_to_hex(out.address.m_spend_public_key.data);
413  std::string out_viewkey_str = epee::string_tools::pod_to_hex(out.address.m_view_public_key.data);
414  if(out_spendkey_str != portal_address_spendkey_hex_str || out_viewkey_str != portal_address_viewkey_hex_str){
415  tvc.m_verification_failed = true;
416  tvc.m_portal_outbound_tx = true;
417  return false;
418  }
419  }
420  }
421 
422  if(!ch_inp_res)
423  {
424  // if the transaction was valid before (kept_by_block), then it
425  // may become valid again, so ignore the failed inputs check.
426  if(kept_by_block)
427  {
428  meta.weight = tx_weight;
429  meta.fee = fee;
430  meta.max_used_block_id = null_hash;
431  meta.max_used_block_height = 0;
432  meta.last_failed_height = 0;
433  meta.last_failed_id = null_hash;
434  meta.kept_by_block = kept_by_block;
435  meta.receive_time = receive_time;
436  meta.last_relayed_time = time(NULL);
437  meta.relayed = relayed;
438  meta.do_not_relay = do_not_relay;
439  meta.double_spend_seen = key_images_already_spent(tx);
440  meta.utxo_nonexistent_seen = utxo_nonexistent(tx);
441  meta.bf_padding = 0;
442  memset(meta.padding, 0, sizeof(meta.padding));
443  try
444  {
445  if (kept_by_block)
446  m_parsed_tx_cache.insert(std::make_pair(id, tx));
447  CRITICAL_REGION_LOCAL1(m_blockchain);
448  LockedTXN lock(m_blockchain);
449  m_blockchain.add_txpool_tx(id, blob, meta);
450  if ((tx.version <= 2 && !insert_key_images(tx, id, kept_by_block)) || (tx.version >= 3 && !insert_utxos(tx, id, kept_by_block)))
451  return false;
452  m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
453  lock.commit();
454  }
455  catch (const std::exception &e)
456  {
457  MERROR("transaction already exists at inserting in memory pool: " << e.what());
458  return false;
459  }
460  tvc.m_verification_impossible = true;
461  tvc.m_added_to_pool = true;
462  }else
463  {
464  LOG_PRINT_L1("tx used wrong inputs, rejected");
465  tvc.m_verification_failed = true;
466  tvc.m_invalid_input = true;
467  return false;
468  }
469  }else
470  {
471  //update transactions container
472  meta.weight = tx_weight;
473  meta.kept_by_block = kept_by_block;
474  meta.fee = fee;
475  meta.max_used_block_id = max_used_block_id;
476  meta.max_used_block_height = max_used_block_height;
477  meta.last_failed_height = 0;
478  meta.last_failed_id = null_hash;
479  meta.receive_time = receive_time;
480  meta.last_relayed_time = time(NULL);
481  meta.relayed = relayed;
482  meta.do_not_relay = do_not_relay;
483  meta.double_spend_seen = false;
484  meta.utxo_nonexistent_seen = false;
485  meta.bf_padding = 0;
486  memset(meta.padding, 0, sizeof(meta.padding));
487 
488  try
489  {
490  if (kept_by_block)
491  m_parsed_tx_cache.insert(std::make_pair(id, tx));
492  CRITICAL_REGION_LOCAL1(m_blockchain);
493  LockedTXN lock(m_blockchain);
494  m_blockchain.remove_txpool_tx(id);
495  m_blockchain.add_txpool_tx(id, blob, meta);
496  if ((tx.version <= 2 && !insert_key_images(tx, id, kept_by_block)) || (tx.version >= 3 && !insert_utxos(tx, id, kept_by_block)))
497  return false;
498  m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
499  lock.commit();
500  }
501  catch (const std::exception &e)
502  {
503  MERROR("internal error: transaction already exists at inserting in memory pool: " << e.what());
504  return false;
505  }
506  tvc.m_added_to_pool = true;
507 
508  if(!do_not_relay)
509  tvc.m_should_be_relayed = true;
510  }
511 
512  tvc.m_verification_failed = false;
513  m_txpool_weight += tx_weight;
514 
515  ++m_cookie;
516 
517  MINFO("Transaction added to pool: txid " << id << " weight: " << tx_weight << " fee/byte: " << (fee / (double)tx_weight));
518 
519  prune(m_txpool_max_weight);
520 
521  return true;
522  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MINFO(x)
Definition: misc_log_ex.h:75
bool add_tx(transaction &tx, 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)
Definition: tx_pool.cpp:122
bool check_outs_valid(const transaction &tx)
#define PERF_TIMER(name)
Definition: perf_timer.h:82
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
::std::string string
Definition: gtest-port.h:1097
uint64_t get_outs_etn_amount(const transaction &tx)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
void remove_txpool_tx(const crypto::hash &txid)
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
time_t time
Definition: blockchain.cpp:93
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
bool check_inputs_types_supported(const transaction &tx)
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
version
Supported socks variants.
Definition: socks.h:57
bool check_fee(size_t tx_weight, uint64_t fee) const
validate a transaction&#39;s fee
a struct containing txpool per transaction metadata
crypto::hash get_transaction_hash(const transaction &t)
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
network_type get_nettype() const
get blockchain nettype
Definition: blockchain.h:1073
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen)
POD_CLASS hash
Definition: hash.h:50
bool check_tx_outputs(const transaction &tx, tx_verification_context &tvc)
check that a transaction&#39;s outputs conform to current standards
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
#define HF_VERSION_PER_BYTE_FEE
void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
Here is the call graph for this function:

◆ add_tx() [2/2]

bool cryptonote::tx_memory_pool::add_tx ( transaction tx,
tx_verification_context tvc,
bool  kept_by_block,
bool  relayed,
bool  do_not_relay,
uint8_t  version 
)

add a transaction to the transaction pool

Most likely the transaction will come from the network, but it is also possible for transactions to come from popped blocks during a reorg, or from local clients creating a transaction and submitting it to the network

Parameters
txthe transaction to be added
tvcreturn-by-reference status about the transaction verification
kept_by_blockhas this transaction been in a block?
relayedwas this transaction from the network or a local client?
do_not_relayto avoid relaying the transaction to the network
versionthe version used to create the transaction
Returns
true if the transaction passes validations, otherwise false

Definition at line 524 of file tx_pool.cpp.

525  {
526  crypto::hash h = null_hash;
527  size_t blob_size = 0;
530  if (bl.size() == 0 || !get_transaction_hash(tx, h))
531  return false;
532  return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, keeped_by_block, relayed, do_not_relay, version);
533  }
bool add_tx(transaction &tx, 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)
Definition: tx_pool.cpp:122
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
version
Supported socks variants.
Definition: socks.h:57
std::string blobdata
Definition: blobdatatype.h:39
crypto::hash get_transaction_hash(const transaction &t)
POD_CLASS hash
Definition: hash.h:50

◆ check_for_key_images()

bool cryptonote::tx_memory_pool::check_for_key_images ( const std::vector< crypto::key_image > &  key_images,
std::vector< bool spent 
) const

check for presence of key images in the pool

Parameters
key_images[in] vector of key images to check
spent[out] vector of bool to return
Returns
true

Definition at line 1151 of file tx_pool.cpp.

1152  {
1153  CRITICAL_REGION_LOCAL(m_transactions_lock);
1154  CRITICAL_REGION_LOCAL1(m_blockchain);
1155 
1156  spent.clear();
1157 
1158  for (const auto& image : key_images)
1159  {
1160  spent.push_back(m_spent_key_images.find(image) == m_spent_key_images.end() ? false : true);
1161  }
1162 
1163  return true;
1164  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define false
Definition: stdbool.h:38
Here is the caller graph for this function:

◆ cookie()

uint64_t cryptonote::tx_memory_pool::cookie ( ) const
inline

return the cookie

Returns
the cookie

Definition at line 381 of file tx_pool.h.

381 { return m_cookie; }
Here is the caller graph for this function:

◆ deinit()

bool cryptonote::tx_memory_pool::deinit ( )

attempts to save the transaction pool state to disk

Currently fails (returns false) if the data directory from init() does not exist and cannot be created, but returns true even if saving to disk is unsuccessful.

Returns
true in most cases (see above)

Definition at line 1800 of file tx_pool.cpp.

1801  {
1802  return true;
1803  }
Here is the caller graph for this function:

◆ fill_block_template()

bool cryptonote::tx_memory_pool::fill_block_template ( block bl,
size_t  median_weight,
uint64_t  already_generated_coins,
size_t &  total_weight,
uint64_t fee,
uint64_t expected_reward,
uint8_t  version 
)

Chooses transactions for a block to include.

Parameters
blreturn-by-reference the block to fill in with transactions
median_weightthe current median block weight
already_generated_coinsthe current total number of coins "minted"
total_weightreturn-by-reference the total weight of the new block
feereturn-by-reference the total of fees from the included transactions
expected_rewardreturn-by-reference the total reward awarded to the miner finding this block, including transaction fees
versionhard fork version to use for consensus rules
Returns
true

Definition at line 1535 of file tx_pool.cpp.

1536  {
1537  CRITICAL_REGION_LOCAL(m_transactions_lock);
1538  CRITICAL_REGION_LOCAL1(m_blockchain);
1539 
1540  uint64_t best_coinbase = 0, coinbase = 0;
1541  total_weight = 0;
1542  fee = 0;
1543 
1544  //baseline empty block
1545  get_block_reward(median_weight, total_weight, already_generated_coins, best_coinbase, version, m_blockchain.get_current_blockchain_height(), m_blockchain.get_nettype());
1546 
1547 
1548  size_t max_total_weight_pre_v5 = (130 * median_weight) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
1549  size_t max_total_weight_v5 = 2 * median_weight - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
1550  size_t max_total_weight = version >= 5 ? max_total_weight_v5 : max_total_weight_pre_v5;
1551  std::unordered_set<crypto::key_image> k_images;
1552  std::unordered_set<std::string> utxos;
1553 
1554  LOG_PRINT_L2("Filling block template, median weight " << median_weight << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
1555 
1556  LockedTXN lock(m_blockchain);
1557 
1558  auto sorted_it = m_txs_by_fee_and_receive_time.begin();
1559  for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
1560  {
1561  txpool_tx_meta_t meta;
1562  if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
1563  {
1564  MERROR(" failed to find tx meta");
1565  continue;
1566  }
1567  LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_etn(best_coinbase));
1568 
1569  // Can not exceed maximum block weight
1570  if (max_total_weight < total_weight + meta.weight)
1571  {
1572  LOG_PRINT_L2(" would exceed maximum block weight");
1573  continue;
1574  }
1575 
1576  // start using the optimal filling algorithm from v5
1577  if (version >= 5)
1578  {
1579  // If we're getting lower coinbase tx,
1580  // stop including more tx
1581  uint64_t block_reward;
1582  if(!get_block_reward(median_weight, total_weight + meta.weight, already_generated_coins, block_reward, version, m_blockchain.get_current_blockchain_height(), m_blockchain.get_nettype()))
1583  {
1584  LOG_PRINT_L2(" would exceed maximum block weight");
1585  continue;
1586  }
1587  coinbase = block_reward + fee + meta.fee;
1588  if (coinbase < template_accept_threshold(best_coinbase))
1589  {
1590  LOG_PRINT_L2(" would decrease coinbase to " << print_etn(coinbase));
1591  continue;
1592  }
1593  }
1594  else
1595  {
1596  // If we've exceeded the penalty free weight,
1597  // stop including more tx
1598  if (total_weight > median_weight)
1599  {
1600  LOG_PRINT_L2(" would exceed median block weight");
1601  break;
1602  }
1603  }
1604 
1605  cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second);
1607 
1608  // Skip transactions that are not ready to be
1609  // included into the blockchain or that are
1610  // missing key images
1611  const cryptonote::txpool_tx_meta_t original_meta = meta;
1612  bool ready = false;
1613  try
1614  {
1615  ready = is_transaction_ready_to_go(meta, sorted_it->second, txblob, tx);
1616  }
1617  catch (const std::exception &e)
1618  {
1619  MERROR("Failed to check transaction readiness: " << e.what());
1620  // continue, not fatal
1621  }
1622  if (memcmp(&original_meta, &meta, sizeof(meta)))
1623  {
1624  try
1625  {
1626  m_blockchain.update_txpool_tx(sorted_it->second, meta);
1627  }
1628  catch (const std::exception &e)
1629  {
1630  MERROR("Failed to update tx meta: " << e.what());
1631  // continue, not fatal
1632  }
1633  }
1634  if (!ready)
1635  {
1636  LOG_PRINT_L2(" not ready to go");
1637  continue;
1638  }
1639  if (have_key_images(k_images, tx))
1640  {
1641  LOG_PRINT_L2(" key images already seen");
1642  continue;
1643  }
1644  if (have_utxos(utxos, tx))
1645  {
1646  LOG_PRINT_L2(" utxos already seen");
1647  continue;
1648  }
1649 
1650  bl.tx_hashes.push_back(sorted_it->second);
1651  total_weight += meta.weight;
1652  fee += meta.fee;
1653  best_coinbase = coinbase;
1654  append_key_images(k_images, tx);
1655  append_utxos(utxos, tx);
1656  LOG_PRINT_L2(" added, new block weight " << total_weight << "/" << max_total_weight << ", coinbase " << print_etn(best_coinbase));
1657  }
1658  lock.commit();
1659 
1660  expected_reward = best_coinbase;
1661  LOG_PRINT_L2("Block template filled with " << bl.tx_hashes.size() << " txes, weight "
1662  << total_weight << "/" << max_total_weight << ", coinbase " << print_etn(best_coinbase)
1663  << " (including " << print_etn(fee) << " in fees)");
1664  return true;
1665  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const
std::string print_etn(uint64_t amount, unsigned int decimal_point)
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta)
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
version
Supported socks variants.
Definition: socks.h:57
std::string blobdata
Definition: blobdatatype.h:39
a struct containing txpool per transaction metadata
network_type get_nettype() const
get blockchain nettype
Definition: blockchain.h:1073
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version, uint64_t current_block_height, network_type nettype)
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_pool_for_rpc()

bool cryptonote::tx_memory_pool::get_pool_for_rpc ( std::vector< cryptonote::rpc::tx_in_pool > &  tx_infos,
cryptonote::rpc::key_images_with_tx_hashes key_image_infos 
) const

get information about all transactions and key images in the pool

see documentation on tx_in_pool and key_images_with_tx_hashes for more details

Parameters
tx_infos[out] the transactions' information
key_image_infos[out] the spent key images' information
Returns
true

Definition at line 1102 of file tx_pool.cpp.

1103  {
1104  CRITICAL_REGION_LOCAL(m_transactions_lock);
1105  CRITICAL_REGION_LOCAL1(m_blockchain);
1106  tx_infos.reserve(m_blockchain.get_txpool_tx_count());
1107  key_image_infos.reserve(m_blockchain.get_txpool_tx_count());
1108  m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
1110  txi.tx_hash = txid;
1111  if (!parse_and_validate_tx_from_blob(*bd, txi.tx))
1112  {
1113  MERROR("Failed to parse tx from txpool");
1114  // continue
1115  return true;
1116  }
1117  txi.tx.set_hash(txid);
1118  txi.blob_size = bd->size();
1119  txi.weight = meta.weight;
1120  txi.fee = meta.fee;
1121  txi.kept_by_block = meta.kept_by_block;
1122  txi.max_used_block_height = meta.max_used_block_height;
1123  txi.max_used_block_hash = meta.max_used_block_id;
1124  txi.last_failed_block_height = meta.last_failed_height;
1125  txi.last_failed_block_hash = meta.last_failed_id;
1126  txi.receive_time = meta.receive_time;
1127  txi.relayed = meta.relayed;
1128  txi.last_relayed_time = meta.last_relayed_time;
1129  txi.do_not_relay = meta.do_not_relay;
1130  txi.double_spend_seen = meta.double_spend_seen;
1131  txi.nonexistent_utxo_seen = meta.utxo_nonexistent_seen;
1132 
1133  tx_infos.push_back(txi);
1134  return true;
1135  }, true, false);
1136 
1137  for (const key_images_container::value_type& kee : m_spent_key_images) {
1138  std::vector<crypto::hash> tx_hashes;
1139  const std::unordered_set<crypto::hash>& kei_image_set = kee.second;
1140  for (const crypto::hash& tx_id_hash : kei_image_set)
1141  {
1142  tx_hashes.push_back(tx_id_hash);
1143  }
1144 
1145  const crypto::key_image& k_image = kee.first;
1146  key_image_infos[k_image] = std::move(tx_hashes);
1147  }
1148  return true;
1149  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
void set_hash(const crypto::hash &h)
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
cryptonote::transaction tx
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
std::string blobdata
Definition: blobdatatype.h:39
const T & move(const T &t)
Definition: gtest-port.h:1317
POD_CLASS key_image
Definition: crypto.h:102
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_relayable_transactions()

bool cryptonote::tx_memory_pool::get_relayable_transactions ( std::vector< std::pair< crypto::hash, cryptonote::blobdata >> &  txs) const

get a list of all relayable transactions and their hashes

"relayable" in this case means: nonzero fee hasn't been relayed too recently isn't old enough that relaying it is considered harmful Note a transaction can be "relayable" even if do_not_relay is true

Parameters
txsreturn-by-reference the transactions and their hashes
Returns
true

Definition at line 836 of file tx_pool.cpp.

837  {
838  CRITICAL_REGION_LOCAL(m_transactions_lock);
839  CRITICAL_REGION_LOCAL1(m_blockchain);
840  const uint64_t now = time(NULL);
841  txs.reserve(m_blockchain.get_txpool_tx_count());
842  m_blockchain.for_all_txpool_txes([this, now, &txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *){
843  // 0 fee transactions are never relayed
844  if(!meta.do_not_relay && now - meta.last_relayed_time > get_relay_delay(now, meta.receive_time))
845  {
846  // if the tx is older than half the max lifetime, we don't re-relay it, to avoid a problem
847  // mentioned by smooth where nodes would flush txes at slightly different times, causing
848  // flushed txes to be re-added when received from a node which was just about to flush it
849  uint32_t mempool_lifetime = m_blockchain.get_mempool_tx_livetime();
850  uint64_t max_age = meta.kept_by_block ? CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME : mempool_lifetime;
851  if (now - meta.receive_time <= max_age / 2)
852  {
853  try
854  {
855  cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid);
856  txs.push_back(std::make_pair(txid, bd));
857  }
858  catch (const std::exception &e)
859  {
860  MERROR("Failed to get transaction blob from db");
861  // ignore error
862  }
863  }
864  }
865  return true;
866  }, false);
867  return true;
868  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
time_t time
Definition: blockchain.cpp:93
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
std::string blobdata
Definition: blobdatatype.h:39
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:

◆ get_transaction()

bool cryptonote::tx_memory_pool::get_transaction ( const crypto::hash h,
cryptonote::blobdata txblob 
) const

get a specific transaction from the pool

Parameters
hthe hash of the transaction to get
txreturn-by-reference the transaction blob requested
Returns
true if the transaction is found, otherwise false

Definition at line 1166 of file tx_pool.cpp.

1167  {
1168  CRITICAL_REGION_LOCAL(m_transactions_lock);
1169  CRITICAL_REGION_LOCAL1(m_blockchain);
1170  try
1171  {
1172  return m_blockchain.get_txpool_tx_blob(id, txblob);
1173  }
1174  catch (const std::exception &e)
1175  {
1176  return false;
1177  }
1178  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transaction_backlog()

void cryptonote::tx_memory_pool::get_transaction_backlog ( std::vector< tx_backlog_entry > &  backlog,
bool  include_unrelayed_txes = true 
) const

get (weight, fee, receive time) for all transaction in the pool

Parameters
txsreturn-by-reference that data
include_unrelayed_txesinclude unrelayed txes in the result

Definition at line 934 of file tx_pool.cpp.

935  {
936  CRITICAL_REGION_LOCAL(m_transactions_lock);
937  CRITICAL_REGION_LOCAL1(m_blockchain);
938  const uint64_t now = time(NULL);
939  backlog.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
940  m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
941  backlog.push_back({meta.weight, meta.fee, meta.receive_time - now});
942  return true;
943  }, false, include_unrelayed_txes);
944  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
time_t time
Definition: blockchain.cpp:93
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
std::string blobdata
Definition: blobdatatype.h:39
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transaction_hashes()

void cryptonote::tx_memory_pool::get_transaction_hashes ( std::vector< crypto::hash > &  txs,
bool  include_unrelayed_txes = true 
) const

get a list of all transaction hashes in the pool

Parameters
txsreturn-by-reference the list of transactions
include_unrelayed_txesinclude unrelayed txes in the result

Definition at line 923 of file tx_pool.cpp.

924  {
925  CRITICAL_REGION_LOCAL(m_transactions_lock);
926  CRITICAL_REGION_LOCAL1(m_blockchain);
927  txs.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
928  m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
929  txs.push_back(txid);
930  return true;
931  }, false, include_unrelayed_txes);
932  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
std::string blobdata
Definition: blobdatatype.h:39
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transaction_stats()

void cryptonote::tx_memory_pool::get_transaction_stats ( struct txpool_stats stats,
bool  include_unrelayed_txes = true 
) const

get a summary statistics of all transaction hashes in the pool

Parameters
statsreturn-by-reference the pool statistics
include_unrelayed_txesinclude unrelayed txes in the result

Definition at line 946 of file tx_pool.cpp.

947  {
948  CRITICAL_REGION_LOCAL(m_transactions_lock);
949  CRITICAL_REGION_LOCAL1(m_blockchain);
950  const uint64_t now = time(NULL);
951  std::map<uint64_t, txpool_histo> agebytes;
952  stats.txs_total = m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
953  std::vector<uint32_t> weights;
954  weights.reserve(stats.txs_total);
955  m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
956  weights.push_back(meta.weight);
957  stats.bytes_total += meta.weight;
958  if (!stats.bytes_min || meta.weight < stats.bytes_min)
959  stats.bytes_min = meta.weight;
960  if (meta.weight > stats.bytes_max)
961  stats.bytes_max = meta.weight;
962  if (!meta.relayed)
963  stats.num_not_relayed++;
964  stats.fee_total += meta.fee;
965  if (!stats.oldest || meta.receive_time < stats.oldest)
966  stats.oldest = meta.receive_time;
967  if (meta.receive_time < now - 600)
968  stats.num_10m++;
969  if (meta.last_failed_height)
970  stats.num_failing++;
971  uint64_t age = now - meta.receive_time + (now == meta.receive_time);
972  agebytes[age].txs++;
973  agebytes[age].bytes += meta.weight;
974  if (meta.double_spend_seen)
975  ++stats.num_double_spends;
976  if(meta.utxo_nonexistent_seen)
977  ++stats.num_nonexistent_utxos;
978  return true;
979  }, false, include_unrelayed_txes);
980  stats.bytes_med = epee::misc_utils::median(weights);
981  if (stats.txs_total > 1)
982  {
983  /* looking for 98th percentile */
984  size_t end = stats.txs_total * 0.02;
985  uint64_t delta, factor;
986  std::map<uint64_t, txpool_histo>::iterator it, i2;
987  if (end)
988  {
989  /* If enough txs, spread the first 98% of results across
990  * the first 9 bins, drop final 2% in last bin.
991  */
992  it=agebytes.end();
993  for (size_t n=0; n <= end; n++, it--);
994  stats.histo_98pc = it->first;
995  factor = 9;
996  delta = it->first;
997  stats.histo.resize(10);
998  } else
999  {
1000  /* If not enough txs, don't reserve the last slot;
1001  * spread evenly across all 10 bins.
1002  */
1003  stats.histo_98pc = 0;
1004  it = agebytes.end();
1005  factor = stats.txs_total > 9 ? 10 : stats.txs_total;
1006  delta = now - stats.oldest;
1007  stats.histo.resize(factor);
1008  }
1009  if (!delta)
1010  delta = 1;
1011  for (i2 = agebytes.begin(); i2 != it; i2++)
1012  {
1013  size_t i = (i2->first * factor - 1) / delta;
1014  stats.histo[i].txs += i2->second.txs;
1015  stats.histo[i].bytes += i2->second.bytes;
1016  }
1017  for (; i2 != agebytes.end(); i2++)
1018  {
1019  stats.histo[factor].txs += i2->second.txs;
1020  stats.histo[factor].bytes += i2->second.bytes;
1021  }
1022  }
1023  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
time_t time
Definition: blockchain.cpp:93
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
std::string blobdata
Definition: blobdatatype.h:39
type_vec_type median(std::vector< type_vec_type > &v)
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transactions()

void cryptonote::tx_memory_pool::get_transactions ( std::vector< transaction > &  txs,
bool  include_unrelayed_txes = true 
) const

get a list of all transactions in the pool

Parameters
txsreturn-by-reference the list of transactions
include_unrelayed_txesinclude unrelayed txes in the result

Definition at line 904 of file tx_pool.cpp.

905  {
906  CRITICAL_REGION_LOCAL(m_transactions_lock);
907  CRITICAL_REGION_LOCAL1(m_blockchain);
908  txs.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
909  m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
910  transaction tx;
911  if (!parse_and_validate_tx_from_blob(*bd, tx))
912  {
913  MERROR("Failed to parse tx from txpool");
914  // continue
915  return true;
916  }
917  tx.set_hash(txid);
918  txs.push_back(std::move(tx));
919  return true;
920  }, true, include_unrelayed_txes);
921  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
std::string blobdata
Definition: blobdatatype.h:39
const T & move(const T &t)
Definition: gtest-port.h:1317
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transactions_and_spent_keys_info()

bool cryptonote::tx_memory_pool::get_transactions_and_spent_keys_info ( std::vector< tx_info > &  tx_infos,
std::vector< spent_key_image_info > &  key_image_infos,
bool  include_sensitive_data = true 
) const

get information about all transactions and key images in the pool

see documentation on tx_info and spent_key_image_info for more details

Parameters
tx_infosreturn-by-reference the transactions' information
key_image_infosreturn-by-reference the spent key images' information
include_sensitive_datainclude unrelayed txes and fields that are sensitive to the node privacy
Returns
true

Definition at line 1026 of file tx_pool.cpp.

1027  {
1028  CRITICAL_REGION_LOCAL(m_transactions_lock);
1029  CRITICAL_REGION_LOCAL1(m_blockchain);
1030  tx_infos.reserve(m_blockchain.get_txpool_tx_count());
1031  key_image_infos.reserve(m_blockchain.get_txpool_tx_count());
1032  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){
1033  tx_info txi;
1034  txi.id_hash = epee::string_tools::pod_to_hex(txid);
1035  txi.tx_blob = *bd;
1036  transaction tx;
1037  if (!parse_and_validate_tx_from_blob(*bd, tx))
1038  {
1039  MERROR("Failed to parse tx from txpool");
1040  // continue
1041  return true;
1042  }
1043  tx.set_hash(txid);
1044  txi.tx_json = obj_to_json_str(tx);
1045  txi.blob_size = bd->size();
1046  txi.weight = meta.weight;
1047  txi.fee = meta.fee;
1048  txi.kept_by_block = meta.kept_by_block;
1049  txi.max_used_block_height = meta.max_used_block_height;
1050  txi.max_used_block_id_hash = epee::string_tools::pod_to_hex(meta.max_used_block_id);
1051  txi.last_failed_height = meta.last_failed_height;
1052  txi.last_failed_id_hash = epee::string_tools::pod_to_hex(meta.last_failed_id);
1053  // In restricted mode we do not include this data:
1054  txi.receive_time = include_sensitive_data ? meta.receive_time : 0;
1055  txi.relayed = meta.relayed;
1056  // In restricted mode we do not include this data:
1057  txi.last_relayed_time = include_sensitive_data ? meta.last_relayed_time : 0;
1058  txi.do_not_relay = meta.do_not_relay;
1059  txi.double_spend_seen = meta.double_spend_seen;
1060  txi.nonexistent_utxo_seen = meta.utxo_nonexistent_seen;
1061 
1062  tx_infos.push_back(std::move(txi));
1063  return true;
1064  }, true, include_sensitive_data);
1065 
1066  txpool_tx_meta_t meta;
1067  for (const key_images_container::value_type& kee : m_spent_key_images) {
1068  const crypto::key_image& k_image = kee.first;
1069  const std::unordered_set<crypto::hash>& kei_image_set = kee.second;
1070  spent_key_image_info ki;
1071  ki.id_hash = epee::string_tools::pod_to_hex(k_image);
1072  for (const crypto::hash& tx_id_hash : kei_image_set)
1073  {
1074  if (!include_sensitive_data)
1075  {
1076  try
1077  {
1078  if (!m_blockchain.get_txpool_tx_meta(tx_id_hash, meta))
1079  {
1080  MERROR("Failed to get tx meta from txpool");
1081  return false;
1082  }
1083  if (!meta.relayed)
1084  // Do not include that transaction if in restricted mode and it's not relayed
1085  continue;
1086  }
1087  catch (const std::exception &e)
1088  {
1089  MERROR("Failed to get tx meta from txpool: " << e.what());
1090  return false;
1091  }
1092  }
1093  ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash));
1094  }
1095  // Only return key images for which we have at least one tx that we can show for them
1096  if (!ki.txs_hashes.empty())
1097  key_image_infos.push_back(ki);
1098  }
1099  return true;
1100  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
std::string obj_to_json_str(T &obj)
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
std::string blobdata
Definition: blobdatatype.h:39
const T & move(const T &t)
Definition: gtest-port.h:1317
POD_CLASS key_image
Definition: crypto.h:102
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transactions_count()

size_t cryptonote::tx_memory_pool::get_transactions_count ( bool  include_unrelayed_txes = true) const

get the total number of transactions in the pool

Returns
the number of transactions in the pool

Definition at line 897 of file tx_pool.cpp.

898  {
899  CRITICAL_REGION_LOCAL(m_transactions_lock);
900  CRITICAL_REGION_LOCAL1(m_blockchain);
901  return m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
902  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_txpool_weight()

size_t cryptonote::tx_memory_pool::get_txpool_weight ( ) const

get the cumulative txpool weight in bytes

Returns
the cumulative txpool weight in bytes

Definition at line 535 of file tx_pool.cpp.

536  {
537  CRITICAL_REGION_LOCAL(m_transactions_lock);
538  return m_txpool_weight;
539  }
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228

◆ have_tx()

bool cryptonote::tx_memory_pool::have_tx ( const crypto::hash id) const

checks if the pool has a transaction with the given hash

Parameters
idthe hash to look for
Returns
true if the transaction is in the pool, otherwise false

Definition at line 1196 of file tx_pool.cpp.

1197  {
1198  CRITICAL_REGION_LOCAL(m_transactions_lock);
1199  CRITICAL_REGION_LOCAL1(m_blockchain);
1200  return m_blockchain.get_db().txpool_has_tx(id);
1201  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
const BlockchainDB & get_db() const
get a reference to the BlockchainDB in use by Blockchain
Definition: blockchain.h:963
virtual bool txpool_has_tx(const crypto::hash &txid) const =0
check whether a txid is in the txpool
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init()

bool cryptonote::tx_memory_pool::init ( size_t  max_txpool_weight = 0)

loads pool state (if any) from disk, and initializes pool

Parameters
max_txpool_weightthe max weight in bytes
Returns
true

Definition at line 1731 of file tx_pool.cpp.

1732  {
1733  CRITICAL_REGION_LOCAL(m_transactions_lock);
1734  CRITICAL_REGION_LOCAL1(m_blockchain);
1735 
1736  m_txpool_max_weight = max_txpool_weight ? max_txpool_weight : DEFAULT_TXPOOL_MAX_WEIGHT;
1737  m_txs_by_fee_and_receive_time.clear();
1738  m_spent_key_images.clear();
1739  m_spent_utxos.clear();
1740  m_txpool_weight = 0;
1741  std::vector<crypto::hash> remove;
1742 
1743  // first add the not kept by block, then the kept by block,
1744  // to avoid rejection due to key image collision
1745  for (int pass = 0; pass < 2; ++pass)
1746  {
1747  const bool kept = pass == 1;
1748  bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) {
1749  if (!!kept != !!meta.kept_by_block)
1750  return true;
1753  {
1754  MWARNING("Failed to parse tx from txpool, removing");
1755  remove.push_back(txid);
1756  return true;
1757  }
1758  if (tx.version <= 2 && !insert_key_images(tx, txid, meta.kept_by_block))
1759  {
1760  MFATAL("Failed to insert key images from txpool tx");
1761  return false;
1762  }
1763  if (tx.version >= 3 && !insert_utxos(tx, txid, meta.kept_by_block))
1764  {
1765  MFATAL("Failed to insert utxos from txpool tx");
1766  return false;
1767  }
1768  m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.weight, meta.receive_time), txid);
1769  m_txpool_weight += meta.weight;
1770  return true;
1771  }, true);
1772  if (!r)
1773  return false;
1774  }
1775  if (!remove.empty())
1776  {
1777  LockedTXN lock(m_blockchain);
1778  for (const auto &txid: remove)
1779  {
1780  try
1781  {
1782  m_blockchain.remove_txpool_tx(txid);
1783  }
1784  catch (const std::exception &e)
1785  {
1786  MWARNING("Failed to remove corrupt transaction: " << txid);
1787  // ignore error
1788  }
1789  }
1790  lock.commit();
1791  }
1792 
1793  m_cookie = 0;
1794 
1795  // Ignore deserialization error
1796  return true;
1797  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MFATAL(x)
Definition: misc_log_ex.h:72
bool parse_and_validate_tx_prefix_from_blob(const blobdata &tx_blob, transaction_prefix &tx)
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
void remove_txpool_tx(const crypto::hash &txid)
#define DEFAULT_TXPOOL_MAX_WEIGHT
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define MWARNING(x)
Definition: misc_log_ex.h:74
std::string blobdata
Definition: blobdatatype.h:39
POD_CLASS hash
Definition: hash.h:50
else if(0==res)
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
Here is the call graph for this function:

◆ lock()

void cryptonote::tx_memory_pool::lock ( void  ) const

locks the transaction pool

Definition at line 1255 of file tx_pool.cpp.

1256  {
1257  m_transactions_lock.lock();
1258  }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ on_blockchain_dec()

bool cryptonote::tx_memory_pool::on_blockchain_dec ( uint64_t  new_block_height,
const crypto::hash top_block_id 
)

action to take when notified of a block removed from the blockchain

Currently does nothing

Parameters
new_block_heightthe height of the blockchain after the change
top_block_idthe hash of the new top block
Returns
true

Definition at line 1188 of file tx_pool.cpp.

1189  {
1190  CRITICAL_REGION_LOCAL(m_transactions_lock);
1191  m_input_cache.clear();
1192  m_parsed_tx_cache.clear();
1193  return true;
1194  }
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228

◆ on_blockchain_inc()

bool cryptonote::tx_memory_pool::on_blockchain_inc ( uint64_t  new_block_height,
const crypto::hash top_block_id 
)

action to take when notified of a block added to the blockchain

Currently does nothing

Parameters
new_block_heightthe height of the blockchain after the change
top_block_idthe hash of the new top block
Returns
true

Definition at line 1180 of file tx_pool.cpp.

1181  {
1182  CRITICAL_REGION_LOCAL(m_transactions_lock);
1183  m_input_cache.clear();
1184  m_parsed_tx_cache.clear();
1185  return true;
1186  }
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228

◆ on_idle()

void cryptonote::tx_memory_pool::on_idle ( )

action to take periodically

Currently checks transaction pool for stale ("stuck") transactions

Definition at line 758 of file tx_pool.cpp.

759  {
760  m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});
761  }
bool do_call(functor_t functr)
Definition: math_helper.h:263
Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_pool()

std::string cryptonote::tx_memory_pool::print_pool ( bool  short_format) const

get a string containing human-readable pool information

Parameters
short_formatwhether to use a shortened format for the info
Returns
the string

Definition at line 1502 of file tx_pool.cpp.

1503  {
1504  std::stringstream ss;
1505  CRITICAL_REGION_LOCAL(m_transactions_lock);
1506  CRITICAL_REGION_LOCAL1(m_blockchain);
1507  m_blockchain.for_all_txpool_txes([&ss, short_format](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *txblob) {
1508  ss << "id: " << txid << std::endl;
1509  if (!short_format) {
1511  if (!parse_and_validate_tx_from_blob(*txblob, tx))
1512  {
1513  MERROR("Failed to parse tx from txpool");
1514  return true; // continue
1515  }
1516  ss << obj_to_json_str(tx) << std::endl;
1517  }
1518  ss << "blob_size: " << (short_format ? "-" : std::to_string(txblob->size())) << std::endl
1519  << "weight: " << meta.weight << std::endl
1520  << "fee: " << print_etn(meta.fee) << std::endl
1521  << "kept_by_block: " << (meta.kept_by_block ? 'T' : 'F') << std::endl
1522  << "double_spend_seen: " << (meta.double_spend_seen ? 'T' : 'F') << std::endl
1523  << "nonexistent_utxo_seen: " << (meta.utxo_nonexistent_seen ? 'T' : 'F') << std::endl
1524  << "max_used_block_height: " << meta.max_used_block_height << std::endl
1525  << "max_used_block_id: " << meta.max_used_block_id << std::endl
1526  << "last_failed_height: " << meta.last_failed_height << std::endl
1527  << "last_failed_id: " << meta.last_failed_id << std::endl;
1528  return true;
1529  }, !short_format);
1530 
1531  return ss.str();
1532  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
std::string obj_to_json_str(T &obj)
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
std::string blobdata
Definition: blobdatatype.h:39
POD_CLASS hash
Definition: hash.h:50
std::string to_string(t_connection_type type)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_relayed()

void cryptonote::tx_memory_pool::set_relayed ( const std::vector< std::pair< crypto::hash, cryptonote::blobdata >> &  txs)

tell the pool that certain transactions were just relayed

Parameters
txsthe list of transactions (and their hashes)

Definition at line 870 of file tx_pool.cpp.

871  {
872  CRITICAL_REGION_LOCAL(m_transactions_lock);
873  CRITICAL_REGION_LOCAL1(m_blockchain);
874  const time_t now = time(NULL);
875  LockedTXN lock(m_blockchain);
876  for (auto it = txs.begin(); it != txs.end(); ++it)
877  {
878  try
879  {
880  txpool_tx_meta_t meta;
881  if (m_blockchain.get_txpool_tx_meta(it->first, meta))
882  {
883  meta.relayed = true;
884  meta.last_relayed_time = now;
885  m_blockchain.update_txpool_tx(it->first, meta);
886  }
887  }
888  catch (const std::exception &e)
889  {
890  MERROR("Failed to update txpool transaction metadata: " << e.what());
891  // continue
892  }
893  }
894  lock.commit();
895  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta)
time_t time
Definition: blockchain.cpp:93
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_txpool_max_weight()

void cryptonote::tx_memory_pool::set_txpool_max_weight ( size_t  bytes)

set the max cumulative txpool weight in bytes

Parameters
bytesthe max cumulative txpool weight in bytes

Definition at line 541 of file tx_pool.cpp.

542  {
543  CRITICAL_REGION_LOCAL(m_transactions_lock);
544  m_txpool_max_weight = bytes;
545  }
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228

◆ take_tx()

bool cryptonote::tx_memory_pool::take_tx ( const crypto::hash id,
transaction tx,
cryptonote::blobdata txblob,
size_t &  tx_weight,
uint64_t fee,
bool relayed,
bool do_not_relay,
bool double_spend_seen,
bool nonexistent_utxo_seen 
)

takes a transaction with the given hash from the pool

Parameters
idthe hash of the transaction
txreturn-by-reference the transaction taken
txblobreturn-by-reference the transaction as a blob
tx_weightreturn-by-reference the transaction's weight
feethe transaction fee
relayedreturn-by-reference was transaction relayed to us by the network?
do_not_relayreturn-by-reference is transaction not to be relayed to the network?
double_spend_seenreturn-by-reference was a double spend seen for that transaction?
nonexistent_utxo_seenreturn-by-reference was a nonexistent utxo seen for that transaction?
Returns
true unless the transaction cannot be found in the pool

Definition at line 702 of file tx_pool.cpp.

703  {
704  CRITICAL_REGION_LOCAL(m_transactions_lock);
705  CRITICAL_REGION_LOCAL1(m_blockchain);
706 
707  auto sorted_it = find_tx_in_sorted_container(id);
708 
709  try
710  {
711  LockedTXN lock(m_blockchain);
712  txpool_tx_meta_t meta;
713  if (!m_blockchain.get_txpool_tx_meta(id, meta))
714  {
715  MERROR("Failed to find tx in txpool");
716  return false;
717  }
718  txblob = m_blockchain.get_txpool_tx_blob(id);
719  auto ci = m_parsed_tx_cache.find(id);
720  if (ci != m_parsed_tx_cache.end())
721  {
722  tx = ci->second;
723  }
724  else if (!parse_and_validate_tx_from_blob(txblob, tx))
725  {
726  MERROR("Failed to parse tx from txpool");
727  return false;
728  }
729  else
730  {
731  tx.set_hash(id);
732  }
733  tx_weight = meta.weight;
734  fee = meta.fee;
735  relayed = meta.relayed;
736  do_not_relay = meta.do_not_relay;
737  double_spend_seen = meta.double_spend_seen;
738  nonexistent_utxo_seen = meta.utxo_nonexistent_seen;
739 
740  // remove first, in case this throws, so key images aren't removed
741  m_blockchain.remove_txpool_tx(id);
742  m_txpool_weight -= tx_weight;
743  remove_transaction_keyimages(tx, id);
744  lock.commit();
745  }
746  catch (const std::exception &e)
747  {
748  MERROR("Failed to remove tx from txpool: " << e.what());
749  return false;
750  }
751 
752  if (sorted_it != m_txs_by_fee_and_receive_time.end())
753  m_txs_by_fee_and_receive_time.erase(sorted_it);
754  ++m_cookie;
755  return true;
756  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const
void remove_txpool_tx(const crypto::hash &txid)
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unlock()

void cryptonote::tx_memory_pool::unlock ( void  ) const

unlocks the transaction pool

Definition at line 1260 of file tx_pool.cpp.

1261  {
1262  m_transactions_lock.unlock();
1263  }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ utxo_spent_in_pool()

bool cryptonote::tx_memory_pool::utxo_spent_in_pool ( const txin_to_key_public in) const

get a summary statistics of all transaction hashes in the pool

Parameters
ininput to check the pool spent status of

Definition at line 1220 of file tx_pool.cpp.

1220  {
1221  CRITICAL_REGION_LOCAL(m_transactions_lock);
1222  CRITICAL_REGION_LOCAL1(m_blockchain);
1223  return have_tx_utxo_as_spent(in);
1224  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
Here is the caller graph for this function:

◆ validate()

size_t cryptonote::tx_memory_pool::validate ( uint8_t  version)

remove transactions from the pool which are no longer valid

With new versions of the currency, what conditions render a transaction invalid may change. This function clears those which were received before a version change and no longer conform to requirements.

Parameters
versionthe version the transactions must conform to
Returns
the number of transactions removed

Definition at line 1667 of file tx_pool.cpp.

1668  {
1669  CRITICAL_REGION_LOCAL(m_transactions_lock);
1670  CRITICAL_REGION_LOCAL1(m_blockchain);
1671  size_t tx_weight_limit = get_transaction_weight_limit(version);
1672  std::unordered_set<crypto::hash> remove;
1673 
1674  m_txpool_weight = 0;
1675  m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
1676  m_txpool_weight += meta.weight;
1677  if (meta.weight > tx_weight_limit) {
1678  LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.weight << " bytes), removing it from pool");
1679  remove.insert(txid);
1680  }
1681  else if (m_blockchain.have_tx(txid)) {
1682  LOG_PRINT_L1("Transaction " << txid << " is in the blockchain, removing it from pool");
1683  remove.insert(txid);
1684  }
1685  return true;
1686  }, false);
1687 
1688  size_t n_removed = 0;
1689  if (!remove.empty())
1690  {
1691  LockedTXN lock(m_blockchain);
1692  for (const crypto::hash &txid: remove)
1693  {
1694  try
1695  {
1696  cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
1698  if (!parse_and_validate_tx_from_blob(txblob, tx))
1699  {
1700  MERROR("Failed to parse tx from txpool");
1701  continue;
1702  }
1703  // remove tx from db first
1704  m_blockchain.remove_txpool_tx(txid);
1705  m_txpool_weight -= get_transaction_weight(tx, txblob.size());
1706  remove_transaction_keyimages(tx, txid);
1707  auto sorted_it = find_tx_in_sorted_container(txid);
1708  if (sorted_it == m_txs_by_fee_and_receive_time.end())
1709  {
1710  LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
1711  }
1712  else
1713  {
1714  m_txs_by_fee_and_receive_time.erase(sorted_it);
1715  }
1716  ++n_removed;
1717  }
1718  catch (const std::exception &e)
1719  {
1720  MERROR("Failed to remove invalid tx from pool");
1721  // continue
1722  }
1723  }
1724  lock.commit();
1725  }
1726  if (n_removed > 0)
1727  ++m_cookie;
1728  return n_removed;
1729  }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
bool for_all_txpool_txes(std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>, bool include_blob=false, bool include_unrelayed_txes=true) const
void remove_txpool_tx(const crypto::hash &txid)
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
version
Supported socks variants.
Definition: socks.h:57
std::string blobdata
Definition: blobdatatype.h:39
bool have_tx(const crypto::hash &id) const
search the blockchain for a transaction by hash
Definition: blockchain.cpp:167
POD_CLASS hash
Definition: hash.h:50
else if(0==res)
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
Here is the call graph for this function:

The documentation for this class was generated from the following files: