示例#1
0
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();
}