Skip to content

Commit

Permalink
Add a configurable size limit for tx_extra in tx pool
Browse files Browse the repository at this point in the history
  • Loading branch information
tevador committed Feb 5, 2023
1 parent 50aa0e8 commit d8aee04
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/cryptonote_basic/verification_context.h
Expand Up @@ -53,6 +53,7 @@ namespace cryptonote
bool m_overspend;
bool m_fee_too_low;
bool m_too_few_outputs;
bool m_tx_extra_too_big;
};

struct block_verification_context
Expand Down
5 changes: 5 additions & 0 deletions src/cryptonote_config.h
Expand Up @@ -206,6 +206,11 @@

#define DNS_BLOCKLIST_LIFETIME (86400 * 8)

//The default limit is enough for the mandatory transaction content with 16 outputs (547 bytes),
//a custom tag and length (3 bytes) and up to 100 bytes of custom data for each recipient.
// (1+32) + (1+1+16*32) + (1+2+16*100) = 2150
#define DEFAULT_TX_EXTRA_MAX_SIZE 2150

// New constants are intended to go here
namespace config
{
Expand Down
9 changes: 8 additions & 1 deletion src/cryptonote_core/cryptonote_core.cpp
Expand Up @@ -223,6 +223,11 @@ namespace cryptonote
, "Keep alternative blocks on restart"
, false
};
static const command_line::arg_descriptor<size_t> arg_max_tx_extra_size = {
"max-tx-extra-size"
, "Set the maximum permitted size of tx_extra in bytes (0 = no limit)."
, DEFAULT_TX_EXTRA_MAX_SIZE
};

//-----------------------------------------------------------------------------------------------
core::core(i_cryptonote_protocol* pprotocol):
Expand Down Expand Up @@ -353,6 +358,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_reorg_notify);
command_line::add_arg(desc, arg_block_rate_notify);
command_line::add_arg(desc, arg_keep_alt_blocks);
command_line::add_arg(desc, arg_max_tx_extra_size);

miner::init_options(desc);
BlockchainDB::init_options(desc);
Expand Down Expand Up @@ -487,6 +493,7 @@ namespace cryptonote
bool prune_blockchain = command_line::get_arg(vm, arg_prune_blockchain);
bool keep_alt_blocks = command_line::get_arg(vm, arg_keep_alt_blocks);
bool keep_fakechain = command_line::get_arg(vm, arg_keep_fakechain);
size_t max_tx_extra_size = command_line::get_arg(vm, arg_max_tx_extra_size);

boost::filesystem::path folder(m_config_folder);
if (m_nettype == FAKECHAIN)
Expand Down Expand Up @@ -680,7 +687,7 @@ namespace cryptonote
r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty, get_checkpoints);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");

r = m_mempool.init(max_txpool_weight, m_nettype == FAKECHAIN);
r = m_mempool.init(max_txpool_weight, m_nettype == FAKECHAIN, max_tx_extra_size);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");

// now that we have a valid m_blockchain_storage, we can clean out any
Expand Down
12 changes: 11 additions & 1 deletion src/cryptonote_core/tx_pool.cpp
Expand Up @@ -218,6 +218,15 @@ namespace cryptonote
return false;
}

size_t tx_extra_size = tx.extra.size();
if (!kept_by_block && m_max_tx_extra_size > 0 && tx_extra_size > m_max_tx_extra_size)
{
LOG_PRINT_L1("transaction tx-extra is too big: " << tx_extra_size << " bytes, the limit is: " << m_max_tx_extra_size);
tvc.m_verifivation_failed = true;
tvc.m_tx_extra_too_big = true;
return false;
}

// if the transaction came from a block popped from the chain,
// don't check if we have its key images as spent.
// TODO: Investigate why not?
Expand Down Expand Up @@ -1687,12 +1696,13 @@ namespace cryptonote
return n_removed;
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::init(size_t max_txpool_weight, bool mine_stem_txes)
bool tx_memory_pool::init(size_t max_txpool_weight, bool mine_stem_txes, size_t max_tx_extra_size)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);

m_txpool_max_weight = max_txpool_weight ? max_txpool_weight : DEFAULT_TXPOOL_MAX_WEIGHT;
m_max_tx_extra_size = max_tx_extra_size;
m_txs_by_fee_and_receive_time.clear();
m_spent_key_images.clear();
m_txpool_weight = 0;
Expand Down
4 changes: 3 additions & 1 deletion src/cryptonote_core/tx_pool.h
Expand Up @@ -207,10 +207,11 @@ namespace cryptonote
*
* @param max_txpool_weight the max weight in bytes
* @param mine_stem_txes whether to mine txes in stem relay mode
* @param max_tx_extra_size the max size of tx_extra
*
* @return true
*/
bool init(size_t max_txpool_weight = 0, bool mine_stem_txes = false);
bool init(size_t max_txpool_weight = 0, bool mine_stem_txes = false, size_t max_tx_extra_size = 0);

/**
* @brief attempts to save the transaction pool state to disk
Expand Down Expand Up @@ -632,6 +633,7 @@ namespace cryptonote
size_t m_txpool_max_weight;
size_t m_txpool_weight;
bool m_mine_stem_txes;
size_t m_max_tx_extra_size;

mutable std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>> m_input_cache;

Expand Down
4 changes: 3 additions & 1 deletion src/rpc/core_rpc_server_commands_defs.h
Expand Up @@ -88,7 +88,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 3
#define CORE_RPC_VERSION_MINOR 11
#define CORE_RPC_VERSION_MINOR 12
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)

Expand Down Expand Up @@ -592,6 +592,7 @@ namespace cryptonote
bool fee_too_low;
bool too_few_outputs;
bool sanity_check_failed;
bool tx_extra_too_big;

BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_access_response_base)
Expand All @@ -606,6 +607,7 @@ namespace cryptonote
KV_SERIALIZE(fee_too_low)
KV_SERIALIZE(too_few_outputs)
KV_SERIALIZE(sanity_check_failed)
KV_SERIALIZE(tx_extra_too_big)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
Expand Down

0 comments on commit d8aee04

Please sign in to comment.