From 02405bb8ff7f31ba424587314d85b5341b10b3b1 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Mon, 10 Oct 2022 14:27:08 +0200 Subject: [PATCH] Workaround for duplicate sidechain IDs Place transactions in the block template in random order, so two different p2pool nodes mining to the same wallet will get different sidechain IDs with high probability if there's more than 2-3 transactions in mempool. --- src/block_template.cpp | 26 +++++++++++++++++++++----- src/block_template.h | 4 ++++ 2 files changed, 25 insertions(+), 5 deletions(-) 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);