From 3a75a55573ca7b60f08876bb09dd0fd21b7770c5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 27 Sep 2017 18:50:31 -0700 Subject: [PATCH] Use SHA256D64 in Merkle root computation Zcash: Excluding change to `BlockWitnessMerkleRoot` as we don't have SegWit (deploying non-malleable txs via ZIP 244 instead). (cherry picked from commit bitcoin/bitcoin@1f0e7ca09c9d7c5787c218156fa5096a1bdf2ea8) --- src/bench/merkle_root.cpp | 2 +- src/consensus/merkle.cpp | 23 ++++++++++++++++++----- src/consensus/merkle.h | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp index dfd4849a5..d4b03d4fe 100644 --- a/src/bench/merkle_root.cpp +++ b/src/bench/merkle_root.cpp @@ -18,7 +18,7 @@ static void MerkleRoot(benchmark::State& state) } while (state.KeepRunning()) { bool mutation = false; - uint256 hash = ComputeMerkleRoot(leaves, &mutation); + uint256 hash = ComputeMerkleRoot(std::vector(leaves), &mutation); leaves[mutation] = hash; } } diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 7abfe1452..b9f69528d 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -126,10 +126,23 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot if (proot) *proot = h; } -uint256 ComputeMerkleRoot(const std::vector& leaves, bool* mutated) { - uint256 hash; - MerkleComputation(leaves, &hash, mutated, -1, NULL); - return hash; +uint256 ComputeMerkleRoot(std::vector hashes, bool* mutated) { + bool mutation = false; + while (hashes.size() > 1) { + if (mutated) { + for (size_t pos = 0; pos + 1 < hashes.size(); pos += 2) { + if (hashes[pos] == hashes[pos + 1]) mutation = true; + } + } + if (hashes.size() & 1) { + hashes.push_back(hashes.back()); + } + SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); + hashes.resize(hashes.size() / 2); + } + if (mutated) *mutated = mutation; + if (hashes.size() == 0) return uint256(); + return hashes[0]; } std::vector ComputeMerkleBranch(const std::vector& leaves, uint32_t position) { @@ -158,7 +171,7 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated) for (size_t s = 0; s < block.vtx.size(); s++) { leaves[s] = block.vtx[s].GetHash(); } - return ComputeMerkleRoot(leaves, mutated); + return ComputeMerkleRoot(std::move(leaves), mutated); } std::vector BlockMerkleBranch(const CBlock& block, uint32_t position) diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h index f50d60ce1..f8f2cd00f 100644 --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -12,7 +12,7 @@ #include "primitives/block.h" #include "uint256.h" -uint256 ComputeMerkleRoot(const std::vector& leaves, bool* mutated = NULL); +uint256 ComputeMerkleRoot(std::vector hashes, bool* mutated); std::vector ComputeMerkleBranch(const std::vector& leaves, uint32_t position); uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector& branch, uint32_t position);