ZIP 244 hashAuthDataRoot computation

This commit is contained in:
Jack Grigg 2021-06-12 19:23:31 +01:00
parent 0b8a348c2b
commit 29ec54fad6
2 changed files with 49 additions and 0 deletions

View File

@ -10,6 +10,9 @@
#include "utilstrencodings.h"
#include "crypto/common.h"
const unsigned char ZCASH_AUTH_DATA_HASH_PERSONALIZATION[BLAKE2bPersonalBytes] =
{'Z','c','a','s','h','A','u','t','h','D','a','t','H','a','s','h'};
uint256 CBlockHeader::GetHash() const
{
return SerializeHash(*this);
@ -109,6 +112,47 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMer
return hash;
}
static uint64_t next_pow2(uint64_t x)
{
x -= 1;
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
x |= (x >> 32);
return x + 1;
}
uint256 CBlock::BuildAuthDataMerkleTree() const
{
std::vector<uint256> tree;
auto perfectSize = next_pow2(vtx.size());
tree.reserve(perfectSize * 2); // Safe upper bound for the number of total nodes.
// Add the leaves to the tree. v1-v4 transactions will append empty leaves.
for (auto &tx : vtx) {
tree.push_back(tx.GetAuthDigest());
}
// Append empty leaves until we get a perfect tree.
tree.insert(tree.end(), perfectSize - vtx.size(), uint256());
int j = 0;
for (int layerWidth = tree.size(); layerWidth > 1; layerWidth = (layerWidth + 1) / 2) {
for (int i = 0; i < layerWidth; i += 2) {
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_AUTH_DATA_HASH_PERSONALIZATION);
ss << tree[j + i];
ss << tree[j + i + 1];
tree.push_back(ss.GetHash());
}
// Move to the next layer.
j += layerWidth;
}
return (tree.empty() ? uint256() : tree.back());
}
std::string CBlock::ToString() const
{
std::stringstream s;

View File

@ -134,6 +134,11 @@ public:
std::vector<uint256> GetMerkleBranch(int nIndex) const;
static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
// Build the authorizing data Merkle tree for this block and return its
// root.
uint256 BuildAuthDataMerkleTree() const;
std::string ToString() const;
};