From 2d1158af64c22def50775582be2265703fa1dfce Mon Sep 17 00:00:00 2001 From: SChernykh <sergey.v.chernykh@gmail.com> Date: Wed, 25 Oct 2023 15:49:25 +0200 Subject: [PATCH] Store Merkle tree root in the merge mining tag --- src/block_template.cpp | 29 ++++++++++++++++++++--------- src/pool_block.cpp | 14 +++++++++----- src/pool_block.h | 12 ++++++++++++ src/pool_block_parser.inl | 23 ++++++++--------------- 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/block_template.cpp b/src/block_template.cpp index 53f1913..860ec77 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -662,6 +662,11 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const m_poolBlockTemplate->m_extraNonce = 0; m_poolBlockTemplate->m_sidechainId = {}; + // TODO: fill in merkle tree data here + m_poolBlockTemplate->m_merkleTreeDataSize = 1; + m_poolBlockTemplate->m_merkleTreeData = 0; + m_poolBlockTemplate->m_merkleRoot = {}; + const std::vector<uint8_t> sidechain_data = m_poolBlockTemplate->serialize_sidechain_data(); const std::vector<uint8_t>& consensus_id = m_sidechain->consensus_id(); @@ -693,9 +698,13 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const m_poolBlockTemplate->m_sidechainId = calc_sidechain_hash(0); + // TODO: fill in merkle tree data here + m_poolBlockTemplate->m_merkleTreeDataSize = 1; + m_poolBlockTemplate->m_merkleTreeData = 0; + m_poolBlockTemplate->m_merkleRoot = m_poolBlockTemplate->m_sidechainId; + if (pool_block_debug()) { - // TODO: fix it, it will change depending on mm_data varint size - const size_t sidechain_hash_offset = m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 3; + const size_t sidechain_hash_offset = m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize; memcpy(m_blockTemplateBlob.data() + sidechain_hash_offset, m_poolBlockTemplate->m_sidechainId.h, HASH_SIZE); memcpy(m_fullDataBlob.data() + sidechain_hash_offset, m_poolBlockTemplate->m_sidechainId.h, HASH_SIZE); @@ -934,11 +943,9 @@ int BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<Mine m_poolBlockTemplate->m_extraNonceSize = corrected_extra_nonce_size; - // Valid for tree size = 1 (no other merge mined chains) - // TODO: insert mm_data and merkle root here m_minerTxExtra.push_back(TX_EXTRA_MERGE_MINING_TAG); - m_minerTxExtra.push_back(1 + HASH_SIZE); - m_minerTxExtra.push_back(0); + m_minerTxExtra.push_back(static_cast<uint8_t>(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 @@ -1024,8 +1031,7 @@ hash BlockTemplate::calc_miner_tx_hash(uint32_t extra_nonce) const // Calculate sidechain id with this extra_nonce const hash sidechain_id = calc_sidechain_hash(extra_nonce); - // TODO: fix it, it will change depending on mm_data varint size - const size_t sidechain_hash_offset = extra_nonce_offset + m_poolBlockTemplate->m_extraNonceSize + 3; + const size_t sidechain_hash_offset = extra_nonce_offset + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize; // 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 @@ -1291,7 +1297,7 @@ std::vector<uint8_t> BlockTemplate::get_block_template_blob(uint32_t template_id nonce_offset = m_nonceOffset; extra_nonce_offset = m_extraNonceOffsetInTemplate; - sidechain_id_offset = m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 3; + sidechain_id_offset = m_extraNonceOffsetInTemplate + m_poolBlockTemplate->m_extraNonceSize + 2 + m_poolBlockTemplate->m_merkleTreeDataSize; sidechain_id = calc_sidechain_hash(sidechain_extra_nonce); return m_blockTemplateBlob; } @@ -1306,6 +1312,11 @@ bool BlockTemplate::submit_sidechain_block(uint32_t template_id, uint32_t nonce, m_poolBlockTemplate->m_sidechainId = calc_sidechain_hash(extra_nonce); m_poolBlockTemplate->m_sidechainExtraBuf[3] = extra_nonce; + // TODO: fill in merkle tree data here + m_poolBlockTemplate->m_merkleTreeDataSize = 1; + m_poolBlockTemplate->m_merkleTreeData = 0; + m_poolBlockTemplate->m_merkleRoot = m_poolBlockTemplate->m_sidechainId; + if (pool_block_debug()) { std::vector<uint8_t> buf = m_poolBlockTemplate->serialize_mainchain_data(); const std::vector<uint8_t> sidechain_data = m_poolBlockTemplate->serialize_sidechain_data(); diff --git a/src/pool_block.cpp b/src/pool_block.cpp index f1bbf4e..83d9386 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -39,6 +39,9 @@ PoolBlock::PoolBlock() , m_txkeyPub{} , m_extraNonceSize(0) , m_extraNonce(0) + , m_merkleTreeDataSize(1) + , m_merkleTreeData(0) + , m_merkleRoot{} , m_txkeySecSeed{} , m_txkeySec{} , m_parent{} @@ -85,6 +88,9 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b) m_txkeyPub = b.m_txkeyPub; m_extraNonceSize = b.m_extraNonceSize; m_extraNonce = b.m_extraNonce; + m_merkleTreeDataSize = b.m_merkleTreeDataSize; + m_merkleTreeData = b.m_merkleTreeData; + m_merkleRoot = b.m_merkleRoot; m_transactions = b.m_transactions; m_minerWallet = b.m_minerWallet; m_txkeySecSeed = b.m_txkeySecSeed; @@ -187,12 +193,10 @@ std::vector<uint8_t> PoolBlock::serialize_mainchain_data(size_t* header_size, si p += extra_nonce_size - EXTRA_NONCE_SIZE; } - // Valid for tree size = 1 (no other merge mined chains) - // TODO: insert mm_data and merkle root here *(p++) = TX_EXTRA_MERGE_MINING_TAG; - *(p++) = 1 + HASH_SIZE; - *(p++) = 0; - memcpy(p, m_sidechainId.h, HASH_SIZE); + *(p++) = static_cast<uint8_t>(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<size_t>(p - tx_extra), data); diff --git a/src/pool_block.h b/src/pool_block.h index ec493eb..ce8ac20 100644 --- a/src/pool_block.h +++ b/src/pool_block.h @@ -101,6 +101,10 @@ struct PoolBlock uint64_t m_extraNonceSize; uint32_t m_extraNonce; + uint32_t m_merkleTreeDataSize; + uint64_t m_merkleTreeData; + hash m_merkleRoot; + // All block transaction hashes including the miner transaction hash at index 0 std::vector<hash> m_transactions; @@ -171,6 +175,14 @@ struct PoolBlock } hash calculate_tx_key_seed() const; + + FORCEINLINE void decode_merkle_tree_data(uint32_t& mm_n_aux_chains, uint32_t& mm_nonce) const + { + const uint32_t k = static_cast<uint32_t>(m_merkleTreeData); + const uint32_t n = 1U + (k & 7U); + mm_n_aux_chains = 1U + ((k >> 3U) & ((1U << n) - 1U)); + mm_nonce = static_cast<uint32_t>(m_merkleTreeData >> (3U + n)); + } }; } // namespace p2pool diff --git a/src/pool_block_parser.inl b/src/pool_block_parser.inl index 044d86f..ea3f03a 100644 --- a/src/pool_block_parser.inl +++ b/src/pool_block_parser.inl @@ -188,26 +188,19 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si uint64_t mm_field_size; READ_VARINT(mm_field_size); - const int mm_field_begin = static_cast<int>(data - data_begin); + const uint8_t* const mm_field_begin = data; - uint64_t mm_data; - READ_VARINT(mm_data); + READ_VARINT(m_merkleTreeData); - if (mm_data > std::numeric_limits<uint32_t>::max()) { - return __LINE__; - } + m_merkleTreeDataSize = static_cast<uint32_t>(data - mm_field_begin); - const uint32_t mm_n_bits = 1 + (mm_data & 7); - const uint32_t mm_n_aux_chains = 1 + ((mm_data >> 3) & ((1 << mm_n_bits) - 1)); - const uint32_t mm_nonce = static_cast<uint32_t>(mm_data >> (3 + mm_n_bits)); + 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<int>((data - data_begin) + outputs_blob_size_diff); - hash mm_root; - READ_BUF(mm_root.h, HASH_SIZE); + READ_BUF(m_merkleRoot.h, HASH_SIZE); - const int mm_field_end = static_cast<int>(data - data_begin); - - if (static_cast<uint64_t>(mm_field_end - mm_field_begin) != mm_field_size) { + if (static_cast<uint64_t>(data - mm_field_begin) != mm_field_size) { return __LINE__; } @@ -432,7 +425,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si const uint32_t mm_aux_slot = get_aux_slot(sidechain.consensus_hash(), mm_nonce, mm_n_aux_chains); - if (!verify_merkle_proof(check, m_merkleProof, mm_aux_slot, mm_n_aux_chains, mm_root)) { + if (!verify_merkle_proof(check, m_merkleProof, mm_aux_slot, mm_n_aux_chains, m_merkleRoot)) { return __LINE__; }