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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
|
#include "merkletree/merkle_tree.h"
#include <assert.h>
#include <stddef.h>
#include <string>
#include <vector>
#include "merkletree/merkle_tree_math.h"
using cert_trans::MerkleTreeInterface;
using std::move;
using std::string;
using std::unique_ptr;
MerkleTree::MerkleTree(unique_ptr<SerialHasher> hasher)
: MerkleTreeInterface(),
treehasher_(move(hasher)),
leaves_processed_(0),
level_count_(0) {
}
MerkleTree::~MerkleTree() {
}
size_t MerkleTree::AddLeaf(const string& data) {
return AddLeafHash(treehasher_.HashLeaf(data));
}
size_t MerkleTree::AddLeafHash(const string& hash) {
if (LazyLevelCount() == 0) {
AddLevel();
// The first leaf hash is also the first root.
leaves_processed_ = 1;
}
PushBack(0, hash);
size_t leaf_count = LeafCount();
// Update level count: a k-level tree can hold 2^{k-1} leaves,
// so increment level count every time we overflow a power of two.
// Do not update the root; we evaluate the tree lazily.
if (MerkleTreeMath::IsPowerOfTwoPlusOne(leaf_count))
++level_count_;
// Return the current leaf count.
return leaf_count;
}
string MerkleTree::CurrentRoot() {
return RootAtSnapshot(LeafCount());
}
string MerkleTree::RootAtSnapshot(size_t snapshot) {
if (snapshot == 0)
return treehasher_.HashEmpty();
size_t leaf_count = LeafCount();
if (snapshot > leaf_count)
return string();
if (snapshot >= leaves_processed_)
return UpdateToSnapshot(snapshot);
// snapshot < leaves_processed_: recompute the snapshot root.
return RecomputePastSnapshot(snapshot, 0, NULL);
}
std::vector<string> MerkleTree::PathToCurrentRoot(size_t leaf) {
return PathToRootAtSnapshot(leaf, LeafCount());
}
std::vector<string> MerkleTree::PathToRootAtSnapshot(size_t leaf,
size_t snapshot) {
std::vector<string> path;
size_t leaf_count = LeafCount();
if (leaf > snapshot || snapshot > leaf_count || leaf == 0)
return path;
return PathFromNodeToRootAtSnapshot(leaf - 1, 0, snapshot);
}
std::vector<string> MerkleTree::SnapshotConsistency(size_t snapshot1,
size_t snapshot2) {
std::vector<string> proof;
size_t leaf_count = LeafCount();
if (snapshot1 == 0 || snapshot1 >= snapshot2 || snapshot2 > leaf_count)
return proof;
size_t level = 0;
// Rightmost node in snapshot1.
size_t node = snapshot1 - 1;
// Compute the (compressed) path to the root of snapshot2.
// Everything left of 'node' is equal in both trees; no need to record.
while (MerkleTreeMath::IsRightChild(node)) {
node = MerkleTreeMath::Parent(node);
++level;
}
if (snapshot2 > leaves_processed_) {
// Bring the tree sufficiently up to date.
UpdateToSnapshot(snapshot2);
}
// Record the node, unless we already reached the root of snapshot1.
if (node)
proof.push_back(Node(level, node));
// Now record the path from this node to the root of snapshot2.
std::vector<string> path =
PathFromNodeToRootAtSnapshot(node, level, snapshot2);
proof.insert(proof.end(), path.begin(), path.end());
return proof;
}
string MerkleTree::UpdateToSnapshot(size_t snapshot) {
if (snapshot == 0)
return treehasher_.HashEmpty();
if (snapshot == 1)
return Node(0, 0);
if (snapshot == leaves_processed_)
return Root();
assert(snapshot <= LeafCount());
assert(snapshot > leaves_processed_);
// Update tree, moving up level-by-level.
size_t level = 0;
// Index of the first node to be processed at the current level.
size_t first_node = leaves_processed_;
// Index of the last node.
size_t last_node = snapshot - 1;
// Process level-by-level until we converge to a single node.
// (first_node, last_node) = (0, 0) means we have reached the root level.
while (last_node) {
if (LazyLevelCount() <= level + 1) {
AddLevel();
} else if (NodeCount(level + 1) ==
MerkleTreeMath::Parent(first_node) + 1) {
// The leftmost parent at level 'level+1' may already exist,
// so we need to update it. Nuke the old parent.
PopBack(level + 1);
}
// Compute the parents of new nodes at the current level.
// Start with a left sibling and parse an even number of nodes.
for (size_t j = first_node & ~1; j < last_node; j += 2) {
PushBack(level + 1,
treehasher_.HashChildren(Node(level, j), Node(level, j + 1)));
}
// If the last node at the current level is a left sibling,
// dummy-propagate it one level up.
if (!MerkleTreeMath::IsRightChild(last_node))
PushBack(level + 1, Node(level, last_node));
first_node = MerkleTreeMath::Parent(first_node);
last_node = MerkleTreeMath::Parent(last_node);
++level;
};
leaves_processed_ = snapshot;
return Root();
}
string MerkleTree::RecomputePastSnapshot(size_t snapshot, size_t node_level,
string* node) {
size_t level = 0;
// Index of the rightmost node at the current level for this snapshot.
size_t last_node = snapshot - 1;
if (snapshot == leaves_processed_) {
// Nothing to recompute.
if (node && LazyLevelCount() > node_level) {
if (node_level > 0) {
node->assign(LastNode(node_level));
} else {
// Leaf level: grab the last processed leaf.
node->assign(Node(node_level, last_node));
}
}
return Root();
}
assert(snapshot < leaves_processed_);
// Recompute nodes on the path of the last leaf.
while (MerkleTreeMath::IsRightChild(last_node)) {
if (node && node_level == level)
node->assign(Node(level, last_node));
// Left sibling and parent exist in the snapshot, and are equal to
// those in the tree; no need to rehash, move one level up.
last_node = MerkleTreeMath::Parent(last_node);
++level;
}
// Now last_node is the index of a left sibling with no right sibling.
// Record the node.
string subtree_root = Node(level, last_node);
if (node && node_level == level)
node->assign(subtree_root);
while (last_node) {
if (MerkleTreeMath::IsRightChild(last_node)) {
// Recompute the parent of tree_[level][last_node].
subtree_root =
treehasher_.HashChildren(Node(level, last_node - 1), subtree_root);
}
// Else the parent is a dummy copy of the current node; do nothing.
last_node = MerkleTreeMath::Parent(last_node);
++level;
if (node && node_level == level)
node->assign(subtree_root);
}
return subtree_root;
}
std::vector<string> MerkleTree::PathFromNodeToRootAtSnapshot(size_t node,
size_t level,
size_t snapshot) {
std::vector<string> path;
if (snapshot == 0)
return path;
// Index of the last node.
size_t last_node = (snapshot - 1) >> level;
if (level >= level_count_ || node > last_node || snapshot > LeafCount())
return path;
if (snapshot > leaves_processed_) {
// Bring the tree sufficiently up to date.
UpdateToSnapshot(snapshot);
}
// Move up, recording the sibling of the current node at each level.
while (last_node) {
size_t sibling = MerkleTreeMath::Sibling(node);
if (sibling < last_node) {
// The sibling is not the last node of the level in the snapshot
// tree, so its value is correct in the tree.
path.push_back(Node(level, sibling));
} else if (sibling == last_node) {
// The sibling is the last node of the level in the snapshot tree,
// so we get its value for the snapshot. Get the root in the same pass.
string recompute_node;
RecomputePastSnapshot(snapshot, level, &recompute_node);
path.push_back(recompute_node);
}
// Else sibling > last_node so the sibling does not exist. Do nothing.
// Continue moving up in the tree, ignoring dummy copies.
node = MerkleTreeMath::Parent(node);
last_node = MerkleTreeMath::Parent(last_node);
++level;
};
return path;
}
string MerkleTree::Node(size_t level, size_t index) const {
assert(NodeCount(level) > index);
return tree_[level].substr(index * treehasher_.DigestSize(),
treehasher_.DigestSize());
}
string MerkleTree::Root() const {
assert(tree_.back().size() == treehasher_.DigestSize());
return tree_.back();
}
size_t MerkleTree::NodeCount(size_t level) const {
assert(LazyLevelCount() > level);
return tree_[level].size() / treehasher_.DigestSize();
}
string MerkleTree::LastNode(size_t level) const {
assert(NodeCount(level) >= 1U);
return tree_[level].substr(tree_[level].size() - treehasher_.DigestSize());
}
void MerkleTree::PopBack(size_t level) {
assert(NodeCount(level) >= 1U);
tree_[level].erase(tree_[level].size() - treehasher_.DigestSize());
}
void MerkleTree::PushBack(size_t level, string node) {
assert(node.size() == treehasher_.DigestSize());
assert(LazyLevelCount() > level);
tree_[level].append(node);
}
void MerkleTree::AddLevel() {
tree_.push_back(string());
}
size_t MerkleTree::LazyLevelCount() const {
return tree_.size();
}
|