#include <consensus/merkle.h>
#include <hash.h>
#include <util/check.h>
uint256 ComputeMerkleRoot(std::vector<uint256> 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];
}
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
{
std::vector<uint256> leaves;
leaves.resize(block.vtx.size());
for (size_t s = 0; s < block.vtx.size(); s++) {
leaves[s] = block.vtx[s]->GetHash();
}
return ComputeMerkleRoot(std::move(leaves), mutated);
}
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
{
std::vector<uint256> leaves;
leaves.resize(block.vtx.size());
leaves[0].SetNull(); for (size_t s = 1; s < block.vtx.size(); s++) {
leaves[s] = block.vtx[s]->GetWitnessHash();
}
return ComputeMerkleRoot(std::move(leaves), mutated);
}
static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t leaf_pos, std::vector<uint256>* path)
{
if (path) path->clear();
Assume(leaves.size() <= UINT32_MAX);
if (leaves.size() == 0) {
if (pmutated) *pmutated = false;
if (proot) *proot = uint256();
return;
}
bool mutated = false;
uint32_t count = 0;
uint256 inner[32];
int matchlevel = -1;
while (count < leaves.size()) {
uint256 h = leaves[count];
bool matchh = count == leaf_pos;
count++;
int level;
for (level = 0; !(count & ((uint32_t{1}) << level)); level++) {
if (path) {
if (matchh) {
path->push_back(inner[level]);
} else if (matchlevel == level) {
path->push_back(h);
matchh = true;
}
}
mutated |= (inner[level] == h);
h = Hash(inner[level], h);
}
inner[level] = h;
if (matchh) {
matchlevel = level;
}
}
int level = 0;
while (!(count & ((uint32_t{1}) << level))) {
level++;
}
uint256 h = inner[level];
bool matchh = matchlevel == level;
while (count != ((uint32_t{1}) << level)) {
if (path && matchh) {
path->push_back(h);
}
h = Hash(h, h);
count += ((uint32_t{1}) << level);
level++;
while (!(count & ((uint32_t{1}) << level))) {
if (path) {
if (matchh) {
path->push_back(inner[level]);
} else if (matchlevel == level) {
path->push_back(h);
matchh = true;
}
}
h = Hash(inner[level], h);
level++;
}
}
if (pmutated) *pmutated = mutated;
if (proot) *proot = h;
}
static std::vector<uint256> ComputeMerklePath(const std::vector<uint256>& leaves, uint32_t position) {
std::vector<uint256> ret;
MerkleComputation(leaves, nullptr, nullptr, position, &ret);
return ret;
}
std::vector<uint256> TransactionMerklePath(const CBlock& block, uint32_t position)
{
std::vector<uint256> leaves;
leaves.resize(block.vtx.size());
for (size_t s = 0; s < block.vtx.size(); s++) {
leaves[s] = block.vtx[s]->GetHash();
}
return ComputeMerklePath(leaves, position);
}