diff --git a/src/block_template.cpp b/src/block_template.cpp index d7f7a0a..a72eb96 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -278,18 +278,21 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet return; } - const uint64_t max_reward_amounts_weight = std::accumulate(m_rewards.begin(), m_rewards.end(), 0ULL, - [](uint64_t a, uint64_t b) - { - writeVarint(b, [&a](uint8_t) { ++a; }); - return a; - }); + auto get_reward_amounts_weight = [this]() { + return std::accumulate(m_rewards.begin(), m_rewards.end(), 0ULL, + [](uint64_t a, uint64_t b) + { + writeVarint(b, [&a](uint8_t) { ++a; }); + return a; + }); + }; + uint64_t max_reward_amounts_weight = get_reward_amounts_weight(); - if (!create_miner_tx(data, m_shares, max_reward_amounts_weight, true)) { + if (create_miner_tx(data, m_shares, max_reward_amounts_weight, true) < 0) { return; } - const uint64_t miner_tx_weight = m_minerTx.size(); + uint64_t miner_tx_weight = m_minerTx.size(); // Select transactions from the mempool uint64_t final_reward, final_fees, final_weight; @@ -432,8 +435,37 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, Wallet m_finalReward = final_reward; - if (!create_miner_tx(data, m_shares, max_reward_amounts_weight, false)) { - return; + const int create_miner_tx_result = create_miner_tx(data, m_shares, max_reward_amounts_weight, false); + if (create_miner_tx_result < 0) { + if (create_miner_tx_result == -3) { + // Too many extra bytes were added, refine max_reward_amounts_weight and miner_tx_weight + if (!SideChain::split_reward(base_reward + final_fees, m_shares, m_rewards)) { + return; + } + + max_reward_amounts_weight = get_reward_amounts_weight(); + + if (create_miner_tx(data, m_shares, max_reward_amounts_weight, true) < 0) { + return; + } + + final_weight -= miner_tx_weight; + final_weight += m_minerTx.size(); + miner_tx_weight = m_minerTx.size(); + + final_reward = get_block_reward(base_reward, data.median_weight, final_fees, final_weight); + + if (!SideChain::split_reward(final_reward, m_shares, m_rewards)) { + return; + } + + if (create_miner_tx(data, m_shares, max_reward_amounts_weight, false) < 0) { + return; + } + } + else { + return; + } } if (m_minerTx.size() != miner_tx_weight) { @@ -600,7 +632,7 @@ void BlockTemplate::fill_optimal_knapsack(const MinerData& data, uint64_t base_r } #endif -bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector& shares, uint64_t max_reward_amounts_weight, bool dry_run) +int BlockTemplate::create_miner_tx(const MinerData& data, const std::vector& shares, uint64_t max_reward_amounts_weight, bool dry_run) { // Miner transaction (coinbase) m_minerTx.clear(); @@ -655,12 +687,12 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector max_reward_amounts_weight) { LOGERR(1, "create_miner_tx: incorrect miner rewards during the real run (" << reward_amounts_weight << " > " << max_reward_amounts_weight << ")"); - return false; + return -2; } m_poolBlockTemplate->m_txkeyPub = m_txkeyPub; @@ -676,6 +708,10 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector EXTRA_NONCE_SIZE) { + if (corrected_extra_nonce_size > EXTRA_NONCE_MAX_SIZE) { + LOGWARN(4, "create_miner_tx: corrected_extra_nonce_size (" << corrected_extra_nonce_size << ") is too large"); + return -3; + } LOGINFO(4, "increased EXTRA_NONCE from " << EXTRA_NONCE_SIZE << " to " << corrected_extra_nonce_size << " bytes to maintain miner tx weight"); } writeVarint(corrected_extra_nonce_size, m_minerTxExtra); @@ -701,7 +737,7 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vector& shares, uint64_t max_reward_amounts_weight, bool dry_run); + int create_miner_tx(const MinerData& data, const std::vector& shares, uint64_t max_reward_amounts_weight, bool dry_run); hash calc_sidechain_hash() const; hash calc_miner_tx_hash(uint32_t extra_nonce) const; void calc_merkle_tree_main_branch(); diff --git a/src/common.h b/src/common.h index 33b9830..e6c52ba 100644 --- a/src/common.h +++ b/src/common.h @@ -85,6 +85,7 @@ constexpr uint8_t HARDFORK_SUPPORTED_VERSION = 14; constexpr uint8_t MINER_REWARD_UNLOCK_TIME = 60; constexpr uint8_t NONCE_SIZE = 4; constexpr uint8_t EXTRA_NONCE_SIZE = 4; +constexpr uint8_t EXTRA_NONCE_MAX_SIZE = EXTRA_NONCE_SIZE + 10; constexpr uint8_t TX_VERSION = 2; constexpr uint8_t TXIN_GEN = 0xFF; constexpr uint8_t TXOUT_TO_KEY = 2; diff --git a/src/pool_block_parser.inl b/src/pool_block_parser.inl index 1a326f4..ca79e49 100644 --- a/src/pool_block_parser.inl +++ b/src/pool_block_parser.inl @@ -187,7 +187,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai READ_VARINT(m_extraNonceSize); // Sanity check - if ((m_extraNonceSize < EXTRA_NONCE_SIZE) || (m_extraNonceSize > EXTRA_NONCE_SIZE + 10)) return __LINE__; + if ((m_extraNonceSize < EXTRA_NONCE_SIZE) || (m_extraNonceSize > EXTRA_NONCE_MAX_SIZE)) return __LINE__; const int extra_nonce_offset = static_cast((data - data_begin) + outputs_blob_size_diff); READ_BUF(&m_extraNonce, EXTRA_NONCE_SIZE);