diff --git a/src/block_template.cpp b/src/block_template.cpp index 34370bb..c8e6ce8 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -639,14 +639,23 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const // First, calculate and store the miner TX hash hash miner_tx_hash = calc_miner_tx_hash(0); - - // Clear and rebuild m_transactionHashes with both hashes + + // m_transactionHashes currently has: [zeros placeholder][mempool tx 0][mempool tx 1]... + // We need: [miner tx][protocol tx][mempool tx 0][mempool tx 1]... + + // Save mempool txs (everything after position 0) + std::vector mempool_txs; + if (m_transactionHashes.size() > HASH_SIZE) { + mempool_txs.assign(m_transactionHashes.begin() + HASH_SIZE, m_transactionHashes.end()); + } + + // Rebuild with correct order m_transactionHashes.clear(); - m_transactionHashes.reserve(HASH_SIZE * 2); + m_transactionHashes.reserve(HASH_SIZE * 2 + mempool_txs.size()); m_transactionHashes.insert(m_transactionHashes.end(), miner_tx_hash.h, miner_tx_hash.h + HASH_SIZE); - + LOGINFO(3, "Stored miner TX hash at position 0: " << miner_tx_hash); - + // Write protocol tx bytes to blob writeVarint(4, m_blockTemplateBlob); // version writeVarint(60, m_blockTemplateBlob); // unlock_time @@ -659,36 +668,36 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const m_blockTemplateBlob.push_back(0x00); // extra[1] writeVarint(2, m_blockTemplateBlob); // type PROTOCOL m_blockTemplateBlob.push_back(0); // RCT type - + // Calculate protocol tx hash and store in member variable calculate_protocol_tx_hash(data.height, m_protocolTxHash); LOGINFO(3, "Protocol TX hash: " << m_protocolTxHash); - - // Add to transaction list after miner tx + + // Add protocol tx hash after miner tx m_transactionHashes.insert(m_transactionHashes.end(), m_protocolTxHash.h, m_protocolTxHash.h + HASH_SIZE); + + // Add mempool txs back + if (!mempool_txs.empty()) { + m_transactionHashes.insert(m_transactionHashes.end(), mempool_txs.begin(), mempool_txs.end()); + } // Now write tx_hashes section // For HF10+, blob tx_count excludes protocol tx (it's implicit like miner tx) - const uint64_t blob_tx_count = (data.major_version >= 10) ? (m_numTransactionHashes >= 2 ? m_numTransactionHashes - 2 : 0) : m_numTransactionHashes; + const uint64_t blob_tx_count = m_numTransactionHashes; writeVarint(blob_tx_count, m_blockTemplateBlob); // Miner tx hash is skipped here because it's not a part of block template m_blockTemplateBlob.insert(m_blockTemplateBlob.end(), m_transactionHashes.begin() + HASH_SIZE * 2, m_transactionHashes.end()); + // Build m_transactions directly from m_transactionHashes to ensure they match m_poolBlockTemplate->m_transactions.clear(); - m_poolBlockTemplate->m_transactions.resize(1); - m_poolBlockTemplate->m_transactions.reserve(m_mempoolTxsOrder.size() + 1); - for (size_t i = 0, n = m_mempoolTxsOrder.size(); i < n; ++i) { - m_poolBlockTemplate->m_transactions.push_back(m_mempoolTxs[m_mempoolTxsOrder[i]].id); - } - - // For Carrot v1 blocks, insert protocol TX at position 1 - if (m_poolBlockTemplate->m_majorVersion >= 10) { - hash protocol_tx_hash; - calculate_protocol_tx_hash(m_poolBlockTemplate->m_txinGenHeight, protocol_tx_hash); - m_poolBlockTemplate->m_transactions.insert( - m_poolBlockTemplate->m_transactions.begin() + 1, - static_cast(protocol_tx_hash)); + m_poolBlockTemplate->m_transactions.resize(1); // Placeholder for coinbase at [0] + // m_transactionHashes layout: [miner_tx][protocol_tx][mempool_tx_0][mempool_tx_1]... + // Copy protocol_tx and all mempool txs (skip miner_tx at position 0) + for (size_t i = HASH_SIZE; i < m_transactionHashes.size(); i += HASH_SIZE) { + hash h; + memcpy(h.h, m_transactionHashes.data() + i, HASH_SIZE); + m_poolBlockTemplate->m_transactions.push_back(static_cast(h)); } m_poolBlockTemplate->m_minerWallet = params->m_miningWallet; @@ -849,7 +858,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const m_minerTx.clear(); m_blockHeader.clear(); m_minerTxExtra.clear(); - m_transactionHashes.clear(); + // m_transactionHashes.clear(); m_transactionHashesSet.clear(); m_rewards.clear(); m_mempoolTxs.clear(); @@ -1562,49 +1571,24 @@ uint32_t BlockTemplate::get_hashing_blob_nolock(uint32_t extra_nonce, uint8_t* b // Block header memcpy(p, m_blockTemplateBlob.data(), m_blockHeaderSize); p += m_blockHeaderSize; + + // Merkle tree hash - build from all transactions and use merkle_hash() + hash miner_tx_hash = calc_miner_tx_hash(extra_nonce); + const size_t num_hashes = m_transactionHashes.size() / HASH_SIZE; - // Merkle tree hash - hash root_hash = calc_miner_tx_hash(extra_nonce); - - // For Carrot v1 (HF10+) with protocol TX, simple 2-transaction merkle tree - if (m_majorVersion >= 10) { - // Just hash miner TX hash + protocol TX hash - uint8_t merkle_data[HASH_SIZE * 2]; - memcpy(merkle_data, root_hash.h, HASH_SIZE); - // Protocol TX hash is the first (and only) entry in transaction hashes after miner TX - memcpy(merkle_data + HASH_SIZE, m_protocolTxHash.h, HASH_SIZE); - - // DEBUG: Show what we're actually hashing - LOGINFO(6, "DEBUG: About to hash merkle data (raw bytes):"); - LOGINFO(6, " Full 64 bytes: " << log::hex_buf(merkle_data, HASH_SIZE * 2)); - - LOGINFO(6, " First 32 bytes (miner): " << log::hex_buf(merkle_data, HASH_SIZE)); - LOGINFO(6, " Second 32 bytes (protocol): " << log::hex_buf(merkle_data + HASH_SIZE, HASH_SIZE)); - LOGINFO(6, " m_transactionHashes size: " << m_transactionHashes.size()); - - keccak(merkle_data, HASH_SIZE * 2, root_hash.h); - - // DEBUG: Verify the result - LOGINFO(6, " Result merkle root: " << log::hex_buf(root_hash.h, HASH_SIZE)); - - // DEBUG: Manually verify by re-hashing - hash verify_hash; - keccak(merkle_data, HASH_SIZE * 2, verify_hash.h); - LOGINFO(6, " Verify merkle root: " << log::hex_buf(verify_hash.h, HASH_SIZE)); - - } else { - // Pre-Carrot: use merkle branch logic - for (size_t i = 0; i < m_merkleTreeMainBranch.size(); i += HASH_SIZE) { - uint8_t h[HASH_SIZE * 2]; - memcpy(h, root_hash.h, HASH_SIZE); - memcpy(h + HASH_SIZE, m_merkleTreeMainBranch.data() + i, HASH_SIZE); - keccak(h, HASH_SIZE * 2, root_hash.h); - } + std::vector hashes(num_hashes); + hashes[0] = miner_tx_hash; // miner tx with current extra_nonce + for (size_t i = 1; i < num_hashes; ++i) { + memcpy(hashes[i].h, m_transactionHashes.data() + i * HASH_SIZE, HASH_SIZE); } + root_hash merkle_root; + merkle_hash(hashes, merkle_root); - memcpy(p, root_hash.h, HASH_SIZE); + LOGINFO(6, " m_transactionHashes size: " << m_transactionHashes.size() << " num_hashes: " << num_hashes); + LOGINFO(6, " Result merkle root: " << static_cast(merkle_root)); + memcpy(p, merkle_root.h, HASH_SIZE); p += HASH_SIZE; - + // Total number of transactions in this block (including the miner tx) // FOR HF10+, include both miner tx and protocol tx const uint64_t tx_count_in_header = m_numTransactionHashes + (m_majorVersion >= 10 ? 2 : 1); diff --git a/src/p2pool.cpp b/src/p2pool.cpp index 6863cde..51c4945 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -556,7 +556,7 @@ void p2pool::get_missing_heights() m_missingHeights.pop_back(); } - LOGWARN(3, "Mainchain data for height " << h << " is missing, requesting it from monerod again"); + LOGWARN(3, "Mainchain data for height " << h << " is missing, requesting it from salviumd again"); char buf[log::Stream::BUF_SIZE + 1] = {}; log::Stream s(buf); @@ -1644,7 +1644,7 @@ void p2pool::parse_get_info_rpc(const char* data, size_t size) } if (info.busy_syncing || !info.synchronized) { - LOGINFO(1, "monerod is " << (info.busy_syncing ? "busy syncing" : "not synchronized") << ", trying again in 1 second"); + LOGINFO(1, "salviumd is " << (info.busy_syncing ? "busy syncing" : "not synchronized") << ", trying again in 1 second"); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); switch_host(); get_info(); @@ -1660,7 +1660,7 @@ void p2pool::parse_get_info_rpc(const char* data, size_t size) const NetworkType sidechain_network = m_sideChain->network_type(); if (monero_network != sidechain_network) { - LOGERR(1, "monerod is on " << monero_network << ", but you're mining to a " << sidechain_network << " sidechain"); + LOGERR(1, "salviumd is on " << monero_network << ", but you're mining to a " << sidechain_network << " sidechain"); PANIC_STOP(); } @@ -1732,7 +1732,7 @@ void p2pool::parse_get_version_rpc(const char* data, size_t size) const uint64_t version_lo = version & 65535; const uint64_t required_version_hi = required >> 16; const uint64_t required_version_lo = required & 65535; - LOGERR(1, "monerod RPC v" << version_hi << '.' << version_lo << " is incompatible, update to RPC >= v" << required_version_hi << '.' << required_version_lo << " (Monero v0.18.0.0 or newer)"); + LOGERR(1, "salviumd RPC v" << version_hi << '.' << version_lo << " is incompatible, update to RPC >= v" << required_version_hi << '.' << required_version_lo << " (Monero v0.18.0.0 or newer)"); PANIC_STOP(); } diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 4519d10..e95de83 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -650,7 +650,7 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector& missing_ } } - LOGINFO(0, "DEBUG PoW check: sidechainHeight=" << block.m_sidechainHeight << " m_difficulty=" << block.m_difficulty << " m_powHash=" << block.m_powHash); + LOGINFO(0, "DEBUG PoW check: sidechainHeight=" << block.m_sidechainHeight << " m_difficulty.lo=" << block.m_difficulty.lo << " m_difficulty.hi=" << block.m_difficulty.hi << " m_powHash=" << block.m_powHash); if (!block.m_difficulty.check_pow(block.m_powHash)) { LOGWARN(3,