From 899a908409a8272942b5a2f3fac35b025d25bd28 Mon Sep 17 00:00:00 2001 From: SChernykh <15806605+SChernykh@users.noreply.github.com> Date: Tue, 14 May 2024 22:48:59 +0200 Subject: [PATCH] Added hardfork code --- src/block_template.cpp | 39 ++++++++++++---- src/p2p_server.cpp | 5 +- src/pool_block.cpp | 37 +++++++++++---- src/pool_block.h | 5 ++ src/pool_block_parser.inl | 75 +++++++++++++++++++----------- src/side_chain.cpp | 7 ++- tests/src/block_template_tests.cpp | 2 +- tests/src/pool_block_tests.cpp | 4 +- 8 files changed, 121 insertions(+), 53 deletions(-) diff --git a/src/block_template.cpp b/src/block_template.cpp index 6f614bd..259d0b8 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -411,9 +411,15 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const }; uint64_t max_reward_amounts_weight = get_reward_amounts_weight(); - m_poolBlockTemplate->m_merkleTreeData = PoolBlock::encode_merkle_tree_data(static_cast(data.aux_chains.size() + 1), data.aux_nonce); - m_poolBlockTemplate->m_merkleTreeDataSize = 0; - writeVarint(m_poolBlockTemplate->m_merkleTreeData, [this](uint8_t) { ++m_poolBlockTemplate->m_merkleTreeDataSize; }); + if (m_poolBlockTemplate->merge_mining_enabled()) { + m_poolBlockTemplate->m_merkleTreeData = PoolBlock::encode_merkle_tree_data(static_cast(data.aux_chains.size() + 1), data.aux_nonce); + m_poolBlockTemplate->m_merkleTreeDataSize = 0; + writeVarint(m_poolBlockTemplate->m_merkleTreeData, [this](uint8_t) { ++m_poolBlockTemplate->m_merkleTreeDataSize; }); + } + else { + m_poolBlockTemplate->m_merkleTreeData = 0; + m_poolBlockTemplate->m_merkleTreeDataSize = 0; + } if (create_miner_tx(data, m_shares, max_reward_amounts_weight, true) < 0) { use_old_template(); @@ -705,7 +711,10 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const } if (pool_block_debug()) { - const size_t merkle_root_offset = m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize; + const size_t merkle_root_offset = + m_poolBlockTemplate->merge_mining_enabled() + ? (m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize) + : (m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2); memcpy(m_blockTemplateBlob.data() + merkle_root_offset, m_poolBlockTemplate->m_merkleRoot.h, HASH_SIZE); memcpy(m_fullDataBlob.data() + merkle_root_offset, m_poolBlockTemplate->m_merkleRoot.h, HASH_SIZE); @@ -945,9 +954,16 @@ int BlockTemplate::create_miner_tx(const MinerData& data, const std::vectorm_extraNonceSize = corrected_extra_nonce_size; m_minerTxExtra.push_back(TX_EXTRA_MERGE_MINING_TAG); - m_minerTxExtra.push_back(static_cast(m_poolBlockTemplate->m_merkleTreeDataSize + HASH_SIZE)); - writeVarint(m_poolBlockTemplate->m_merkleTreeData, m_minerTxExtra); - m_minerTxExtra.insert(m_minerTxExtra.end(), HASH_SIZE, 0); + + if (!m_poolBlockTemplate->merge_mining_enabled()) { + m_minerTxExtra.push_back(HASH_SIZE); + m_minerTxExtra.insert(m_minerTxExtra.end(), HASH_SIZE, 0); + } + else { + m_minerTxExtra.push_back(static_cast(m_poolBlockTemplate->m_merkleTreeDataSize + HASH_SIZE)); + writeVarint(m_poolBlockTemplate->m_merkleTreeData, m_minerTxExtra); + m_minerTxExtra.insert(m_minerTxExtra.end(), HASH_SIZE, 0); + } // TX_EXTRA end writeVarint(m_minerTxExtra.size(), m_minerTx); @@ -1037,7 +1053,10 @@ hash BlockTemplate::calc_miner_tx_hash(uint32_t extra_nonce) const const uint32_t aux_slot = get_aux_slot(m_sidechain->consensus_hash(), m_poolBlockTemplate->m_auxNonce, n_aux_chains); merge_mining_root = get_root_from_proof(sidechain_id, m_poolBlockTemplate->m_merkleProof, aux_slot, n_aux_chains); } - const size_t merkle_root_offset = extra_nonce_offset + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize; + + const size_t merkle_root_offset = m_poolBlockTemplate->merge_mining_enabled() + ? (extra_nonce_offset + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize) + : (extra_nonce_offset + m_poolBlockTemplate->m_extraNonceSize + 2); // 1. Prefix (everything except vin_rct_type byte in the end) // Apply extra_nonce in-place because we can't write to the block template here @@ -1374,7 +1393,9 @@ std::vector BlockTemplate::get_block_template_blob(uint32_t template_id const uint32_t aux_slot = get_aux_slot(m_sidechain->consensus_hash(), m_poolBlockTemplate->m_auxNonce, n_aux_chains); merge_mining_root = get_root_from_proof(sidechain_id, m_poolBlockTemplate->m_merkleProof, aux_slot, n_aux_chains); - merkle_root_offset = m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize; + merkle_root_offset = m_poolBlockTemplate->merge_mining_enabled() + ? (m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize) + : (m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2); *pThis = this; diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index a8c1a0b..bf6d9be 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -804,7 +804,10 @@ void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent) writeVarint(total_reward, data->pruned_blob); writeVarint(outputs_blob_size, data->pruned_blob); - data->pruned_blob.insert(data->pruned_blob.end(), block.m_sidechainId.h, block.m_sidechainId.h + HASH_SIZE); + + if (block.merge_mining_enabled()) { + data->pruned_blob.insert(data->pruned_blob.end(), block.m_sidechainId.h, block.m_sidechainId.h + HASH_SIZE); + } data->pruned_blob.insert(data->pruned_blob.end(), mainchain_data.begin() + outputs_offset + outputs_blob_size, mainchain_data.end()); diff --git a/src/pool_block.cpp b/src/pool_block.cpp index bcdb8c8..a2d6bff 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -201,10 +201,18 @@ std::vector PoolBlock::serialize_mainchain_data(size_t* header_size, si } *(p++) = TX_EXTRA_MERGE_MINING_TAG; - *(p++) = static_cast(m_merkleTreeDataSize + HASH_SIZE); - writeVarint(m_merkleTreeData, [&p](const uint8_t b) { *(p++) = b; }); - memcpy(p, m_merkleRoot.h, HASH_SIZE); - p += HASH_SIZE; + + if (!merge_mining_enabled()) { + *(p++) = HASH_SIZE; + memcpy(p, m_sidechainId.h, HASH_SIZE); + p += HASH_SIZE; + } + else { + *(p++) = static_cast(m_merkleTreeDataSize + HASH_SIZE); + writeVarint(m_merkleTreeData, [&p](const uint8_t b) { *(p++) = b; }); + memcpy(p, m_merkleRoot.h, HASH_SIZE); + p += HASH_SIZE; + } writeVarint(static_cast(p - tx_extra), data); data.insert(data.end(), tx_extra, p); @@ -257,12 +265,14 @@ std::vector PoolBlock::serialize_sidechain_data() const writeVarint(m_cumulativeDifficulty.lo, data); writeVarint(m_cumulativeDifficulty.hi, data); - const uint8_t n = static_cast(m_merkleProof.size()); - data.push_back(n); + if (merge_mining_enabled()) { + const uint8_t n = static_cast(m_merkleProof.size()); + data.push_back(n); - for (uint8_t i = 0; i < n; ++i) { - const hash& h = m_merkleProof[i]; - data.insert(data.end(), h.h, h.h + HASH_SIZE); + for (uint8_t i = 0; i < n; ++i) { + const hash& h = m_merkleProof[i]; + data.insert(data.end(), h.h, h.h + HASH_SIZE); + } } const uint8_t* p = reinterpret_cast(m_sidechainExtraBuf); @@ -401,4 +411,13 @@ hash PoolBlock::calculate_tx_key_seed() const return result; } +bool PoolBlock::merge_mining_enabled() const +{ +#ifdef P2POOL_UNIT_TESTS + return false; +#else + return (SideChain::network_type() != NetworkType::Mainnet) || (m_timestamp >= MERGE_MINING_FORK_TIME); +#endif +} + } // namespace p2pool diff --git a/src/pool_block.h b/src/pool_block.h index ca6e90d..8322b0c 100644 --- a/src/pool_block.h +++ b/src/pool_block.h @@ -60,6 +60,9 @@ static constexpr difficulty_type MAX_CUMULATIVE_DIFFICULTY{ 13019633956666736640 // 1000 years at 1 block/second. It should be enough for any normal use. static constexpr uint64_t MAX_SIDECHAIN_HEIGHT = 31556952000ULL; +// Jul 01 2024 00:00:00 GMT+0000 +static constexpr uint64_t MERGE_MINING_FORK_TIME = 1719792000; + struct DifficultyData { FORCEINLINE DifficultyData(uint64_t t, const difficulty_type& d) : m_timestamp(t), m_cumulativeDifficulty(d) {} @@ -203,6 +206,8 @@ struct PoolBlock mm_n_aux_chains = 1U + ((k >> 3U) & ((1U << n) - 1U)); mm_nonce = static_cast(m_merkleTreeData >> (3U + n)); } + + bool merge_mining_enabled() const; }; } // namespace p2pool diff --git a/src/pool_block_parser.inl b/src/pool_block_parser.inl index 12d0afc..dd40b50 100644 --- a/src/pool_block_parser.inl +++ b/src/pool_block_parser.inl @@ -148,7 +148,9 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si outputs_blob_size = static_cast(tmp); // Required by sidechain.get_outputs_blob() to speed up repeated broadcasts from different peers - READ_BUF(m_sidechainId.h, HASH_SIZE); + if (merge_mining_enabled()) { + READ_BUF(m_sidechainId.h, HASH_SIZE); + } } // Technically some p2pool node could keep stuffing block with transactions until reward is less than 0.6 XMR @@ -186,23 +188,39 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si EXPECT_BYTE(TX_EXTRA_MERGE_MINING_TAG); - uint64_t mm_field_size; - READ_VARINT(mm_field_size); - - const uint8_t* const mm_field_begin = data; - - READ_VARINT(m_merkleTreeData); - - m_merkleTreeDataSize = static_cast(data - mm_field_begin); - + int mm_root_hash_offset; uint32_t mm_n_aux_chains, mm_nonce; - decode_merkle_tree_data(mm_n_aux_chains, mm_nonce); - const int mm_root_hash_offset = static_cast((data - data_begin) + outputs_blob_size_diff); - READ_BUF(m_merkleRoot.h, HASH_SIZE); + if (!merge_mining_enabled()) { + EXPECT_BYTE(HASH_SIZE); - if (static_cast(data - mm_field_begin) != mm_field_size) { - return __LINE__; + mm_root_hash_offset = static_cast((data - data_begin) + outputs_blob_size_diff); + READ_BUF(m_sidechainId.h, HASH_SIZE); + + mm_n_aux_chains = 1; + mm_nonce = 0; + + m_merkleRoot = static_cast(m_sidechainId); + m_merkleTreeDataSize = 0; + } + else { + uint64_t mm_field_size; + READ_VARINT(mm_field_size); + + const uint8_t* const mm_field_begin = data; + + READ_VARINT(m_merkleTreeData); + + m_merkleTreeDataSize = static_cast(data - mm_field_begin); + + decode_merkle_tree_data(mm_n_aux_chains, mm_nonce); + + mm_root_hash_offset = static_cast((data - data_begin) + outputs_blob_size_diff); + READ_BUF(m_merkleRoot.h, HASH_SIZE); + + if (static_cast(data - mm_field_begin) != mm_field_size) { + return __LINE__; + } } if (static_cast(data - tx_extra_begin) != tx_extra_size) return __LINE__; @@ -340,20 +358,23 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si return __LINE__; } - uint8_t merkle_proof_size; - READ_BYTE(merkle_proof_size); - - if (merkle_proof_size > 7) { - return __LINE__; - } - m_merkleProof.clear(); - m_merkleProof.reserve(merkle_proof_size); - for (uint8_t i = 0; i < merkle_proof_size; ++i) { - hash h; - READ_BUF(h.h, HASH_SIZE); - m_merkleProof.emplace_back(h); + if (merge_mining_enabled()) { + uint8_t merkle_proof_size; + READ_BYTE(merkle_proof_size); + + if (merkle_proof_size > 8) { + return __LINE__; + } + + m_merkleProof.reserve(merkle_proof_size); + + for (uint8_t i = 0; i < merkle_proof_size; ++i) { + hash h; + READ_BUF(h.h, HASH_SIZE); + m_merkleProof.emplace_back(h); + } } READ_BUF(m_sidechainExtraBuf, sizeof(m_sidechainExtraBuf)); diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 199c077..8f422e2 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -42,7 +42,7 @@ LOG_CATEGORY(SideChain) -static constexpr uint64_t MIN_DIFFICULTY = 1000; +static constexpr uint64_t MIN_DIFFICULTY = 100000; static constexpr size_t UNCLE_BLOCK_DEPTH = 3; static_assert(1 <= UNCLE_BLOCK_DEPTH && UNCLE_BLOCK_DEPTH <= 10, "Invalid UNCLE_BLOCK_DEPTH"); @@ -63,7 +63,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name) , m_poolName(pool_name ? pool_name : "default") , m_targetBlockTime(10) , m_minDifficulty(MIN_DIFFICULTY, 0) - , m_chainWindowSize(216) + , m_chainWindowSize(2160) , m_unclePenalty(20) , m_precalcFinished(false) #ifdef DEV_TEST_SYNC @@ -103,8 +103,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name) // cppcheck-suppress uninitvar log::Stream s(buf); - s << "mm" << '\0' - << s_networkType << '\0' + s << s_networkType << '\0' << m_poolName << '\0' << m_poolPassword << '\0' << m_targetBlockTime << '\0' diff --git a/tests/src/block_template_tests.cpp b/tests/src/block_template_tests.cpp index 147a423..1d0d68f 100644 --- a/tests/src/block_template_tests.cpp +++ b/tests/src/block_template_tests.cpp @@ -26,7 +26,7 @@ namespace p2pool { -TEST(block_template, DISABLED_update) +TEST(block_template, update) { init_crypto_cache(); diff --git a/tests/src/pool_block_tests.cpp b/tests/src/pool_block_tests.cpp index efcc737..a540ef8 100644 --- a/tests/src/pool_block_tests.cpp +++ b/tests/src/pool_block_tests.cpp @@ -25,7 +25,7 @@ namespace p2pool { -TEST(pool_block, DISABLED_deserialize) +TEST(pool_block, deserialize) { init_crypto_cache(); @@ -132,7 +132,7 @@ TEST(pool_block, DISABLED_deserialize) destroy_crypto_cache(); } -TEST(pool_block, DISABLED_verify) +TEST(pool_block, verify) { init_crypto_cache();