/// <summary> /// Builds the Merkle Tree recursivly from the list of Leaf nodes to the root node. /// </summary> /// <remarks> /// Merkle tree is built from lowest level to the highest (root) level. /// In each level nodes are paired and their parent node is constructed. /// If there is odd number of nodes, then last parent node is calculated using same node for both childs. /// </remarks> /// <param name="nodes">The list of nodes.</param> private void BuildTree(IList <MerkleNodeBase> nodes) { // if only one node, then we reached the root level if (nodes.Count == 1) { this.root = nodes[0]; return; } // new list of next level nodes var nextLevelNodes = new List <MerkleNodeBase>(); // the lenght of list where each node has a pair. var lenghtOfPairs = (nodes.Count / 2) * 2; // calculate next level nodes for each current level node pair for (var i = 0; i < lenghtOfPairs; i += 2) { var newNode = new MerkleNode(this.hashProvider, nodes[i], nodes[i + 1]); nextLevelNodes.Add(newNode); } // if there is one node left without pair (odd number of nodes), then use same node for both childs if (nodes.Count > lenghtOfPairs) { var newNode = new MerkleNode(this.hashProvider, nodes[nodes.Count - 1], nodes[nodes.Count - 1]); nextLevelNodes.Add(newNode); } this.BuildTree(nextLevelNodes); }
/// <summary> /// Initializes a new instance of the <see cref="MerkleNode"/> class. /// </summary> /// <param name="hashProvider">The hash provider.</param> /// <param name="left">The left child node.</param> /// <param name="right">The right child node.</param> internal MerkleNode(IHashProvider hashProvider, MerkleNodeBase left, MerkleNodeBase right) { this.right = right; this.left = left; this.nodeHash = hashProvider.ComputeHash(left.Hash.GetHashBytes().Concat(right.Hash.GetHashBytes()).ToArray()); }