diff --git a/src/block_template.cpp b/src/block_template.cpp index acf5afb..e1096a0 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -54,7 +54,11 @@ BlockTemplate::BlockTemplate(p2pool* pool) , m_txkeySec{} , m_poolBlockTemplate(new PoolBlock()) , m_finalReward(0) + , m_rng(RandomDeviceSeed::instance) { + // Diffuse the initial state in case it has low quality + m_rng.discard(10000); + uv_rwlock_init_checked(&m_lock); m_blockHeader.reserve(64); @@ -133,6 +137,8 @@ BlockTemplate& BlockTemplate::operator=(const BlockTemplate& b) m_mempoolTxsOrder.clear(); m_shares.clear(); + m_rng = b.m_rng; + #if TEST_MEMPOOL_PICKING_ALGORITHM m_knapsack.clear(); #endif @@ -171,6 +177,14 @@ static FORCEINLINE uint64_t get_block_reward(uint64_t base_reward, uint64_t medi return reward + fees; } +void BlockTemplate::shuffle_tx_order() +{ + const int64_t n = static_cast(m_mempoolTxsOrder.size()); + for (int64_t i = n - 1; i > 0; --i) { + std::swap(m_mempoolTxsOrder[i], m_mempoolTxsOrder[m_rng() % (i + 1)]); + } +} + void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet* miner_wallet) { if (data.major_version > HARDFORK_SUPPORTED_VERSION) { @@ -315,16 +329,16 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet // if a block doesn't get into the penalty zone, just pick all transactions if (total_tx_weight + miner_tx_weight <= data.median_weight) { - m_numTransactionHashes = 0; - final_fees = 0; final_weight = miner_tx_weight; + shuffle_tx_order(); + + m_numTransactionHashes = m_mempoolTxsOrder.size(); m_transactionHashes.assign(HASH_SIZE, 0); - for (const TxMempoolData& tx : m_mempoolTxs) { + for (size_t i = 0; i < m_mempoolTxsOrder.size(); ++i) { + const TxMempoolData& tx = m_mempoolTxs[m_mempoolTxsOrder[i]]; m_transactionHashes.insert(m_transactionHashes.end(), tx.id.h, tx.id.h + HASH_SIZE); - ++m_numTransactionHashes; - final_fees += tx.fee; final_weight += tx.weight; } @@ -398,6 +412,8 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet final_fees = 0; final_weight = miner_tx_weight; + shuffle_tx_order(); + m_numTransactionHashes = m_mempoolTxsOrder.size(); m_transactionHashes.assign(HASH_SIZE, 0); for (size_t i = 0; i < m_mempoolTxsOrder.size(); ++i) { diff --git a/src/block_template.h b/src/block_template.h index d651330..4a13189 100644 --- a/src/block_template.h +++ b/src/block_template.h @@ -106,6 +106,10 @@ private: std::vector m_mempoolTxsOrder; std::vector m_shares; + std::mt19937_64 m_rng; + + void shuffle_tx_order(); + #if TEST_MEMPOOL_PICKING_ALGORITHM void fill_optimal_knapsack(const MinerData& data, uint64_t base_reward, uint64_t miner_tx_weight, uint64_t& best_reward, uint64_t& final_fees, uint64_t& final_weight);