blob: a579350c2951edb5a138a68d277879ef4e60ed98 [file] [log] [blame]
peizhen guo410e0e12014-08-12 13:24:14 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014, Regents of the University of California
4 *
5 * This file is part of NSL (NDN Signature Logger).
6 * See AUTHORS.md for complete list of NSL authors and contributors.
7 *
8 * NSL is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * NSL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * NSL, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
Yingdi Yu0c3e5912015-03-17 14:22:38 -070019 * See AUTHORS.md for complete list of nsl authors and contributors.
peizhen guo410e0e12014-08-12 13:24:14 -070020 */
Yingdi Yu0c3e5912015-03-17 14:22:38 -070021
peizhen guo410e0e12014-08-12 13:24:14 -070022#include "merkle-tree.hpp"
23
24namespace nsl {
25
Yingdi Yu0c3e5912015-03-17 14:22:38 -070026MerkleTree::MerkleTree(Db& db)
27 : m_db(db)
28 , m_nextLeafSeqNo(0)
peizhen guo410e0e12014-08-12 13:24:14 -070029{
peizhen guo410e0e12014-08-12 13:24:14 -070030}
31
Yingdi Yu0c3e5912015-03-17 14:22:38 -070032MerkleTree::MerkleTree(const Name& loggerName, Db& db)
33 : m_loggerName(loggerName)
34 , m_db(db)
35 , m_nextLeafSeqNo(0)
peizhen guo410e0e12014-08-12 13:24:14 -070036{
Yingdi Yu0c3e5912015-03-17 14:22:38 -070037 loadPendingSubTrees();
38}
39
40MerkleTree::~MerkleTree()
41{
42 savePendingTree();
43}
44
45void
46MerkleTree::setLoggerName(const Name& loggerName)
47{
48 m_loggerName = loggerName;
49}
50
51bool
52MerkleTree::addLeaf(const NonNegativeInteger& seqNo, ndn::ConstBufferPtr hash)
53{
54 auto baseTree = m_pendingTrees[SubTreeBinary::SUB_TREE_DEPTH - 1];
55 BOOST_ASSERT(baseTree != nullptr);
56
57 NodePtr leaf = make_shared<Node>(seqNo, 0, seqNo + 1, hash);
58 return baseTree->addLeaf(leaf);
59}
60
61void
62MerkleTree::savePendingTree()
63{
64 size_t level = m_rootSubTree->getPeakIndex().level;
65 size_t step = SubTreeBinary::SUB_TREE_DEPTH - 1;
66
67 for (size_t i = level; i > 0; i -= step) {
68 auto pendingTree = m_pendingTrees[i];
69 BOOST_ASSERT(pendingTree != nullptr);
70
71 auto data = pendingTree->encode();
72 if (data != nullptr) {
73 m_db.insertSubTreeData(pendingTree->getPeakIndex().level, pendingTree->getPeakIndex().seqNo,
74 *data, false, pendingTree->getNextLeafSeqNo());
peizhen guo410e0e12014-08-12 13:24:14 -070075 }
Yingdi Yu0c3e5912015-03-17 14:22:38 -070076 }
77}
78
79shared_ptr<Data>
80MerkleTree::getPendingSubTreeData(size_t level)
81{
82 auto it = m_pendingTrees.find(level);
83 if (it != m_pendingTrees.end())
84 return it->second->encode();
peizhen guo410e0e12014-08-12 13:24:14 -070085 else
Yingdi Yu0c3e5912015-03-17 14:22:38 -070086 return nullptr;
peizhen guo410e0e12014-08-12 13:24:14 -070087}
88
Yingdi Yu0c3e5912015-03-17 14:22:38 -070089// private:
90void
91MerkleTree::loadPendingSubTrees()
peizhen guo410e0e12014-08-12 13:24:14 -070092{
Yingdi Yu0c3e5912015-03-17 14:22:38 -070093 std::vector<shared_ptr<Data>> subtreeDatas = m_db.getPendingSubTrees();
94
95 shared_ptr<SubTreeBinary> subtree;
96 if (subtreeDatas.empty()) {
97 subtree = make_shared<SubTreeBinary>(m_loggerName,
98 Node::Index(0, SubTreeBinary::SUB_TREE_DEPTH - 1),
99 [this] (const Node::Index& idx) {
100 // std::cerr << "complete: " << idx.level << ", " << idx.seqNo << std::endl;
101 this->getNewRoot(idx);
102 },
103 [this] (const Node::Index& idx,
104 const NonNegativeInteger& seqNo,
105 ndn::ConstBufferPtr hash) {
106 // std::cerr << "update: " << idx.level << ", " << idx.seqNo << std::endl;
107 // std::cerr << "seqNo: " << seqNo << std::endl;
108 this->m_nextLeafSeqNo = seqNo;
109 this->m_hash = hash;
110 });
111 m_pendingTrees[SubTreeBinary::SUB_TREE_DEPTH - 1] = subtree;
112 m_rootSubTree = subtree;
113 return;
114 }
115
116 subtree = make_shared<SubTreeBinary>(m_loggerName,
117 [this] (const Node::Index& idx) { this->getNewRoot(idx); },
118 [this] (const Node::Index& idx,
119 const NonNegativeInteger& seqNo,
120 ndn::ConstBufferPtr hash) {
121 this->m_nextLeafSeqNo = seqNo;
122 this->m_hash = hash;
123 });
124
125 subtree->decode(*subtreeDatas[0]);
126 m_pendingTrees[subtree->getPeakIndex().level] = subtree;
127 m_rootSubTree = subtree;
128
129 shared_ptr<SubTreeBinary> parentTree = subtree;
130 for (size_t i = 1; i < subtreeDatas.size(); i++) {
131 subtree = make_shared<SubTreeBinary>(m_loggerName,
132 [this] (const Node::Index& idx) {
133 this->getNewSibling(idx);
134 },
135 [parentTree] (const Node::Index&,
136 const NonNegativeInteger& seqNo,
137 ndn::ConstBufferPtr hash) {
138 parentTree->updateLeaf(seqNo, hash);
139 });
140
141 subtree->decode(*subtreeDatas[i]);
142 if (parentTree->getPeakIndex().level + 1 - SubTreeBinary::SUB_TREE_DEPTH !=
143 subtree->getPeakIndex().level)
144 throw Error("loadPendingSubTrees: inconsistent pending subtree level");
145
146 if (parentTree->getNextLeafSeqNo() != subtree->getNextLeafSeqNo())
147 throw Error("loadPendingSubTrees: inconsistent pending subtree next leaf seqNo");
148
149 m_pendingTrees[subtree->getPeakIndex().level] = subtree;
150 parentTree = subtree;
151 }
peizhen guo410e0e12014-08-12 13:24:14 -0700152}
153
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700154void
155MerkleTree::getNewRoot(const Node::Index& idx)
peizhen guo410e0e12014-08-12 13:24:14 -0700156{
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700157 // save the old root tree into db
158 auto oldRoot = m_pendingTrees[idx.level];
159 BOOST_ASSERT(oldRoot != nullptr);
160 m_db.insertSubTreeData(idx.level, idx.seqNo, *oldRoot->encode());
161
162 // create a new root tree
163 Node::Index newRootIdx(0, idx.level + SubTreeBinary::SUB_TREE_DEPTH - 1);
164 auto newRoot = make_shared<SubTreeBinary>(m_loggerName, newRootIdx,
165 [this] (const Node::Index& idx) {
166 // std::cerr << "complete: " << idx.level << ", " << idx.seqNo << std::endl;
167 this->getNewRoot(idx);
168 },
169 [this] (const Node::Index& index,
170 const NonNegativeInteger& seqNo,
171 ndn::ConstBufferPtr hash) {
172 // std::cerr << "update: " << index.level << ", " << index.seqNo << std::endl;
173 // std::cerr << "seqNo: " << seqNo << std::endl;
174 this->m_nextLeafSeqNo = seqNo;
175 this->m_hash = hash;
176 });
177
178 m_pendingTrees[newRoot->getPeakIndex().level] = newRoot;
179 m_rootSubTree = newRoot;
180
181 bool result = newRoot->updateLeaf(idx.seqNo + idx.range, oldRoot->getRoot()->getHash());
182 BOOST_ASSERT(result);
183
184 // create a sibling
185 getNewSibling(idx);
peizhen guo410e0e12014-08-12 13:24:14 -0700186}
187
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700188void
189MerkleTree::getNewSibling(const Node::Index& idx)
peizhen guo410e0e12014-08-12 13:24:14 -0700190{
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700191 // save old sibling
192 auto oldSibling = m_pendingTrees[idx.level];
193 BOOST_ASSERT(oldSibling != nullptr);
194 m_db.insertSubTreeData(idx.level, idx.seqNo, *oldSibling->encode());
195
196 // get parent tree
197 Node::Index parentIdx(0, idx.level + SubTreeBinary::SUB_TREE_DEPTH - 1);
198 auto parent = m_pendingTrees[parentIdx.level];
199 BOOST_ASSERT(parent != nullptr);
200
201 // create a new sibling
202 Node::Index newSiblingIdx(idx.seqNo + idx.range, idx.level);
203 // std::cerr << "new Sibling: " << newSiblingIdx.level << ", " << newSiblingIdx.seqNo << std::endl;
204 auto newSibling = make_shared<SubTreeBinary>(m_loggerName, newSiblingIdx,
205 [this] (const Node::Index& idx) { this->getNewSibling(idx); },
206 [parent] (const Node::Index& index,
207 const NonNegativeInteger& seqNo,
208 ndn::ConstBufferPtr hash) {
209 // std::cerr << "update: " << index.level << ", " << index.seqNo << std::endl;
210 // std::cerr << "seqNo: " << seqNo << std::endl;
211 // std::cerr << "parent: " << parent->getRoot()->getIndex().level << ", " <<
212 // parent->getRoot()->getIndex().seqNo << std::endl;
213 bool result = parent->updateLeaf(seqNo, hash);
214 BOOST_ASSERT(result);
215 });
216
217 m_pendingTrees[newSibling->getPeakIndex().level] = newSibling;
peizhen guo410e0e12014-08-12 13:24:14 -0700218}
219
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700220}// namespace nsl