Electroneum
Loading...
Searching...
No Matches
tx_pool.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31
32#include <algorithm>
33#include <boost/filesystem.hpp>
34#include <unordered_set>
35#include <vector>
36#include <regex>
37#include <bitset>
38
39#include "tx_pool.h"
40#include "cryptonote_tx_utils.h"
42#include "cryptonote_config.h"
43#include "blockchain.h"
46#include "int-util.h"
47#include "misc_language.h"
48#include "warnings.h"
49#include "common/perf_timer.h"
50#include "crypto/hash.h"
51#include "string_tools.h"
52
53#undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
54#define ELECTRONEUM_DEFAULT_LOG_CATEGORY "txpool"
55
56DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated
57
58using namespace crypto;
59
60namespace cryptonote
61{
62 namespace
63 {
64 //TODO: constants such as these should at least be in the header,
65 // but probably somewhere more accessible to the rest of the
66 // codebase. As it stands, it is at best nontrivial to test
67 // whether or not changing these parameters (or adding new)
68 // will work correctly.
69 time_t const MIN_RELAY_TIME = (60 * 5); // only start re-relaying transactions after that many seconds
70 time_t const MAX_RELAY_TIME = (60 * 60 * 4); // at most that many seconds between resends
71 float const ACCEPT_THRESHOLD = 1.0f;
72
73 // a kind of increasing backoff within min/max bounds
74 uint64_t get_relay_delay(time_t now, time_t received)
75 {
76 time_t d = (now - received + MIN_RELAY_TIME) / MIN_RELAY_TIME * MIN_RELAY_TIME;
77 if (d > MAX_RELAY_TIME)
78 d = MAX_RELAY_TIME;
79 return d;
80 }
81
82 uint64_t template_accept_threshold(uint64_t amount)
83 {
84 return amount * ACCEPT_THRESHOLD;
85 }
86
87 uint64_t get_transaction_weight_limit(uint8_t version)
88 {
89 // from v8, limit a tx to 50% of the minimum block weight
90 if (version >= 8)
91 return get_min_block_weight(version) / 2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
92 else
93 return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
94 }
95
96 // This class is meant to create a batch when none currently exists.
97 // If a batch exists, it can't be from another thread, since we can
98 // only be called with the txpool lock taken, and it is held during
99 // the whole prepare/handle/cleanup incoming block sequence.
100 class LockedTXN {
101 public:
102 LockedTXN(Blockchain &b): m_blockchain(b), m_batch(false), m_active(false) {
103 m_batch = m_blockchain.get_db().batch_start();
104 m_active = true;
105 }
106 void commit() { try { if (m_batch && m_active) { m_blockchain.get_db().batch_stop(); m_active = false; } } catch (const std::exception &e) { MWARNING("LockedTXN::commit filtering exception: " << e.what()); } }
107 void abort() { try { if (m_batch && m_active) { m_blockchain.get_db().batch_abort(); m_active = false; } } catch (const std::exception &e) { MWARNING("LockedTXN::abort filtering exception: " << e.what()); } }
108 ~LockedTXN() { abort(); }
109 private:
110 Blockchain &m_blockchain;
111 bool m_batch;
112 bool m_active;
113 };
114 }
115 //---------------------------------------------------------------------------------
116 //---------------------------------------------------------------------------------
117 tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_cookie(0)
118 {
119
120 }
121 //---------------------------------------------------------------------------------
122 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)
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;
338 return false;
339 }
340
341 // Verify ownership signature: proves the sender controls the spend key of bridge_source_address
343 if(!find_tx_extra_field_by_type(tx_extra_fields, bridge_ownership_sig) || bridge_ownership_sig.data.size() != sizeof(crypto::signature)){
344 tvc.m_verification_failed = true;
346 return false;
347 }
348 std::string sig_message = bridge_source_address.data + bridge_smartchain_address.data;
349 crypto::hash sig_hash;
350 crypto::cn_fast_hash(sig_message.data(), sig_message.size(), sig_hash);
351 crypto::signature ownership_sig;
352 memcpy(&ownership_sig, bridge_ownership_sig.data.data(), sizeof(crypto::signature));
353 if(!crypto::check_signature(sig_hash, parse_info_dummy.address.m_spend_public_key, ownership_sig)){
354 tvc.m_verification_failed = true;
356 return false;
357 }
358
359 // The regular expression pattern for a valid Ethereum address
360 bool valid_smartchain_address = true;
361 std::string string_smartchain_address = bridge_smartchain_address.data;
362 //string_smartchain_address = "0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d";
363 std::regex pattern("^(0x|0X)[a-fA-F0-9]{40}$");
364 if(!std::regex_match(string_smartchain_address, pattern))
365 valid_smartchain_address = false;
366
367
368 bool isMixedCase = std::any_of(string_smartchain_address.begin(), string_smartchain_address.end(), [](char c) {
369 return std::isupper(c);
370 }) && std::any_of(string_smartchain_address.begin(), string_smartchain_address.end(), [](char c) {
371 return std::islower(c);
372 });
373
374 if(isMixedCase && valid_smartchain_address != false){ // if it's mixed case, we have to do extra checks
375 // Convert the address to lowercase for hashing
376 std::string lower_address = string_smartchain_address.substr(2);
377 std::transform(lower_address.begin(), lower_address.end(), lower_address.begin(), ::tolower);
378
379 unsigned char hashed_lower[32];
380 keccak(reinterpret_cast<const uint8_t *>(lower_address.data()), 40, hashed_lower, 32);
381 std::string address_hash = epee::string_tools::pod_to_hex(hashed_lower); // should be 0x12ed7467c3852e6b2Bd3C22AF694be8DF7637B10.
382
383 std::string hash;
384 for (size_t i = 0; i < lower_address.length(); i++) {
385 if (std::isdigit(lower_address[i])) {
386 hash += lower_address[i];
387 }
388 else if (address_hash[i] >= '8') {
389 hash += std::toupper(lower_address[i]);
390 }
391 else {
392 hash += lower_address[i];
393 }
394 }
395 std::string checksum = hash.substr(0, 8);
396 for (size_t i = 2; i < checksum.length() + 2; i++) {
397 if (std::islower(string_smartchain_address[i]) && checksum[i - 2] < 'a') {
398 valid_smartchain_address = false;
399 }
400 else if (std::isupper(string_smartchain_address[i]) && checksum[i - 2] < 'A') {
401 char lower_char = std::tolower(string_smartchain_address[i]);
402 if (checksum[i - 2] != lower_char) {
403 valid_smartchain_address = false;
404 }
405 }
406 else if (checksum[i - 2] != string_smartchain_address[i]) {
407 valid_smartchain_address = false;
408 }
409 }
410
411 } //end of is mixed case
412
413 if(!valid_smartchain_address){
414 tvc.m_verification_failed = true;
416 return false;
417 }
418 //BLOCK ALL TX NOT GOING TO THE PORTAL ADDRESS
419 std::string portal_address_viewkey_hex_str;
420 std::string portal_address_spendkey_hex_str;
421 if(m_blockchain.get_nettype() == MAINNET){
422 portal_address_viewkey_hex_str = "2b95a2eb2c62253c57e82b082b850bbf22a1a7829aaea09c7c1511c1cced4375";
423 portal_address_spendkey_hex_str = "8ce0f34fd37c7f7d07c44024eb5b3cdf275d1b3e75c3464b808dce532e861137";
424 }else{
425 portal_address_viewkey_hex_str = "5866666666666666666666666666666666666666666666666666666666666666"; //private view is just 0100000000000000000000000000000000000000000000000000000000000000
426 portal_address_spendkey_hex_str = "5bd0c0e25eee6133850edd2b255ed9e3d6bb99fd5f08b7b5cf7f2618ad6ff2a3"; //
427 }
428
429 for (auto output: tx.vout){
430 const auto out = boost::get<txout_to_key_public>(output.target);
431 std::string out_spendkey_str = epee::string_tools::pod_to_hex(out.address.m_spend_public_key.data);
432 std::string out_viewkey_str = epee::string_tools::pod_to_hex(out.address.m_view_public_key.data);
433 if(out_spendkey_str != portal_address_spendkey_hex_str || out_viewkey_str != portal_address_viewkey_hex_str){
434 tvc.m_verification_failed = true;
435 tvc.m_portal_outbound_tx = true;
436 return false;
437 }
438 }
439 }
440
441 if(!ch_inp_res)
442 {
443 // if the transaction was valid before (kept_by_block), then it
444 // may become valid again, so ignore the failed inputs check.
445 if(kept_by_block)
446 {
447 meta.weight = tx_weight;
448 meta.fee = fee;
449 meta.max_used_block_id = null_hash;
450 meta.max_used_block_height = 0;
451 meta.last_failed_height = 0;
452 meta.last_failed_id = null_hash;
453 meta.kept_by_block = kept_by_block;
454 meta.receive_time = receive_time;
455 meta.last_relayed_time = time(NULL);
456 meta.relayed = relayed;
457 meta.do_not_relay = do_not_relay;
458 meta.double_spend_seen = key_images_already_spent(tx);
459 meta.utxo_nonexistent_seen = utxo_nonexistent(tx);
460 meta.bf_padding = 0;
461 memset(meta.padding, 0, sizeof(meta.padding));
462 try
463 {
464 if (kept_by_block)
465 m_parsed_tx_cache.insert(std::make_pair(id, tx));
466 CRITICAL_REGION_LOCAL1(m_blockchain);
467 LockedTXN lock(m_blockchain);
468 m_blockchain.add_txpool_tx(id, blob, meta);
469 if ((tx.version <= 2 && !insert_key_images(tx, id, kept_by_block)) || (tx.version >= 3 && !insert_utxos(tx, id, kept_by_block)))
470 return false;
471 m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
472 lock.commit();
473 }
474 catch (const std::exception &e)
475 {
476 MERROR("transaction already exists at inserting in memory pool: " << e.what());
477 return false;
478 }
479 tvc.m_verification_impossible = true;
480 tvc.m_added_to_pool = true;
481 }else
482 {
483 LOG_PRINT_L1("tx used wrong inputs, rejected");
484 tvc.m_verification_failed = true;
485 tvc.m_invalid_input = true;
486 return false;
487 }
488 }else
489 {
490 //update transactions container
491 meta.weight = tx_weight;
492 meta.kept_by_block = kept_by_block;
493 meta.fee = fee;
494 meta.max_used_block_id = max_used_block_id;
495 meta.max_used_block_height = max_used_block_height;
496 meta.last_failed_height = 0;
497 meta.last_failed_id = null_hash;
498 meta.receive_time = receive_time;
499 meta.last_relayed_time = time(NULL);
500 meta.relayed = relayed;
501 meta.do_not_relay = do_not_relay;
502 meta.double_spend_seen = false;
503 meta.utxo_nonexistent_seen = false;
504 meta.bf_padding = 0;
505 memset(meta.padding, 0, sizeof(meta.padding));
506
507 try
508 {
509 if (kept_by_block)
510 m_parsed_tx_cache.insert(std::make_pair(id, tx));
511 CRITICAL_REGION_LOCAL1(m_blockchain);
512 LockedTXN lock(m_blockchain);
513 m_blockchain.remove_txpool_tx(id);
514 m_blockchain.add_txpool_tx(id, blob, meta);
515 if ((tx.version <= 2 && !insert_key_images(tx, id, kept_by_block)) || (tx.version >= 3 && !insert_utxos(tx, id, kept_by_block)))
516 return false;
517 m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
518 lock.commit();
519 }
520 catch (const std::exception &e)
521 {
522 MERROR("internal error: transaction already exists at inserting in memory pool: " << e.what());
523 return false;
524 }
525 tvc.m_added_to_pool = true;
526
527 if(!do_not_relay)
528 tvc.m_should_be_relayed = true;
529 }
530
531 tvc.m_verification_failed = false;
532 m_txpool_weight += tx_weight;
533
534 ++m_cookie;
535
536 MINFO("Transaction added to pool: txid " << id << " weight: " << tx_weight << " fee/byte: " << (fee / (double)tx_weight));
537
538 prune(m_txpool_max_weight);
539
540 return true;
541 }
542 //---------------------------------------------------------------------------------
543 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)
544 {
545 crypto::hash h = null_hash;
546 size_t blob_size = 0;
549 if (bl.size() == 0 || !get_transaction_hash(tx, h))
550 return false;
551 return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, keeped_by_block, relayed, do_not_relay, version);
552 }
553 //---------------------------------------------------------------------------------
555 {
556 CRITICAL_REGION_LOCAL(m_transactions_lock);
557 return m_txpool_weight;
558 }
559 //---------------------------------------------------------------------------------
561 {
562 CRITICAL_REGION_LOCAL(m_transactions_lock);
563 m_txpool_max_weight = bytes;
564 }
565 //---------------------------------------------------------------------------------
566 void tx_memory_pool::prune(size_t bytes)
567 {
568 CRITICAL_REGION_LOCAL(m_transactions_lock);
569 if (bytes == 0)
570 bytes = m_txpool_max_weight;
571 CRITICAL_REGION_LOCAL1(m_blockchain);
572 LockedTXN lock(m_blockchain);
573 bool changed = false;
574
575 // this will never remove the first one, but we don't care
576 auto it = --m_txs_by_fee_and_receive_time.end();
577 while (it != m_txs_by_fee_and_receive_time.begin())
578 {
579 if (m_txpool_weight <= bytes)
580 break;
581 try
582 {
583 const crypto::hash &txid = it->second;
584 txpool_tx_meta_t meta;
585 if (!m_blockchain.get_txpool_tx_meta(txid, meta))
586 {
587 MERROR("Failed to find tx in txpool");
588 return;
589 }
590 // don't prune the kept_by_block ones, they're likely added because we're adding a block with those
591 if (meta.kept_by_block)
592 {
593 --it;
594 continue;
595 }
596 cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
597 cryptonote::transaction_prefix tx;
599 {
600 MERROR("Failed to parse tx from txpool");
601 return;
602 }
603 // remove first, in case this throws, so key images aren't removed
604 MINFO("Pruning tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first);
605 m_blockchain.remove_txpool_tx(txid);
606 m_txpool_weight -= meta.weight;
607 remove_transaction_keyimages(tx, txid);
608 MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first);
609 m_txs_by_fee_and_receive_time.erase(it--);
610 changed = true;
611 }
612 catch (const std::exception &e)
613 {
614 MERROR("Error while pruning txpool: " << e.what());
615 return;
616 }
617 }
618 lock.commit();
619 if (changed)
620 ++m_cookie;
621 if (m_txpool_weight > bytes)
622 MINFO("Pool weight after pruning is larger than limit: " << m_txpool_weight << "/" << bytes);
623 }
624 //---------------------------------------------------------------------------------
625 bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block)
626 {
627 for(const auto& in: tx.vin)
628 {
629 CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, txin, false);
630 std::unordered_set<crypto::hash>& kei_image_set = m_spent_key_images[txin.k_image];
631 CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block
632 << ", kei_image_set.size()=" << kei_image_set.size() << ENDL << "txin.k_image=" << txin.k_image << ENDL
633 << "tx_id=" << id );
634 auto ins_res = kei_image_set.insert(id);
635 CHECK_AND_ASSERT_MES(ins_res.second, false, "internal error: try to insert duplicate iterator in key_image set");
636 }
637 ++m_cookie;
638 return true;
639 }
640 //---------------------------------------------------------------------------------
641 bool tx_memory_pool::insert_utxos(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block)
642 {
643 for(const auto& in: tx.vin)
644 {
645 CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key_public, txin, false);
647 std::unordered_set<crypto::hash>& utxo_set = m_spent_utxos[txin_key];
648 CHECK_AND_ASSERT_MES(kept_by_block || utxo_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block
649 << ", utxo_set.size()=" << utxo_set.size() << ENDL << "txin=" << txin_key << ENDL
650 << "tx_id=" << id );
651 auto ins_res = utxo_set.insert(id);
652 CHECK_AND_ASSERT_MES(ins_res.second, false, "internal error: try to insert duplicate iterator in utxo set");
653 }
654 ++m_cookie;
655 return true;
656 }
657 //---------------------------------------------------------------------------------
658 //FIXME: Can return early before removal of all of the key images.
659 // At the least, need to make sure that a false return here
660 // is treated properly. Should probably not return early, however.
661 bool tx_memory_pool::remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &actual_hash)
662 {
663 CRITICAL_REGION_LOCAL(m_transactions_lock);
664 CRITICAL_REGION_LOCAL1(m_blockchain);
665 // ND: Speedup
666 for(const txin_v& vi: tx.vin)
667 {
668 if(vi.type() == typeid(txin_to_key))
669 {
670 const auto &txin = boost::get<txin_to_key>(vi);
671
672 auto it = m_spent_key_images.find(txin.k_image);
673 CHECK_AND_ASSERT_MES(it != m_spent_key_images.end(), false, "failed to find transaction input in key images. img=" << txin.k_image << ENDL
674 << "transaction id = " << actual_hash);
675 std::unordered_set<crypto::hash>& key_image_set = it->second;
676 CHECK_AND_ASSERT_MES(key_image_set.size(), false, "empty key_image set, img=" << txin.k_image << ENDL
677 << "transaction id = " << actual_hash);
678
679 auto it_in_set = key_image_set.find(actual_hash);
680 CHECK_AND_ASSERT_MES(it_in_set != key_image_set.end(), false, "transaction id not found in key_image set, img=" << txin.k_image << ENDL
681 << "transaction id = " << actual_hash);
682 key_image_set.erase(it_in_set);
683 if(!key_image_set.size())
684 {
685 //it is now empty hash container for this key_image
686 m_spent_key_images.erase(it);
687 }
688 }
689 else if (vi.type() == typeid(txin_to_key_public))
690 {
691 const auto &txin = boost::get<txin_to_key_public>(vi);
692
694
695 auto it = m_spent_utxos.find(txin_key);
696 CHECK_AND_ASSERT_MES(it != m_spent_utxos.end(), false, "failed to find transaction input in utxos. utxo=" << txin_key << ENDL
697 << "transaction id = " << actual_hash);
698 std::unordered_set<crypto::hash>& utxo_set = it->second;
699 CHECK_AND_ASSERT_MES(utxo_set.size(), false, "empty utxo set, utxo=" << txin_key << ENDL
700 << "transaction id = " << actual_hash);
701
702 auto it_in_set = utxo_set.find(actual_hash);
703 CHECK_AND_ASSERT_MES(it_in_set != utxo_set.end(), false, "transaction id not found in utxo set, utxo=" << txin_key << ENDL
704 << "transaction id = " << actual_hash);
705 utxo_set.erase(it_in_set);
706 if(!utxo_set.size())
707 {
708 //it is now empty hash container for this key_image
709 m_spent_utxos.erase(it);
710 }
711 }
712 else
713 {
714 return false;
715 }
716 }
717 ++m_cookie;
718 return true;
719 }
720 //---------------------------------------------------------------------------------
721 bool 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)
722 {
723 CRITICAL_REGION_LOCAL(m_transactions_lock);
724 CRITICAL_REGION_LOCAL1(m_blockchain);
725
726 auto sorted_it = find_tx_in_sorted_container(id);
727
728 try
729 {
730 LockedTXN lock(m_blockchain);
731 txpool_tx_meta_t meta;
732 if (!m_blockchain.get_txpool_tx_meta(id, meta))
733 {
734 MERROR("Failed to find tx in txpool");
735 return false;
736 }
737 txblob = m_blockchain.get_txpool_tx_blob(id);
738 auto ci = m_parsed_tx_cache.find(id);
739 if (ci != m_parsed_tx_cache.end())
740 {
741 tx = ci->second;
742 }
743 else if (!parse_and_validate_tx_from_blob(txblob, tx))
744 {
745 MERROR("Failed to parse tx from txpool");
746 return false;
747 }
748 else
749 {
750 tx.set_hash(id);
751 }
752 tx_weight = meta.weight;
753 fee = meta.fee;
754 relayed = meta.relayed;
755 do_not_relay = meta.do_not_relay;
756 double_spend_seen = meta.double_spend_seen;
757 nonexistent_utxo_seen = meta.utxo_nonexistent_seen;
758
759 // remove first, in case this throws, so key images aren't removed
760 m_blockchain.remove_txpool_tx(id);
761 m_txpool_weight -= tx_weight;
762 remove_transaction_keyimages(tx, id);
763 lock.commit();
764 }
765 catch (const std::exception &e)
766 {
767 MERROR("Failed to remove tx from txpool: " << e.what());
768 return false;
769 }
770
771 if (sorted_it != m_txs_by_fee_and_receive_time.end())
772 m_txs_by_fee_and_receive_time.erase(sorted_it);
773 ++m_cookie;
774 return true;
775 }
776 //---------------------------------------------------------------------------------
778 {
779 m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});
780 }
781 //---------------------------------------------------------------------------------
782 sorted_tx_container::iterator tx_memory_pool::find_tx_in_sorted_container(const crypto::hash& id) const
783 {
784 return std::find_if( m_txs_by_fee_and_receive_time.begin(), m_txs_by_fee_and_receive_time.end()
785 , [&](const sorted_tx_container::value_type& a){
786 return a.second == id;
787 }
788 );
789 }
790 //---------------------------------------------------------------------------------
791 //TODO: investigate whether boolean return is appropriate
792 bool tx_memory_pool::remove_stuck_transactions()
793 {
794 CRITICAL_REGION_LOCAL(m_transactions_lock);
795 CRITICAL_REGION_LOCAL1(m_blockchain);
796 std::list<std::pair<crypto::hash, uint64_t>> remove;
797 m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
798 uint64_t tx_age = time(nullptr) - meta.receive_time;
799 uint32_t mempool_lifetime = m_blockchain.get_mempool_tx_livetime();
800 if((tx_age > mempool_lifetime && !meta.kept_by_block) ||
801 (tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && meta.kept_by_block) )
802 {
803 LOG_PRINT_L1("Tx " << txid << " removed from tx pool due to outdated, age: " << tx_age );
804 auto sorted_it = find_tx_in_sorted_container(txid);
805 if (sorted_it == m_txs_by_fee_and_receive_time.end())
806 {
807 LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
808 }
809 else
810 {
811 m_txs_by_fee_and_receive_time.erase(sorted_it);
812 }
813 m_timed_out_transactions.insert(txid);
814 remove.push_back(std::make_pair(txid, meta.weight));
815 }
816 return true;
817 }, false);
818
819 if (!remove.empty())
820 {
821 LockedTXN lock(m_blockchain);
822 for (const std::pair<crypto::hash, uint64_t> &entry: remove)
823 {
824 const crypto::hash &txid = entry.first;
825 try
826 {
827 cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid);
828 cryptonote::transaction_prefix tx;
830 {
831 MERROR("Failed to parse tx from txpool");
832 // continue
833 }
834 else
835 {
836 // remove first, so we only remove key images if the tx removal succeeds
837 m_blockchain.remove_txpool_tx(txid);
838 m_txpool_weight -= entry.second;
839 remove_transaction_keyimages(tx, txid);
840 }
841 }
842 catch (const std::exception &e)
843 {
844 MWARNING("Failed to remove stuck transaction: " << txid);
845 // ignore error
846 }
847 }
848 lock.commit();
849 ++m_cookie;
850 }
851 return true;
852 }
853 //---------------------------------------------------------------------------------
854 //TODO: investigate whether boolean return is appropriate
855 bool tx_memory_pool::get_relayable_transactions(std::vector<std::pair<crypto::hash, cryptonote::blobdata>> &txs) const
856 {
857 CRITICAL_REGION_LOCAL(m_transactions_lock);
858 CRITICAL_REGION_LOCAL1(m_blockchain);
859 const uint64_t now = time(NULL);
860 txs.reserve(m_blockchain.get_txpool_tx_count());
861 m_blockchain.for_all_txpool_txes([this, now, &txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *){
862 // 0 fee transactions are never relayed
863 if(!meta.do_not_relay && now - meta.last_relayed_time > get_relay_delay(now, meta.receive_time))
864 {
865 // if the tx is older than half the max lifetime, we don't re-relay it, to avoid a problem
866 // mentioned by smooth where nodes would flush txes at slightly different times, causing
867 // flushed txes to be re-added when received from a node which was just about to flush it
868 uint32_t mempool_lifetime = m_blockchain.get_mempool_tx_livetime();
869 uint64_t max_age = meta.kept_by_block ? CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME : mempool_lifetime;
870 if (now - meta.receive_time <= max_age / 2)
871 {
872 try
873 {
874 cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid);
875 txs.push_back(std::make_pair(txid, bd));
876 }
877 catch (const std::exception &e)
878 {
879 MERROR("Failed to get transaction blob from db");
880 // ignore error
881 }
882 }
883 }
884 return true;
885 }, false);
886 return true;
887 }
888 //---------------------------------------------------------------------------------
889 void tx_memory_pool::set_relayed(const std::vector<std::pair<crypto::hash, cryptonote::blobdata>> &txs)
890 {
891 CRITICAL_REGION_LOCAL(m_transactions_lock);
892 CRITICAL_REGION_LOCAL1(m_blockchain);
893 const time_t now = time(NULL);
894 LockedTXN lock(m_blockchain);
895 for (auto it = txs.begin(); it != txs.end(); ++it)
896 {
897 try
898 {
899 txpool_tx_meta_t meta;
900 if (m_blockchain.get_txpool_tx_meta(it->first, meta))
901 {
902 meta.relayed = true;
903 meta.last_relayed_time = now;
904 m_blockchain.update_txpool_tx(it->first, meta);
905 }
906 }
907 catch (const std::exception &e)
908 {
909 MERROR("Failed to update txpool transaction metadata: " << e.what());
910 // continue
911 }
912 }
913 lock.commit();
914 }
915 //---------------------------------------------------------------------------------
916 size_t tx_memory_pool::get_transactions_count(bool include_unrelayed_txes) const
917 {
918 CRITICAL_REGION_LOCAL(m_transactions_lock);
919 CRITICAL_REGION_LOCAL1(m_blockchain);
920 return m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
921 }
922 //---------------------------------------------------------------------------------
923 void tx_memory_pool::get_transactions(std::vector<transaction>& txs, bool include_unrelayed_txes) const
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 transaction tx;
931 {
932 MERROR("Failed to parse tx from txpool");
933 // continue
934 return true;
935 }
936 tx.set_hash(txid);
937 txs.push_back(std::move(tx));
938 return true;
939 }, true, include_unrelayed_txes);
940 }
941 //------------------------------------------------------------------
942 void tx_memory_pool::get_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes) const
943 {
944 CRITICAL_REGION_LOCAL(m_transactions_lock);
945 CRITICAL_REGION_LOCAL1(m_blockchain);
946 txs.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
947 m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
948 txs.push_back(txid);
949 return true;
950 }, false, include_unrelayed_txes);
951 }
952 //------------------------------------------------------------------
953 void tx_memory_pool::get_transaction_backlog(std::vector<tx_backlog_entry>& backlog, bool include_unrelayed_txes) const
954 {
955 CRITICAL_REGION_LOCAL(m_transactions_lock);
956 CRITICAL_REGION_LOCAL1(m_blockchain);
957 const uint64_t now = time(NULL);
958 backlog.reserve(m_blockchain.get_txpool_tx_count(include_unrelayed_txes));
959 m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
960 backlog.push_back({meta.weight, meta.fee, meta.receive_time - now});
961 return true;
962 }, false, include_unrelayed_txes);
963 }
964 //------------------------------------------------------------------
965 void tx_memory_pool::get_transaction_stats(struct txpool_stats& stats, bool include_unrelayed_txes) const
966 {
967 CRITICAL_REGION_LOCAL(m_transactions_lock);
968 CRITICAL_REGION_LOCAL1(m_blockchain);
969 const uint64_t now = time(NULL);
970 std::map<uint64_t, txpool_histo> agebytes;
971 stats.txs_total = m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
972 std::vector<uint32_t> weights;
973 weights.reserve(stats.txs_total);
974 m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
975 weights.push_back(meta.weight);
976 stats.bytes_total += meta.weight;
977 if (!stats.bytes_min || meta.weight < stats.bytes_min)
978 stats.bytes_min = meta.weight;
979 if (meta.weight > stats.bytes_max)
980 stats.bytes_max = meta.weight;
981 if (!meta.relayed)
982 stats.num_not_relayed++;
983 stats.fee_total += meta.fee;
984 if (!stats.oldest || meta.receive_time < stats.oldest)
985 stats.oldest = meta.receive_time;
986 if (meta.receive_time < now - 600)
987 stats.num_10m++;
988 if (meta.last_failed_height)
989 stats.num_failing++;
990 uint64_t age = now - meta.receive_time + (now == meta.receive_time);
991 agebytes[age].txs++;
992 agebytes[age].bytes += meta.weight;
993 if (meta.double_spend_seen)
994 ++stats.num_double_spends;
995 if(meta.utxo_nonexistent_seen)
996 ++stats.num_nonexistent_utxos;
997 return true;
998 }, false, include_unrelayed_txes);
999 stats.bytes_med = epee::misc_utils::median(weights);
1000 if (stats.txs_total > 1)
1001 {
1002 /* looking for 98th percentile */
1003 size_t end = stats.txs_total * 0.02;
1004 uint64_t delta, factor;
1005 std::map<uint64_t, txpool_histo>::iterator it, i2;
1006 if (end)
1007 {
1008 /* If enough txs, spread the first 98% of results across
1009 * the first 9 bins, drop final 2% in last bin.
1010 */
1011 it=agebytes.end();
1012 for (size_t n=0; n <= end; n++, it--);
1013 stats.histo_98pc = it->first;
1014 factor = 9;
1015 delta = it->first;
1016 stats.histo.resize(10);
1017 } else
1018 {
1019 /* If not enough txs, don't reserve the last slot;
1020 * spread evenly across all 10 bins.
1021 */
1022 stats.histo_98pc = 0;
1023 it = agebytes.end();
1024 factor = stats.txs_total > 9 ? 10 : stats.txs_total;
1025 delta = now - stats.oldest;
1026 stats.histo.resize(factor);
1027 }
1028 if (!delta)
1029 delta = 1;
1030 for (i2 = agebytes.begin(); i2 != it; i2++)
1031 {
1032 size_t i = (i2->first * factor - 1) / delta;
1033 stats.histo[i].txs += i2->second.txs;
1034 stats.histo[i].bytes += i2->second.bytes;
1035 }
1036 for (; i2 != agebytes.end(); i2++)
1037 {
1038 stats.histo[factor].txs += i2->second.txs;
1039 stats.histo[factor].bytes += i2->second.bytes;
1040 }
1041 }
1042 }
1043 //------------------------------------------------------------------
1044 //TODO: investigate whether boolean return is appropriate
1045 bool 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) const
1046 {
1047 CRITICAL_REGION_LOCAL(m_transactions_lock);
1048 CRITICAL_REGION_LOCAL1(m_blockchain);
1049 tx_infos.reserve(m_blockchain.get_txpool_tx_count());
1050 key_image_infos.reserve(m_blockchain.get_txpool_tx_count());
1051 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){
1052 tx_info txi;
1054 txi.tx_blob = *bd;
1055 transaction tx;
1056 if (!parse_and_validate_tx_from_blob(*bd, tx))
1057 {
1058 MERROR("Failed to parse tx from txpool");
1059 // continue
1060 return true;
1061 }
1062 tx.set_hash(txid);
1063 txi.tx_json = obj_to_json_str(tx);
1064 txi.blob_size = bd->size();
1065 txi.weight = meta.weight;
1066 txi.fee = meta.fee;
1067 txi.kept_by_block = meta.kept_by_block;
1072 // In restricted mode we do not include this data:
1073 txi.receive_time = include_sensitive_data ? meta.receive_time : 0;
1074 txi.relayed = meta.relayed;
1075 // In restricted mode we do not include this data:
1076 txi.last_relayed_time = include_sensitive_data ? meta.last_relayed_time : 0;
1077 txi.do_not_relay = meta.do_not_relay;
1080
1081 tx_infos.push_back(std::move(txi));
1082 return true;
1083 }, true, include_sensitive_data);
1084
1085 txpool_tx_meta_t meta;
1086 for (const key_images_container::value_type& kee : m_spent_key_images) {
1087 const crypto::key_image& k_image = kee.first;
1088 const std::unordered_set<crypto::hash>& kei_image_set = kee.second;
1091 for (const crypto::hash& tx_id_hash : kei_image_set)
1092 {
1093 if (!include_sensitive_data)
1094 {
1095 try
1096 {
1097 if (!m_blockchain.get_txpool_tx_meta(tx_id_hash, meta))
1098 {
1099 MERROR("Failed to get tx meta from txpool");
1100 return false;
1101 }
1102 if (!meta.relayed)
1103 // Do not include that transaction if in restricted mode and it's not relayed
1104 continue;
1105 }
1106 catch (const std::exception &e)
1107 {
1108 MERROR("Failed to get tx meta from txpool: " << e.what());
1109 return false;
1110 }
1111 }
1112 ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash));
1113 }
1114 // Only return key images for which we have at least one tx that we can show for them
1115 if (!ki.txs_hashes.empty())
1116 key_image_infos.push_back(ki);
1117 }
1118 return true;
1119 }
1120 //---------------------------------------------------------------------------------
1121 bool 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
1122 {
1123 CRITICAL_REGION_LOCAL(m_transactions_lock);
1124 CRITICAL_REGION_LOCAL1(m_blockchain);
1125 tx_infos.reserve(m_blockchain.get_txpool_tx_count());
1126 key_image_infos.reserve(m_blockchain.get_txpool_tx_count());
1127 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){
1129 txi.tx_hash = txid;
1130 if (!parse_and_validate_tx_from_blob(*bd, txi.tx))
1131 {
1132 MERROR("Failed to parse tx from txpool");
1133 // continue
1134 return true;
1135 }
1136 txi.tx.set_hash(txid);
1137 txi.blob_size = bd->size();
1138 txi.weight = meta.weight;
1139 txi.fee = meta.fee;
1140 txi.kept_by_block = meta.kept_by_block;
1145 txi.receive_time = meta.receive_time;
1146 txi.relayed = meta.relayed;
1148 txi.do_not_relay = meta.do_not_relay;
1151
1152 tx_infos.push_back(txi);
1153 return true;
1154 }, true, false);
1155
1156 for (const key_images_container::value_type& kee : m_spent_key_images) {
1157 std::vector<crypto::hash> tx_hashes;
1158 const std::unordered_set<crypto::hash>& kei_image_set = kee.second;
1159 for (const crypto::hash& tx_id_hash : kei_image_set)
1160 {
1161 tx_hashes.push_back(tx_id_hash);
1162 }
1163
1164 const crypto::key_image& k_image = kee.first;
1165 key_image_infos[k_image] = std::move(tx_hashes);
1166 }
1167 return true;
1168 }
1169 //---------------------------------------------------------------------------------
1170 bool tx_memory_pool::check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool> spent) const
1171 {
1172 CRITICAL_REGION_LOCAL(m_transactions_lock);
1173 CRITICAL_REGION_LOCAL1(m_blockchain);
1174
1175 spent.clear();
1176
1177 for (const auto& image : key_images)
1178 {
1179 spent.push_back(m_spent_key_images.find(image) == m_spent_key_images.end() ? false : true);
1180 }
1181
1182 return true;
1183 }
1184 //---------------------------------------------------------------------------------
1186 {
1187 CRITICAL_REGION_LOCAL(m_transactions_lock);
1188 CRITICAL_REGION_LOCAL1(m_blockchain);
1189 try
1190 {
1191 return m_blockchain.get_txpool_tx_blob(id, txblob);
1192 }
1193 catch (const std::exception &e)
1194 {
1195 return false;
1196 }
1197 }
1198 //---------------------------------------------------------------------------------
1199 bool tx_memory_pool::on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id)
1200 {
1201 CRITICAL_REGION_LOCAL(m_transactions_lock);
1202 m_input_cache.clear();
1203 m_parsed_tx_cache.clear();
1204 return true;
1205 }
1206 //---------------------------------------------------------------------------------
1207 bool tx_memory_pool::on_blockchain_dec(uint64_t new_block_height, const crypto::hash& top_block_id)
1208 {
1209 CRITICAL_REGION_LOCAL(m_transactions_lock);
1210 m_input_cache.clear();
1211 m_parsed_tx_cache.clear();
1212 return true;
1213 }
1214 //---------------------------------------------------------------------------------
1216 {
1217 CRITICAL_REGION_LOCAL(m_transactions_lock);
1218 CRITICAL_REGION_LOCAL1(m_blockchain);
1219 return m_blockchain.get_db().txpool_has_tx(id);
1220 }
1221
1222 //---------------------------------------------------------------------------------
1223 bool tx_memory_pool::key_images_already_spent(const transaction& tx) const
1224 {
1225 CRITICAL_REGION_LOCAL(m_transactions_lock);
1226 CRITICAL_REGION_LOCAL1(m_blockchain);
1227 for(const auto& in: tx.vin)
1228 {
1229 if(in.type() == typeid(txin_to_key))
1230 {
1231 const auto &tokey_in = boost::get<txin_to_key>(in);
1232 if(have_tx_keyimg_as_spent(tokey_in.k_image)) // key_image
1233 return true;
1234 }
1235 }
1236 return false;
1237 }
1238
1240 CRITICAL_REGION_LOCAL(m_transactions_lock);
1241 CRITICAL_REGION_LOCAL1(m_blockchain);
1242 return have_tx_utxo_as_spent(in);
1243 }
1244 //---------------------------------------------------------------------------------
1245 bool tx_memory_pool::utxo_nonexistent(const transaction& tx) const
1246 {
1247 CRITICAL_REGION_LOCAL(m_transactions_lock);
1248 CRITICAL_REGION_LOCAL1(m_blockchain);
1249 for(const auto& in: tx.vin)
1250 {
1251 if (in.type() == typeid(txin_to_key_public))
1252 {
1253 const auto &tokey_in = boost::get<txin_to_key_public>(in);
1254 if(have_tx_utxo_as_spent(tokey_in)) // UTXO
1255 return true;
1256 }
1257 }
1258 return false;
1259 }
1260 //---------------------------------------------------------------------------------
1261 bool tx_memory_pool::have_tx_keyimg_as_spent(const crypto::key_image& key_im) const
1262 {
1263 CRITICAL_REGION_LOCAL(m_transactions_lock);
1264 return m_spent_key_images.end() != m_spent_key_images.find(key_im);
1265 }
1266 //---------------------------------------------------------------------------------
1267 bool tx_memory_pool::have_tx_utxo_as_spent(const txin_to_key_public& in) const
1268 {
1269 CRITICAL_REGION_LOCAL(m_transactions_lock);
1271 return m_spent_utxos.end() != m_spent_utxos.find(txin_key);
1272 }
1273 //---------------------------------------------------------------------------------
1275 {
1276 m_transactions_lock.lock();
1277 }
1278 //---------------------------------------------------------------------------------
1280 {
1281 m_transactions_lock.unlock();
1282 }
1283 //---------------------------------------------------------------------------------
1284 bool tx_memory_pool::check_tx_inputs(const std::function<cryptonote::transaction&(void)> &get_tx, const crypto::hash &txid, uint64_t &max_used_block_height, crypto::hash &max_used_block_id, tx_verification_context &tvc, bool kept_by_block) const
1285 {
1286 if (!kept_by_block)
1287 {
1288 const std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>>::const_iterator i = m_input_cache.find(txid);
1289 if (i != m_input_cache.end())
1290 {
1291 max_used_block_height = std::get<2>(i->second);
1292 max_used_block_id = std::get<3>(i->second);
1293 tvc = std::get<1>(i->second);
1294 return std::get<0>(i->second);
1295 }
1296 }
1297 bool ret = m_blockchain.check_tx_inputs(get_tx(), max_used_block_height, max_used_block_id, tvc, kept_by_block);
1298 if (!kept_by_block)
1299 m_input_cache.insert(std::make_pair(txid, std::make_tuple(ret, tvc, max_used_block_height, max_used_block_id)));
1300 return ret;
1301 }
1302 //---------------------------------------------------------------------------------
1303 bool tx_memory_pool::is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction &tx) const
1304 {
1305 struct transction_parser
1306 {
1307 transction_parser(const cryptonote::blobdata &txblob, const crypto::hash &txid, transaction &tx): txblob(txblob), txid(txid), tx(tx), parsed(false) {}
1308 cryptonote::transaction &operator()()
1309 {
1310 if (!parsed)
1311 {
1312 if (!parse_and_validate_tx_from_blob(txblob, tx))
1313 throw std::runtime_error("failed to parse transaction blob");
1314 tx.set_hash(txid);
1315 parsed = true;
1316 }
1317 return tx;
1318 }
1319 const cryptonote::blobdata &txblob;
1320 const crypto::hash &txid;
1321 transaction &tx;
1322 bool parsed;
1323 } lazy_tx(txblob, txid, tx);
1324
1325 //not the best implementation at this time, sorry :(
1326 //check is ring_signature already checked ?
1327 if(txd.max_used_block_id == null_hash)
1328 {//not checked, lets try to check
1329
1330 if(txd.last_failed_id != null_hash && m_blockchain.get_current_blockchain_height() > txd.last_failed_height && txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height))
1331 return false;//we already sure that this tx is broken for this height
1332
1333 tx_verification_context tvc;
1334 if(!check_tx_inputs([&lazy_tx]()->cryptonote::transaction&{ return lazy_tx(); }, txid, txd.max_used_block_height, txd.max_used_block_id, tvc))
1335 {
1336 txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1;
1337 txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
1338 return false;
1339 }
1340 }else
1341 {
1342 if(txd.max_used_block_height >= m_blockchain.get_current_blockchain_height())
1343 return false;
1344 if(true)
1345 {
1346 //if we already failed on this height and id, skip actual ring signature check
1347 if(txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height))
1348 return false;
1349 //check ring signature again, it is possible (with very small chance) that this transaction become again valid
1350 tx_verification_context tvc;
1351 if(!check_tx_inputs([&lazy_tx]()->cryptonote::transaction&{ return lazy_tx(); }, txid, txd.max_used_block_height, txd.max_used_block_id, tvc))
1352 {
1353 txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1;
1354 txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height);
1355 return false;
1356 }
1357 }
1358 }
1359
1360 //if we here, transaction seems valid, but, anyway, check for key_images collisions with blockchain, just to be sure
1361 if(tx.version < 3 && m_blockchain.key_images_already_spent(lazy_tx()))
1362 {
1363 txd.double_spend_seen = true;
1364 return false;
1365 }
1366 if(tx.version > 2 && m_blockchain.utxo_nonexistent(lazy_tx()))
1367 {
1368 txd.utxo_nonexistent_seen = true;
1369 return false;
1370 }
1371
1372 //transaction is ok.
1373 return true;
1374 }
1375 //---------------------------------------------------------------------------------
1376 bool tx_memory_pool::have_key_images(const std::unordered_set<crypto::key_image>& k_images, const transaction_prefix& tx)
1377 {
1378 for(size_t i = 0; i!= tx.vin.size(); i++)
1379 {
1380 if(tx.vin[i].type() == typeid(txin_to_key))
1381 {
1382 const auto &itk = boost::get<txin_to_key>(tx.vin[i]);
1383 if(k_images.count(itk.k_image))
1384 return true;
1385 }
1386 }
1387 return false;
1388 }
1389 //---------------------------------------------------------------------------------
1390 bool tx_memory_pool::append_key_images(std::unordered_set<crypto::key_image>& k_images, const transaction_prefix& tx)
1391 {
1392 for(size_t i = 0; i!= tx.vin.size(); i++)
1393 {
1394 if(tx.vin[i].type() == typeid(txin_to_key))
1395 {
1396 const auto &itk = boost::get<txin_to_key>(tx.vin[i]);
1397 auto i_res = k_images.insert(itk.k_image);
1398 CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << itk.k_image);
1399 }
1400 }
1401 return true;
1402 }
1403 //---------------------------------------------------------------------------------
1404 bool tx_memory_pool::have_utxos(const std::unordered_set<std::string>& utxos, const transaction_prefix& tx)
1405 {
1406 for(size_t i = 0; i!= tx.vin.size(); i++)
1407 {
1408 if(tx.vin[i].type() == typeid(txin_to_key_public))
1409 {
1410 const auto &itk = boost::get<txin_to_key_public>(tx.vin[i]);
1412 if(utxos.count(txin_key))
1413 return true;
1414 }
1415
1416 }
1417 return false;
1418 }
1419 //---------------------------------------------------------------------------------
1420 bool tx_memory_pool::append_utxos(std::unordered_set<std::string>& utxos, const transaction_prefix& tx)
1421 {
1422 for(size_t i = 0; i!= tx.vin.size(); i++)
1423 {
1424 if(tx.vin[i].type() == typeid(txin_to_key_public))
1425 {
1426 const auto &itk = boost::get<txin_to_key_public>(tx.vin[i]);
1427
1429 auto i_res = utxos.insert(txin_key);
1430 CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: utxo pool cache - inserted duplicate image in set: " << txin_key);
1431 }
1432 }
1433 return true;
1434 }
1435 //---------------------------------------------------------------------------------
1436 void tx_memory_pool::mark_double_spend_or_nonexistent_utxo(const transaction &tx)
1437 {
1438 CRITICAL_REGION_LOCAL(m_transactions_lock);
1439 CRITICAL_REGION_LOCAL1(m_blockchain);
1440 bool changed = false;
1441 LockedTXN lock(m_blockchain);
1442 for(size_t i = 0; i!= tx.vin.size(); i++)
1443 {
1444 if(tx.vin[i].type() == typeid(txin_to_key))
1445 {
1446 CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, void());
1447 const key_images_container::const_iterator it = m_spent_key_images.find(itk.k_image);
1448 if (it != m_spent_key_images.end())
1449 {
1450 for (const crypto::hash &txid: it->second)
1451 {
1452 txpool_tx_meta_t meta;
1453 if (!m_blockchain.get_txpool_tx_meta(txid, meta))
1454 {
1455 MERROR("Failed to find tx meta in txpool");
1456 // continue, not fatal
1457 continue;
1458 }
1459 if (!meta.double_spend_seen)
1460 {
1461 MDEBUG("Marking " << txid << " as double spending " << itk.k_image);
1462 meta.double_spend_seen = true;
1463 changed = true;
1464 try
1465 {
1466 m_blockchain.update_txpool_tx(txid, meta);
1467 }
1468 catch (const std::exception &e)
1469 {
1470 MERROR("Failed to update tx meta: " << e.what());
1471 // continue, not fatal
1472 }
1473 }
1474 }
1475 }
1476 }
1477 else if (tx.vin[i].type() == typeid(txin_to_key_public))
1478 {
1479 CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key_public, itk, void());
1481 const utxos_container::const_iterator it = m_spent_utxos.find(txin_key);
1482 if (it != m_spent_utxos.end())
1483 {
1484 for (const crypto::hash &txid: it->second)
1485 {
1486 txpool_tx_meta_t meta;
1487 if (!m_blockchain.get_txpool_tx_meta(txid, meta))
1488 {
1489 MERROR("Failed to find tx meta in txpool");
1490 // continue, not fatal
1491 continue;
1492 }
1493 if (!meta.double_spend_seen)
1494 {
1495 MDEBUG("Marking " << txid << " as double spending " << txin_key);
1496 meta.utxo_nonexistent_seen = true;
1497 changed = true;
1498 try
1499 {
1500 m_blockchain.update_txpool_tx(txid, meta);
1501 }
1502 catch (const std::exception &e)
1503 {
1504 MERROR("Failed to update tx meta: " << e.what());
1505 // continue, not fatal
1506 }
1507 }
1508 }
1509 }
1510 }
1511 else
1512 {
1513 return;
1514 }
1515 }
1516 lock.commit();
1517 if (changed)
1518 ++m_cookie;
1519 }
1520 //---------------------------------------------------------------------------------
1521 std::string tx_memory_pool::print_pool(bool short_format) const
1522 {
1523 std::stringstream ss;
1524 CRITICAL_REGION_LOCAL(m_transactions_lock);
1525 CRITICAL_REGION_LOCAL1(m_blockchain);
1526 m_blockchain.for_all_txpool_txes([&ss, short_format](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *txblob) {
1527 ss << "id: " << txid << std::endl;
1528 if (!short_format) {
1530 if (!parse_and_validate_tx_from_blob(*txblob, tx))
1531 {
1532 MERROR("Failed to parse tx from txpool");
1533 return true; // continue
1534 }
1535 ss << obj_to_json_str(tx) << std::endl;
1536 }
1537 ss << "blob_size: " << (short_format ? "-" : std::to_string(txblob->size())) << std::endl
1538 << "weight: " << meta.weight << std::endl
1539 << "fee: " << print_etn(meta.fee) << std::endl
1540 << "kept_by_block: " << (meta.kept_by_block ? 'T' : 'F') << std::endl
1541 << "double_spend_seen: " << (meta.double_spend_seen ? 'T' : 'F') << std::endl
1542 << "nonexistent_utxo_seen: " << (meta.utxo_nonexistent_seen ? 'T' : 'F') << std::endl
1543 << "max_used_block_height: " << meta.max_used_block_height << std::endl
1544 << "max_used_block_id: " << meta.max_used_block_id << std::endl
1545 << "last_failed_height: " << meta.last_failed_height << std::endl
1546 << "last_failed_id: " << meta.last_failed_id << std::endl;
1547 return true;
1548 }, !short_format);
1549
1550 return ss.str();
1551 }
1552 //---------------------------------------------------------------------------------
1553 //TODO: investigate whether boolean return is appropriate
1554 bool 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)
1555 {
1556 CRITICAL_REGION_LOCAL(m_transactions_lock);
1557 CRITICAL_REGION_LOCAL1(m_blockchain);
1558
1559 uint64_t best_coinbase = 0, coinbase = 0;
1560 total_weight = 0;
1561 fee = 0;
1562
1563 //baseline empty block
1564 get_block_reward(median_weight, total_weight, already_generated_coins, best_coinbase, version, m_blockchain.get_current_blockchain_height(), m_blockchain.get_nettype());
1565
1566
1567 size_t max_total_weight_pre_v5 = (130 * median_weight) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
1568 size_t max_total_weight_v5 = 2 * median_weight - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
1569 size_t max_total_weight = version >= 5 ? max_total_weight_v5 : max_total_weight_pre_v5;
1570 std::unordered_set<crypto::key_image> k_images;
1571 std::unordered_set<std::string> utxos;
1572
1573 LOG_PRINT_L2("Filling block template, median weight " << median_weight << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
1574
1575 LockedTXN lock(m_blockchain);
1576
1577 auto sorted_it = m_txs_by_fee_and_receive_time.begin();
1578 for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
1579 {
1580 txpool_tx_meta_t meta;
1581 if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
1582 {
1583 MERROR(" failed to find tx meta");
1584 continue;
1585 }
1586 LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_etn(best_coinbase));
1587
1588 // Can not exceed maximum block weight
1589 if (max_total_weight < total_weight + meta.weight)
1590 {
1591 LOG_PRINT_L2(" would exceed maximum block weight");
1592 continue;
1593 }
1594
1595 // start using the optimal filling algorithm from v5
1596 if (version >= 5)
1597 {
1598 // If we're getting lower coinbase tx,
1599 // stop including more tx
1600 uint64_t block_reward;
1601 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()))
1602 {
1603 LOG_PRINT_L2(" would exceed maximum block weight");
1604 continue;
1605 }
1606 coinbase = block_reward + fee + meta.fee;
1607 if (coinbase < template_accept_threshold(best_coinbase))
1608 {
1609 LOG_PRINT_L2(" would decrease coinbase to " << print_etn(coinbase));
1610 continue;
1611 }
1612 }
1613 else
1614 {
1615 // If we've exceeded the penalty free weight,
1616 // stop including more tx
1617 if (total_weight > median_weight)
1618 {
1619 LOG_PRINT_L2(" would exceed median block weight");
1620 break;
1621 }
1622 }
1623
1624 cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second);
1626
1627 // Skip transactions that are not ready to be
1628 // included into the blockchain or that are
1629 // missing key images
1630 const cryptonote::txpool_tx_meta_t original_meta = meta;
1631 bool ready = false;
1632 try
1633 {
1634 ready = is_transaction_ready_to_go(meta, sorted_it->second, txblob, tx);
1635 }
1636 catch (const std::exception &e)
1637 {
1638 MERROR("Failed to check transaction readiness: " << e.what());
1639 // continue, not fatal
1640 }
1641 if (memcmp(&original_meta, &meta, sizeof(meta)))
1642 {
1643 try
1644 {
1645 m_blockchain.update_txpool_tx(sorted_it->second, meta);
1646 }
1647 catch (const std::exception &e)
1648 {
1649 MERROR("Failed to update tx meta: " << e.what());
1650 // continue, not fatal
1651 }
1652 }
1653 if (!ready)
1654 {
1655 LOG_PRINT_L2(" not ready to go");
1656 continue;
1657 }
1658 if (have_key_images(k_images, tx))
1659 {
1660 LOG_PRINT_L2(" key images already seen");
1661 continue;
1662 }
1663 if (have_utxos(utxos, tx))
1664 {
1665 LOG_PRINT_L2(" utxos already seen");
1666 continue;
1667 }
1668
1669 bl.tx_hashes.push_back(sorted_it->second);
1670 total_weight += meta.weight;
1671 fee += meta.fee;
1672 best_coinbase = coinbase;
1673 append_key_images(k_images, tx);
1674 append_utxos(utxos, tx);
1675 LOG_PRINT_L2(" added, new block weight " << total_weight << "/" << max_total_weight << ", coinbase " << print_etn(best_coinbase));
1676 }
1677 lock.commit();
1678
1679 expected_reward = best_coinbase;
1680 LOG_PRINT_L2("Block template filled with " << bl.tx_hashes.size() << " txes, weight "
1681 << total_weight << "/" << max_total_weight << ", coinbase " << print_etn(best_coinbase)
1682 << " (including " << print_etn(fee) << " in fees)");
1683 return true;
1684 }
1685 //---------------------------------------------------------------------------------
1687 {
1688 CRITICAL_REGION_LOCAL(m_transactions_lock);
1689 CRITICAL_REGION_LOCAL1(m_blockchain);
1690 size_t tx_weight_limit = get_transaction_weight_limit(version);
1691 std::unordered_set<crypto::hash> remove;
1692
1693 m_txpool_weight = 0;
1694 m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
1695 m_txpool_weight += meta.weight;
1696 if (meta.weight > tx_weight_limit) {
1697 LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.weight << " bytes), removing it from pool");
1698 remove.insert(txid);
1699 }
1700 else if (m_blockchain.have_tx(txid)) {
1701 LOG_PRINT_L1("Transaction " << txid << " is in the blockchain, removing it from pool");
1702 remove.insert(txid);
1703 }
1704 return true;
1705 }, false);
1706
1707 size_t n_removed = 0;
1708 if (!remove.empty())
1709 {
1710 LockedTXN lock(m_blockchain);
1711 for (const crypto::hash &txid: remove)
1712 {
1713 try
1714 {
1715 cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
1717 if (!parse_and_validate_tx_from_blob(txblob, tx))
1718 {
1719 MERROR("Failed to parse tx from txpool");
1720 continue;
1721 }
1722 // remove tx from db first
1723 m_blockchain.remove_txpool_tx(txid);
1724 m_txpool_weight -= get_transaction_weight(tx, txblob.size());
1725 remove_transaction_keyimages(tx, txid);
1726 auto sorted_it = find_tx_in_sorted_container(txid);
1727 if (sorted_it == m_txs_by_fee_and_receive_time.end())
1728 {
1729 LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
1730 }
1731 else
1732 {
1733 m_txs_by_fee_and_receive_time.erase(sorted_it);
1734 }
1735 ++n_removed;
1736 }
1737 catch (const std::exception &e)
1738 {
1739 MERROR("Failed to remove invalid tx from pool");
1740 // continue
1741 }
1742 }
1743 lock.commit();
1744 }
1745 if (n_removed > 0)
1746 ++m_cookie;
1747 return n_removed;
1748 }
1749 //---------------------------------------------------------------------------------
1750 bool tx_memory_pool::init(size_t max_txpool_weight)
1751 {
1752 CRITICAL_REGION_LOCAL(m_transactions_lock);
1753 CRITICAL_REGION_LOCAL1(m_blockchain);
1754
1755 m_txpool_max_weight = max_txpool_weight ? max_txpool_weight : DEFAULT_TXPOOL_MAX_WEIGHT;
1756 m_txs_by_fee_and_receive_time.clear();
1757 m_spent_key_images.clear();
1758 m_spent_utxos.clear();
1759 m_txpool_weight = 0;
1760 std::vector<crypto::hash> remove;
1761
1762 // first add the not kept by block, then the kept by block,
1763 // to avoid rejection due to key image collision
1764 for (int pass = 0; pass < 2; ++pass)
1765 {
1766 const bool kept = pass == 1;
1767 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) {
1768 if (!!kept != !!meta.kept_by_block)
1769 return true;
1772 {
1773 MWARNING("Failed to parse tx from txpool, removing");
1774 remove.push_back(txid);
1775 return true;
1776 }
1777 if (tx.version <= 2 && !insert_key_images(tx, txid, meta.kept_by_block))
1778 {
1779 MFATAL("Failed to insert key images from txpool tx");
1780 return false;
1781 }
1782 if (tx.version >= 3 && !insert_utxos(tx, txid, meta.kept_by_block))
1783 {
1784 MFATAL("Failed to insert utxos from txpool tx");
1785 return false;
1786 }
1787 m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.weight, meta.receive_time), txid);
1788 m_txpool_weight += meta.weight;
1789 return true;
1790 }, true);
1791 if (!r)
1792 return false;
1793 }
1794 if (!remove.empty())
1795 {
1796 LockedTXN lock(m_blockchain);
1797 for (const auto &txid: remove)
1798 {
1799 try
1800 {
1801 m_blockchain.remove_txpool_tx(txid);
1802 }
1803 catch (const std::exception &e)
1804 {
1805 MWARNING("Failed to remove corrupt transaction: " << txid);
1806 // ignore error
1807 }
1808 }
1809 lock.commit();
1810 }
1811
1812 m_cookie = 0;
1813
1814 // Ignore deserialization error
1815 return true;
1816 }
1817
1818 //---------------------------------------------------------------------------------
1820 {
1821 return true;
1822 }
1823}
uint8_t version
time_t time
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
uint32_t get_mempool_tx_livetime() const
void set_hash(const crypto::hash &h)
void unlock() const
unlocks the transaction pool
Definition tx_pool.cpp:1279
void lock() const
locks the transaction pool
Definition tx_pool.cpp:1274
void on_idle()
action to take periodically
Definition tx_pool.cpp:777
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
Definition tx_pool.cpp:1121
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
Definition tx_pool.cpp:1207
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.
Definition tx_pool.cpp:1554
void set_relayed(const std::vector< std::pair< crypto::hash, cryptonote::blobdata > > &txs)
tell the pool that certain transactions were just relayed
Definition tx_pool.cpp:889
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
Definition tx_pool.cpp:1215
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
Definition tx_pool.cpp:1199
bool utxo_spent_in_pool(const txin_to_key_public &in) const
get a summary statistics of all transaction hashes in the pool
Definition tx_pool.cpp:1239
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
Definition tx_pool.cpp:942
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
void set_txpool_max_weight(size_t bytes)
set the max cumulative txpool weight in bytes
Definition tx_pool.cpp:560
void get_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
Definition tx_pool.cpp:923
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
Definition tx_pool.cpp:721
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
Definition tx_pool.cpp:1045
bool init(size_t max_txpool_weight=0)
loads pool state (if any) from disk, and initializes pool
Definition tx_pool.cpp:1750
std::string print_pool(bool short_format) const
get a string containing human-readable pool information
Definition tx_pool.cpp:1521
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
Definition tx_pool.cpp:953
tx_memory_pool(Blockchain &bchs)
Constructor.
Definition tx_pool.cpp:117
size_t validate(uint8_t version)
remove transactions from the pool which are no longer valid
Definition tx_pool.cpp:1686
size_t get_txpool_weight() const
get the cumulative txpool weight in bytes
Definition tx_pool.cpp:554
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
Definition tx_pool.cpp:965
size_t get_transactions_count(bool include_unrelayed_txes=true) const
get the total number of transactions in the pool
Definition tx_pool.cpp:916
bool get_transaction(const crypto::hash &h, cryptonote::blobdata &txblob) const
get a specific transaction from the pool
Definition tx_pool.cpp:1185
bool get_relayable_transactions(std::vector< std::pair< crypto::hash, cryptonote::blobdata > > &txs) const
get a list of all relayable transactions and their hashes
Definition tx_pool.cpp:855
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
Definition tx_pool.cpp:1170
bool deinit()
attempts to save the transaction pool state to disk
Definition tx_pool.cpp:1819
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE
#define DEFAULT_TXPOOL_MAX_WEIGHT
#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME
#define HF_VERSION_PER_BYTE_FEE
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val)
void * memcpy(void *a, const void *b, size_t c)
void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen)
#define MERROR(x)
Definition misc_log_ex.h:73
#define MFATAL(x)
Definition misc_log_ex.h:72
#define MWARNING(x)
Definition misc_log_ex.h:74
#define MDEBUG(x)
Definition misc_log_ex.h:76
#define ENDL
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define LOG_PRINT_L1(x)
#define MINFO(x)
Definition misc_log_ex.h:75
#define LOG_PRINT_L2(x)
crypto namespace.
Definition crypto.cpp:58
POD_CLASS signature
Definition crypto.h:108
void cn_fast_hash(const void *data, size_t length, char *hash)
POD_CLASS key_image
Definition crypto.h:105
bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig)
Definition crypto.h:295
POD_CLASS hash
Definition hash.h:50
std::unordered_map< crypto::key_image, std::vector< crypto::hash > > key_images_with_tx_hashes
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
std::string obj_to_json_str(T &obj)
uint64_t get_outs_etn_amount(const transaction &tx)
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)
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
crypto::hash get_transaction_hash(const transaction &t)
bool check_outs_valid(const transaction &tx)
bool find_tx_extra_field_by_type(const std::vector< tx_extra_field > &tx_extra_fields, T &field, size_t index=0)
bool parse_tx_extra(const std::vector< uint8_t > &tx_extra, std::vector< tx_extra_field > &tx_extra_fields)
std::string blobdata
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
bool parse_and_validate_tx_prefix_from_blob(const blobdata &tx_blob, transaction_prefix &tx)
bool check_inputs_types_supported(const transaction &tx)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
bool t_serializable_object_to_blob(const t_object &to, blobdata &b_blob)
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
type_vec_type median(std::vector< type_vec_type > &v)
std::string pod_to_hex(const t_pod_type &s)
std::string buff_to_hex_nodelimer(const std::string &src)
#define PERF_TIMER(name)
Definition perf_timer.h:82
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
#define false
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
std::vector< crypto::hash > tx_hashes
a struct containing txpool per transaction metadata
#define CRITICAL_REGION_LOCAL1(x)
Definition syncobj.h:230
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:228
#define DISABLE_VS_WARNINGS(w)
Definition warnings.h:18