diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 32f5a43..1796f6e 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1499,6 +1499,14 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl // check for treasury payouts const uint64_t height = boost::get(b.miner_tx.vin[0]).height; + bool has_active_stakes = false; + if (height > 0) + { + cryptonote::yield_block_info previous_ybi{}; + const int result = m_db->get_yield_block_info(height - 1, previous_ybi); + CHECK_AND_ASSERT_MES(result == 0, false, "Failed to get previous yield block info"); + has_active_stakes = previous_ybi.locked_coins_tally > 0; + } const auto treasury_payout_data = get_config(m_nettype).TREASURY_SAL1_MINT_OUTPUT_DATA; const bool treasury_payout_exists = (treasury_payout_data.count(height) == 1); size_t treasury_index_in_tx_outputs = 0; @@ -1540,8 +1548,10 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt"); money_in_use += b.miner_tx.amount_burnt; } - if (already_generated_coins != 0) + if (already_generated_coins != 0 && has_active_stakes) CHECK_AND_ASSERT_MES(money_in_use / 5 == b.miner_tx.amount_burnt, false, "miner_transaction has incorrect amount_burnt amount"); + if (already_generated_coins != 0 && !has_active_stakes) + CHECK_AND_ASSERT_MES(b.miner_tx.amount_burnt == 0, false, "miner_transaction must not burn reward before staking is active"); break; default: assert(false); @@ -2301,7 +2311,15 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, //make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight uint8_t hf_version = b.major_version; size_t max_outs = hf_version >= 4 ? 1 : 11; - bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, m_nettype, m_hardfork->get_hardforks(), ex_nonce, max_outs, hf_version); + bool has_active_stakes = false; + if (height > 0) + { + cryptonote::yield_block_info previous_ybi{}; + const int result = m_db->get_yield_block_info(height - 1, previous_ybi); + CHECK_AND_ASSERT_MES(result == 0, false, "Failed to get previous yield block info"); + has_active_stakes = previous_ybi.locked_coins_tally > 0; + } + bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, m_nettype, m_hardfork->get_hardforks(), ex_nonce, max_outs, hf_version, has_active_stakes); CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance"); size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx); #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) @@ -2310,7 +2328,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, #endif for (size_t try_count = 0; try_count != 10; ++try_count) { - r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, m_nettype, m_hardfork->get_hardforks(), ex_nonce, max_outs, hf_version); + r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, m_nettype, m_hardfork->get_hardforks(), ex_nonce, max_outs, hf_version, has_active_stakes); CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance"); size_t coinbase_weight = get_transaction_weight(b.miner_tx); diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index f5fb0a7..504280b 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -459,7 +459,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype, const std::vector& hardforks, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) { + bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype, const std::vector& hardforks, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version, bool has_active_stakes) { // Clear the TX contents tx.set_null(); @@ -587,26 +587,28 @@ namespace cryptonote // Should we award some of the block reward to the stakers? if (height != 0) { - // Different forks take a different proportion of the block_reward for stakers - switch (hard_fork_version) { - case HF_VERSION_BULLETPROOF_PLUS: - case HF_VERSION_ENABLE_N_OUTS: - case HF_VERSION_FULL_PROOFS: - case HF_VERSION_ENFORCE_FULL_PROOFS: - case HF_VERSION_SHUTDOWN_USER_TXS: - case HF_VERSION_SALVIUM_ONE_PROOFS: - case HF_VERSION_AUDIT1_PAUSE: - case HF_VERSION_AUDIT2: - case HF_VERSION_AUDIT2_PAUSE: - case HF_VERSION_CARROT: - case HF_VERSION_ENABLE_TOKENS: - // SRCG: subtract 20% that will be rewarded to staking users - CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero"); - tx.amount_burnt = amount / 5; - amount -= tx.amount_burnt; - break; - default: - assert(false); + if (has_active_stakes) { + // Different forks take a different proportion of the block_reward for stakers + switch (hard_fork_version) { + case HF_VERSION_BULLETPROOF_PLUS: + case HF_VERSION_ENABLE_N_OUTS: + case HF_VERSION_FULL_PROOFS: + case HF_VERSION_ENFORCE_FULL_PROOFS: + case HF_VERSION_SHUTDOWN_USER_TXS: + case HF_VERSION_SALVIUM_ONE_PROOFS: + case HF_VERSION_AUDIT1_PAUSE: + case HF_VERSION_AUDIT2: + case HF_VERSION_AUDIT2_PAUSE: + case HF_VERSION_CARROT: + case HF_VERSION_ENABLE_TOKENS: + // Subtract 20% that will be rewarded to staking users. + CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero"); + tx.amount_burnt = amount / 5; + amount -= tx.amount_burnt; + break; + default: + assert(false); + } } tx_out out; diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index 7fff2fd..c27d761 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -77,7 +77,7 @@ namespace cryptonote //--------------------------------------------------------------- bool construct_protocol_tx(const size_t height, transaction& tx, std::vector& protocol_data, const uint8_t hf_version); //--------------------------------------------------------------- - bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype = network_type::FAKECHAIN, const std::vector& hardforks = {}, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1); + bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype = network_type::FAKECHAIN, const std::vector& hardforks = {}, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1, bool has_active_stakes = false); struct tx_source_entry {