diff --git a/src/node/sv2_messages.cpp b/src/node/sv2_messages.cpp index 9f400d85c3ff9..34fb93a112e0a 100644 --- a/src/node/sv2_messages.cpp +++ b/src/node/sv2_messages.cpp @@ -3,6 +3,61 @@ #include #include #include +#include +#include +#include +#include + +uint256 HashTwoTxIDs(const uint256& txid1, const uint256& txid2) { + CHashWriter hasher(SER_GETHASH, 0); + hasher << txid1 << txid2; + return hasher.GetHash(); +} +std::vector GetMerklePathForCoinbase(const CBlock& block) { + auto size = block.vtx.size(); + // If we have only the coinbase tx, we don't have a merkle path + if (size == 1) { + return {}; + // If we have coinbase tx and another tx the path is the second node id + } else if (size == 2) { + std::vector path; + path.push_back(block.vtx[1]->GetHash()); + return path; + // Otherwise we calculate the merkle path + } else { + std::deque id_list; + for (const auto& tx : block.vtx) { + id_list.push_back(tx->GetHash()); + } + // Last id must be dublicated when txs are odds + if (size % 2 == 1) { + id_list.push_back(block.vtx[size - 1]->GetHash()); + } + + // Remove coinbase + id_list.pop_front(); + + std::vector path; + + // First path element is always the second tx + path.push_back(id_list.front()); + id_list.pop_front(); + + while (!id_list.empty()) { + for (size_t i = 0; i < id_list.size() / 2; ++i) { + id_list[i] = HashTwoTxIDs(id_list[i * 2], id_list[i * 2 + 1]); + } + id_list.resize(id_list.size()/2); + path.push_back(id_list.front()); + id_list.pop_front(); + if (id_list.size() % 2 == 1) { + id_list.push_back(id_list[id_list.size() - 1]); + } + } + + return path; + } +} node::Sv2NewTemplateMsg::Sv2NewTemplateMsg(const CBlock& block, uint64_t template_id, bool future_template) : m_template_id{template_id}, m_future_template{future_template} @@ -28,11 +83,16 @@ node::Sv2NewTemplateMsg::Sv2NewTemplateMsg(const CBlock& block, uint64_t templat m_coinbase_tx_locktime = coinbase_tx->nLockTime; - // Skip the coinbase_tx hash from the merkle path since the downstream client - // will build their own coinbase tx. - for (auto it = block.vtx.begin() + 1; it != block.vtx.end(); ++it) { - m_merkle_path.push_back((*it)->GetHash()); + std::vector merklepath = GetMerklePathForCoinbase(block); + + for (const auto& hash : merklepath) { + m_merkle_path.push_back(hash); } + + //for (auto it = block.vtx.begin() + 1; it != block.vtx.end(); ++it) { + // m_merkle_path.push_back((*it)->GetHash()); + //} + } node::Sv2SetNewPrevHashMsg::Sv2SetNewPrevHashMsg(const CBlock& block, uint64_t template_id) : m_template_id{template_id} @@ -42,3 +102,4 @@ node::Sv2SetNewPrevHashMsg::Sv2SetNewPrevHashMsg(const CBlock& block, uint64_t t m_nBits = block.nBits; m_target = ArithToUint256(arith_uint256().SetCompact(block.nBits)); } +