/// <summary> /// Get merkle proof path for one node. /// </summary> /// <param name="index">Should be less than <see cref="LeafCount"/>.</param> /// <returns> /// Return null if <see cref="Root"/> is not calculated or index is not leaf node. /// </returns> /// <example> /// In the tree like /// 12 /// 10 ------ 11 /// 6 -- 7 8 -- 9 /// 0-1 2-3 4-5 /// For leaf [4], the returned <see cref="MerklePath.Path"/> is {5, 9, 10}. /// </example> public MerklePath GenerateMerklePath(int index) { if (Root == null || index >= LeafCount) { return(null); } List <Hash> path = new List <Hash>(); int firstInRow = 0; int rowcount = LeafCount; while (index < Nodes.Count - 1) { path.Add(index % 2 == 0 ? Nodes[index + 1].Clone() : Nodes[index - 1].Clone()); rowcount = rowcount % 2 == 0 ? rowcount : rowcount + 1; int shift = (index - firstInRow) / 2; firstInRow += rowcount; index = firstInRow + shift; rowcount /= 2; } var res = new MerklePath(); res.Path.AddRange(path); return(res); }
/// <summary> /// Calculate the <see cref="BinaryMerkleTree.Root"/> with path and provided leaf. /// </summary> /// <param name="merklePath"></param> /// <param name="leaf"></param> /// <returns></returns> public static Hash ComputeRootWith(this MerklePath merklePath, Hash leaf) { Hash hash = leaf.Clone(); foreach (var node in merklePath.Path) { hash = BinaryMerkleTree.CalculateRootFromMultiHash(new[] { hash, node }); } return(hash); }
public static MerklePath AddRange(this MerklePath merklePath, IEnumerable <Hash> hashes) { merklePath.Path.AddRange(hashes); return(merklePath); }