void PartialMerkleTree::setCompressed(std::queue<uchar_vector>& hashQueue, std::queue<bool>& bitQueue, unsigned int depth) { depth_ = depth; if (hashQueue.empty() || bitQueue.empty()) { throw std::runtime_error("PartialMerkleTree::setCompressed - Invalid compressed partial merkle tree data."); } bool bit = bitQueue.front(); bits_.push_back(bit); bitQueue.pop(); // We've reached a leaf of the partial merkle tree if (depth == 0 || !bit) { root_ = hashQueue.front(); merkleHashes_.push_back(hashQueue.front()); if (bit) txHashes_.push_back(hashQueue.front()); hashQueue.pop(); return; } depth--; // we're not at a leaf and bit is set so recurse PartialMerkleTree leftSubtree; leftSubtree.setCompressed(hashQueue, bitQueue, depth); merkleHashes_.swap(leftSubtree.merkleHashes_); txHashes_.swap(leftSubtree.txHashes_); bits_.splice(bits_.end(), leftSubtree.bits_); if (!hashQueue.empty()) { // A right subtree also exists, so find it PartialMerkleTree rightSubtree; rightSubtree.setCompressed(hashQueue, bitQueue, depth); root_ = sha256_2(leftSubtree.root_ + rightSubtree.root_); merkleHashes_.splice(merkleHashes_.end(), rightSubtree.merkleHashes_); txHashes_.splice(txHashes_.end(), rightSubtree.txHashes_); bits_.splice(bits_.end(), rightSubtree.bits_); } else { // There's no right subtree - copy over this node's hash root_ = sha256_2(leftSubtree.root_ + leftSubtree.root_); } }
void PartialMerkleTree::merge(std::queue<uchar_vector>& hashQueue1, std::queue<uchar_vector>& hashQueue2, std::queue<bool>& bitQueue1, std::queue<bool>& bitQueue2, unsigned int depth) { if (hashQueue1.empty()) { hashQueue1.swap(hashQueue2); bitQueue1.swap(bitQueue2); } if (hashQueue2.empty()) { if (hashQueue1.empty()) return; PartialMerkleTree tree; tree.setCompressed(hashQueue1, bitQueue1, depth); merkleHashes_.splice(merkleHashes_.end(), tree.merkleHashes_); txHashes_.splice(txHashes_.end(), tree.txHashes_); bits_.splice(bits_.end(), tree.bits_); return; } bool bit1 = bitQueue1.front(); bool bit2 = bitQueue2.front(); bool hasMatch = (bit1 || bit2); bitQueue1.pop(); bitQueue2.pop(); // We've reached a leaf of the partial merkle tree if (depth == 0 || !hasMatch) { if (hashQueue1.front() != hashQueue2.front()) { std::stringstream error; error << "PartialMerkleTree::merge - leaves do not match: " << hashQueue1.front().getReverse().getHex() << ", " << hashQueue2.front().getReverse().getHex() << std::endl; throw std::runtime_error(error.str()); } merkleHashes_.push_back(hashQueue1.front()); std::cout << hashQueue1.front().getReverse().getHex() << std::endl; if (hasMatch) { txHashes_.push_back(hashQueue1.front()); } bits_.push_back(hasMatch); hashQueue1.pop(); hashQueue2.pop(); return; } bits_.push_back(true); depth--; // Both trees continue down this branch. if (bit1 && bit2) { merge(hashQueue1, hashQueue2, bitQueue1, bitQueue2, depth); merge(hashQueue1, hashQueue2, bitQueue1, bitQueue2, depth); return; } // Only one tree continues down this branch. Swap them if it's the second. if (bit2) { hashQueue1.swap(hashQueue2); bitQueue1.swap(bitQueue2); } PartialMerkleTree leftSubtree; leftSubtree.setCompressed(hashQueue1, bitQueue1, depth); merkleHashes_.splice(merkleHashes_.end(), leftSubtree.merkleHashes_); txHashes_.splice(txHashes_.end(), leftSubtree.txHashes_); bits_.splice(bits_.end(), leftSubtree.bits_); uchar_vector root; if (!hashQueue1.empty()) { PartialMerkleTree rightSubtree; rightSubtree.setCompressed(hashQueue1, bitQueue1, depth); root = sha256_2(leftSubtree.root_ + rightSubtree.root_); merkleHashes_.splice(merkleHashes_.end(), rightSubtree.merkleHashes_); txHashes_.splice(txHashes_.end(), rightSubtree.txHashes_); bits_.splice(bits_.end(), rightSubtree.bits_); } else { root = sha256_2(leftSubtree.root_ + leftSubtree.root_); } if (root != hashQueue2.front()) { std::stringstream error; error << "PartialMerkleTree::merge - inner nodes do not match: " << root.getHex() << ", " << hashQueue2.front().getReverse().getHex(); throw std::runtime_error(error.str()); } hashQueue2.pop(); }