6#ifndef VERIBLOCK_MERKLE_TREE_H_
7#define VERIBLOCK_MERKLE_TREE_H_
11#include <unordered_map>
13#include <veriblock/pop/arith_uint256.hpp>
14#include <veriblock/pop/entities/atv.hpp>
15#include <veriblock/pop/entities/merkle_path.hpp>
20template <
typename Specific,
typename TxHash>
22 using hash_t = TxHash;
24 MerkleTree(Specific& instance,
const std::vector<hash_t>& hashes)
25 : instance(instance) {
27 for (int32_t i = 0, size =
static_cast<int32_t
>(hashes.size()); i < size;
29 hash_indices[hashes[i]] = i;
33 std::vector<hash_t> getMerklePathLayers(
const hash_t& hash)
const {
34 auto it = hash_indices.find(hash);
35 VBK_ASSERT(it != hash_indices.end());
36 size_t index = it->second;
37 return getMerklePathLayers(index);
40 std::vector<hash_t> getMerklePathLayers(
size_t index)
const {
41 VBK_ASSERT(!layers.empty());
42 auto& leafs = layers[0];
43 if (leafs.size() == 1) {
44 VBK_ASSERT(layers.size() == 1);
48 VBK_ASSERT(index < leafs.size());
49 std::vector<hash_t> merklePath{};
50 for (
size_t i = 0, size = layers.size(); i < (size - 1); ++i) {
51 auto& layer = layers[i];
53 if (layer.size() == index + 1) {
54 merklePath.push_back(layer[index]);
56 merklePath.push_back(layer[index + 1]);
59 merklePath.push_back(layer[index - 1]);
68 hash_t getMerkleRoot()
const {
73 auto& root = layers.back();
74 VBK_ASSERT(root.size() == 1);
78 const std::vector<std::vector<hash_t>>& getLayers()
const {
return layers; }
80 const std::unordered_map<hash_t, int32_t>& getHashIndices()
const {
85 void buildTree(std::vector<hash_t> layer) {
86 size_t n = layer.size();
95 layers.push_back(layer);
97 layer.resize(n % 2 == 0 ? n : n + 1);
100 layer[n] = layer[n - 1];
104 for (
size_t i = 0; i < n; i++) {
105 layer[i] = instance.hash(layer[2 * i], layer[2 * i + 1]);
107 layers.push_back({layer.begin(), layer.begin() + n});
112 std::vector<std::vector<hash_t>> layers;
113 std::unordered_map<hash_t, int32_t> hash_indices;
117struct VbkMerkleTree {
118 using hash_t =
typename MerkleTree<VbkMerkleTree, uint256>::hash_t;
120 enum class TreeIndex : int32_t {
125 explicit VbkMerkleTree(
const std::vector<hash_t>& normal_hashes,
126 const std::vector<hash_t>& pop_hashes)
127 : pop_tree(*this, pop_hashes), normal_tree(*this, normal_hashes) {}
129 hash_t hash(
const hash_t& a,
const hash_t& b)
const {
return sha256(a, b); }
131 std::vector<hash_t> finalizePath(std::vector<hash_t> path,
132 const TreeIndex treeIndex)
const {
134 case TreeIndex::POP: {
136 if (path.empty() && normal_tree.getLayers().empty()) {
140 path.emplace_back(normal_tree.getMerkleRoot());
143 case TreeIndex::NORMAL: {
145 if (path.empty() && pop_tree.getLayers().empty()) {
149 path.emplace_back(pop_tree.getMerkleRoot());
159 hash_t getMerkleRoot()
const {
160 if (pop_tree.getLayers().empty() && normal_tree.getLayers().empty()) {
164 if ((pop_tree.getLayers().size() == 1) && normal_tree.getLayers().empty()) {
166 VBK_ASSERT(pop_tree.getLayers()[0].size() == 1);
167 return pop_tree.getMerkleRoot();
170 if ((normal_tree.getLayers().size() == 1) && pop_tree.getLayers().empty()) {
172 VBK_ASSERT(normal_tree.getLayers()[0].size() == 1);
173 return normal_tree.getMerkleRoot();
176 auto pop_hash = pop_tree.getMerkleRoot();
177 auto normal_hash = normal_tree.getMerkleRoot();
180 auto metapackageHash = hash_t();
181 return hash(metapackageHash, hash(pop_hash, normal_hash));
184 std::vector<hash_t> getMerklePathLayers(
const size_t index,
185 const TreeIndex treeIndex)
const {
188 return finalizePath(pop_tree.getMerklePathLayers(index), treeIndex);
189 case TreeIndex::NORMAL:
190 return finalizePath(normal_tree.getMerklePathLayers(index), treeIndex);
196 VbkMerklePath getMerklePath(
const hash_t& hash,
197 const TreeIndex treeIndex)
const {
198 VbkMerklePath merklePath;
199 merklePath.subject = hash;
200 merklePath.treeIndex =
static_cast<int32_t
>(treeIndex);
202 case TreeIndex::POP: {
203 const auto it = pop_tree.getHashIndices().find(hash);
204 VBK_ASSERT(it != pop_tree.getHashIndices().end());
205 const int32_t index = it->second;
207 merklePath.index = index;
208 merklePath.layers = finalizePath(
209 pop_tree.getMerklePathLayers(
static_cast<size_t>(index)),
213 case TreeIndex::NORMAL: {
214 const auto it = normal_tree.getHashIndices().find(hash);
215 VBK_ASSERT(it != normal_tree.getHashIndices().end());
216 const int32_t index = it->second;
218 merklePath.index = index;
219 merklePath.layers = finalizePath(
220 normal_tree.getMerklePathLayers(
static_cast<size_t>(index)),
232 MerkleTree<VbkMerkleTree, uint256> pop_tree;
233 MerkleTree<VbkMerkleTree, uint256> normal_tree;
237inline uint32_t estimateNumberOfPopTxs(
238 const std::vector<VbkMerklePath>& paths) {
240 std::set<int32_t> indexes;
241 int32_t maxIndex = -1;
242 for (
const auto& path : paths) {
243 if (path.treeIndex == (int32_t)VbkMerkleTree::TreeIndex::POP &&
244 maxIndex < path.index) {
245 maxIndex = path.index;
250 uint32_t aproximate_leaves_number = 0;
251 for (
const auto& path : paths) {
252 if (path.treeIndex == (int32_t)VbkMerkleTree::TreeIndex::POP &&
253 maxIndex == path.index) {
254 if (path.layers.empty()) {
255 aproximate_leaves_number = 1;
258 auto vec = path.equalLayerIndexes();
260 aproximate_leaves_number = (1 << (path.layers.size() - 2));
262 }
else if (vec.front() == 0) {
263 aproximate_leaves_number = path.index + 1;
266 aproximate_leaves_number = (1 << (path.layers.size() - 2));
267 for (
const auto& i : vec) {
268 aproximate_leaves_number -= (1 << i);
275 return aproximate_leaves_number;
278inline bool isPopSubTreeFull(
const std::vector<VbkMerklePath>& paths) {
279 return (uint32_t)paths.size() == estimateNumberOfPopTxs(paths);
283struct BtcMerkleTree :
public MerkleTree<BtcMerkleTree, uint256> {
284 using base = MerkleTree<BtcMerkleTree, uint256>;
286 explicit BtcMerkleTree(
const std::vector<hash_t>& txes) : base(*this, txes) {}
288 hash_t hash(
const hash_t& a,
const hash_t& b)
const {
292 MerklePath getMerklePath(
const hash_t& hash)
const {
293 auto it = hash_indices.find(hash);
294 VBK_ASSERT(it != hash_indices.end());
295 size_t index = it->second;
297 MerklePath merklePath;
298 merklePath.index = (int32_t)index;
299 merklePath.subject = hash;
300 merklePath.layers = getMerklePathLayers(index);
304 hash_t getMerkleRoot() {
return base::getMerkleRoot().reverse(); }
308template <
typename pop_t>
309struct PayloadsMerkleTree
310 :
public MerkleTree<PayloadsMerkleTree<pop_t>, typename pop_t::id_t> {
311 using base = MerkleTree<PayloadsMerkleTree<pop_t>,
typename pop_t::id_t>;
312 using hash_t =
typename base::hash_t;
314 explicit PayloadsMerkleTree(
const std::vector<hash_t>& hashes)
315 : base(*this, hashes) {}
317 hash_t hash(
const hash_t& a,
const hash_t& b)
const {
318 return sha256twice(a, b).template trimLE<hash_t::size()>();
321 hash_t getMerkleRoot() {
return base::getMerkleRoot().reverse(); }
uint256 sha256twice(Slice< const uint8_t > data)
Calculates SHA256 of the input data twice.
uint256 sha256(Slice< const uint8_t > data)
Calculates SHA256 of the input data.