-
Notifications
You must be signed in to change notification settings - Fork 12
/
MerkleTree.hpp
141 lines (109 loc) · 3.01 KB
/
MerkleTree.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef _SNARKFRONT_MERKLE_TREE_HPP_
#define _SNARKFRONT_MERKLE_TREE_HPP_
#include <cstdint>
#include <iostream>
#include <istream>
#include <ostream>
#include <vector>
#include <cryptl/SHA_256.hpp>
#include <cryptl/SHA_512.hpp>
#include <snarkfront/MerkleAuthPath.hpp>
namespace snarkfront {
////////////////////////////////////////////////////////////////////////////////
// Merkle tree (binary)
//
template <typename HASH>
class MerkleTree
{
public:
typedef HASH HashType;
typedef typename HASH::DigType DigType;
MerkleTree()
: m_isFull(true),
m_authPath(0)
{}
// unmanaged (eval namespace)
MerkleTree(const std::size_t depth)
: m_isFull(false),
m_authPath(depth)
{}
// true when number of occupied leaves is 2^depth
bool isFull() const {
return m_isFull;
}
const MerkleAuthPath<HASH, int>& authPath() const {
return m_authPath;
}
// update hash codes along path back to root
void updatePath(const DigType& leaf) {
m_authPath.updatePath(leaf);
}
// update hash codes along path back to root
void updatePath(const DigType& leaf,
std::vector<MerkleAuthPath<HASH, int>>& v)
{
m_authPath.updatePath(leaf, v);
}
// prepare tree for next leaf
void updateSiblings(const DigType& leaf)
{
// counter for next leaf element
const int firstBit = m_authPath.incChildBits();
if (-1 == firstBit) {
// tree is full
m_isFull = true;
return;
} else if (0 == firstBit) {
// next leaf is right child
m_authPath.leafSibling(leaf);
} else {
// left sibling of new branch in tree
m_authPath.hashSibling(firstBit);
}
}
void marshal_out(std::ostream& os) const {
os << m_isFull << ' ' << m_authPath;
}
bool marshal_in(std::istream& is) {
m_isFull = true; // use as valid flag
// is full
bool full = true;
if (! (is >> full)) return false;
// space
char c;
if (!is.get(c) || (' ' != c)) return false;
if (! m_authPath.marshal_in(is)) return false;
m_isFull = full;
return true;
}
void clear() {
m_isFull = true;
m_authPath.clear();
}
bool empty() const
{
return
isFull() ||
authPath().empty();
}
private:
bool m_isFull;
MerkleAuthPath<HASH, int> m_authPath;
};
template <typename HASH>
std::ostream& operator<< (std::ostream& os, const MerkleTree<HASH>& a) {
a.marshal_out(os);
return os;
}
template <typename HASH>
std::istream& operator>> (std::istream& is, MerkleTree<HASH>& a) {
if (! a.marshal_in(is)) a.clear();
return is;
}
////////////////////////////////////////////////////////////////////////////////
// typedefs
//
typedef MerkleTree<cryptl::SHA256> MerkleTree_SHA256;
typedef MerkleTree<cryptl::SHA512> MerkleTree_SHA512;
} // namespace snarkfront
#endif