protected void BuildAuditTrail(List <MerkleProofHash> auditTrail, MerkleNode parent, MerkleNode child)
        {
            if (parent != null)
            {
                Contract(() => child.Parent == parent, "Parent of child is not expected parent.");
                var nextChild = parent.LeftNode == child ? parent.RightNode : parent.LeftNode;
                var direction = parent.LeftNode == child ? MerkleProofHash.Branch.Left : MerkleProofHash.Branch.Right;

                // For the last leaf, the right node may not exist.  In that case, we ignore it because it's
                // the hash we are given to verify.
                if (nextChild != null)
                {
                    auditTrail.Add(new MerkleProofHash(nextChild.Hash, direction));
                }

                BuildAuditTrail(auditTrail, child.Parent.Parent, child.Parent);
            }
        }
 protected virtual MerkleNode CreateNode(MerkleNode left, MerkleNode right)
 {
     return(new MerkleNode(left, right));
 }
        /// <summary>
        /// 함수 이름이 일관적인 감사다..;;
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public List <MerkleProofHash> ConsistencyProof(int m)
        {
            // Rule 1:
            // 일관성 증명을 시작할 수 있는 트리의 가장 왼쪽 노드를 찾는다.
            // 이 노드의 입사귀 갯수를 k로 설정한다.
            List <MerkleProofHash> hashNodes = new List <MerkleProofHash>();
            int idx = (int)Math.Log(m, 2);

            // 맨 왼쪽 노드를 가져온다.
            MerkleNode node = leaves[0];

            // idx가 지정된 노드에 도달할 때까지 트리를 탐색.
            while (idx > 0)
            {
                node = node.Parent;
                --idx;
            }

            int k = node.Leaves().Count();

            hashNodes.Add(new MerkleProofHash(node.Hash, MerkleProofHash.Branch.OldRoot));

            if (m == k)
            {
                // Continue with Rule 3 -- the remainder is the audit proof
            }
            else
            {
                // Rule 2:
                // 초기 형제 노드 (SN)를 규칙 1에 의해 획득 된 노드의 형제로 설정합니다.
                // m-k == # SN의 잎의 # 경우 형제 SN의 해시를 연결하고 규칙 2를 종료하십시오. 이는 이전 루트의 해시를 나타냅니다.
                // m-k <SN의 잎수이면 SN을 왼쪽 자식 노드로 설정하고 규칙 2를 반복합니다.

                // sibling node:
                MerkleNode sn           = node.Parent.RightNode;
                bool       traverseTree = true;

                while (traverseTree)
                {
                    Contract(() => sn != null, "Sibling node must exist because m != k");
                    int sncount = sn.Leaves().Count();

                    if (m - k == sncount)
                    {
                        hashNodes.Add(new MerkleProofHash(sn.Hash, MerkleProofHash.Branch.OldRoot));
                        break;
                    }

                    if (m - k > sncount)
                    {
                        hashNodes.Add(new MerkleProofHash(sn.Hash, MerkleProofHash.Branch.OldRoot));
                        sn = sn.Parent.RightNode;
                        k += sncount;
                    }
                    else // (m - k < sncount)
                    {
                        sn = sn.LeftNode;
                    }
                }
            }

            // Rule 3: Apply ConsistencyAuditProof below.

            return(hashNodes);
        }