aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/blockchain.cpp20
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp48
-rw-r--r--src/cryptonote_core/cryptonote_core.h3
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp22
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h2
-rw-r--r--src/cryptonote_core/tx_pool.cpp95
-rw-r--r--src/cryptonote_core/tx_pool.h27
7 files changed, 177 insertions, 40 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 178479f3c..fe4004caa 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -127,7 +127,8 @@ static const struct {
{ 5, 802660, 0, 1472415036 + 86400*180 }, // add 5 months on testnet to shut the update warning up since there's a large gap to v6
{ 6, 971400, 0, 1501709789 },
- { 7, 1057028, 0, 1512211236 },
+ { 7, 1057027, 0, 1512211236 },
+ { 8, 1057058, 0, 1515967497 },
};
static const uint64_t testnet_hard_fork_version_1_till = 624633;
@@ -2395,11 +2396,11 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
}
- // from v7, allow bulletproofs
- if (hf_version < 7 || !m_testnet) {
+ // from v8, allow bulletproofs
+ if (hf_version < 8) {
if (!tx.rct_signatures.p.bulletproofs.empty())
{
- MERROR("Bulletproofs are not allowed before v7 or on mainnet");
+ MERROR("Bulletproofs are not allowed before v8");
tvc.m_invalid_output = true;
return false;
}
@@ -3753,6 +3754,10 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::list<c
if (height >= m_blocks_hash_of_hashes.size() * HASH_OF_HASHES_STEP)
return hashes.size();
+ // if we're getting old blocks, we might have jettisoned the hashes already
+ if (m_blocks_hash_check.empty())
+ return hashes.size();
+
// find hashes encompassing those block
size_t first_index = height / HASH_OF_HASHES_STEP;
size_t last_index = (height + hashes.size() - 1) / HASH_OF_HASHES_STEP;
@@ -4343,8 +4348,13 @@ void Blockchain::load_compiled_in_block_hashes()
{
const unsigned char *p = get_blocks_dat_start(m_testnet);
const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
+ if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) / sizeof(hash))
+ {
+ MERROR("Block hash data is too large");
+ return;
+ }
const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
- if(nblocks > 0 && nblocks * HASH_OF_HASHES_STEP > m_db->height() && get_blocks_dat_size(m_testnet) >= size_needed)
+ if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(m_testnet) >= size_needed)
{
p += sizeof(uint32_t);
m_blocks_hash_of_hashes.reserve(nblocks);
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 81a7b4724..8b837f2e4 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -66,19 +66,22 @@ DISABLE_VS_WARNINGS(4355)
namespace cryptonote
{
- const command_line::arg_descriptor<std::string> arg_data_dir = {
- "data-dir"
- , "Specify data directory"
- };
- const command_line::arg_descriptor<std::string> arg_testnet_data_dir = {
- "testnet-data-dir"
- , "Specify testnet data directory"
- };
const command_line::arg_descriptor<bool, false> arg_testnet_on = {
"testnet"
, "Run on testnet. The wallet must be launched with --testnet flag."
, false
};
+ const command_line::arg_descriptor<std::string, false, true> arg_data_dir = {
+ "data-dir"
+ , "Specify data directory"
+ , tools::get_default_data_dir()
+ , arg_testnet_on
+ , [](bool testnet, bool defaulted, std::string val) {
+ if (testnet)
+ return (boost::filesystem::path(val) / "testnet").string();
+ return val;
+ }
+ };
const command_line::arg_descriptor<bool> arg_offline = {
"offline"
, "Do not listen for peers, nor connect to any"
@@ -134,9 +137,19 @@ namespace cryptonote
};
static const command_line::arg_descriptor<bool> arg_fluffy_blocks = {
"fluffy-blocks"
- , "Relay blocks as fluffy blocks where possible (automatic on testnet)"
+ , "Relay blocks as fluffy blocks (obsolete, now default)"
+ , true
+ };
+ static const command_line::arg_descriptor<bool> arg_no_fluffy_blocks = {
+ "no-fluffy-blocks"
+ , "Relay blocks as normal blocks"
, false
};
+ static const command_line::arg_descriptor<size_t> arg_max_txpool_size = {
+ "max-txpool-size"
+ , "Set maximum txpool size in bytes."
+ , DEFAULT_TXPOOL_MAX_SIZE
+ };
//-----------------------------------------------------------------------------------------------
core::core(i_cryptonote_protocol* pprotocol):
@@ -224,8 +237,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------
void core::init_options(boost::program_options::options_description& desc)
{
- command_line::add_arg(desc, arg_data_dir, tools::get_default_data_dir());
- command_line::add_arg(desc, arg_testnet_data_dir, (boost::filesystem::path(tools::get_default_data_dir()) / "testnet").string());
+ command_line::add_arg(desc, arg_data_dir);
command_line::add_arg(desc, arg_test_drop_download);
command_line::add_arg(desc, arg_test_drop_download_height);
@@ -238,9 +250,11 @@ namespace cryptonote
command_line::add_arg(desc, arg_block_sync_size);
command_line::add_arg(desc, arg_check_updates);
command_line::add_arg(desc, arg_fluffy_blocks);
+ command_line::add_arg(desc, arg_no_fluffy_blocks);
command_line::add_arg(desc, arg_test_dbg_lock_sleep);
command_line::add_arg(desc, arg_offline);
command_line::add_arg(desc, arg_disable_dns_checkpoints);
+ command_line::add_arg(desc, arg_max_txpool_size);
miner::init_options(desc);
BlockchainDB::init_options(desc);
@@ -250,8 +264,7 @@ namespace cryptonote
{
m_testnet = command_line::get_arg(vm, arg_testnet_on);
- auto data_dir_arg = m_testnet ? arg_testnet_data_dir : arg_data_dir;
- m_config_folder = command_line::get_arg(vm, data_dir_arg);
+ m_config_folder = command_line::get_arg(vm, arg_data_dir);
auto data_dir = boost::filesystem::path(m_config_folder);
@@ -273,9 +286,11 @@ namespace cryptonote
set_enforce_dns_checkpoints(command_line::get_arg(vm, arg_dns_checkpoints));
test_drop_download_height(command_line::get_arg(vm, arg_test_drop_download_height));
- m_fluffy_blocks_enabled = m_testnet || get_arg(vm, arg_fluffy_blocks);
+ m_fluffy_blocks_enabled = !get_arg(vm, arg_no_fluffy_blocks);
m_offline = get_arg(vm, arg_offline);
m_disable_dns_checkpoints = get_arg(vm, arg_disable_dns_checkpoints);
+ if (!command_line::is_arg_defaulted(vm, arg_fluffy_blocks))
+ MWARNING(arg_fluffy_blocks.name << " is obsolete, it is now default");
if (command_line::get_arg(vm, arg_test_drop_download) == true)
test_drop_download();
@@ -359,6 +374,7 @@ namespace cryptonote
bool fast_sync = command_line::get_arg(vm, arg_fast_block_sync) != 0;
uint64_t blocks_threads = command_line::get_arg(vm, arg_prep_blocks_threads);
std::string check_updates_string = command_line::get_arg(vm, arg_check_updates);
+ size_t max_txpool_size = command_line::get_arg(vm, arg_max_txpool_size);
boost::filesystem::path folder(m_config_folder);
if (m_fakechain)
@@ -477,7 +493,7 @@ namespace cryptonote
r = m_blockchain_storage.init(db.release(), m_testnet, m_offline, test_options);
- r = m_mempool.init();
+ r = m_mempool.init(max_txpool_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
@@ -1372,7 +1388,7 @@ namespace cryptonote
break;
case HardFork::UpdateNeeded:
MCLOG_RED(level, "global", "**********************************************************************");
- MCLOG_RED(level, "global", "Last scheduled hard fork time shows a daemon update is needed now.");
+ MCLOG_RED(level, "global", "Last scheduled hard fork time shows a daemon update is needed soon.");
MCLOG_RED(level, "global", "**********************************************************************");
break;
default:
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 429f6b820..ce39aaddf 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -58,8 +58,7 @@ namespace cryptonote
const std::pair<uint8_t, uint64_t> *hard_forks;
};
- extern const command_line::arg_descriptor<std::string> arg_data_dir;
- extern const command_line::arg_descriptor<std::string> arg_testnet_data_dir;
+ extern const command_line::arg_descriptor<std::string, false, true> arg_data_dir;
extern const command_line::arg_descriptor<bool, false> arg_testnet_on;
extern const command_line::arg_descriptor<bool> arg_offline;
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index 431d71556..4a10f7133 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -172,20 +172,24 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
- crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys)
+ crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr)
{
- if (destinations.empty())
- return null_pkey;
- for (size_t n = 1; n < destinations.size(); ++n)
+ account_public_address addr = {null_pkey, null_pkey};
+ size_t count = 0;
+ for (const auto &i : destinations)
{
- if (!memcmp(&destinations[n].addr, &sender_keys.m_account_address, sizeof(destinations[0].addr)))
+ if (i.amount == 0)
continue;
- if (destinations[n].amount == 0)
+ if (change_addr && i.addr == *change_addr)
continue;
- if (memcmp(&destinations[n].addr, &destinations[0].addr, sizeof(destinations[0].addr)))
+ if (i.addr == addr)
+ continue;
+ if (count > 0)
return null_pkey;
+ addr = i.addr;
+ ++count;
}
- return destinations[0].addr.m_view_public_key;
+ return addr.m_view_public_key;
}
//---------------------------------------------------------------
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, bool bulletproof, rct::multisig_out *msout)
@@ -221,7 +225,7 @@ namespace cryptonote
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
{
LOG_PRINT_L2("Encrypting payment id " << payment_id);
- crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys);
+ crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr);
if (view_key_pub == null_pkey)
{
LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids");
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index e3b7a4f8c..1c390078d 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -88,7 +88,7 @@ namespace cryptonote
};
//---------------------------------------------------------------
- crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys);
+ crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr);
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, bool bulletproof = false, rct::multisig_out *msout = NULL);
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, bool bulletproof = false, rct::multisig_out *msout = NULL);
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index e75584bce..762feb5ee 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -102,7 +102,7 @@ namespace cryptonote
}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
- tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs)
+ tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_txpool_max_size(DEFAULT_TXPOOL_MAX_SIZE), m_txpool_size(0)
{
}
@@ -151,13 +151,20 @@ namespace cryptonote
}
uint64_t outputs_amount = get_outs_money_amount(tx);
- if(outputs_amount >= inputs_amount)
+ if(outputs_amount > inputs_amount)
{
LOG_PRINT_L1("transaction use more money then it has: use " << print_money(outputs_amount) << ", have " << print_money(inputs_amount));
tvc.m_verifivation_failed = true;
tvc.m_overspend = true;
return false;
}
+ else if(outputs_amount == inputs_amount)
+ {
+ LOG_PRINT_L1("transaction fee is zero: outputs_amount == inputs_amount, rejecting.");
+ tvc.m_verifivation_failed = true;
+ tvc.m_fee_too_low = true;
+ return false;
+ }
fee = inputs_amount - outputs_amount;
}
@@ -174,7 +181,7 @@ namespace cryptonote
}
size_t tx_size_limit = get_transaction_size_limit(version);
- if (!kept_by_block && blob_size >= tx_size_limit)
+ if (!kept_by_block && blob_size > tx_size_limit)
{
LOG_PRINT_L1("transaction is too big: " << blob_size << " bytes, maximum size: " << tx_size_limit);
tvc.m_verifivation_failed = true;
@@ -295,8 +302,12 @@ namespace cryptonote
}
tvc.m_verifivation_failed = false;
+ m_txpool_size += blob_size;
MINFO("Transaction added to pool: txid " << id << " bytes: " << blob_size << " fee/byte: " << (fee / (double)blob_size));
+
+ prune(m_txpool_max_size);
+
return true;
}
//---------------------------------------------------------------------------------
@@ -309,6 +320,72 @@ namespace cryptonote
return add_tx(tx, h, blob_size, tvc, keeped_by_block, relayed, do_not_relay, version);
}
//---------------------------------------------------------------------------------
+ size_t tx_memory_pool::get_txpool_size() const
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ return m_txpool_size;
+ }
+ //---------------------------------------------------------------------------------
+ void tx_memory_pool::set_txpool_max_size(size_t bytes)
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ m_txpool_max_size = bytes;
+ }
+ //---------------------------------------------------------------------------------
+ void tx_memory_pool::prune(size_t bytes)
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ if (bytes == 0)
+ bytes = m_txpool_max_size;
+ CRITICAL_REGION_LOCAL1(m_blockchain);
+ LockedTXN lock(m_blockchain);
+
+ // this will never remove the first one, but we don't care
+ auto it = --m_txs_by_fee_and_receive_time.end();
+ while (it != m_txs_by_fee_and_receive_time.begin())
+ {
+ if (m_txpool_size <= bytes)
+ break;
+ try
+ {
+ const crypto::hash &txid = it->second;
+ txpool_tx_meta_t meta;
+ if (!m_blockchain.get_txpool_tx_meta(txid, meta))
+ {
+ MERROR("Failed to find tx in txpool");
+ return;
+ }
+ // don't prune the kept_by_block ones, they're likely added because we're adding a block with those
+ if (meta.kept_by_block)
+ {
+ --it;
+ continue;
+ }
+ cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
+ cryptonote::transaction tx;
+ if (!parse_and_validate_tx_from_blob(txblob, tx))
+ {
+ MERROR("Failed to parse tx from txpool");
+ return;
+ }
+ // remove first, in case this throws, so key images aren't removed
+ MINFO("Pruning tx " << txid << " from txpool: size: " << it->first.second << ", fee/byte: " << it->first.first);
+ m_blockchain.remove_txpool_tx(txid);
+ m_txpool_size -= txblob.size();
+ remove_transaction_keyimages(tx);
+ MINFO("Pruned tx " << txid << " from txpool: size: " << it->first.second << ", fee/byte: " << it->first.first);
+ m_txs_by_fee_and_receive_time.erase(it--);
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Error while pruning txpool: " << e.what());
+ return;
+ }
+ }
+ if (m_txpool_size > bytes)
+ MINFO("Pool size after pruning is larger than limit: " << m_txpool_size << "/" << bytes);
+ }
+ //---------------------------------------------------------------------------------
bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block)
{
for(const auto& in: tx.vin)
@@ -391,6 +468,7 @@ namespace cryptonote
// remove first, in case this throws, so key images aren't removed
m_blockchain.remove_txpool_tx(id);
+ m_txpool_size -= blob_size;
remove_transaction_keyimages(tx);
}
catch (const std::exception &e)
@@ -463,6 +541,7 @@ namespace cryptonote
{
// remove first, so we only remove key images if the tx removal succeeds
m_blockchain.remove_txpool_tx(txid);
+ m_txpool_size -= bd.size();
remove_transaction_keyimages(tx);
}
}
@@ -1125,8 +1204,10 @@ namespace cryptonote
size_t tx_size_limit = get_transaction_size_limit(version);
std::unordered_set<crypto::hash> remove;
+ m_txpool_size = 0;
m_blockchain.for_all_txpool_txes([this, &remove, tx_size_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
- if (meta.blob_size >= tx_size_limit) {
+ m_txpool_size += meta.blob_size;
+ if (meta.blob_size > tx_size_limit) {
LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.blob_size << " bytes), removing it from pool");
remove.insert(txid);
}
@@ -1154,6 +1235,7 @@ namespace cryptonote
}
// remove tx from db first
m_blockchain.remove_txpool_tx(txid);
+ m_txpool_size -= txblob.size();
remove_transaction_keyimages(tx);
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
@@ -1176,13 +1258,15 @@ namespace cryptonote
return n_removed;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::init()
+ bool tx_memory_pool::init(size_t max_txpool_size)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
+ m_txpool_max_size = max_txpool_size ? max_txpool_size : DEFAULT_TXPOOL_MAX_SIZE;
m_txs_by_fee_and_receive_time.clear();
m_spent_key_images.clear();
+ m_txpool_size = 0;
std::vector<crypto::hash> remove;
bool r = m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) {
cryptonote::transaction tx;
@@ -1197,6 +1281,7 @@ namespace cryptonote
return false;
}
m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.blob_size, meta.receive_time), txid);
+ m_txpool_size += meta.blob_size;
return true;
}, true);
if (!r)
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index b4ea5a8f4..19cd83ed9 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -198,11 +198,11 @@ namespace cryptonote
/**
* @brief loads pool state (if any) from disk, and initializes pool
*
- * @param config_folder folder name where pool state will be
+ * @param max_txpool_size the max size in bytes
*
* @return true
*/
- bool init();
+ bool init(size_t max_txpool_size = 0);
/**
* @brief attempts to save the transaction pool state to disk
@@ -362,6 +362,19 @@ namespace cryptonote
*/
size_t validate(uint8_t version);
+ /**
+ * @brief get the cumulative txpool size in bytes
+ *
+ * @return the cumulative txpool size in bytes
+ */
+ size_t get_txpool_size() const;
+
+ /**
+ * @brief set the max cumulative txpool size in bytes
+ *
+ * @param bytes the max cumulative txpool size in bytes
+ */
+ void set_txpool_max_size(size_t bytes);
#define CURRENT_MEMPOOL_ARCHIVE_VER 11
#define CURRENT_MEMPOOL_TX_DETAILS_ARCHIVE_VER 12
@@ -496,6 +509,13 @@ namespace cryptonote
*/
void mark_double_spend(const transaction &tx);
+ /**
+ * @brief prune lowest fee/byte txes till we're not above bytes
+ *
+ * if bytes is 0, use m_txpool_max_size
+ */
+ void prune(size_t bytes = 0);
+
//TODO: confirm the below comments and investigate whether or not this
// is the desired behavior
//! map key images to transactions which spent them
@@ -542,6 +562,9 @@ private:
std::unordered_set<crypto::hash> m_timed_out_transactions;
Blockchain& m_blockchain; //!< reference to the Blockchain object
+
+ size_t m_txpool_max_size;
+ size_t m_txpool_size;
};
}