blob: 300456a34c08dab07aef6e3f2682db4b7406e6de [file] [log] [blame]
peizhen guo410e0e12014-08-12 13:24:14 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07003 * Copyright (c) 2014-2017, Regents of the University of California
peizhen guo410e0e12014-08-12 13:24:14 -07004 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07005 * This file is part of NDN DeLorean, An Authentication System for Data Archives in
6 * Named Data Networking. See AUTHORS.md for complete list of NDN DeLorean authors
7 * and contributors.
peizhen guo410e0e12014-08-12 13:24:14 -07008 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -07009 * NDN DeLorean is free software: you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
peizhen guo410e0e12014-08-12 13:24:14 -070013 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -070014 * NDN DeLorean is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
peizhen guo410e0e12014-08-12 13:24:14 -070017 *
Alexander Afanasyevbe998ac2017-05-06 13:11:42 -070018 * You should have received a copy of the GNU General Public License along with NDN
19 * DeLorean, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
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
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -070024namespace ndn {
25namespace delorean {
peizhen guo410e0e12014-08-12 13:24:14 -070026
Yingdi Yu0c3e5912015-03-17 14:22:38 -070027MerkleTree::MerkleTree(Db& db)
28 : m_db(db)
29 , m_nextLeafSeqNo(0)
peizhen guo410e0e12014-08-12 13:24:14 -070030{
peizhen guo410e0e12014-08-12 13:24:14 -070031}
32
Yingdi Yu0c3e5912015-03-17 14:22:38 -070033MerkleTree::MerkleTree(const Name& loggerName, Db& db)
34 : m_loggerName(loggerName)
35 , m_db(db)
36 , m_nextLeafSeqNo(0)
peizhen guo410e0e12014-08-12 13:24:14 -070037{
Yingdi Yu0c3e5912015-03-17 14:22:38 -070038 loadPendingSubTrees();
39}
40
41MerkleTree::~MerkleTree()
42{
43 savePendingTree();
44}
45
46void
47MerkleTree::setLoggerName(const Name& loggerName)
48{
49 m_loggerName = loggerName;
50}
51
52bool
53MerkleTree::addLeaf(const NonNegativeInteger& seqNo, ndn::ConstBufferPtr hash)
54{
55 auto baseTree = m_pendingTrees[SubTreeBinary::SUB_TREE_DEPTH - 1];
56 BOOST_ASSERT(baseTree != nullptr);
57
58 NodePtr leaf = make_shared<Node>(seqNo, 0, seqNo + 1, hash);
59 return baseTree->addLeaf(leaf);
60}
61
62void
63MerkleTree::savePendingTree()
64{
65 size_t level = m_rootSubTree->getPeakIndex().level;
66 size_t step = SubTreeBinary::SUB_TREE_DEPTH - 1;
67
68 for (size_t i = level; i > 0; i -= step) {
69 auto pendingTree = m_pendingTrees[i];
70 BOOST_ASSERT(pendingTree != nullptr);
71
72 auto data = pendingTree->encode();
73 if (data != nullptr) {
74 m_db.insertSubTreeData(pendingTree->getPeakIndex().level, pendingTree->getPeakIndex().seqNo,
75 *data, false, pendingTree->getNextLeafSeqNo());
peizhen guo410e0e12014-08-12 13:24:14 -070076 }
Yingdi Yu0c3e5912015-03-17 14:22:38 -070077 }
78}
79
80shared_ptr<Data>
81MerkleTree::getPendingSubTreeData(size_t level)
82{
83 auto it = m_pendingTrees.find(level);
84 if (it != m_pendingTrees.end())
85 return it->second->encode();
peizhen guo410e0e12014-08-12 13:24:14 -070086 else
Yingdi Yu0c3e5912015-03-17 14:22:38 -070087 return nullptr;
peizhen guo410e0e12014-08-12 13:24:14 -070088}
89
Yingdi Yu0c3e5912015-03-17 14:22:38 -070090// private:
91void
92MerkleTree::loadPendingSubTrees()
peizhen guo410e0e12014-08-12 13:24:14 -070093{
Yingdi Yu0c3e5912015-03-17 14:22:38 -070094 std::vector<shared_ptr<Data>> subtreeDatas = m_db.getPendingSubTrees();
95
96 shared_ptr<SubTreeBinary> subtree;
97 if (subtreeDatas.empty()) {
98 subtree = make_shared<SubTreeBinary>(m_loggerName,
99 Node::Index(0, SubTreeBinary::SUB_TREE_DEPTH - 1),
100 [this] (const Node::Index& idx) {
101 // std::cerr << "complete: " << idx.level << ", " << idx.seqNo << std::endl;
102 this->getNewRoot(idx);
103 },
104 [this] (const Node::Index& idx,
105 const NonNegativeInteger& seqNo,
106 ndn::ConstBufferPtr hash) {
107 // std::cerr << "update: " << idx.level << ", " << idx.seqNo << std::endl;
108 // std::cerr << "seqNo: " << seqNo << std::endl;
109 this->m_nextLeafSeqNo = seqNo;
110 this->m_hash = hash;
111 });
112 m_pendingTrees[SubTreeBinary::SUB_TREE_DEPTH - 1] = subtree;
113 m_rootSubTree = subtree;
114 return;
115 }
116
117 subtree = make_shared<SubTreeBinary>(m_loggerName,
118 [this] (const Node::Index& idx) { this->getNewRoot(idx); },
119 [this] (const Node::Index& idx,
120 const NonNegativeInteger& seqNo,
121 ndn::ConstBufferPtr hash) {
122 this->m_nextLeafSeqNo = seqNo;
123 this->m_hash = hash;
124 });
125
126 subtree->decode(*subtreeDatas[0]);
127 m_pendingTrees[subtree->getPeakIndex().level] = subtree;
128 m_rootSubTree = subtree;
129
130 shared_ptr<SubTreeBinary> parentTree = subtree;
131 for (size_t i = 1; i < subtreeDatas.size(); i++) {
132 subtree = make_shared<SubTreeBinary>(m_loggerName,
133 [this] (const Node::Index& idx) {
134 this->getNewSibling(idx);
135 },
136 [parentTree] (const Node::Index&,
137 const NonNegativeInteger& seqNo,
138 ndn::ConstBufferPtr hash) {
139 parentTree->updateLeaf(seqNo, hash);
140 });
141
142 subtree->decode(*subtreeDatas[i]);
143 if (parentTree->getPeakIndex().level + 1 - SubTreeBinary::SUB_TREE_DEPTH !=
144 subtree->getPeakIndex().level)
145 throw Error("loadPendingSubTrees: inconsistent pending subtree level");
146
147 if (parentTree->getNextLeafSeqNo() != subtree->getNextLeafSeqNo())
148 throw Error("loadPendingSubTrees: inconsistent pending subtree next leaf seqNo");
149
150 m_pendingTrees[subtree->getPeakIndex().level] = subtree;
151 parentTree = subtree;
152 }
peizhen guo410e0e12014-08-12 13:24:14 -0700153}
154
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700155void
156MerkleTree::getNewRoot(const Node::Index& idx)
peizhen guo410e0e12014-08-12 13:24:14 -0700157{
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700158 // save the old root tree into db
159 auto oldRoot = m_pendingTrees[idx.level];
160 BOOST_ASSERT(oldRoot != nullptr);
161 m_db.insertSubTreeData(idx.level, idx.seqNo, *oldRoot->encode());
162
163 // create a new root tree
164 Node::Index newRootIdx(0, idx.level + SubTreeBinary::SUB_TREE_DEPTH - 1);
165 auto newRoot = make_shared<SubTreeBinary>(m_loggerName, newRootIdx,
166 [this] (const Node::Index& idx) {
167 // std::cerr << "complete: " << idx.level << ", " << idx.seqNo << std::endl;
168 this->getNewRoot(idx);
169 },
170 [this] (const Node::Index& index,
171 const NonNegativeInteger& seqNo,
172 ndn::ConstBufferPtr hash) {
173 // std::cerr << "update: " << index.level << ", " << index.seqNo << std::endl;
174 // std::cerr << "seqNo: " << seqNo << std::endl;
175 this->m_nextLeafSeqNo = seqNo;
176 this->m_hash = hash;
177 });
178
179 m_pendingTrees[newRoot->getPeakIndex().level] = newRoot;
180 m_rootSubTree = newRoot;
181
Alexander Afanasyevb1ba9c92017-05-06 13:16:18 -0700182 newRoot->updateLeaf(idx.seqNo + idx.range, oldRoot->getRoot()->getHash());
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700183
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;
Alexander Afanasyevb1ba9c92017-05-06 13:16:18 -0700213 parent->updateLeaf(seqNo, hash);
Yingdi Yu0c3e5912015-03-17 14:22:38 -0700214 });
215
216 m_pendingTrees[newSibling->getPeakIndex().level] = newSibling;
peizhen guo410e0e12014-08-12 13:24:14 -0700217}
218
Alexander Afanasyev49e2e4c2017-05-06 13:42:57 -0700219} // namespace delorean
220} // namespace ndn